Viewing File: /usr/local/cpanel/base/3rdparty/roundcube/plugins/cpanelvcfimport/cpanelvcfimport.php
<?php
/**
+-----------------------------------------------------------------------+
| |
| cpanelvcfimport Copyright 2022 cPanel, L.L.C. |
| All rights reserved. |
| copyright@cpanel.net https://cpanel.net |
| This code is subject to the cPanel license. |
| Unauthorized copying is prohibited. |
| |
+-----------------------------------------------------------------------+
*/
class cpanelvcfimport extends rcube_plugin
{
private const PLUGIN_VERSION = 'v11.108';
/**
* Information about this plugin that is queried by roundcube.
*/
private const PLUGIN_INFO = [
'name' => 'cpanelvcfimport',
'vendor' => 'cPanel, LLC',
'version' => self::PLUGIN_VERSION,
'license' => 'cPanel License',
'uri' => 'https://cpanel.net'
];
const LOG_DISABLED = 0;
const LOG_FAILURE = 1;
const LOG_VERBOSE = 2;
const TOUCH_FILE = '.cpanel_vcf_import';
public $task = 'login';
private $rcmail;
private $contacts;
private $group;
private $log_level;
function init()
{
$this->add_hook('login_after', array($this, 'attemptImport'));
}
function attemptImport($params)
{
$this->initialize();
$user = str_replace('..', '', $this->rcmail->user->get_username());
$srcdir = $this->rcmail->config->get('cpanel_data_dir');
if( posix_getpwuid(posix_geteuid())['name'] === 'cpanelroundcube' ) {
$cpuser = substr( $_ENV['HOME'], strrpos( $_ENV['HOME'], "/" ) + 1 );
$srcdir = "/var/cpanel/userhomes/cpanelroundcube/{$cpuser}/vcards/";
}
$run_once = $this->rcmail->config->get('cpanel_run_once');
$charset = $this->rcmail->config->get('cpanel_file_charset');
$touch_file = slashify($srcdir) . cpanelvcfimport::TOUCH_FILE . "_{$user}";
if(!is_dir($srcdir)){ mkdir(slashify($srcdir), 0711, true); }
if (file_exists($touch_file)) {
if (!$run_once) { //cleanup old touch file
if (!unlink($touch_file)) {
$this->log("Unable to remove touch file for {$user}",
cpanelvcfimport::LOG_FAILURE);
}
} else { // dont run again
$this->log("Touch file {$touch_file} exists for {$user} and cpanel_run_once is true, exiting");
return;
}
}
$this->group = $this->get_contact_group($this->contacts);
//create touch file so we only run once, whether success or failure
if ($run_once) {
if (touch($touch_file)) {
$this->log("Touch file created for {$user}");
} else {
$this->log("Error creating touch file {$touch_file} for {$user}",
cpanelvcfimport::LOG_FAILURE);
}
}
$vcard_backup = slashify($srcdir) . $user . '.vcf';
if ( file_exists($vcard_backup) && filesize($vcard_backup) ) {
$added_contacts = array();
$vcards = array();
$file_content = file_get_contents($vcard_backup);
// let rcube_vcard do the hard work :-)
$vcard_o = new rcube_vcard();
$vcard_o->extend_fieldmap($this->contacts->vcard_map);
$v_list = $vcard_o->import($file_content);
if (!empty($v_list)) {
$vcards = array_merge($vcards, $v_list);
}
$IMPORT_STATS = new stdClass;
$IMPORT_STATS->names = array();
$IMPORT_STATS->skipped_names = array();
$IMPORT_STATS->countup = count($vcards);
$IMPORT_STATS->inserted = $IMPORT_STATS->skipped = $IMPORT_STATS->invalid = $IMPORT_STATS->errors = 0;
if ($replace) {
$this->contacts->delete_all($this->contacts->groups && $with_groups < 2);
}
if ($with_groups) {
$import_groups = $this->contacts->list_groups();
}
foreach ($vcards as $vcard) {
$a_record = $vcard->get_assoc();
// Generate contact's display name (must be before validation), the same we do in save.inc
if (empty($a_record['name'])) {
$a_record['name'] = rcube_addressbook::compose_display_name($a_record, true);
// Reset it if equals to email address (from compose_display_name())
if ($a_record['name'] == $a_record['email'][0]) {
$a_record['name'] = '';
}
}
// skip invalid (incomplete) entries
if (!$this->contacts->validate($a_record, true)) {
$IMPORT_STATS->invalid++;
continue;
}
// We're using UTF8 internally
$email = $vcard->email[0];
$email = rcube_utils::idn_to_utf8($email);
$a_record['vcard'] = $vcard->export();
$plugin = $this->rcmail->plugins->exec_hook('contact_create',
array('record' => $a_record, 'source' => null));
$a_record = $plugin['record'];
// insert record and send response
if (!$plugin['abort'])
$success = $this->contacts->insert($a_record);
else
$success = $plugin['result'];
if ($success) {
// assign groups for this contact (if enabled)
if ($with_groups && !empty($a_record['groups'])) {
foreach (explode(',', $a_record['groups'][0]) as $group_name) {
if ($group_id = rcmail_import_group_id($group_name, $this->contacts, $with_groups == 1, $import_groups)) {
$this->contacts->add_to_group($group_id, $success);
}
}
}
// assign to 'Imported Contacts' group
if ($this->group) {
$this->contacts->add_to_group($this->group['id'], $success);
}
$IMPORT_STATS->inserted++;
$IMPORT_STATS->names[] = $a_record['name'] ?: $email;
}
else {
$IMPORT_STATS->errors++;
}
}
$this->log("IMPORTED " . $IMPORT_STATS->inserted);
$this->log("ERRORS " . $IMPORT_STATS->errors);
}
return $params;
}
/**
* If the configuration requests it, create a new group
* to add contacts to. If the group exists, create a new one with
* a number such as Imported Contacts 2
*
* @param $rc_contacts rcube_contacts
* @return mixed False on error, array with record props in success
*/
private function get_contact_group($rc_contacts)
{
$group_name = $this->rcmail->config->get('cpanel_group_name');
if ($group_name) {
return $rc_contacts->create_group($group_name);
}
return false;
}
/**
* Initialize an rcmail instance for our user
* and load our configuration
*/
private function initialize()
{
$this->rcmail = rcmail::get_instance();
// Load plugin's config file
$this->load_config();
$this->log_level = $this->rcmail->config->get('cpanel_log_level');
$this->contacts = $this->rcmail->get_address_book(null, true);
}
/**
* Converts $str to $charset
* if not charset is specified it will attempt to
* determine the charset.
* @param $str
* @param null $charset
* @return string
*/
private function convert_charset($str, $charset = null)
{
if (!$charset) {
$charset = rcube_charset::detect($str);
}
return rcube_charset::convert($str, $charset, RCUBE_CHARSET);
}
private function log($message, $level = cpanelvcfimport::LOG_VERBOSE)
{
if ($this->log_level && $level <= $this->log_level) {
error_log("[CPANELVCFIMPORT: {$message}]");
}
}
}
Back to Directory
File Manager