397 lines
13 KiB
PHP
397 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* Turba data.php.
|
|
*
|
|
* Copyright 2001-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file LICENSE for license information (ASL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/apache.
|
|
*
|
|
* @author Jan Schneider <jan@horde.org>
|
|
*/
|
|
|
|
/**
|
|
* Remove empty attributes from attributes array.
|
|
*
|
|
* @param mixed $val Value from attributes array.
|
|
*
|
|
* @return boolean Boolean used by array_filter.
|
|
*/
|
|
function _emptyAttributeFilter($var)
|
|
{
|
|
if (!is_array($var)) {
|
|
return ($var != '');
|
|
}
|
|
|
|
foreach ($var as $v) {
|
|
if ($v == '') {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
require_once __DIR__ . '/lib/Application.php';
|
|
$app_ob = Horde_Registry::appInit('turba');
|
|
|
|
if (!$conf['menu']['import_export']) {
|
|
require TURBA_BASE . '/index.php';
|
|
exit;
|
|
}
|
|
|
|
/* If there are absolutely no valid sources, abort. */
|
|
if (!$cfgSources) {
|
|
$notification->push(_("No Address Books are currently available. Import and Export is disabled."), 'horde.error');
|
|
$page_output->header();
|
|
$notification->notify(array('listeners' => 'status'));
|
|
$page_output->footer();
|
|
exit;
|
|
}
|
|
|
|
/* Importable file types. */
|
|
$file_types = array(
|
|
'csv' => _("CSV"),
|
|
'tsv' => _("TSV"),
|
|
'vcard' => _("vCard"),
|
|
'mulberry' => _("Mulberry Address Book"),
|
|
'pine' => _("Pine Address Book"),
|
|
'ldif' => _("LDIF Address Book")
|
|
);
|
|
|
|
/* Templates for the different import steps. */
|
|
$templates = array(
|
|
Horde_Data::IMPORT_FILE => array(TURBA_TEMPLATES . '/data/export.inc'),
|
|
Horde_Data::IMPORT_CSV => array($registry->get('templates', 'horde') . '/data/csvinfo.inc'),
|
|
Horde_Data::IMPORT_TSV => array($registry->get('templates', 'horde') . '/data/tsvinfo.inc'),
|
|
Horde_Data::IMPORT_MAPPED => array($registry->get('templates', 'horde') . '/data/csvmap.inc'),
|
|
Horde_Data::IMPORT_DATETIME => array($registry->get('templates', 'horde') . '/data/datemap.inc')
|
|
);
|
|
|
|
/* Initial values. */
|
|
$vars = $injector->getInstance('Horde_Variables');
|
|
$import_step = $vars->get('import_step', 0) + 1;
|
|
$next_step = Horde_Data::IMPORT_FILE;
|
|
$app_fields = $bad_charset = $time_fields = array();
|
|
$error = false;
|
|
$import_mapping = array(
|
|
'e-mail' => 'email',
|
|
'homeaddress' => 'homeAddress',
|
|
'businessaddress' => 'workAddress',
|
|
'homephone' => 'homePhone',
|
|
'businessphone' => 'workPhone',
|
|
'mobilephone' => 'cellPhone',
|
|
'businessfax' => 'fax',
|
|
'jobtitle' => 'title',
|
|
'internetfreebusy' => 'freebusyUrl',
|
|
|
|
// Entourage on MacOS
|
|
'Dept' => 'department',
|
|
'Work Street Address' => 'workStreet',
|
|
'Work City' => 'workCity',
|
|
'Work State' => 'workProvince',
|
|
'Work Zip' => 'workPostalCode',
|
|
'Work Country/Region' => 'workCountry',
|
|
'Home Street Address' => 'homeStreet',
|
|
'Home City' => 'homeCity',
|
|
'Home State' => 'homeProvince',
|
|
'Home Zip' => 'homePostalCode',
|
|
'Home Country/Region' => 'homeCountry',
|
|
'Work Fax' => 'workFax',
|
|
'Work Phone 1' => 'workPhone',
|
|
'Home Phone 1' => 'homePhone',
|
|
'Instant Messaging 1' => 'imaddress',
|
|
|
|
// Thunderbird
|
|
'Primary Email' => 'email',
|
|
'Fax Number' => 'fax',
|
|
'Pager Number' => 'pager',
|
|
'Mobile Number' => 'Mobile Phone',
|
|
'Home Address' => 'homeStreet',
|
|
'Home ZipCode' => 'homePostalCode',
|
|
'Work Address' => 'workStreet',
|
|
'Work ZipCode' => 'workPostalCode',
|
|
'Work Country' => 'workCountry',
|
|
'Work Phone' => 'workPhone',
|
|
'Organization' => 'company',
|
|
'Web Page 1' => 'website',
|
|
);
|
|
$param = array(
|
|
'time_fields' => $time_fields,
|
|
'file_types' => $file_types,
|
|
'import_mapping' => array_merge(
|
|
$app_ob->getOutlookMapping(),
|
|
$import_mapping
|
|
)
|
|
);
|
|
if (in_array($vars->import_format, array('mulberry', 'pine'))) {
|
|
$vars->import_format = 'tsv';
|
|
}
|
|
if ($vars->actionID != 'select') {
|
|
array_unshift($templates[Horde_Data::IMPORT_FILE], TURBA_TEMPLATES . '/data/import.inc');
|
|
}
|
|
|
|
$data = null;
|
|
if ($vars->import_format) {
|
|
switch ($vars->import_format) {
|
|
case 'ldif':
|
|
$driver = 'Turba_Data_Ldif';
|
|
break;
|
|
|
|
case 'csv':
|
|
$param['check_charset'] = true;
|
|
// Fall-through
|
|
|
|
default:
|
|
$driver = $vars->import_format;
|
|
break;
|
|
}
|
|
|
|
try {
|
|
$data = $injector->getInstance('Horde_Core_Factory_Data')->create(
|
|
$driver,
|
|
array(
|
|
'cleanup' => array($app_ob, 'cleanupData')
|
|
)
|
|
);
|
|
} catch (Horde_Exception $e) {
|
|
$notification->push(_("This file format is not supported."), 'horde.error');
|
|
$next_step = Horde_Data::IMPORT_FILE;
|
|
}
|
|
}
|
|
|
|
/* Loop through the action handlers. */
|
|
switch ($vars->actionID) {
|
|
case Horde_Data::IMPORT_FILE:
|
|
try {
|
|
$driver = $injector->getInstance('Turba_Factory_Driver')->create($vars->dest);
|
|
} catch (Horde_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
$error = true;
|
|
break;
|
|
}
|
|
|
|
/* Check permissions. */
|
|
$max_contacts = Turba::getExtendedPermission($driver, 'max_contacts');
|
|
if (($max_contacts !== true) && ($max_contacts <= count($driver))) {
|
|
Horde::permissionDeniedError(
|
|
'turba',
|
|
'max_contacts',
|
|
sprintf(_("You are not allowed to create more than %d contacts in \"%s\"."), $max_contacts, $driver->title)
|
|
);
|
|
$error = true;
|
|
} else {
|
|
$data->storage->set('target', $vars->dest);
|
|
$data->storage->set('purge', $vars->purge);
|
|
}
|
|
break;
|
|
|
|
case Horde_Data::IMPORT_MAPPED:
|
|
case Horde_Data::IMPORT_DATETIME:
|
|
foreach ($cfgSources[$data->storage->get('target')]['map'] as $field => $null) {
|
|
if (substr($field, 0, 2) != '__' && !is_array($null)) {
|
|
switch ($attributes[$field]['type']) {
|
|
case 'monthyear':
|
|
case 'monthdayyear':
|
|
$time_fields[$field] = 'date';
|
|
break;
|
|
|
|
case 'time':
|
|
$time_fields[$field] = 'time';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
$param['time_fields'] = $time_fields;
|
|
break;
|
|
}
|
|
|
|
if (!$error && $data) {
|
|
try {
|
|
try {
|
|
$next_step = $data->nextStep($vars->actionID, $param);
|
|
|
|
/* Raise warnings if some exist. */
|
|
if (method_exists($data, 'warnings')) {
|
|
$warnings = $data->warnings();
|
|
if (count($warnings)) {
|
|
foreach ($warnings as $warning) {
|
|
$notification->push($warning, 'horde.warning');
|
|
}
|
|
$notification->push(_("The import can be finished despite the warnings."), 'horde.message');
|
|
}
|
|
}
|
|
} catch (Horde_Data_Exception_Charset $e) {
|
|
if ($e->badCharset != 'UTF-8') {
|
|
$bad_charset[] = $e->badCharset;
|
|
throw $e;
|
|
}
|
|
|
|
$param['charset'] = 'windows-1252';
|
|
try {
|
|
$next_step = $data->nextStep($vars->actionID, $param);
|
|
} catch (Horde_Data_Exception_Charset $e) {
|
|
$bad_charset = array('UTF-8', 'windows-1252');
|
|
throw $e;
|
|
}
|
|
}
|
|
} catch (Horde_Data_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
$next_step = $data->cleanup();
|
|
}
|
|
}
|
|
|
|
/* We have a final result set. */
|
|
if (is_array($next_step)) {
|
|
/* Create a Turba storage instance. */
|
|
$dest = $data->storage->get('target');
|
|
try {
|
|
$driver = $injector->getInstance('Turba_Factory_Driver')->create($dest);
|
|
} catch (Horde_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
$driver = null;
|
|
}
|
|
|
|
if (!count($next_step)) {
|
|
$notification->push(sprintf(_("The %s file didn't contain any contacts."), $file_types[$data->storage->get('format')]), 'horde.error');
|
|
} elseif ($driver) {
|
|
/* Purge old address book if requested. */
|
|
if ($data->storage->get('purge')) {
|
|
try {
|
|
$driver->deleteAll();
|
|
$notification->push(_("Address book successfully purged."), 'horde.success');
|
|
} catch (Turba_Exception $e) {
|
|
$notification->push(sprintf(_("The address book could not be purged: %s"), $e->getMessage()), 'horde.error');
|
|
}
|
|
}
|
|
|
|
$error = false;
|
|
$imported = 0;
|
|
foreach ($next_step as $row) {
|
|
if ($row instanceof Horde_Icalendar_Vcard) {
|
|
$row = $driver->toHash($row);
|
|
}
|
|
|
|
/* Don't search for empty attributes. */
|
|
try {
|
|
$result = $driver->search(array_filter($row, '_emptyAttributeFilter'));
|
|
} catch (Turba_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
$error = true;
|
|
break;
|
|
}
|
|
|
|
if (count($result)) {
|
|
$result->reset();
|
|
$object = $result->next();
|
|
$notification->push(sprintf(_("\"%s\" already exists and was not imported."),
|
|
$object->getValue('name')), 'horde.message');
|
|
} else {
|
|
/* Check for, and validate, any email fields */
|
|
foreach (array_keys($row) as $field) {
|
|
if ($attributes[$field]['type'] == 'email') {
|
|
$allow_multi = is_array($attributes[$field]['params']) &&
|
|
!empty($attributes[$field]['params']['allow_multi']);
|
|
|
|
$rfc822 = $injector->getInstance('Horde_Mail_Rfc822');
|
|
try {
|
|
$row[$field] = strval($rfc822->parseAddressList($row[$field], array(
|
|
'limit' => $allow_multi ? 0 : 1
|
|
)));
|
|
} catch (Horde_Mail_Exception $e) {
|
|
$row[$field] = '';
|
|
}
|
|
}
|
|
}
|
|
$row['__owner'] = $driver->getContactOwner();
|
|
|
|
try {
|
|
$driver->add($row);
|
|
$imported++;
|
|
} catch (Turba_Exception $e) {
|
|
$notification->push(sprintf(_("There was an error importing the data: %s"), $e->getMessage()), 'horde.error');
|
|
$error = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!$error && $imported) {
|
|
$notification->push(sprintf(_("%s file successfully imported."),
|
|
$file_types[$data->storage->get('format')]), 'horde.success');
|
|
}
|
|
}
|
|
$next_step = $data->cleanup();
|
|
}
|
|
|
|
switch ($next_step) {
|
|
case Horde_Data::IMPORT_MAPPED:
|
|
case Horde_Data::IMPORT_DATETIME:
|
|
foreach ($cfgSources[$data->storage->get('target')]['map'] as $field => $null) {
|
|
if (substr($field, 0, 2) != '__' && !is_array($null)) {
|
|
$app_fields[$field] = $attributes[$field]['label'];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
$page_output->header(array(
|
|
'title' => _("Import/Export Address Books")
|
|
));
|
|
$notification->notify(array('listeners' => 'status'));
|
|
|
|
$default_source = $prefs->getValue('default_dir');
|
|
if ($next_step == Horde_Data::IMPORT_FILE) {
|
|
/* Build the directory sources select widget. */
|
|
$unique_source = '';
|
|
$source_options = array();
|
|
foreach (Turba::getAddressBooks() as $key => $entry) {
|
|
if (!empty($entry['export'])) {
|
|
$source_options[] = '<option value="' . htmlspecialchars($key) . '">' .
|
|
htmlspecialchars($entry['title']) . "</option>\n";
|
|
$unique_source = $key;
|
|
}
|
|
}
|
|
|
|
/* Build the directory destination select widget. */
|
|
$unique_dest = '';
|
|
$dest_options = array();
|
|
$hasWriteable = false;
|
|
foreach (Turba::getAddressBooks(Horde_Perms::EDIT) as $key => $entry) {
|
|
$selected = ($key == $default_source) ? ' selected="selected"' : '';
|
|
$dest_options[] = '<option value="' . htmlspecialchars($key) . '" ' . $selected . '>' .
|
|
htmlspecialchars($entry['title']) . "</option>\n";
|
|
$unique_dest = $key;
|
|
$hasWriteable = true;
|
|
}
|
|
|
|
if (!$hasWriteable) {
|
|
array_shift($templates[$next_step]);
|
|
}
|
|
|
|
/* Build the charset options. */
|
|
$charsets = array();
|
|
|
|
if (!empty($bad_charset)) {
|
|
$charsets = $registry->nlsconfig->encodings_sort;
|
|
foreach ($registry->nlsconfig->charsets as $charset) {
|
|
if (!isset($charsets[$charset]) &&
|
|
!in_array($charset, $bad_charset)) {
|
|
$charsets[$charset] = $charset;
|
|
}
|
|
}
|
|
$my_charset = $GLOBALS['registry']->getLanguageCharset();
|
|
}
|
|
}
|
|
|
|
// @todo: These variables are needed for stuff that is in *Horde*, not Turba.
|
|
// That's not correct.
|
|
if ($data) {
|
|
$storage = $data->storage;
|
|
}
|
|
|
|
foreach ($templates[$next_step] as $template) {
|
|
require $template;
|
|
}
|
|
|
|
$page_output->footer();
|