lib/plugins

Aleksander Machniak machniak at kolabsys.com
Thu Jan 2 15:51:00 CET 2014


 lib/plugins/libkolab/SQL/mysql.initial.sql             |   18 +-
 lib/plugins/libkolab/SQL/mysql/2013110400.sql          |    1 
 lib/plugins/libkolab/SQL/mysql/2013121100.sql          |   13 +
 lib/plugins/libkolab/lib/kolab_date_recurrence.php     |   27 ++-
 lib/plugins/libkolab/lib/kolab_format.php              |    8 
 lib/plugins/libkolab/lib/kolab_format_event.php        |   14 -
 lib/plugins/libkolab/lib/kolab_storage.php             |  151 ++++++++++++++---
 lib/plugins/libkolab/lib/kolab_storage_cache.php       |   43 +++-
 lib/plugins/libkolab/lib/kolab_storage_cache_event.php |    2 
 lib/plugins/libkolab/lib/kolab_storage_folder.php      |    3 
 10 files changed, 220 insertions(+), 60 deletions(-)

New commits:
commit 18672e97970855f36dd87efea9a46764731c53ec
Author: Aleksander Machniak <alec at alec.pl>
Date:   Thu Jan 2 15:50:07 2014 +0100

    Update libkolab plugin

diff --git a/lib/plugins/libkolab/SQL/mysql.initial.sql b/lib/plugins/libkolab/SQL/mysql.initial.sql
index 4f23a52..40b8631 100644
--- a/lib/plugins/libkolab/SQL/mysql.initial.sql
+++ b/lib/plugins/libkolab/SQL/mysql.initial.sql
@@ -30,7 +30,7 @@ CREATE TABLE `kolab_cache_contact` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   `type` VARCHAR(32) CHARACTER SET ascii NOT NULL,
@@ -49,7 +49,7 @@ CREATE TABLE `kolab_cache_event` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   `dtstart` DATETIME,
@@ -68,7 +68,7 @@ CREATE TABLE `kolab_cache_task` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   `dtstart` DATETIME,
@@ -87,7 +87,7 @@ CREATE TABLE `kolab_cache_journal` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   `dtstart` DATETIME,
@@ -106,7 +106,7 @@ CREATE TABLE `kolab_cache_note` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   CONSTRAINT `fk_kolab_cache_note_folder` FOREIGN KEY (`folder_id`)
@@ -123,7 +123,7 @@ CREATE TABLE `kolab_cache_file` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   `filename` varchar(255) DEFAULT NULL,
@@ -142,7 +142,7 @@ CREATE TABLE `kolab_cache_configuration` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   `type` VARCHAR(32) CHARACTER SET ascii NOT NULL,
@@ -161,7 +161,7 @@ CREATE TABLE `kolab_cache_freebusy` (
   `created` DATETIME DEFAULT NULL,
   `changed` DATETIME DEFAULT NULL,
   `data` TEXT NOT NULL,
-  `xml` TEXT NOT NULL,
+  `xml` LONGBLOB NOT NULL,
   `tags` VARCHAR(255) NOT NULL,
   `words` TEXT NOT NULL,
   `dtstart` DATETIME,
@@ -172,4 +172,4 @@ CREATE TABLE `kolab_cache_freebusy` (
 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
 
 
-INSERT INTO `system` (`name`, `value`) VALUES ('libkolab-version', '2013100400');
+INSERT INTO `system` (`name`, `value`) VALUES ('libkolab-version', '2013121100');
diff --git a/lib/plugins/libkolab/SQL/mysql/2013110400.sql b/lib/plugins/libkolab/SQL/mysql/2013110400.sql
new file mode 100644
index 0000000..5b7a9ef
--- /dev/null
+++ b/lib/plugins/libkolab/SQL/mysql/2013110400.sql
@@ -0,0 +1 @@
+ALTER TABLE `kolab_cache_contact` CHANGE `xml` `xml` LONGTEXT NOT NULL;
diff --git a/lib/plugins/libkolab/SQL/mysql/2013121100.sql b/lib/plugins/libkolab/SQL/mysql/2013121100.sql
new file mode 100644
index 0000000..8cab5ef
--- /dev/null
+++ b/lib/plugins/libkolab/SQL/mysql/2013121100.sql
@@ -0,0 +1,13 @@
+-- well, these deletes are really optional
+-- we can clear all caches or only contacts/events/tasks
+-- the issue we're fixing here was about contacts (Bug #2662)
+DELETE FROM `kolab_folders` WHERE `type` IN ('contact', 'event', 'task');
+
+ALTER TABLE `kolab_cache_contact` CHANGE `xml` `xml` LONGBLOB NOT NULL;
+ALTER TABLE `kolab_cache_event` CHANGE `xml` `xml` LONGBLOB NOT NULL;
+ALTER TABLE `kolab_cache_task` CHANGE `xml` `xml` LONGBLOB NOT NULL;
+ALTER TABLE `kolab_cache_journal` CHANGE `xml` `xml` LONGBLOB NOT NULL;
+ALTER TABLE `kolab_cache_note` CHANGE `xml` `xml` LONGBLOB NOT NULL;
+ALTER TABLE `kolab_cache_file` CHANGE `xml` `xml` LONGBLOB NOT NULL;
+ALTER TABLE `kolab_cache_configuration` CHANGE `xml` `xml` LONGBLOB NOT NULL;
+ALTER TABLE `kolab_cache_freebusy` CHANGE `xml` `xml` LONGBLOB NOT NULL;
diff --git a/lib/plugins/libkolab/lib/kolab_date_recurrence.php b/lib/plugins/libkolab/lib/kolab_date_recurrence.php
index 3aaa399..85ffd91 100644
--- a/lib/plugins/libkolab/lib/kolab_date_recurrence.php
+++ b/lib/plugins/libkolab/lib/kolab_date_recurrence.php
@@ -101,16 +101,35 @@ class kolab_date_recurrence
     /**
      * Get the end date of the occurence of this recurrence cycle
      *
-     * @param string Date limit (where infinite recurrences should abort)
      * @return mixed Timestamp with end date of the last event or False if recurrence exceeds limit
      */
-    public function end($limit = 'now +1 year')
+    public function end()
     {
-        $limit_dt = new DateTime($limit);
-        if ($this->engine && ($cend = $this->engine->getLastOccurrence()) && ($end_dt = kolab_format::php_datetime(new cDateTime($cend))) && $end_dt < $limit_dt) {
+        $event = $this->object->to_array();
+
+        // recurrence end date is given
+        if ($event['recurrence']['UNTIL'] instanceof DateTime) {
+            return $event['recurrence']['UNTIL']->format('U');
+        }
+
+        // let libkolab do the work
+        if ($this->engine && ($cend = $this->engine->getLastOccurrence()) && ($end_dt = kolab_format::php_datetime(new cDateTime($cend)))) {
             return $end_dt->format('U');
         }
 
+        // determine a reasonable end date if none given
+        if (!$event['recurrence']['COUNT']) {
+          switch ($event['recurrence']['FREQ']) {
+            case 'YEARLY':  $intvl = 'P100Y'; break;
+            case 'MONTHLY': $intvl = 'P20Y';  break;
+            default:        $intvl = 'P10Y';  break;
+          }
+
+          $end_dt = clone $event['start'];
+          $end_dt->add(new DateInterval($intvl));
+          return $end_dt->format('U');
+        }
+
         return false;
     }
 }
diff --git a/lib/plugins/libkolab/lib/kolab_format.php b/lib/plugins/libkolab/lib/kolab_format.php
index 5bcc57a..679ae10 100644
--- a/lib/plugins/libkolab/lib/kolab_format.php
+++ b/lib/plugins/libkolab/lib/kolab_format.php
@@ -123,7 +123,7 @@ abstract class kolab_format
             if (!$dateonly)
                 $result->setTime($datetime->format('G'), $datetime->format('i'), $datetime->format('s'));
 
-            if ($tz && $tz->getName() == 'UTC')
+            if ($tz && in_array($tz->getName(), array('UTC', 'GMT', '+00:00', 'Z')))
                 $result->setUTC(true);
             else if ($tz !== false)
                 $result->setTimezone($tz->getName());
@@ -401,13 +401,13 @@ abstract class kolab_format
         // set some automatic values if missing
         if (empty($object['created']) && method_exists($this->obj, 'setCreated')) {
             $cdt = $this->obj->created();
-            $object['created'] = $cdt && $cdt->isValid() ? self::php_datetime($cdt) : new DateTime('now', self::$timezone);
+            $object['created'] = $cdt && $cdt->isValid() ? self::php_datetime($cdt) : new DateTime('now', new DateTimeZone('UTC'));
             if (!$cdt || !$cdt->isValid())
                 $this->obj->setCreated(self::get_datetime($object['created']));
         }
 
-        $object['changed'] = new DateTime('now', self::$timezone);
-        $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
+        $object['changed'] = new DateTime('now', new DateTimeZone('UTC'));
+        $this->obj->setLastModified(self::get_datetime($object['changed']));
 
         // Save custom properties of the given object
         if (isset($object['x-custom'])) {
diff --git a/lib/plugins/libkolab/lib/kolab_format_event.php b/lib/plugins/libkolab/lib/kolab_format_event.php
index 9be9bdf..6a8c3ae 100644
--- a/lib/plugins/libkolab/lib/kolab_format_event.php
+++ b/lib/plugins/libkolab/lib/kolab_format_event.php
@@ -163,20 +163,22 @@ class kolab_format_event extends kolab_format_xcal
         else if ($status == kolabformat::StatusCancelled)
           $object['cancelled'] = true;
 
+        // this is an exception object
+        if ($this->obj->recurrenceID()->isValid()) {
+            $object['thisandfuture'] = $this->obj->thisAndFuture();
+        }
         // read exception event objects
-        if (($exceptions = $this->obj->exceptions()) && is_object($exceptions) && $exceptions->size()) {
+        else if (($exceptions = $this->obj->exceptions()) && is_object($exceptions) && $exceptions->size()) {
+            $recurrence_exceptions = array();
             for ($i=0; $i < $exceptions->size(); $i++) {
                 if (($exobj = $exceptions->get($i))) {
                     $exception = new kolab_format_event($exobj);
                     if ($exception->is_valid()) {
-                        $object['recurrence']['EXCEPTIONS'][] = $this->expand_exception($exception->to_array(), $object);
+                        $recurrence_exceptions[] = $this->expand_exception($exception->to_array(), $object);
                     }
                 }
             }
-        }
-        // this is an exception object
-        else if ($this->obj->recurrenceID()->isValid()) {
-          $object['thisandfuture'] = $this->obj->thisAndFuture();
+            $object['recurrence']['EXCEPTIONS'] = $recurrence_exceptions;
         }
 
         return $this->data = $object;
diff --git a/lib/plugins/libkolab/lib/kolab_storage.php b/lib/plugins/libkolab/lib/kolab_storage.php
index 5f8b9c6..3d1dccb 100644
--- a/lib/plugins/libkolab/lib/kolab_storage.php
+++ b/lib/plugins/libkolab/lib/kolab_storage.php
@@ -433,13 +433,14 @@ class kolab_storage
                     // get username
                     $pos    = strpos($folder, $delim);
                     if ($pos) {
-                        $prefix = '('.substr($folder, 0, $pos).') ';
+                        $prefix = '('.substr($folder, 0, $pos).')';
                         $folder = substr($folder, $pos+1);
                     }
                     else {
-                        $prefix = '('.$folder.')';
+                        $prefix = $folder;
                         $folder = '';
                     }
+
                     $found  = true;
                     $folder_ns = 'other';
                     break;
@@ -467,7 +468,7 @@ class kolab_storage
         $folder = str_replace(html::quote($delim), ' » ', $folder);
 
         if ($prefix)
-            $folder = html::quote($prefix) . ' ' . $folder;
+            $folder = html::quote($prefix) . ($folder !== '' ? ' ' . $folder : '');
 
         if (!$folder_ns)
             $folder_ns = 'personal';
@@ -492,7 +493,8 @@ class kolab_storage
     }
 
     /**
-     * Helper method to generate a truncated folder name to display
+     * Helper method to generate a truncated folder name to display.
+     * Note: $origname is a string returned by self::object_name()
      */
     public static function folder_displayname($origname, &$names)
     {
@@ -504,10 +506,29 @@ class kolab_storage
                 $length = strlen($names[$i] . ' » ');
                 $prefix = substr($name, 0, $length);
                 $count  = count(explode(' » ', $prefix));
-                $name   = str_repeat('   ', $count-1) . '» ' . substr($name, $length);
+                $diff   = 1;
+
+                // check if prefix folder is in other users namespace
+                for ($n = count($names)-1; $n >= 0; $n--) {
+                    if (strpos($prefix, '(' . $names[$n] . ') ') === 0) {
+                        $diff = 0;
+                        break;
+                    }
+                }
+
+                $name = str_repeat('   ', $count - $diff) . '» ' . substr($name, $length);
+                break;
+            }
+            // other users namespace and parent folder exists
+            else if (strpos($name, '(' . $names[$i] . ') ') === 0) {
+                $length = strlen('(' . $names[$i] . ') ');
+                $prefix = substr($name, 0, $length);
+                $count  = count(explode(' » ', $prefix));
+                $name   = str_repeat('   ', $count) . '» ' . substr($name, $length);
                 break;
             }
         }
+
         $names[] = $origname;
 
         return $name;
@@ -525,8 +546,8 @@ class kolab_storage
      */
     public static function folder_selector($type, $attrs, $current = '')
     {
-        // get all folders of specified type
-        $folders = self::get_folders($type, false);
+        // get all folders of specified type (sorted)
+        $folders = self::get_folders($type, true);
 
         $delim = self::$imap->get_hierarchy_delimiter();
         $names = array();
@@ -540,13 +561,15 @@ class kolab_storage
         // Filter folders list
         foreach ($folders as $c_folder) {
             $name = $c_folder->name;
+
             // skip current folder and it's subfolders
             if ($len && ($name == $current || strpos($name, $current.$delim) === 0)) {
                 continue;
             }
 
             // always show the parent of current folder
-            if ($p_len && $name == $parent) { }
+            if ($p_len && $name == $parent) {
+            }
             // skip folders where user have no rights to create subfolders
             else if ($c_folder->get_owner() != $_SESSION['username']) {
                 $rights = $c_folder->get_myrights();
@@ -555,17 +578,14 @@ class kolab_storage
                 }
             }
 
-            $names[$name] = self::object_name($name);
-        }
+            // Make sure parent folder is listed (might be skipped e.g. if it's namespace root)
+            if ($p_len && !isset($names[$parent]) && strpos($name, $parent.$delim) === 0) {
+                $names[$parent] = self::object_name($parent);
+            }
 
-        // Make sure parent folder is listed (might be skipped e.g. if it's namespace root)
-        if ($p_len && !isset($names[$parent])) {
-            $names[$parent] = self::object_name($parent);
+            $names[$name] = self::object_name($name);
         }
 
-        // Sort folders list
-        asort($names, SORT_LOCALE_STRING);
-
         // Build SELECT field of parent folder
         $attrs['is_escaped'] = true;
         $select = new html_select($attrs);
@@ -643,7 +663,8 @@ class kolab_storage
                     unset($folderdata[$folder]);
                 }
             }
-            return array_keys($folderdata);
+
+            return self::$imap->sort_folder_list(array_keys($folderdata), true);
         }
 
         // Get folders list
@@ -683,26 +704,74 @@ class kolab_storage
      */
     public static function sort_folders($folders)
     {
-        $pad = '  ';
+        $pad     = '  ';
+        $out     = array();
         $nsnames = array('personal' => array(), 'shared' => array(), 'other' => array());
+
         foreach ($folders as $folder) {
             $folders[$folder->name] = $folder;
             $ns = $folder->get_namespace();
             $nsnames[$ns][$folder->name] = strtolower(html_entity_decode(self::object_name($folder->name, $ns), ENT_COMPAT, RCUBE_CHARSET)) . $pad;  // decode »
         }
 
-        $names = array();
-        foreach ($nsnames as $ns => $dummy) {
-            asort($nsnames[$ns], SORT_LOCALE_STRING);
-            $names += $nsnames[$ns];
+        // $folders is a result of get_folders() we can assume folders were already sorted
+        foreach (array_keys($nsnames) as $ns) {
+            // asort($nsnames[$ns], SORT_LOCALE_STRING);
+            foreach (array_keys($nsnames[$ns]) as $utf7name) {
+                $out[] = $folders[$utf7name];
+            }
         }
 
-        $out = array();
-        foreach ($names as $utf7name => $name) {
-            $out[] = $folders[$utf7name];
+        return $out;
+    }
+
+
+    /**
+     * Check the folder tree and add the missing parents as virtual folders
+     *
+     * @param array $folders Folders list
+     *
+     * @return array Folders list
+     */
+    public static function folder_hierarchy($folders)
+    {
+        $_folders = array();
+        $existing = array_map(function($folder){ return $folder->get_name(); }, $folders);
+        $delim    = rcube::get_instance()->get_storage()->get_hierarchy_delimiter();
+
+        foreach ($folders as $idx => $folder) {
+            $path = explode($delim, $folder->name);
+            array_pop($path);
+
+            // skip top folders or ones with a custom displayname
+            if (count($path) <= 1 || kolab_storage::custom_displayname($folder->name)) {
+            }
+            else {
+                $parents = array();
+
+                while (count($path) > 1 && ($parent = join($delim, $path))) {
+                    $name = kolab_storage::object_name($parent, $folder->get_namespace());
+                    if (!in_array($name, $existing)) {
+                        $parents[$parent] = new virtual_kolab_storage_folder($parent, $name, $folder->get_namespace());
+                        $existing[] = $name;
+                    }
+
+                    array_pop($path);
+                }
+
+                if (!empty($parents)) {
+                    $parents = array_reverse(array_values($parents));
+                    foreach ($parents as $parent) {
+                        $_folders[] = $parent;
+                    }
+                }
+            }
+
+            $_folders[] = $folder;
+            unset($folders[$idx]);
         }
 
-        return $out;
+        return $_folders;
     }
 
 
@@ -1047,3 +1116,33 @@ class kolab_storage
     }
 
 }
+
+/**
+ * Helper class that represents a virtual IMAP folder
+ * with a subset of the kolab_storage_folder API.
+ */
+class virtual_kolab_storage_folder
+{
+    public $id;
+    public $name;
+    public $namespace;
+    public $virtual = true;
+
+    public function __construct($realname, $name, $ns)
+    {
+        $this->id        = kolab_storage::folder_id($realname);
+        $this->name      = $name;
+        $this->namespace = $ns;
+    }
+
+    public function get_namespace()
+    {
+        return $this->namespace;
+    }
+
+    public function get_name()
+    {
+        // this is already kolab_storage::object_name() result
+        return $this->name;
+    }
+}
diff --git a/lib/plugins/libkolab/lib/kolab_storage_cache.php b/lib/plugins/libkolab/lib/kolab_storage_cache.php
index 732ce8f..db174e5 100644
--- a/lib/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/lib/plugins/libkolab/lib/kolab_storage_cache.php
@@ -117,6 +117,15 @@ class kolab_storage_cache
     }
 
     /**
+     * Getter for the numeric ID used in cache tables
+     */
+    public function get_folder_id()
+    {
+        $this->_read_folder_data();
+        return $this->folder_id;
+    }
+
+    /**
      * Synchronize local cache data with remote
      */
     public function synchronize()
@@ -133,7 +142,6 @@ class kolab_storage_cache
 
         // check cache status hash first ($this->metadata is set in _read_folder_data())
         if ($this->metadata['ctag'] != $this->folder->get_ctag()) {
-
             // lock synchronization for this folder or wait if locked
             $this->_sync_lock();
 
@@ -144,7 +152,7 @@ class kolab_storage_cache
             $this->imap->folder_sync($this->folder->name);
 
             // compare IMAP index with object cache index
-            $imap_index = $this->imap->index($this->folder->name);
+            $imap_index = $this->imap->index($this->folder->name, null, null, true, true);
             $this->index = $imap_index->get();
 
             // determine objects to fetch or to invalidate
@@ -342,7 +350,7 @@ class kolab_storage_cache
             $this->db->query(
                 "UPDATE $this->cache_table SET folder_id=?, msguid=? ".
                 "WHERE folder_id=? AND msguid=?",
-                $target->folder_id,
+                $target->cache->get_folder_id(),
                 $new_msguid,
                 $this->folder_id,
                 $msguid
@@ -365,7 +373,7 @@ class kolab_storage_cache
         $this->_read_folder_data();
 
         $result = $this->db->query(
-            "DELETE FROM $this->cache_table WHERE folder_id=?".
+            "DELETE FROM $this->cache_table WHERE folder_id=?",
             $this->folder_id
         );
         return $this->db->affected_rows($result);
@@ -660,7 +668,9 @@ class kolab_storage_cache
             }
         }
 
-        $sql_data['data'] = serialize($data);
+        // use base64 encoding (Bug #1912, #2662)
+        $sql_data['data'] = base64_encode(serialize($data));
+
         return $sql_data;
     }
 
@@ -669,8 +679,23 @@ class kolab_storage_cache
      */
     protected function _unserialize($sql_arr)
     {
+        // check if data is a base64-encoded string, for backward compat.
+        if (strpos(substr($sql_arr['data'], 0, 64), ':') === false) {
+            $sql_arr['data'] = base64_decode($sql_arr['data']);
+        }
+
         $object = unserialize($sql_arr['data']);
 
+        // de-serialization failed
+        if ($object === false) {
+            rcube::raise_error(array(
+                'code' => 900, 'type' => 'php',
+                'message' => "Malformed data for {$this->resource_uri}/{$sql_arr['msguid']} object."
+            ), true);
+
+            return null;
+        }
+
         // decode binary properties
         foreach ($this->binary_items as $key => $regexp) {
             if (!empty($object[$key]) && preg_match($regexp, $sql_arr['xml'], $m)) {
@@ -679,10 +704,10 @@ class kolab_storage_cache
         }
 
         // add meta data
-        $object['_type'] = $sql_arr['type'] ?: $this->folder->type;
-        $object['_msguid'] = $sql_arr['msguid'];
-        $object['_mailbox'] = $this->folder->name;
-        $object['_size'] = strlen($sql_arr['xml']);
+        $object['_type']      = $sql_arr['type'] ?: $this->folder->type;
+        $object['_msguid']    = $sql_arr['msguid'];
+        $object['_mailbox']   = $this->folder->name;
+        $object['_size']      = strlen($sql_arr['xml']);
         $object['_formatobj'] = kolab_format::factory($object['_type'], 3.0, $sql_arr['xml']);
 
         return $object;
diff --git a/lib/plugins/libkolab/lib/kolab_storage_cache_event.php b/lib/plugins/libkolab/lib/kolab_storage_cache_event.php
index 69134e7..876c3b4 100644
--- a/lib/plugins/libkolab/lib/kolab_storage_cache_event.php
+++ b/lib/plugins/libkolab/lib/kolab_storage_cache_event.php
@@ -41,7 +41,7 @@ class kolab_storage_cache_event extends kolab_storage_cache
         // extend date range for recurring events
         if ($object['recurrence'] && $object['_formatobj']) {
             $recurrence = new kolab_date_recurrence($object['_formatobj']);
-            $sql_data['dtend'] = date('Y-m-d 23:59:59', $recurrence->end() ?: strtotime('now +1 year'));
+            $sql_data['dtend'] = date('Y-m-d 23:59:59', $recurrence->end() ?: strtotime('now +10 years'));
         }
 
         return $sql_data;
diff --git a/lib/plugins/libkolab/lib/kolab_storage_folder.php b/lib/plugins/libkolab/lib/kolab_storage_folder.php
index 80f13fc..12da5e9 100644
--- a/lib/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/lib/plugins/libkolab/lib/kolab_storage_folder.php
@@ -280,7 +280,7 @@ class kolab_storage_folder
         }
 
         // generate a folder UID and set it to IMAP
-        $uid = rtrim(chunk_split(md5($this->name . $this->get_owner()), 12, '-'), '-');
+        $uid = rtrim(chunk_split(md5($this->name . $this->get_owner() . uniqid('-', true)), 12, '-'), '-');
         $this->set_uid($uid);
 
         return $uid;
@@ -764,6 +764,7 @@ class kolab_storage_folder
             // update cache with new UID
             if ($result) {
                 $object['_msguid'] = $result;
+                $object['_mailbox'] = $this->name;
                 $this->cache->insert($result, $object);
 
                 // remove temp file




More information about the commits mailing list