Skip to content

Commit

Permalink
[jan] Add script to import contacts from Open-Xchange.
Browse files Browse the repository at this point in the history
  • Loading branch information
yunosh committed Mar 14, 2014
1 parent 98c1596 commit 265496d
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 2 deletions.
246 changes: 246 additions & 0 deletions turba/bin/turba-import-openxchange
@@ -0,0 +1,246 @@
#!/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 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();
$contactMap = array();

// 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);
if (!count($cfgSources)) {
$cli->message('No address book available for ' . $user, 'cli.error');
continue;
}

$count = 0;
$groups = array();
$abooks = $ox->listAddressBooks(
$admin
? Horde_OpenXchange_Contacts::ADDRESS_BOOK_PUBLIC
: Horde_OpenXchange_Contacts::ADDRESS_BOOK_PRIVATE
);

// 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')
->create($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();

// 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) {
if (isset($member['id'])) {
$object->addMember(
$contactMap[$member['folder_id']][$member['id']][1],
$contactMap[$member['folder_id']][$member['id']][0]
);
} else {
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;
}
1 change: 1 addition & 0 deletions turba/docs/CHANGES
Expand Up @@ -2,6 +2,7 @@
v4.2.0-git
----------

[jan] Add script to import contacts from Open-Xchange.
[jan] Don't remove missing contacts from distributions lists in Kolab backends
(Bug #12861).
[jan] Support binary fields (photos) in Kolab backends.
Expand Down
15 changes: 13 additions & 2 deletions turba/package.xml
Expand Up @@ -28,7 +28,7 @@
<email>slusarz@horde.org</email>
<active>yes</active>
</developer>
<date>2014-03-10</date>
<date>2014-03-14</date>
<version>
<release>4.2.0alpha1</release>
<api>4.0.0</api>
Expand All @@ -39,6 +39,7 @@
</stability>
<license uri="http://www.horde.org/licenses/apache">ASL</license>
<notes>
* [jan] Add script to import contacts from Open-Xchange.
* [jan] Don&apos;t remove missing contacts from distributions lists in Kolab backends (Bug #12861).
* [jan] Support binary fields (photos) in Kolab backends.
* [mms] Allow tagging system to be disabled via configuration option.
Expand Down Expand Up @@ -66,6 +67,7 @@
<file name="turba-convert-sql-shares-to-sqlng" role="script">
<tasks:replace from="/usr/bin/env php" to="php_bin" type="pear-config" />
</file>
<file name="turba-import-openxchange" role="script" />
<file name="turba-import-squirrelmail-file-abook" role="script">
<tasks:replace from="/usr/bin/env php" to="php_bin" type="pear-config" />
</file>
Expand Down Expand Up @@ -864,6 +866,13 @@
<max>3.0.0alpha1</max>
<exclude>3.0.0alpha1</exclude>
</package>
<package>
<name>Horde_OpenXchange</name>
<channel>pear.horde.org</channel>
<min>1.0.0</min>
<max>2.0.0alpha1</max>
<exclude>2.0.0alpha1</exclude>
</package>
<package>
<name>Horde_Service_Facebook</name>
<channel>pear.horde.org</channel>
Expand All @@ -886,6 +895,7 @@
<install as="turba/addressbooks/index.php" name="addressbooks/index.php" />
<install as="turba-convert-datatree-shares-to-sql" name="bin/turba-convert-datatree-shares-to-sql" />
<install as="turba-convert-sql-shares-to-sqlng" name="bin/turba-convert-sql-shares-to-sqlng" />
<install as="turba-import-openxchange" name="bin/turba-import-openxchange" />
<install as="turba-import-squirrelmail-file-abook" name="bin/turba-import-squirrelmail-file-abook" />
<install as="turba-import-squirrelmail-sql-abook" name="bin/turba-import-squirrelmail-sql-abook" />
<install as="turba-import-vcards" name="bin/turba-import-vcards" />
Expand Down Expand Up @@ -1781,9 +1791,10 @@
<stability>
<release>alpha</release>
<api>stable</api></stability>
<date>2014-03-10</date>
<date>2014-03-14</date>
<license uri="http://www.horde.org/licenses/apache">ASL</license>
<notes>
* [jan] Add script to import contacts from Open-Xchange.
* [jan] Don&apos;t remove missing contacts from distributions lists in Kolab backends (Bug #12861).
* [jan] Support binary fields (photos) in Kolab backends.
* [mms] Allow tagging system to be disabled via configuration option.
Expand Down

0 comments on commit 265496d

Please sign in to comment.