Files
server/usr/share/psa-pear/pear/turba-import-openxchange
2026-01-07 20:52:11 +01:00

259 lines
9.1 KiB
PHP
Executable File

#!/usr/bin/env php
<?php
/**
* This script imports Open-Xchange addressbooks into Turba.
*
* The first argument must be the API endpoint of an Open-Xchange servers,
* usually something like http://servername/ajax.
*
* If called with three arguments, the further arguments must be the user name
* (usually "Administrator") and password of an administrator user to import
* public address books.
*
* If called with two arguments, the second argument must be a file with user
* names and cleartext passwords separated by spaces.
*
* Copyright 2014-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>
*/
/**
* (Re-)load the $cfgSources array, necessary after adding new address books.
*
* @param array $sources The orginal $cfgSources from backends(.local).php.
* @param boolean $admin Is the current user an admin and are we updating
* global address books?
*
* @return array List with the updated $cfgSources and flag whether we use
* shares.
*/
function loadSources($sources, $admin)
{
foreach ($sources as $key => $cfg) {
if ($admin && !empty($cfg['use_shares'])) {
continue;
}
$cfgSources[$key] = $cfg;
if (!empty($cfg['use_shares'])) {
$hasShares = true;
}
}
if ($hasShares && !$admin) {
$cfgSources = Turba::getConfigFromShares($cfgSources, true);
}
$cfgSources = Turba::permissionsFilter(
$cfgSources,
Horde_Perms::EDIT,
array('require_add' => true)
);
return array($cfgSources, $hasShares);
}
// Init application.
if (file_exists(__DIR__ . '/../../turba/lib/Application.php')) {
$baseDir = __DIR__ . '/../';
} else {
require_once 'PEAR/Config.php';
$baseDir = PEAR_Config::singleton()
->get('horde_dir', null, 'pear.horde.org') . '/turba/';
}
require_once $baseDir . 'lib/Application.php';
Horde_Registry::appInit('turba', array('cli' => true, 'user_admin' => true));
// Read command line parameters.
if ($argc < 3 || $argc > 4) {
$cli->message('Too many or too few parameters.', 'cli.error');
$cli->writeln('Usage: turba-import-openxchange url [ file | user password ]');
$cli->writeln($cli->indent('url is the URL of an Open-Xchange AJAX endpoint'));
$cli->writeln($cli->indent('file is a file with space separated user names and passwords to import'));
$cli->writeln($cli->indent('personal address books.'));
$cli->writeln($cli->indent('user and password are credentials of an administrator user to import public'));
$cli->writeln($cli->indent('address books.'));
exit;
}
$admin = $argc == 4;
// Basic objects and variables.
$endpoint = parse_url($argv[1]);
$cli->message('Opening endpoint ' . $argv[1]);
$ox = new Horde_OpenXchange_Contacts(array('endpoint' => $argv[1]));
$turba_shares = $injector->getInstance('Turba_Shares');
$sources = Turba::availableSources();
// Prepare handle on user/password list.
if ($admin) {
$fp = fopen('php://temp', 'r+');
fwrite($fp, $argv[2] . ' ' . $argv[3]);
rewind($fp);
} else {
if (!is_readable($argv[2]) || !filesize($argv[2])) {
$cli->message($argv[2] . ' is not readable or empty', 'cli.error');
exit(1);
}
$fp = fopen($argv[2], 'r');
}
if (!$fp) {
exit(1);
}
// Loop through all users.
while ($row = fgetcsv($fp, 0, ' ')) {
$user = $row[0];
if (is_null($user)) {
continue;
}
$ox->logout();
$ox->login($user, $row[1]);
$registry->setAuth($user, array());
$cli->message('Importing ' . $user . '\'s address books');
// Reset sources for current user.
list($cfgSources, $hasShares) = loadSources($sources, $admin);
$count = 0;
$contactMap = $groups = array();
$abooks = $ox->listResources(
$admin
? Horde_OpenXchange_Contacts::RESOURCE_PUBLIC
: Horde_OpenXchange_Contacts::RESOURCE_PRIVATE
);
$default = $ox->getConfig('folder/contacts');
// Loop through all address books.
foreach ($abooks as $folderId => $abook) {
// Check if we already have an address book matching the name.
$target = null;
foreach ($cfgSources as $id => $source) {
if ($abook['label'] == $source['title']) {
$target = $id;
break;
}
}
if ($target) {
$cli->message('Address book "' . $abook['label'] . '" found, updating...');
} else {
// Create new address book.
$cli->message('Address book "' . $abook['label'] . '" not found, creating...');
$driver = $injector
->getInstance('Turba_Factory_Driver')
->createFromConfig($sources[$conf['shares']['source']]);
$params = array(
'params' => array('source' => $conf['shares']['source']),
'name' => $abook['label'],
);
$target = strval(new Horde_Support_Randomid());
$share = $driver->createShare($target, $params);
foreach ($abook['hordePermission']['group'] as $group => $perm) {
$share->addGroupPermission($group, $perm);
}
foreach ($abook['hordePermission']['user'] as $user => $perm) {
$share->addUserPermission($user, $perm);
}
list($cfgSources, $hasShares) = loadSources($sources, $admin);
}
$groups[$target] = array();
if ($folderId == $default) {
$prefs->setValue('default_dir', $target);
}
// Initiate driver.
try {
$driver = $injector
->getInstance('Turba_Factory_Driver')
->create($target);
} catch (Turba_Exception $e) {
$cli->message(' ' . sprintf(_("Connection failed: %s"), $e->getMessage()), 'cli.error');
continue;
}
$contacts = $ox->listContacts($folderId);
// Loop through all contacts.
foreach ($contacts as $contact) {
$contact['__uid'] == $contact['uid'];
$contact['__tags'] == $contact['categories'];
if ($contact['distributionList']) {
// Keep contact lists for later.
$groups[$target][] = $contact;
} else {
// Regular contact.
if (!empty($contact['photourl'])) {
$contact['photo'] = file_get_contents($endpoint['scheme'] . '://' . $endpoint['host'] . $contact['photourl']);
if (!$contact['photo']) {
$contact['phototype'] = null;
}
}
try {
$contactMap[$folderId][$contact['id']] = array(
$target,
$driver->add($contact)
);
$count++;
} catch (Turba_Exception $e) {
$cli->message(' ' . $e->getMessage(), 'cli.error');
}
}
}
}
// Add all contact lists now, that we have all IDs from the imported
// contacts.
foreach ($groups as $target => $tmp) {
if (!count($tmp)) {
continue;
}
$driver = $injector
->getInstance('Turba_Factory_Driver')
->create($target);
foreach ($tmp as $group) {
$gid = $driver->add($group);
$object = new Turba_Object_Group(
$driver,
array_merge($group, array('__key' => $gid))
);
$count++;
foreach ($group['members'] as $member) {
$found = false;
if (isset($member['id'])) {
if (!isset($member['folder_id'])) {
$member['folder_id'] = $group['folder_id'];
}
try {
$object->addMember(
$contactMap[$member['folder_id']][$member['id']][1],
$contactMap[$member['folder_id']][$member['id']][0]
);
$found = true;
} catch (Horde_Exception_NotFound $e) {
// OX < 6.22 doesn't provide folder IDs with group
// members but still allows members from different
// folders.
}
}
if (!$found) {
try {
$result = $driver->add(array(
'name' => $member['display_name'],
'email' => $member['mail']
));
$object->addMember($result, $target);
$count++;
} catch (Turba_Exception $e) {
$cli->message(' ' . $e->getMessage(), 'cli.error');
}
}
}
$object->store();
}
}
$cli->message(' Added ' . $count . ' contacts', 'cli.success');
$count = 0;
}