plugins/kolab_addressbook plugins/libkolab

Aleksander Machniak machniak at kolabsys.com
Wed Aug 7 09:42:35 CEST 2013


 plugins/kolab_addressbook/kolab_addressbook.php |   87 +++++++++------
 plugins/libkolab/lib/kolab_storage.php          |  139 ++++++++++++++++++++----
 2 files changed, 178 insertions(+), 48 deletions(-)

New commits:
commit 27eb70693985a5e8aa8033b95b70433ff68aec71
Author: Aleksander Machniak <machniak at kolabsys.com>
Date:   Wed Aug 7 09:39:21 2013 +0200

    Fixed bug where Error No.700 was thrown by Roundcube in cases
    when there's no addressbook (no subscribed contact folders and no
    global addressbooks). It's fixed by forcing folder creation/subscription
    and forcing of kolab_addressbook_prio value accordingly (Bug #2086).

diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php
index 2059dea..d6f0d6d 100644
--- a/plugins/kolab_addressbook/kolab_addressbook.php
+++ b/plugins/kolab_addressbook/kolab_addressbook.php
@@ -31,7 +31,6 @@ class kolab_addressbook extends rcube_plugin
 {
     public $task = 'mail|settings|addressbook|calendar';
 
-    private $folders;
     private $sources;
     private $rc;
     private $ui;
@@ -93,11 +92,8 @@ class kolab_addressbook extends rcube_plugin
      */
     public function address_sources($p)
     {
-        // Load configuration
-        $this->load_config();
-
-        $abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
-        $undelete = $this->rc->config->get('undo_timeout');
+        $abook_prio = $this->addressbook_prio();
+        $undelete   = $this->rc->config->get('undo_timeout');
 
         // Disable all global address books
         // Assumes that all non-kolab_addressbook sources are global
@@ -155,10 +151,7 @@ class kolab_addressbook extends rcube_plugin
             return $args;
         }
 
-        // Load configuration
-        $this->load_config();
-
-        $abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
+        $abook_prio = $this->addressbook_prio();
         // here we cannot use rc->config->get()
         $sources    = $GLOBALS['CONFIG']['autocomplete_addressbooks'];
 
@@ -222,10 +215,7 @@ class kolab_addressbook extends rcube_plugin
 
         $this->sources = array();
 
-        // Load configuration
-        $this->load_config();
-
-        $abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
+        $abook_prio = $this->addressbook_prio();
 
         // Personal address source(s) disabled?
         if ($abook_prio == self::GLOBAL_ONLY) {
@@ -233,19 +223,27 @@ class kolab_addressbook extends rcube_plugin
         }
 
         // get all folders that have "contact" type
-        $this->folders = kolab_storage::sort_folders(kolab_storage::get_folders('contact'));
+        $folders = kolab_storage::sort_folders(kolab_storage::get_folders('contact'));
 
-        if (PEAR::isError($this->folders)) {
+        if (PEAR::isError($folders)) {
             rcube::raise_error(array(
               'code' => 600, 'type' => 'php',
               'file' => __FILE__, 'line' => __LINE__,
-              'message' => "Failed to list contact folders from Kolab server:" . $this->folders->getMessage()),
+              'message' => "Failed to list contact folders from Kolab server:" . $folders->getMessage()),
             true, false);
         }
         else {
+            // we need at least one folder to prevent from errors in Roundcube core
+            // when there's also no sql nor ldap addressbook (Bug #2086)
+            if (empty($folders)) {
+                if ($folder = kolab_storage::create_default_folder('contact')) {
+                    $folders = array(new kolab_storage_folder($folder, 'contact'));
+                }
+            }
+
             // convert to UTF8 and sort
             $names = array();
-            foreach ($this->folders as $folder) {
+            foreach ($folders as $folder) {
                 // create instance of rcube_contacts
                 $abook_id = kolab_storage::folder_id($folder->name);
                 $abook = new rcube_kolab_contacts($folder->name);
@@ -325,16 +323,22 @@ class kolab_addressbook extends rcube_plugin
             return $args;
         }
 
-        // Load configuration
-        $this->load_config();
+        $ldap_public = $this->rc->config->get('ldap_public');
+        $abook_type  = $this->rc->config->get('address_book_type');
 
-        // Load localization
-        $this->add_texts('localization');
+        // Hide option if there's no global addressbook
+        if (empty($ldap_public) || $abook_type != 'ldap') {
+            return $args;
+        }
 
         // Check that configuration is not disabled
-        $dont_override  = (array) $this->rc->config->get('dont_override', array());
+        $dont_override = (array) $this->rc->config->get('dont_override', array());
+        $prio          = $this->addressbook_prio();
 
         if (!in_array('kolab_addressbook_prio', $dont_override)) {
+            // Load localization
+            $this->add_texts('localization');
+
             $field_id = '_kolab_addressbook_prio';
             $select   = new html_select(array('name' => $field_id, 'id' => $field_id));
 
@@ -345,7 +349,7 @@ class kolab_addressbook extends rcube_plugin
 
             $args['blocks']['main']['options']['kolab_addressbook_prio'] = array(
                 'title' => html::label($field_id, Q($this->gettext('addressbookprio'))),
-                'content' => $select->show((int)$this->rc->config->get('kolab_addressbook_prio')),
+                'content' => $select->show($prio),
             );
         }
 
@@ -365,14 +369,11 @@ class kolab_addressbook extends rcube_plugin
             return $args;
         }
 
-        // Load configuration
-        $this->load_config();
-
         // Check that configuration is not disabled
-        $dont_override  = (array) $this->rc->config->get('dont_override', array());
+        $dont_override = (array) $this->rc->config->get('dont_override', array());
+        $key           = 'kolab_addressbook_prio';
 
-        if (!in_array('kolab_addressbook_prio', $dont_override)) {
-            $key = 'kolab_addressbook_prio';
+        if (!in_array('kolab_addressbook_prio', $dont_override) || !isset($_POST['_'.$key])) {
             $args['prefs'][$key] = (int) get_input_value('_'.$key, RCUBE_INPUT_POST);
         }
 
@@ -506,4 +507,30 @@ class kolab_addressbook extends rcube_plugin
 
         $this->rc->output->send();
     }
+
+    /**
+     * Returns value of kolab_addressbook_prio setting
+     */
+    private function addressbook_prio()
+    {
+        // Load configuration
+        if (!$this->config_loaded) {
+            $this->load_config();
+            $this->config_loaded = true;
+        }
+
+        $abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
+
+        // Make sure any global addressbooks are defined
+        if ($abook_prio == 0 || $abook_prio == 2) {
+            $ldap_public = $this->rc->config->get('ldap_public');
+            $abook_type  = $this->rc->config->get('address_book_type');
+
+            if (empty($ldap_public) || $abook_type != 'ldap') {
+                $abook_prio = 1;
+            }
+        }
+
+        return $abook_prio;
+    }
 }
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 777702d..ee6ede0 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -41,6 +41,23 @@ class kolab_storage
     private static $config;
     private static $imap;
 
+    // Default folder names
+    private static $default_folders = array(
+        'event'         => 'Calendar',
+        'contact'       => 'Contacts',
+        'task'          => 'Tasks',
+        'note'          => 'Notes',
+        'file'          => 'Files',
+        'configuration' => 'Configuration',
+        'journal'       => 'Journal',
+        'mail.inbox'       => 'INBOX',
+        'mail.drafts'      => 'Drafts',
+        'mail.sentitems'   => 'Sent',
+        'mail.wastebasket' => 'Trash',
+        'mail.outbox'      => 'Outbox',
+        'mail.junkemail'   => 'Junk',
+    );
+
 
     /**
      * Setup the environment needed by the libs
@@ -349,25 +366,8 @@ class kolab_storage
             $result = self::folder_create($folder, $prop['type'], $prop['subscribed'], $prop['active']);
         }
 
-        // save displayname and color in METADATA
-        // TODO: also save 'showalarams' and other properties here
         if ($result) {
-            $ns = null;
-            foreach (array('color'       => array(self::COLOR_KEY_SHARED,self::COLOR_KEY_PRIVATE),
-                           'displayname' => array(self::NAME_KEY_SHARED,self::NAME_KEY_PRIVATE)) as $key => $metakeys) {
-                if (!empty($prop[$key])) {
-                    if (!isset($ns))
-                        $ns = self::$imap->folder_namespace($folder);
-
-                    $meta_saved = false;
-                    if ($ns == 'personal')  // save in shared namespace for personal folders
-                        $meta_saved = self::$imap->set_metadata($folder, array($metakeys[0] => $prop[$key]));
-                    if (!$meta_saved)    // try in private namespace
-                        $meta_saved = self::$imap->set_metadata($folder, array($metakeys[1] => $prop[$key]));
-                    if ($meta_saved)
-                        unset($prop[$key]);  // unsetting will prevent fallback to local user prefs
-                }
-            }
+            self::set_folder_props($folder, $prop);
         }
 
         return $result ? $folder : false;
@@ -913,4 +913,107 @@ class kolab_storage
         $rcube   = rcube::get_instance();
         return $rcube->user->save_prefs(array('kolab_active_folders' => $folders));
     }
+
+    /**
+     * Creates default folder of specified type
+     * To be run when none of subscribed folders (of specified type) is found
+     *
+     * @param string $type  Folder type
+     * @param string $props Folder properties (color, etc)
+     *
+     * @return string Folder name
+     */
+    public static function create_default_folder($type, $props = array())
+    {
+        if (!self::setup()) {
+            return;
+        }
+
+        $folders = self::$imap->get_metadata('*', array(kolab_storage::CTYPE_KEY_PRIVATE));
+
+        // from kolab_folders config
+        $folder_type  = strpos($type, '.') ? str_replace('.', '_', $type) : $type . '_default';
+        $default_name = self::$config->get('kolab_folders_' . $folder_type);
+        $folder_type  = str_replace('_', '.', $folder_type);
+
+        // check if we have any folder in personal namespace
+        // folder(s) may exist but not subscribed
+        foreach ($folders as $f => $data) {
+            if (strpos($data[self::CTYPE_KEY_PRIVATE], $type) === 0) {
+                $folder = $f;
+                break;
+            }
+        }
+
+        if (!$folder) {
+            if (!$default_name) {
+                $default_name = self::$default_folders[$type];
+            }
+
+            if (!$default_name) {
+                return;
+            }
+
+            $folder = rcube_charset::convert($default_name, RCUBE_CHARSET, 'UTF7-IMAP');
+            $prefix = self::$imap->get_namespace('prefix');
+
+            // add personal namespace prefix if needed
+            if ($prefix && strpos($folder, $prefix) !== 0 && $folder != 'INBOX') {
+                $folder = $prefix . $folder;
+            }
+
+            if (!self::$imap->folder_exists($folder)) {
+                if (!self::$imap->folder_create($folder)) {
+                    return;
+                }
+            }
+
+            self::set_folder_type($folder, $folder_type);
+        }
+
+        self::folder_subscribe($folder);
+
+        if ($props['active']) {
+            self::set_state($folder, true);
+        }
+
+        if (!empty($props)) {
+            self::set_folder_props($folder, $props);
+        }
+
+        return $folder;
+    }
+
+    /**
+     * Sets folder metadata properties
+     *
+     * @param string $folder Folder name
+     * @param array  $prop   Folder properties
+     */
+    public static function set_folder_props($folder, &$prop)
+    {
+        if (!self::setup()) {
+            return;
+        }
+
+        // TODO: also save 'showalarams' and other properties here
+        $ns        = self::$imap->folder_namespace($folder);
+        $supported = array(
+            'color'       => array(self::COLOR_KEY_SHARED, self::COLOR_KEY_PRIVATE),
+            'displayname' => array(self::NAME_KEY_SHARED, self::NAME_KEY_PRIVATE),
+        );
+
+        foreach ($supported as $key => $metakeys) {
+            if (array_key_exists($key, $prop)) {
+                $meta_saved = false;
+                if ($ns == 'personal')  // save in shared namespace for personal folders
+                    $meta_saved = self::$imap->set_metadata($folder, array($metakeys[0] => $prop[$key]));
+                if (!$meta_saved)    // try in private namespace
+                    $meta_saved = self::$imap->set_metadata($folder, array($metakeys[1] => $prop[$key]));
+                if ($meta_saved)
+                    unset($prop[$key]);  // unsetting will prevent fallback to local user prefs
+            }
+        }
+    }
+
 }




More information about the commits mailing list