summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2014-10-14 11:47:35 (GMT)
committerAleksander Machniak <machniak@kolabsys.com>2014-10-14 11:47:35 (GMT)
commit782709e22773493e8d6ce9a70abdfc45b175d01a (patch)
tree86c926e2e165ab7f8e59ec1e9ca20952fe614078
parent2d729975897985ab2fcc9784a8352c90a185db27 (diff)
downloadkolab-chwala-782709e22773493e8d6ce9a70abdfc45b175d01a.tar.gz
Finish storing external storage configuration in Kolab driver
-rw-r--r--lib/api/folder_create.php5
-rw-r--r--lib/client/file_ui_client_main.php4
-rw-r--r--lib/drivers/kolab/kolab_file_storage.php8
-rw-r--r--lib/drivers/kolab/plugins/libkolab/lib/kolab_format.php124
-rw-r--r--lib/drivers/kolab/plugins/libkolab/lib/kolab_format_configuration.php42
-rw-r--r--lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_cache.php7
-rw-r--r--lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_config.php144
-rw-r--r--lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_folder.php5
-rw-r--r--lib/drivers/seafile/seafile_api.php6
-rw-r--r--lib/file_api.php2
10 files changed, 307 insertions, 40 deletions
diff --git a/lib/api/folder_create.php b/lib/api/folder_create.php
index 1100f5b..55b3b3a 100644
--- a/lib/api/folder_create.php
+++ b/lib/api/folder_create.php
@@ -78,8 +78,9 @@ class file_api_folder_create extends file_api_common
// check if authentication works
$data = $driver->driver_validate($this->args);
- $data['title'] = $this->args['folder'];
- $data['driver'] = $this->args['driver'];
+ $data['title'] = $this->args['folder'];
+ $data['driver'] = $this->args['driver'];
+ $data['enabled'] = 1;
// don't store password
// @TODO: store passwords encrypted?
diff --git a/lib/client/file_ui_client_main.php b/lib/client/file_ui_client_main.php
index d6b8d4a..bc78220 100644
--- a/lib/client/file_ui_client_main.php
+++ b/lib/client/file_ui_client_main.php
@@ -72,7 +72,7 @@ class file_ui_client_main extends file_ui
'id' => 'folder-driver-checkbox',
));
$drivers = html::div('drivers',
- html::span('drivers-header', $drivers_input->show()
+ html::span('drivers-header', $drivers_input->show() . '&nbsp;'
. html::label('folder-driver-checkbox', $this->translate('folder.driverselect')))
. html::div('drivers-list', '')
);
@@ -85,7 +85,7 @@ class file_ui_client_main extends file_ui
$content = html::tag('fieldset', null,
html::tag('legend', null, $this->translate('folder.createtitle'))
. $table->show()
- . $input_parent->show()
+ . $input_parent->show() . '&nbsp;'
. html::label('folder-parent-checkbox', $this->translate('folder.under'))
. $drivers
);
diff --git a/lib/drivers/kolab/kolab_file_storage.php b/lib/drivers/kolab/kolab_file_storage.php
index eef9a8e..70a7f43 100644
--- a/lib/drivers/kolab/kolab_file_storage.php
+++ b/lib/drivers/kolab/kolab_file_storage.php
@@ -359,13 +359,7 @@ class kolab_file_storage implements file_storage
$result = array();
foreach ($drivers as $driver) {
- $result[$driver['title']] = array(
- 'title' => $driver['title'],
- 'driver' => $driver['driver'],
- 'settings' => $driver['settings'],
- // Kolab specific
- 'uid' => $driver['uid'],
- );
+ $result[$driver['title']] = $driver;
}
return $result;
diff --git a/lib/drivers/kolab/plugins/libkolab/lib/kolab_format.php b/lib/drivers/kolab/plugins/libkolab/lib/kolab_format.php
index ae7705c..8c6b1d4 100644
--- a/lib/drivers/kolab/plugins/libkolab/lib/kolab_format.php
+++ b/lib/drivers/kolab/plugins/libkolab/lib/kolab_format.php
@@ -47,6 +47,117 @@ abstract class kolab_format
const KTYPE_PREFIX = 'application/x-vnd.kolab.';
const PRODUCT_ID = 'Roundcube-libkolab-1.1';
+ // mapping table for valid PHP timezones not supported by libkolabxml
+ // basically the entire list of ftp://ftp.iana.org/tz/data/backward
+ protected static $timezone_map = array(
+ 'Africa/Asmera' => 'Africa/Asmara',
+ 'Africa/Timbuktu' => 'Africa/Abidjan',
+ 'America/Argentina/ComodRivadavia' => 'America/Argentina/Catamarca',
+ 'America/Atka' => 'America/Adak',
+ 'America/Buenos_Aires' => 'America/Argentina/Buenos_Aires',
+ 'America/Catamarca' => 'America/Argentina/Catamarca',
+ 'America/Coral_Harbour' => 'America/Atikokan',
+ 'America/Cordoba' => 'America/Argentina/Cordoba',
+ 'America/Ensenada' => 'America/Tijuana',
+ 'America/Fort_Wayne' => 'America/Indiana/Indianapolis',
+ 'America/Indianapolis' => 'America/Indiana/Indianapolis',
+ 'America/Jujuy' => 'America/Argentina/Jujuy',
+ 'America/Knox_IN' => 'America/Indiana/Knox',
+ 'America/Louisville' => 'America/Kentucky/Louisville',
+ 'America/Mendoza' => 'America/Argentina/Mendoza',
+ 'America/Porto_Acre' => 'America/Rio_Branco',
+ 'America/Rosario' => 'America/Argentina/Cordoba',
+ 'America/Virgin' => 'America/Port_of_Spain',
+ 'Asia/Ashkhabad' => 'Asia/Ashgabat',
+ 'Asia/Calcutta' => 'Asia/Kolkata',
+ 'Asia/Chungking' => 'Asia/Shanghai',
+ 'Asia/Dacca' => 'Asia/Dhaka',
+ 'Asia/Katmandu' => 'Asia/Kathmandu',
+ 'Asia/Macao' => 'Asia/Macau',
+ 'Asia/Saigon' => 'Asia/Ho_Chi_Minh',
+ 'Asia/Tel_Aviv' => 'Asia/Jerusalem',
+ 'Asia/Thimbu' => 'Asia/Thimphu',
+ 'Asia/Ujung_Pandang' => 'Asia/Makassar',
+ 'Asia/Ulan_Bator' => 'Asia/Ulaanbaatar',
+ 'Atlantic/Faeroe' => 'Atlantic/Faroe',
+ 'Atlantic/Jan_Mayen' => 'Europe/Oslo',
+ 'Australia/ACT' => 'Australia/Sydney',
+ 'Australia/Canberra' => 'Australia/Sydney',
+ 'Australia/LHI' => 'Australia/Lord_Howe',
+ 'Australia/NSW' => 'Australia/Sydney',
+ 'Australia/North' => 'Australia/Darwin',
+ 'Australia/Queensland' => 'Australia/Brisbane',
+ 'Australia/South' => 'Australia/Adelaide',
+ 'Australia/Tasmania' => 'Australia/Hobart',
+ 'Australia/Victoria' => 'Australia/Melbourne',
+ 'Australia/West' => 'Australia/Perth',
+ 'Australia/Yancowinna' => 'Australia/Broken_Hill',
+ 'Brazil/Acre' => 'America/Rio_Branco',
+ 'Brazil/DeNoronha' => 'America/Noronha',
+ 'Brazil/East' => 'America/Sao_Paulo',
+ 'Brazil/West' => 'America/Manaus',
+ 'Canada/Atlantic' => 'America/Halifax',
+ 'Canada/Central' => 'America/Winnipeg',
+ 'Canada/East-Saskatchewan' => 'America/Regina',
+ 'Canada/Eastern' => 'America/Toronto',
+ 'Canada/Mountain' => 'America/Edmonton',
+ 'Canada/Newfoundland' => 'America/St_Johns',
+ 'Canada/Pacific' => 'America/Vancouver',
+ 'Canada/Saskatchewan' => 'America/Regina',
+ 'Canada/Yukon' => 'America/Whitehorse',
+ 'Chile/Continental' => 'America/Santiago',
+ 'Chile/EasterIsland' => 'Pacific/Easter',
+ 'Cuba' => 'America/Havana',
+ 'Egypt' => 'Africa/Cairo',
+ 'Eire' => 'Europe/Dublin',
+ 'Europe/Belfast' => 'Europe/London',
+ 'Europe/Tiraspol' => 'Europe/Chisinau',
+ 'GB' => 'Europe/London',
+ 'GB-Eire' => 'Europe/London',
+ 'Greenwich' => 'Etc/GMT',
+ 'Hongkong' => 'Asia/Hong_Kong',
+ 'Iceland' => 'Atlantic/Reykjavik',
+ 'Iran' => 'Asia/Tehran',
+ 'Israel' => 'Asia/Jerusalem',
+ 'Jamaica' => 'America/Jamaica',
+ 'Japan' => 'Asia/Tokyo',
+ 'Kwajalein' => 'Pacific/Kwajalein',
+ 'Libya' => 'Africa/Tripoli',
+ 'Mexico/BajaNorte' => 'America/Tijuana',
+ 'Mexico/BajaSur' => 'America/Mazatlan',
+ 'Mexico/General' => 'America/Mexico_City',
+ 'NZ' => 'Pacific/Auckland',
+ 'NZ-CHAT' => 'Pacific/Chatham',
+ 'Navajo' => 'America/Denver',
+ 'PRC' => 'Asia/Shanghai',
+ 'Pacific/Ponape' => 'Pacific/Pohnpei',
+ 'Pacific/Samoa' => 'Pacific/Pago_Pago',
+ 'Pacific/Truk' => 'Pacific/Chuuk',
+ 'Pacific/Yap' => 'Pacific/Chuuk',
+ 'Poland' => 'Europe/Warsaw',
+ 'Portugal' => 'Europe/Lisbon',
+ 'ROC' => 'Asia/Taipei',
+ 'ROK' => 'Asia/Seoul',
+ 'Singapore' => 'Asia/Singapore',
+ 'Turkey' => 'Europe/Istanbul',
+ 'UCT' => 'Etc/UCT',
+ 'US/Alaska' => 'America/Anchorage',
+ 'US/Aleutian' => 'America/Adak',
+ 'US/Arizona' => 'America/Phoenix',
+ 'US/Central' => 'America/Chicago',
+ 'US/East-Indiana' => 'America/Indiana/Indianapolis',
+ 'US/Eastern' => 'America/New_York',
+ 'US/Hawaii' => 'Pacific/Honolulu',
+ 'US/Indiana-Starke' => 'America/Indiana/Knox',
+ 'US/Michigan' => 'America/Detroit',
+ 'US/Mountain' => 'America/Denver',
+ 'US/Pacific' => 'America/Los_Angeles',
+ 'US/Samoa' => 'Pacific/Pago_Pago',
+ 'Universal' => 'Etc/UTC',
+ 'W-SU' => 'Europe/Moscow',
+ 'Zulu' => 'Etc/UTC',
+ );
+
/**
* Factory method to instantiate a kolab_format object of the given type and version
*
@@ -63,7 +174,7 @@ abstract class kolab_format
if (!self::supports($version))
return PEAR::raiseError("No support for Kolab format version " . $version);
- $type = preg_replace('/configuration\.[a-z.]+$/', 'configuration', $type);
+ $type = preg_replace('/configuration\.[a-z._]+$/', 'configuration', $type);
$suffix = preg_replace('/[^a-z]+/', '', $type);
$classname = 'kolab_format_' . $suffix;
if (class_exists($classname))
@@ -123,10 +234,15 @@ abstract class kolab_format
if (!$dateonly)
$result->setTime($datetime->format('G'), $datetime->format('i'), $datetime->format('s'));
- if ($tz && in_array($tz->getName(), array('UTC', 'GMT', '+00:00', 'Z')))
+ if ($tz && in_array($tz->getName(), array('UTC', 'GMT', '+00:00', 'Z'))) {
$result->setUTC(true);
- else if ($tz !== false)
- $result->setTimezone($tz->getName());
+ }
+ else if ($tz !== false) {
+ $tzid = $tz->getName();
+ if (array_key_exists($tzid, self::$timezone_map))
+ $tzid = self::$timezone_map[$tzid];
+ $result->setTimezone($tzid);
+ }
}
return $result;
diff --git a/lib/drivers/kolab/plugins/libkolab/lib/kolab_format_configuration.php b/lib/drivers/kolab/plugins/libkolab/lib/kolab_format_configuration.php
index 17b46a7..24bc8de 100644
--- a/lib/drivers/kolab/plugins/libkolab/lib/kolab_format_configuration.php
+++ b/lib/drivers/kolab/plugins/libkolab/lib/kolab_format_configuration.php
@@ -32,12 +32,14 @@ class kolab_format_configuration extends kolab_format
protected $write_func = 'writeConfiguration';
private $type_map = array(
- 'category' => Configuration::TypeCategoryColor,
- 'dictionary' => Configuration::TypeDictionary,
- 'relation' => Configuration::TypeRelation,
- 'snippet' => Configuration::TypeSnippet,
+ 'category' => Configuration::TypeCategoryColor,
+ 'dictionary' => Configuration::TypeDictionary,
+ 'file_driver' => Configuration::TypeFileDriver,
+ 'relation' => Configuration::TypeRelation,
+ 'snippet' => Configuration::TypeSnippet,
);
+ private $driver_settings_fields = array('host', 'port', 'username', 'password');
/**
* Set properties to the kolabformat object
@@ -63,6 +65,21 @@ class kolab_format_configuration extends kolab_format
$this->obj = new Configuration($categories);
break;
+ case 'file_driver':
+ $driver = new FileDriver($object['driver'], $object['title']);
+
+ $driver->setEnabled((bool) $object['enabled']);
+
+ foreach ($this->driver_settings_fields as $field) {
+ $value = $object[$field];
+ if ($value !== null) {
+ $driver->{'set' . ucfirst($field)}($value);
+ }
+ }
+
+ $this->obj = new Configuration($driver);
+ break;
+
case 'relation':
$relation = new Relation(strval($object['name']), strval($object['category']));
@@ -157,6 +174,19 @@ class kolab_format_configuration extends kolab_format
// TODO: implement this
break;
+ case 'file_driver':
+ $driver = $this->obj->file_driver();
+
+ $object['driver'] = $driver->driver();
+ $object['title'] = $driver->title();
+ $object['enabled'] = $driver->enabled();
+
+ foreach ($this->driver_settings_fields as $field) {
+ $object[$field] = $driver->{$field}();
+ }
+
+ break;
+
case 'relation':
$relation = $this->obj->relation();
@@ -241,6 +271,10 @@ class kolab_format_configuration extends kolab_format
else if (!empty($member['params']['message-id'])) {
$words[] = $member['params']['message-id'];
}
+ else {
+ // derive message identifier from URI
+ $words[] = md5($url);
+ }
}
return $words;
diff --git a/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_cache.php b/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_cache.php
index 4f09e0f..bced3b3 100644
--- a/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_cache.php
@@ -376,12 +376,13 @@ class kolab_storage_cache
*
* @param string Entry's IMAP message UID
* @param string Entry's Object UID
- * @param string Target IMAP folder to move it to
+ * @param object kolab_storage_folder Target storage folder instance
*/
- public function move($msguid, $uid, $target_folder)
+ public function move($msguid, $uid, $target)
{
if ($this->ready) {
- $target = kolab_storage::get_folder($target_folder);
+ // clear cached uid mapping and force new lookup
+ unset($target->cache->uid2msg[$uid]);
// resolve new message UID in target folder
if ($new_msguid = $target->cache->uid2msguid($uid)) {
diff --git a/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_config.php b/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_config.php
index 8a0fab5..d58e3c0 100644
--- a/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_config.php
+++ b/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_config.php
@@ -351,6 +351,8 @@ class kolab_storage_config
'params' => $params,
);
}
+
+ return false;
}
/**
@@ -654,6 +656,100 @@ class kolab_storage_config
}
/**
+ * Find objects linked with the given groupware object through a relation
+ *
+ * @param string Object UUID
+ * @param array List of related URIs
+ */
+ public function get_object_links($uid)
+ {
+ $links = array();
+ $object_uri = self::build_member_url($uid);
+
+ foreach ($this->get_relations_for_member($uid) as $relation) {
+ if (in_array($object_uri, (array) $relation['members'])) {
+ // make relation members up-to-date
+ kolab_storage_config::resolve_members($relation);
+
+ foreach ($relation['members'] as $member) {
+ if ($member != $object_uri) {
+ $links[] = $member;
+ }
+ }
+ }
+ }
+
+ return array_unique($links);
+ }
+
+ /**
+ *
+ */
+ public function save_object_links($uid, $links, $remove = array())
+ {
+ $object_uri = self::build_member_url($uid);
+ $relations = $this->get_relations_for_member($uid);
+ $done = false;
+
+ foreach ($relations as $relation) {
+ // make relation members up-to-date
+ kolab_storage_config::resolve_members($relation);
+
+ // remove and add links
+ $members = array_diff($relation['members'], (array)$remove);
+ $members = array_unique(array_merge($members, $links));
+
+ // make sure the object_uri is still a member
+ if (!in_array($object_uri, $members)) {
+ $members[$object_uri];
+ }
+
+ // remove relation if no other members remain
+ if (count($members) <= 1) {
+ $done = $this->delete($relation['uid']);
+ }
+ // update relation object if members changed
+ else if (count(array_diff($members, $relation['members'])) || count(array_diff($relation['members'], $members))) {
+ $relation['members'] = $members;
+ $done = $this->save($relation, 'relation');
+ $links = array();
+ }
+ // no changes, we're happy
+ else {
+ $done = true;
+ $links = array();
+ }
+ }
+
+ // create a new relation
+ if (!$done && !empty($links)) {
+ $relation = array(
+ 'members' => array_merge($links, array($object_uri)),
+ 'category' => 'generic',
+ );
+
+ $ret = $this->save($relation, 'relation');
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Find relation objects referring to specified note
+ */
+ public function get_relations_for_member($uid, $reltype = 'generic')
+ {
+ $default = true;
+ $filter = array(
+ array('type', '=', 'relation'),
+ array('category', '=', $reltype),
+ array('member', '=', $uid),
+ );
+
+ return $this->get_objects($filter, $default, 100);
+ }
+
+ /**
* Find kolab objects assigned to specified e-mail message
*
* @param rcube_message $message E-mail message
@@ -664,6 +760,8 @@ class kolab_storage_config
*/
public function get_message_relations($message, $folder, $type)
{
+ static $_cache = array();
+
$result = array();
$uids = array();
$default = true;
@@ -671,28 +769,42 @@ class kolab_storage_config
$filter = array(
array('type', '=', 'relation'),
array('category', '=', 'generic'),
- // @TODO: what if Message-Id (and Date) does not exist?
- array('member', '=', $message->get('message-id', false)),
);
- // get UIDs of assigned notes
- foreach ($this->get_objects($filter, $default) as $relation) {
- // we don't need to update members if the URI is found
- if (in_array($uri, $relation['members'])) {
- // update members...
- $messages = kolab_storage_config::resolve_members($relation);
- // ...and check again
- if (empty($messages[$folder]) || !in_array($message->uid, $messages[$folder])) {
- continue;
+ // query by message-id
+ $member_id = $message->get('message-id', false);
+ if (empty($member_id)) {
+ // derive message identifier from URI
+ $member_id = md5($uri);
+ }
+ $filter[] = array('member', '=', $member_id);
+
+ if (!isset($_cache[$uri])) {
+ // get UIDs of related groupware objects
+ foreach ($this->get_objects($filter, $default) as $relation) {
+ // we don't need to update members if the URI is found
+ if (!in_array($uri, $relation['members'])) {
+ // update members...
+ $messages = kolab_storage_config::resolve_members($relation);
+ // ...and check again
+ if (empty($messages[$folder]) || !in_array($message->uid, $messages[$folder])) {
+ continue;
+ }
}
- }
- // find note UID(s)
- foreach ($relation['members'] as $member) {
- if (strpos($member, 'urn:uuid:') === 0) {
- $uids[] = substr($member, 9);
+ // find groupware object UID(s)
+ foreach ($relation['members'] as $member) {
+ if (strpos($member, 'urn:uuid:') === 0) {
+ $uids[] = substr($member, 9);
+ }
}
}
+
+ // remember this lookup
+ $_cache[$uri] = $uids;
+ }
+ else {
+ $uids = $_cache[$uri];
}
// get kolab objects of specified type
diff --git a/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_folder.php b/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_folder.php
index 2b25826..2435fa3 100644
--- a/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/lib/drivers/kolab/plugins/libkolab/lib/kolab_storage_folder.php
@@ -799,9 +799,12 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/
public function move($uid, $target_folder)
{
+ if (is_string($target_folder))
+ $target_folder = kolab_storage::get_folder($target_folder);
+
if ($msguid = $this->cache->uid2msguid($uid)) {
$this->cache->bypass(true);
- $result = $this->imap->move_message($msguid, $target_folder, $this->name);
+ $result = $this->imap->move_message($msguid, $target_folder->name, $this->name);
$this->cache->bypass(false);
if ($result) {
diff --git a/lib/drivers/seafile/seafile_api.php b/lib/drivers/seafile/seafile_api.php
index 17168eb..f3ec251 100644
--- a/lib/drivers/seafile/seafile_api.php
+++ b/lib/drivers/seafile/seafile_api.php
@@ -257,6 +257,12 @@ class seafile_api
*/
public function authenticate($username, $password)
{
+ // sanity checks
+ if ($username === '' || !is_string($username) || $password === '' || !is_string($password)) {
+ $this->status = self::BAD_REQUEST;
+ return false;
+ }
+
$result = $this->request('POST', 'auth-token', null, array(
'username' => $username,
'password' => $password,
diff --git a/lib/file_api.php b/lib/file_api.php
index 10d2b44..4871e65 100644
--- a/lib/file_api.php
+++ b/lib/file_api.php
@@ -329,7 +329,7 @@ class file_api extends file_locale
foreach ($drivers as $item) {
$all[] = $item['title'];
- if ($item['enabled'] && !in_array($item['driver'], (array) $enabled)) {
+ if ($item['enabled'] && in_array($item['driver'], (array) $enabled)) {
$result[] = $as_objects ? $this->get_driver_object($item) : $item;
}
}