Files
server/usr/share/psa-horde/turba/data.php
2026-01-07 20:52:11 +01:00

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();