From dce4ed076b1f0b36e068a995a37e60e488cdbaf6 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Thu, 21 Jun 2012 09:42:24 +0200 Subject: [PATCH] Move folder create/rename logic to libkolab for common use in different Kolab plugins --- .../calendar/drivers/kolab/kolab_calendar.php | 7 +- .../calendar/drivers/kolab/kolab_driver.php | 103 +----------------- plugins/libkolab/lib/kolab_storage.php | 98 +++++++++++++++++ 3 files changed, 105 insertions(+), 103 deletions(-) diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index a8a2755a..9e9825e7 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -26,9 +26,6 @@ class kolab_calendar { - const COLOR_KEY_SHARED = '/shared/vendor/kolab/color'; - const COLOR_KEY_PRIVATE = '/shared/vendor/kolab/color'; - public $id; public $ready = false; public $readonly = true; @@ -146,8 +143,8 @@ class kolab_calendar public function get_color() { // color is defined in folder METADATA - $metadata = $this->storage->get_metadata(array(self::COLOR_KEY_PRIVATE, self::COLOR_KEY_SHARED)); - if (($color = $metadata[self::COLOR_KEY_PRIVATE]) || ($color = $metadata[self::COLOR_KEY_SHARED])) { + $metadata = $this->storage->get_metadata(array(kolab_storage::COLOR_KEY_PRIVATE, kolab_storage::COLOR_KEY_SHARED)); + if (($color = $metadata[kolab_storage::COLOR_KEY_PRIVATE]) || ($color = $metadata[kolab_storage::COLOR_KEY_SHARED])) { return $color; } diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php index 41dc3372..089909d6 100644 --- a/plugins/calendar/drivers/kolab/kolab_driver.php +++ b/plugins/calendar/drivers/kolab/kolab_driver.php @@ -154,15 +154,13 @@ class kolab_driver extends calendar_driver */ public function create_calendar($prop) { - $folder = $this->folder_update($prop); + $prop['type'] = 'event'; + $prop['subscribed'] = $prop['active'] ? kolab_storage::SERVERSIDE_SUBSCRIPTION : null; + $folder = kolab_storage::folder_update($prop); if ($folder === false) { return false; } - - // subscribe to new calendar by default - $storage = kolab_storage::get_folder($folder); - $storage->subscribe($prop['active'], kolab_storage::SERVERSIDE_SUBSCRIPTION); // create ID $id = kolab_storage::folder_id($folder); @@ -190,8 +188,8 @@ class kolab_driver extends calendar_driver public function edit_calendar($prop) { if ($prop['id'] && ($cal = $this->calendars[$prop['id']])) { - $oldfolder = $cal->get_realname(); - $newfolder = $this->folder_update($prop); + $prop['oldname'] = $cal->get_realname(); + $newfolder = kolab_storage::folder_update($prop); if ($newfolder === false) { return false; @@ -234,97 +232,6 @@ class kolab_driver extends calendar_driver } - /** - * Rename or Create a new IMAP folder - * - * @param array Hash array with calendar properties - * - * @return mixed New folder name or False on failure - */ - private function folder_update(&$prop) - { - $folder = rcube_charset::convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP'); - $oldfolder = $prop['oldname']; // UTF7 - $parent = $prop['parent']; // UTF7 - $storage = $this->rc->get_storage(); - $delimiter = $storage->get_hierarchy_delimiter(); - - if (strlen($oldfolder)) { - $options = $storage->folder_info($oldfolder); - } - - if (!empty($options) && ($options['norename'] || $options['protected'])) { - } - // sanity checks (from steps/settings/save_folder.inc) - else if (!strlen($folder)) { - $this->last_error = 'Invalid folder name'; - return false; - } - else if (strlen($folder) > 128) { - $this->last_error = 'Folder name too long'; - return false; - } - else { - // these characters are problematic e.g. when used in LIST/LSUB - foreach (array($delimiter, '%', '*') as $char) { - if (strpos($folder, $delimiter) !== false) { - $this->last_error = 'Invalid folder name'; - return false; - } - } - } - - if (!empty($options) && ($options['protected'] || $options['norename'])) { - $folder = $oldfolder; - } - else if (strlen($parent)) { - $folder = $parent . $delimiter . $folder; - } - else { - // add namespace prefix (when needed) - $folder = $storage->mod_folder($folder, 'in'); - } - - // Check access rights to the parent folder - if (strlen($parent) && (!strlen($oldfolder) || $oldfolder != $folder)) { - $parent_opts = $storage->folder_info($parent); - if ($parent_opts['namespace'] != 'personal' - && (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts['rights']))) - ) { - $this->last_error = 'No permission to create folder'; - return false; - } - } - - // update the folder name - if (strlen($oldfolder)) { - if ($oldfolder != $folder) { - if (!($result = kolab_storage::folder_rename($oldfolder, $folder))) - $this->last_error = kolab_storage::$last_error; - } - else - $result = true; - } - // create new folder - else { - if (!($result = kolab_storage::folder_create($folder, 'event'))) - $this->last_error = kolab_storage::$last_error; - } - - // save color in METADATA - // TODO: also save 'showalarams' and other properties here - - if ($result && $prop['color']) { - if (!($meta_saved = $storage->set_metadata(array(kolab_calendar::COLOR_KEY_SHARED => $prop['color'])))) // try in shared namespace - $meta_saved = $storage->set_metadata(array(kolab_calendar::COLOR_KEY_PRIVATE => $prop['color'])); // try in private namespace - if ($meta_saved) - unset($prop['color']); // unsetting will prevent fallback to local user prefs - } - - return $result ? $folder : false; - } - - /** * Delete the given calendar with all its contents * diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php index 5924530d..a19c71bc 100644 --- a/plugins/libkolab/lib/kolab_storage.php +++ b/plugins/libkolab/lib/kolab_storage.php @@ -25,6 +25,8 @@ class kolab_storage { const CTYPE_KEY = '/shared/vendor/kolab/folder-type'; + const COLOR_KEY_SHARED = '/shared/vendor/kolab/color'; + const COLOR_KEY_PRIVATE = '/shared/vendor/kolab/color'; const SERVERSIDE_SUBSCRIPTION = 0; const CLIENTSIDE_SUBSCRIPTION = 1; @@ -222,6 +224,102 @@ class kolab_storage } + /** + * Rename or Create a new IMAP folder. + * + * Does additional checks for permissions and folder name restrictions + * + * @param array Hash array with folder properties and metadata + * - name: Folder name + * - oldname: Old folder name when changed + * - parent: Parent folder to create the new one in + * - type: Folder type to create + * @return mixed New folder name or False on failure + */ + public static function folder_update(&$prop) + { + self::setup(); + + $folder = rcube_charset::convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP'); + $oldfolder = $prop['oldname']; // UTF7 + $parent = $prop['parent']; // UTF7 + $delimiter = self::$imap->get_hierarchy_delimiter(); + + if (strlen($oldfolder)) { + $options = self::$imap->folder_info($oldfolder); + } + + if (!empty($options) && ($options['norename'] || $options['protected'])) { + } + // sanity checks (from steps/settings/save_folder.inc) + else if (!strlen($folder)) { + self::$last_error = 'Invalid folder name'; + return false; + } + else if (strlen($folder) > 128) { + self::$last_error = 'Folder name too long'; + return false; + } + else { + // these characters are problematic e.g. when used in LIST/LSUB + foreach (array($delimiter, '%', '*') as $char) { + if (strpos($folder, $delimiter) !== false) { + self::$last_error = 'Invalid folder name'; + return false; + } + } + } + + if (!empty($options) && ($options['protected'] || $options['norename'])) { + $folder = $oldfolder; + } + else if (strlen($parent)) { + $folder = $parent . $delimiter . $folder; + } + else { + // add namespace prefix (when needed) + $folder = self::$imap->mod_folder($folder, 'in'); + } + + // Check access rights to the parent folder + if (strlen($parent) && (!strlen($oldfolder) || $oldfolder != $folder)) { + $parent_opts = self::$imap->folder_info($parent); + if ($parent_opts['namespace'] != 'personal' + && (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts['rights']))) + ) { + self::$last_error = 'No permission to create folder'; + return false; + } + } + + // update the folder name + if (strlen($oldfolder)) { + if ($oldfolder != $folder) { + $result = self::folder_rename($oldfolder, $folder); + } + else + $result = true; + } + // create new folder + else { + $result = self::folder_create($folder, $prop['type'], $prop['subscribed'] === self::SERVERSIDE_SUBSCRIPTION); + } + + // save color in METADATA + // TODO: also save 'showalarams' and other properties here + // TODO: change private/shared precedence depending on private or shared folder + + if ($result && $prop['color']) { + if (!($meta_saved = self::$imap->set_metadata($folder, array(self::COLOR_KEY_SHARED => $prop['color'])))) // try in shared namespace + $meta_saved = self::$imap->set_metadata($folder, array(self::COLOR_KEY_PRIVATE => $prop['color'])); // try in private namespace + if ($meta_saved) + unset($prop['color']); // unsetting will prevent fallback to local user prefs + } + + return $result ? $folder : false; + } + + /** * Getter for human-readable name of Kolab object (folder) * See http://wiki.kolab.org/UI-Concepts/Folder-Listing for reference