5 commits - lib/ext lib/kolab_sync_backend_common.php lib/kolab_sync_backend_content.php lib/kolab_sync_backend_device.php lib/kolab_sync_backend_folder.php lib/kolab_sync_backend_state.php lib/kolab_sync_data_calendar.php lib/kolab_sync_data_contacts.php lib/kolab_sync_data_email.php lib/kolab_sync_data_gal.php lib/kolab_sync_data.php lib/kolab_sync_data_tasks.php lib/kolab_sync.php

Aleksander Machniak machniak at kolabsys.com
Tue Aug 21 15:47:53 CEST 2012


 lib/ext/Roundcube/html.php               |   30 
 lib/ext/Roundcube/rcube.php              | 1439 ++++++++++++++++---------------
 lib/ext/Roundcube/rcube_browser.php      |    2 
 lib/ext/Roundcube/rcube_cache.php        |    4 
 lib/ext/Roundcube/rcube_config.php       |    4 
 lib/ext/Roundcube/rcube_db.php           |    4 
 lib/ext/Roundcube/rcube_imap.php         |   29 
 lib/ext/Roundcube/rcube_imap_generic.php |    4 
 lib/ext/Roundcube/rcube_ldap.php         |   13 
 lib/ext/Roundcube/rcube_message.php      |    2 
 lib/ext/Roundcube/rcube_output_html.php  |    8 
 lib/ext/Roundcube/rcube_plugin.php       |    2 
 lib/ext/Roundcube/rcube_plugin_api.php   |    4 
 lib/ext/Roundcube/rcube_session.php      |   11 
 lib/ext/Roundcube/rcube_shared.inc       |   23 
 lib/ext/Roundcube/rcube_smtp.php         |    2 
 lib/ext/Roundcube/rcube_storage.php      |    5 
 lib/ext/Roundcube/rcube_user.php         |    2 
 lib/ext/Roundcube/rcube_utils.php        |   15 
 lib/kolab_sync.php                       |   18 
 lib/kolab_sync_backend_common.php        |   15 
 lib/kolab_sync_backend_content.php       |    1 
 lib/kolab_sync_backend_device.php        |   28 
 lib/kolab_sync_backend_folder.php        |   47 -
 lib/kolab_sync_backend_state.php         |   89 -
 lib/kolab_sync_data.php                  |   75 -
 lib/kolab_sync_data_calendar.php         |   13 
 lib/kolab_sync_data_contacts.php         |   50 -
 lib/kolab_sync_data_email.php            |   44 
 lib/kolab_sync_data_gal.php              |   10 
 lib/kolab_sync_data_tasks.php            |   13 
 31 files changed, 994 insertions(+), 1012 deletions(-)

New commits:
commit 9579054cbcbb7b776edcb6e02d3e0cd515620a04
Author: Aleksander Machniak <alec at alec.pl>
Date:   Tue Aug 21 15:02:46 2012 +0200

    Code cleanup

diff --git a/lib/kolab_sync_backend_common.php b/lib/kolab_sync_backend_common.php
index c7c3b58..d72c908 100644
--- a/lib/kolab_sync_backend_common.php
+++ b/lib/kolab_sync_backend_common.php
@@ -70,11 +70,12 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
     }
 
     /**
-     * Creates new Syncroton data object in database
+     * Creates new Syncroton object in database
+     *
+     * @param Syncroton_Model_* $object Object
      *
-     * @param Syncroton_Model_* $object
      * @throws InvalidArgumentException
-     * @return Syncroton_Model_*
+     * @return Syncroton_Model_* Object
      */
     public function create($object)
     {
@@ -125,8 +126,9 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
     /**
      * Deletes Syncroton data object
      *
-     * @param string  $id
-     * @return bool
+     * @param string|Syncroton_Model_* $id Object or identifier
+     *
+     * @return bool True on success, False on failure
      */
     public function delete($id)
     {
@@ -141,8 +143,9 @@ class kolab_sync_backend_common implements Syncroton_Backend_IBackend
      * Updates Syncroton data object
      *
      * @param Syncroton_Model_* $object
+     *
      * @throws InvalidArgumentException
-     * @return Syncroton_Model_*
+     * @return Syncroton_Model_* Object
      */
     public function update($object)
     {
diff --git a/lib/kolab_sync_backend_content.php b/lib/kolab_sync_backend_content.php
index c13a343..72a673e 100644
--- a/lib/kolab_sync_backend_content.php
+++ b/lib/kolab_sync_backend_content.php
@@ -47,7 +47,6 @@ class kolab_sync_backend_content extends kolab_sync_backend_common implements Sy
         return (bool) $this->db->affected_rows($result);
     }
 
-
     /**
      * @param Syncroton_Model_IDevice|string $_deviceId
      * @param Syncroton_Model_IFolder|string $_folderId
diff --git a/lib/kolab_sync_backend_device.php b/lib/kolab_sync_backend_device.php
index 34a9759..fec5193 100644
--- a/lib/kolab_sync_backend_device.php
+++ b/lib/kolab_sync_backend_device.php
@@ -48,13 +48,12 @@ class kolab_sync_backend_device extends kolab_sync_backend_common implements Syn
         $this->backend = kolab_sync_backend::get_instance();
     }
 
-
     /**
-     * create new device
+     * Create (register) a new device
      *
-     * @param Syncroton_Model_IDevice $device
+     * @param Syncroton_Model_IDevice $device Device object
      *
-     * @return Syncroton_Model_IDevice
+     * @return Syncroton_Model_IDevice Device object
      */
     public function create($device)
     {
@@ -73,11 +72,10 @@ class kolab_sync_backend_device extends kolab_sync_backend_common implements Syn
         return $device;
     }
 
-
     /**
      * Delete a device
      *
-     * @param Syncroton_Model_IDevice $device
+     * @param Syncroton_Model_IDevice $device Device object
      *
      * @return bool True on success, False on failure
      */
@@ -92,19 +90,19 @@ class kolab_sync_backend_device extends kolab_sync_backend_common implements Syn
         return $result;
     }
 
-
     /**
-     * return device for this user
+     * Return device for a given user
+     *
+     * @param string $ownerid  User identifier
+     * @param string $deviceid Device identifier
      *
-     * @param  string  $ownerId
-     * @param  string  $deviceId
      * @throws Syncroton_Exception_NotFound
-     * @return Syncroton_Model_Device
+     * @return Syncroton_Model_Device Device object
      */
-    public function getUserDevice($ownerId, $deviceId)
+    public function getUserDevice($ownerid, $deviceid)
     {
-        $where[] = $this->db->quote_identifier('deviceid') . ' = ' . $this->db->quote($deviceId);
-        $where[] = $this->db->quote_identifier('owner_id') . ' = ' . $this->db->quote($ownerId);
+        $where[] = $this->db->quote_identifier('deviceid') . ' = ' . $this->db->quote($deviceid);
+        $where[] = $this->db->quote_identifier('owner_id') . ' = ' . $this->db->quote($ownerid);
 
         $select = $this->db->query('SELECT * FROM ' . $this->table_name . ' WHERE ' . implode(' AND ', $where));
         $device = $this->db->fetch_assoc($select);
@@ -116,7 +114,7 @@ class kolab_sync_backend_device extends kolab_sync_backend_common implements Syn
         $device = $this->get_object($device);
 
         // Make sure device exists (could be deleted by the user)
-        $dev = $this->backend->device_get($deviceId);
+        $dev = $this->backend->device_get($deviceid);
         if (empty($dev)) {
             // Remove the device (and related cached data) from database
             $this->delete($device);
diff --git a/lib/kolab_sync_backend_folder.php b/lib/kolab_sync_backend_folder.php
index 8b60b18..f2a846c 100644
--- a/lib/kolab_sync_backend_folder.php
+++ b/lib/kolab_sync_backend_folder.php
@@ -32,35 +32,33 @@ class kolab_sync_backend_folder extends kolab_sync_backend_common implements Syn
     protected $interface_name = 'Syncroton_Model_IFolder';
 
     /**
-     * delete all stored folderId's for given device
+     * Delete all stored folder ids for a given device
      *
-     * @param Syncroton_Model_Device|string $_deviceId
-     * @param string $_class
+     * @param Syncroton_Model_Device|string $deviceid Device object or identifier
      */
-    public function resetState($_deviceId)
+    public function resetState($deviceid)
     {
-        $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
+        $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
 
-        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
+        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
 
         $this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
     }
 
-
     /**
-     * get array of ids which got send to the client for a given class
+     * Get array of ids which got send to the client for a given class
      *
-     * @param Syncroton_Model_Device|string $_deviceId
-     * @param string $_class
+     * @param Syncroton_Model_Device|string $deviceid Device object or identifier
+     * @param string                        $class    Class name
      *
-     * @return array
+     * @return array List of object identifiers
      */
-    public function getFolderState($_deviceId, $_class)
+    public function getFolderState($deviceid, $class)
     {
-        $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
+        $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
 
-        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
-        $where[] = $this->db->quote_identifier('class')     . ' = ' . $this->db->quote($_class);
+        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
+        $where[] = $this->db->quote_identifier('class')     . ' = ' . $this->db->quote($class);
 
         $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
         $result = array();
@@ -73,18 +71,19 @@ class kolab_sync_backend_folder extends kolab_sync_backend_common implements Syn
     }
 
     /**
-     * get folder indentified by $_folderId
+     * Get folder
+     *
+     * @param Syncroton_Model_Device|string  $deviceid Device object or identifier
+     * @param string                         $folderid Folder identifier
      *
-     * @param  Syncroton_Model_Device|string  $_deviceId
-     * @param  string                       $_folderId
-     * @return Syncroton_Model_IFolder
+     * @return Syncroton_Model_IFolder Folder object
      */
-    public function getFolder($_deviceId, $_folderId)
+    public function getFolder($deviceid, $folderid)
     {
-        $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
+        $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
 
-        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
-        $where[] = $this->db->quote_identifier('folderid')  . ' = ' . $this->db->quote($_folderId);
+        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
+        $where[] = $this->db->quote_identifier('folderid')  . ' = ' . $this->db->quote($folderid);
 
         $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
         $folder = $this->db->fetch_assoc($select);
@@ -96,7 +95,6 @@ class kolab_sync_backend_folder extends kolab_sync_backend_common implements Syn
         return $this->get_object($folder);
     }
 
-
     /**
      * (non-PHPdoc)
      * @see kolab_sync_backend_common::from_camelcase()
@@ -119,7 +117,6 @@ class kolab_sync_backend_folder extends kolab_sync_backend_common implements Syn
         }
     }
 
-
     /**
      * (non-PHPdoc)
      * @see kolab_sync_backend_common::to_camelcase()
diff --git a/lib/kolab_sync_backend_state.php b/lib/kolab_sync_backend_state.php
index b239d36..99a69bc 100644
--- a/lib/kolab_sync_backend_state.php
+++ b/lib/kolab_sync_backend_state.php
@@ -32,16 +32,18 @@ class kolab_sync_backend_state extends kolab_sync_backend_common implements Sync
     protected $interface_name = 'Syncroton_Model_ISyncState';
 
     /**
-     * create new sync state
+     * Create new sync state of a folder
+     *
+     * @param Syncroton_Model_ISyncState $object              State object
+     * @param bool                       $keep_previous_state Don't remove other states
      *
-     * @param Syncroton_Model_ISyncState $_syncState
      * @return Syncroton_Model_SyncState
      */
-    public function create($object, $_keepPreviousSyncState = true)
+    public function create($object, $keep_previous_state = true)
     {
         $object = parent::create($object);
 
-        if ($_keepPreviousSyncState !== true) {
+        if ($keep_previous_state !== true) {
             // remove all other synckeys
             $this->_deleteOtherStates($object);
         }
@@ -49,19 +51,19 @@ class kolab_sync_backend_state extends kolab_sync_backend_common implements Sync
         return $object;
     }
 
-    protected function _deleteOtherStates(Syncroton_Model_ISyncState $_state)
+    /**
+     * Deletes states other than specified one
+     */
+    protected function _deleteOtherStates(Syncroton_Model_ISyncState $state)
     {
         // remove all other synckeys
-        $where[] = $this->db->quote_identifier('device_id') . ' = '  . $this->db->quote($_state->device_id);
-        $where[] = $this->db->quote_identifier('type')      . ' = '  . $this->db->quote($_state->type);
-        $where[] = $this->db->quote_identifier('counter')   . ' <> ' . $this->db->quote($_state->counter);
+        $where[] = $this->db->quote_identifier('device_id') . ' = '  . $this->db->quote($state->device_id);
+        $where[] = $this->db->quote_identifier('type')      . ' = '  . $this->db->quote($state->type);
+        $where[] = $this->db->quote_identifier('counter')   . ' <> ' . $this->db->quote($state->counter);
 
         $this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
-
-        return true;
     }
 
-
     /**
      * @see kolab_sync_backend_common::object_to_array()
      */
@@ -76,7 +78,6 @@ class kolab_sync_backend_state extends kolab_sync_backend_common implements Sync
         return $data;
     }
 
-
     /**
      * @see kolab_sync_backend_common::get_object()
      */
@@ -91,21 +92,21 @@ class kolab_sync_backend_state extends kolab_sync_backend_common implements Sync
         return $object;
     }
 
-
     /**
-     * always returns the latest syncstate
+     * Returns the latest sync state
+     *
+     * @param Syncroton_Model_IDevice|string $deviceid Device object or identifier
+     * @param Syncroton_Model_IFolder|string $folderid Folder object or identifier
      *
-     * @param  Syncroton_Model_IDevice|string  $_deviceId
-     * @param  Syncroton_Model_IFolder|string  $_folderId
      * @return Syncroton_Model_SyncState
      */
-    public function getSyncState($_deviceId, $_folderId)
+    public function getSyncState($deviceid, $folderid)
     {
-        $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
-        $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+        $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
+        $folder_id = $folderid instanceof Syncroton_Model_IFolder ? $folderid->id : $folderid;
 
-        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
-        $where[] = $this->db->quote_identifier('type')      . ' = ' . $this->db->quote($folderId);
+        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
+        $where[] = $this->db->quote_identifier('type')      . ' = ' . $this->db->quote($folder_id);
 
         $select = $this->db->limitquery('SELECT * FROM ' . $this->table_name . ' WHERE ' . implode(' AND ', $where)
             .' ORDER BY counter DESC', 0, 1);
@@ -120,43 +121,43 @@ class kolab_sync_backend_state extends kolab_sync_backend_common implements Sync
     }
 
     /**
-     * delete all stored synckeys for given type
+     * Delete all stored synckeys of given type
      *
-     * @param  Syncroton_Model_IDevice|string  $_deviceId
-     * @param  Syncroton_Model_IFolder|string  $_folderId
+     * @param Syncroton_Model_IDevice|string $deviceid Device object or identifier
+     * @param Syncroton_Model_IFolder|string $folderid Folder object or identifier
      */
-    public function resetState($_deviceId, $_folderId)
+    public function resetState($deviceid, $folderid)
     {
-        $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
-        $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+        $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
+        $folder_id = $folderid instanceof Syncroton_Model_IFolder ? $folderid->id : $folderid;
 
-        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
-        $where[] = $this->db->quote_identifier('type')      . ' = ' . $this->db->quote($folderId);
+        $where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
+        $where[] = $this->db->quote_identifier('type')      . ' = ' . $this->db->quote($folder_id);
 
         $this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
     }
 
-
     /**
-     * get array of ids which got send to the client for a given class
+     * Validates specified sync state by checking for existance of newer keys
      *
-     * @param  Syncroton_Model_IDevice|string  $_deviceId
-     * @param  Syncroton_Model_IFolder|string  $_folderId
+     * @param Syncroton_Model_IDevice|string $deviceid Device object or identifier
+     * @param Syncroton_Model_IFolder|string $folderid Folder object or identifier
+     * @param int                            $sync_key State key
      *
      * @return Syncroton_Model_SyncState
      */
-    public function validate($_deviceId, $_folderId, $_syncKey)
+    public function validate($deviceid, $folderid, $sync_key)
     {
-        $deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
-        $folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+        $device_id = $deviceid instanceof Syncroton_Model_IDevice ? $deviceid->id : $deviceid;
+        $folder_id = $folderid instanceof Syncroton_Model_IFolder ? $folderid->id : $folderid;
 
         // get sync data for current request and check if it's the last one
         // by fetching synckey+1
         $states = array();
-        $keys   = array($_syncKey, $_syncKey + 1);
+        $keys   = array($sync_key, $sync_key + 1);
 
-        $where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
-        $where['type']      = $this->db->quote_identifier('type')      . ' = ' . $this->db->quote($folderId);
+        $where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($device_id);
+        $where['type']      = $this->db->quote_identifier('type')      . ' = ' . $this->db->quote($folder_id);
         $where['counter']   = $this->db->quote_identifier('counter')   . ' IN (' . $this->db->array2list($keys, 'int') . ')';
 
         $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
@@ -165,19 +166,19 @@ class kolab_sync_backend_state extends kolab_sync_backend_common implements Sync
             $states[$row['counter']] = $this->get_object($row);
         }
 
-        if (empty($states) || empty($states[$_syncKey])) {
+        if (empty($states) || empty($states[$sync_key])) {
             return false;
         }
 
-        $state = $states[$_syncKey];
+        $state = $states[$sync_key];
 
         $where = array();
-        $where['device_id']  = $this->db->quote_identifier('device_id')  . ' = ' . $this->db->quote($deviceId);
-        $where['folder_id']  = $this->db->quote_identifier('folder_id')  . ' = ' . $this->db->quote($folderId);
+        $where['device_id']  = $this->db->quote_identifier('device_id')  . ' = ' . $this->db->quote($device_id);
+        $where['folder_id']  = $this->db->quote_identifier('folder_id')  . ' = ' . $this->db->quote($folder_id);
         $where['is_deleted'] = $this->db->quote_identifier('is_deleted') . ' = 1';
 
         // found more recent synckey => the last sync repsonse got not received by the client
-        if (!empty($states[$_syncKey + 1])) {
+        if (!empty($states[$sync_key + 1])) {
             $where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' = ' . $this->db->quote($state->counter);
             // undelete entries marked as deleted in syncroton_content table
             $this->db->query('UPDATE syncroton_content SET is_deleted = 0 WHERE ' . implode(' AND ', $where));


commit 57754b856f8dca5e1ff05dc45f7130bb481e294f
Author: Aleksander Machniak <alec at alec.pl>
Date:   Tue Aug 21 14:20:21 2012 +0200

    Update Roundcube Framework

diff --git a/lib/ext/Roundcube/html.php b/lib/ext/Roundcube/html.php
index b42da1d..c6507f8 100644
--- a/lib/ext/Roundcube/html.php
+++ b/lib/ext/Roundcube/html.php
@@ -154,7 +154,7 @@ class html
             $attr = array('src' => $attr);
         }
         return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib,
-	        array('src','alt','width','height','border','usemap','onclick')));
+            array('src','alt','width','height','border','usemap','onclick')));
     }
 
     /**
@@ -171,7 +171,7 @@ class html
             $attr = array('href' => $attr);
         }
         return self::tag('a', $attr, $cont, array_merge(self::$common_attrib,
-	    array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
+        array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup')));
     }
 
     /**
@@ -358,7 +358,7 @@ class html_inputfield extends html
     protected $tagname = 'input';
     protected $type = 'text';
     protected $allowed = array(
-        'type','name','value','size','tabindex',
+        'type','name','value','size','tabindex','autocapitalize',
         'autocomplete','checked','onchange','onclick','disabled','readonly',
         'spellcheck','results','maxlength','src','multiple','placeholder',
     );
@@ -532,7 +532,7 @@ class html_textarea extends html
 {
     protected $tagname = 'textarea';
     protected $allowed = array('name','rows','cols','wrap','tabindex',
-	'onchange','disabled','readonly','spellcheck');
+        'onchange','disabled','readonly','spellcheck');
 
     /**
      * Get HTML code for this object
@@ -563,7 +563,7 @@ class html_textarea extends html
         }
 
         return self::tag($this->tagname, $this->attrib, $value,
-	        array_merge(self::$common_attrib, $this->allowed));
+            array_merge(self::$common_attrib, $this->allowed));
     }
 }
 
@@ -591,7 +591,7 @@ class html_select extends html
     protected $tagname = 'select';
     protected $options = array();
     protected $allowed = array('name','size','tabindex','autocomplete',
-	'multiple','onchange','disabled','rel');
+        'multiple','onchange','disabled','rel');
 
     /**
      * Add a new option to this drop-down
@@ -655,7 +655,7 @@ class html_table extends html
 {
     protected $tagname = 'table';
     protected $allowed = array('id','class','style','width','summary',
-	    'cellpadding','cellspacing','border');
+        'cellpadding','cellspacing','border');
 
     private $header = array();
     private $rows = array();
@@ -705,8 +705,9 @@ class html_table extends html
      */
     public function add_header($attr, $cont)
     {
-        if (is_string($attr))
-    	    $attr = array('class' => $attr);
+        if (is_string($attr)) {
+            $attr = array('class' => $attr);
+        }
 
         $cell = new stdClass;
         $cell->attrib = $attr;
@@ -763,11 +764,13 @@ class html_table extends html
      */
     public function set_row_attribs($attr = array(), $index = null)
     {
-        if (is_string($attr))
-    	    $attr = array('class' => $attr);
+        if (is_string($attr)) {
+            $attr = array('class' => $attr);
+        }
 
-        if ($index === null)
+        if ($index === null) {
             $index = $this->rowindex;
+        }
 
         $this->rows[$index]->attrib = $attr;
     }
@@ -781,8 +784,9 @@ class html_table extends html
      */
     public function get_row_attribs($index = null)
     {
-        if ($index === null)
+        if ($index === null) {
             $index = $this->rowindex;
+        }
 
         return $this->rows[$index] ? $this->rows[$index]->attrib : null;
     }
diff --git a/lib/ext/Roundcube/rcube.php b/lib/ext/Roundcube/rcube.php
index 494b5c3..0e40b3c 100644
--- a/lib/ext/Roundcube/rcube.php
+++ b/lib/ext/Roundcube/rcube.php
@@ -25,364 +25,372 @@
  * Base class of the Roundcube Framework
  * implemented as singleton
  *
- * @package Core
+ * @package    Framework
+ * @subpackage Core
  */
 class rcube
 {
-  const INIT_WITH_DB = 1;
-  const INIT_WITH_PLUGINS = 2;
-
-  /**
-   * Singleton instace of rcube
-   *
-   * @var rcmail
-   */
-  static protected $instance;
-
-  /**
-   * Stores instance of rcube_config.
-   *
-   * @var rcube_config
-   */
-  public $config;
-
-  /**
-   * Instace of database class.
-   *
-   * @var rcube_pdo
-   */
-  public $db;
-
-  /**
-   * Instace of Memcache class.
-   *
-   * @var Memcache
-   */
-  public $memcache;
-
-  /**
-   * Instace of rcube_session class.
-   *
-   * @var rcube_session
-   */
-  public $session;
-
-  /**
-   * Instance of rcube_smtp class.
-   *
-   * @var rcube_smtp
-   */
-  public $smtp;
-
-  /**
-   * Instance of rcube_storage class.
-   *
-   * @var rcube_storage
-   */
-  public $storage;
-
-  /**
-   * Instance of rcube_output class.
-   *
-   * @var rcube_output
-   */
-  public $output;
-
-  /**
-   * Instance of rcube_plugin_api.
-   *
-   * @var rcube_plugin_api
-   */
-  public $plugins;
-
-
-  /* private/protected vars */
-  protected $texts;
-  protected $caches = array();
-  protected $shutdown_functions = array();
-  protected $expunge_cache = false;
-
-
-  /**
-   * This implements the 'singleton' design pattern
-   *
-   * @param integer Options to initialize with this instance. See rcube::INIT_WITH_* constants
-   * @return rcube The one and only instance
-   */
-  static function get_instance($mode = 0)
-  {
-    if (!self::$instance) {
-      self::$instance = new rcube();
-      self::$instance->init($mode);
-    }
+    const INIT_WITH_DB = 1;
+    const INIT_WITH_PLUGINS = 2;
 
-    return self::$instance;
-  }
-
-
-  /**
-   * Private constructor
-   */
-  protected function __construct()
-  {
-    // load configuration
-    $this->config = new rcube_config();
-    $this->plugins = new rcube_dummy_plugin_api;
-
-    register_shutdown_function(array($this, 'shutdown'));
-  }
-
-
-  /**
-   * Initial startup function
-   */
-  protected function init($mode = 0)
-  {
-    // initialize syslog
-    if ($this->config->get('log_driver') == 'syslog') {
-      $syslog_id = $this->config->get('syslog_id', 'roundcube');
-      $syslog_facility = $this->config->get('syslog_facility', LOG_USER);
-      openlog($syslog_id, LOG_ODELAY, $syslog_facility);
-    }
+    /**
+     * Singleton instace of rcube
+     *
+     * @var rcmail
+     */
+    static protected $instance;
 
-    // connect to database
-    if ($mode & self::INIT_WITH_DB) {
-      $this->get_dbh();
-    }
+    /**
+     * Stores instance of rcube_config.
+     *
+     * @var rcube_config
+     */
+    public $config;
+
+    /**
+     * Instace of database class.
+     *
+     * @var rcube_db
+     */
+    public $db;
+
+    /**
+     * Instace of Memcache class.
+     *
+     * @var Memcache
+     */
+    public $memcache;
+
+   /**
+     * Instace of rcube_session class.
+     *
+     * @var rcube_session
+     */
+    public $session;
+
+    /**
+     * Instance of rcube_smtp class.
+     *
+     * @var rcube_smtp
+     */
+    public $smtp;
+
+    /**
+     * Instance of rcube_storage class.
+     *
+     * @var rcube_storage
+     */
+    public $storage;
+
+    /**
+     * Instance of rcube_output class.
+     *
+     * @var rcube_output
+     */
+    public $output;
+
+    /**
+     * Instance of rcube_plugin_api.
+     *
+     * @var rcube_plugin_api
+     */
+    public $plugins;
 
-    // create plugin API and load plugins
-    if ($mode & self::INIT_WITH_PLUGINS) {
-      $this->plugins = rcube_plugin_api::get_instance();
+
+    /* private/protected vars */
+    protected $texts;
+    protected $caches = array();
+    protected $shutdown_functions = array();
+    protected $expunge_cache = false;
+
+
+    /**
+     * This implements the 'singleton' design pattern
+     *
+     * @param integer Options to initialize with this instance. See rcube::INIT_WITH_* constants
+     *
+     * @return rcube The one and only instance
+     */
+    static function get_instance($mode = 0)
+    {
+        if (!self::$instance) {
+            self::$instance = new rcube();
+            self::$instance->init($mode);
+        }
+
+        return self::$instance;
     }
-  }
-
-
-  /**
-   * Get the current database connection
-   *
-   * @return rcube_pdo  Database connection object
-   */
-  public function get_dbh()
-  {
-    if (!$this->db) {
-      $config_all = $this->config->all();
-      $this->db = rcube_db::factory($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']);
-      $this->db->set_debug((bool)$config_all['sql_debug']);
+
+
+    /**
+     * Private constructor
+     */
+    protected function __construct()
+    {
+        // load configuration
+        $this->config  = new rcube_config;
+        $this->plugins = new rcube_dummy_plugin_api;
+
+        register_shutdown_function(array($this, 'shutdown'));
     }
 
-    return $this->db;
-  }
-
-
-  /**
-   * Get global handle for memcache access
-   *
-   * @return object Memcache
-   */
-  public function get_memcache()
-  {
-    if (!isset($this->memcache)) {
-      // no memcache support in PHP
-      if (!class_exists('Memcache')) {
-        $this->memcache = false;
-        return false;
-      }
 
-      $this->memcache = new Memcache;
-      $this->mc_available = 0;
+    /**
+     * Initial startup function
+     */
+    protected function init($mode = 0)
+    {
+        // initialize syslog
+        if ($this->config->get('log_driver') == 'syslog') {
+            $syslog_id       = $this->config->get('syslog_id', 'roundcube');
+            $syslog_facility = $this->config->get('syslog_facility', LOG_USER);
+            openlog($syslog_id, LOG_ODELAY, $syslog_facility);
+        }
 
-      // add all configured hosts to pool
-      $pconnect = $this->config->get('memcache_pconnect', true);
-      foreach ($this->config->get('memcache_hosts', array()) as $host) {
-        if (substr($host, 0, 7) != 'unix://') {
-          list($host, $port) = explode(':', $host);
-          if (!$port) $port = 11211;
+        // connect to database
+        if ($mode & self::INIT_WITH_DB) {
+            $this->get_dbh();
         }
-        else {
-          $port = 0;
+
+        // create plugin API and load plugins
+        if ($mode & self::INIT_WITH_PLUGINS) {
+            $this->plugins = rcube_plugin_api::get_instance();
         }
+    }
 
-        $this->mc_available += intval($this->memcache->addServer($host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure')));
-      }
 
-      // test connection and failover (will result in $this->mc_available == 0 on complete failure)
-      $this->memcache->increment('__CONNECTIONTEST__', 1);  // NOP if key doesn't exist
+    /**
+     * Get the current database connection
+     *
+     * @return rcube_db Database object
+     */
+    public function get_dbh()
+    {
+        if (!$this->db) {
+            $config_all = $this->config->all();
+            $this->db = rcube_db::factory($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']);
+            $this->db->set_debug((bool)$config_all['sql_debug']);
+        }
 
-      if (!$this->mc_available)
-        $this->memcache = false;
+        return $this->db;
     }
 
-    return $this->memcache;
-  }
 
+    /**
+     * Get global handle for memcache access
+     *
+     * @return object Memcache
+     */
+    public function get_memcache()
+    {
+        if (!isset($this->memcache)) {
+            // no memcache support in PHP
+            if (!class_exists('Memcache')) {
+                $this->memcache = false;
+                return false;
+            }
 
-  /**
-   * Callback for memcache failure
-   */
-  public function memcache_failure($host, $port)
-  {
-    static $seen = array();
+            $this->memcache     = new Memcache;
+            $this->mc_available = 0;
 
-    // only report once
-    if (!$seen["$host:$port"]++) {
-      $this->mc_available--;
-      self::raise_error(array('code' => 604, 'type' => 'db',
-        'line' => __LINE__, 'file' => __FILE__,
-        'message' => "Memcache failure on host $host:$port"),
-        true, false);
-    }
-  }
-
-
-  /**
-   * Initialize and get cache object
-   *
-   * @param string $name   Cache identifier
-   * @param string $type   Cache type ('db', 'apc' or 'memcache')
-   * @param string $ttl    Expiration time for cache items
-   * @param bool   $packed Enables/disables data serialization
-   *
-   * @return rcube_cache Cache object
-   */
-  public function get_cache($name, $type='db', $ttl=0, $packed=true)
-  {
-    if (!isset($this->caches[$name]) && ($userid = $this->get_user_id())) {
-      $this->caches[$name] = new rcube_cache($type, $userid, $name, $ttl, $packed);
-    }
+            // add all configured hosts to pool
+            $pconnect = $this->config->get('memcache_pconnect', true);
+            foreach ($this->config->get('memcache_hosts', array()) as $host) {
+                if (substr($host, 0, 7) != 'unix://') {
+                    list($host, $port) = explode(':', $host);
+                    if (!$port) $port = 11211;
+                }
+                else {
+                    $port = 0;
+                }
 
-    return $this->caches[$name];
-  }
-
-
-  /**
-   * Create SMTP object and connect to server
-   *
-   * @param boolean True if connection should be established
-   */
-  public function smtp_init($connect = false)
-  {
-    $this->smtp = new rcube_smtp();
-
-    if ($connect)
-      $this->smtp->connect();
-  }
-
-
-  /**
-   * Initialize and get storage object
-   *
-   * @return rcube_storage Storage object
-   */
-  public function get_storage()
-  {
-    // already initialized
-    if (!is_object($this->storage)) {
-      $this->storage_init();
-    }
+                $this->mc_available += intval($this->memcache->addServer(
+                    $host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure')));
+            }
 
-    return $this->storage;
-  }
+            // test connection and failover (will result in $this->mc_available == 0 on complete failure)
+            $this->memcache->increment('__CONNECTIONTEST__', 1);  // NOP if key doesn't exist
 
+            if (!$this->mc_available) {
+                $this->memcache = false;
+            }
+        }
 
-  /**
-   * Initialize storage object
-   */
-  public function storage_init()
-  {
-    // already initialized
-    if (is_object($this->storage)) {
-      return;
+        return $this->memcache;
     }
 
-    $driver = $this->config->get('storage_driver', 'imap');
-    $driver_class = "rcube_{$driver}";
 
-    if (!class_exists($driver_class)) {
-      self::raise_error(array(
-        'code' => 700, 'type' => 'php',
-        'file' => __FILE__, 'line' => __LINE__,
-        'message' => "Storage driver class ($driver) not found!"),
-        true, true);
+    /**
+     * Callback for memcache failure
+     */
+    public function memcache_failure($host, $port)
+    {
+        static $seen = array();
+
+        // only report once
+        if (!$seen["$host:$port"]++) {
+            $this->mc_available--;
+            self::raise_error(array(
+                'code' => 604, 'type' => 'db',
+                'line' => __LINE__, 'file' => __FILE__,
+                'message' => "Memcache failure on host $host:$port"),
+                true, false);
+        }
     }
 
-    // Initialize storage object
-    $this->storage = new $driver_class;
 
-    // for backward compat. (deprecated, will be removed)
-    $this->imap = $this->storage;
+    /**
+     * Initialize and get cache object
+     *
+     * @param string $name   Cache identifier
+     * @param string $type   Cache type ('db', 'apc' or 'memcache')
+     * @param string $ttl    Expiration time for cache items
+     * @param bool   $packed Enables/disables data serialization
+     *
+     * @return rcube_cache Cache object
+     */
+    public function get_cache($name, $type='db', $ttl=0, $packed=true)
+    {
+        if (!isset($this->caches[$name]) && ($userid = $this->get_user_id())) {
+            $this->caches[$name] = new rcube_cache($type, $userid, $name, $ttl, $packed);
+        }
 
-    // enable caching of mail data
-    $storage_cache  = $this->config->get("{$driver}_cache");
-    $messages_cache = $this->config->get('messages_cache');
-    // for backward compatybility
-    if ($storage_cache === null && $messages_cache === null && $this->config->get('enable_caching')) {
-        $storage_cache  = 'db';
-        $messages_cache = true;
+        return $this->caches[$name];
     }
 
-    if ($storage_cache)
-        $this->storage->set_caching($storage_cache);
-    if ($messages_cache)
-        $this->storage->set_messages_caching(true);
 
-    // set pagesize from config
-    $pagesize = $this->config->get('mail_pagesize');
-    if (!$pagesize) {
-        $pagesize = $this->config->get('pagesize', 50);
+    /**
+     * Create SMTP object and connect to server
+     *
+     * @param boolean True if connection should be established
+     */
+    public function smtp_init($connect = false)
+    {
+        $this->smtp = new rcube_smtp();
+
+        if ($connect) {
+            $this->smtp->connect();
+        }
     }
-    $this->storage->set_pagesize($pagesize);
-
-    // set class options
-    $options = array(
-      'auth_type'   => $this->config->get("{$driver}_auth_type", 'check'),
-      'auth_cid'    => $this->config->get("{$driver}_auth_cid"),
-      'auth_pw'     => $this->config->get("{$driver}_auth_pw"),
-      'debug'       => (bool) $this->config->get("{$driver}_debug"),
-      'force_caps'  => (bool) $this->config->get("{$driver}_force_caps"),
-      'timeout'     => (int) $this->config->get("{$driver}_timeout"),
-      'skip_deleted' => (bool) $this->config->get('skip_deleted'),
-      'driver'      => $driver,
-    );
-
-    if (!empty($_SESSION['storage_host'])) {
-      $options['host']     = $_SESSION['storage_host'];
-      $options['user']     = $_SESSION['username'];
-      $options['port']     = $_SESSION['storage_port'];
-      $options['ssl']      = $_SESSION['storage_ssl'];
-      $options['password'] = $this->decrypt($_SESSION['password']);
-      $_SESSION[$driver.'_host'] = $_SESSION['storage_host'];
+
+
+    /**
+     * Initialize and get storage object
+     *
+     * @return rcube_storage Storage object
+     */
+    public function get_storage()
+    {
+        // already initialized
+        if (!is_object($this->storage)) {
+            $this->storage_init();
+        }
+
+        return $this->storage;
     }
 
-    $options = $this->plugins->exec_hook("storage_init", $options);
 
-    // for backward compat. (deprecated, to be removed)
-    $options = $this->plugins->exec_hook("imap_init", $options);
+    /**
+     * Initialize storage object
+     */
+    public function storage_init()
+    {
+        // already initialized
+        if (is_object($this->storage)) {
+            return;
+        }
 
-    $this->storage->set_options($options);
-    $this->set_storage_prop();
-  }
+        $driver       = $this->config->get('storage_driver', 'imap');
+        $driver_class = "rcube_{$driver}";
 
+        if (!class_exists($driver_class)) {
+            self::raise_error(array(
+                'code' => 700, 'type' => 'php',
+                'file' => __FILE__, 'line' => __LINE__,
+                'message' => "Storage driver class ($driver) not found!"),
+                true, true);
+        }
 
-  /**
-   * Set storage parameters.
-   * This must be done AFTER connecting to the server!
-   */
-  protected function set_storage_prop()
-  {
-    $storage = $this->get_storage();
+        // Initialize storage object
+        $this->storage = new $driver_class;
 
-    $storage->set_charset($this->config->get('default_charset', RCMAIL_CHARSET));
+        // for backward compat. (deprecated, will be removed)
+        $this->imap = $this->storage;
 
-    if ($default_folders = $this->config->get('default_folders')) {
-      $storage->set_default_folders($default_folders);
-    }
-    if (isset($_SESSION['mbox'])) {
-      $storage->set_folder($_SESSION['mbox']);
+        // enable caching of mail data
+        $storage_cache  = $this->config->get("{$driver}_cache");
+        $messages_cache = $this->config->get('messages_cache');
+        // for backward compatybility
+        if ($storage_cache === null && $messages_cache === null && $this->config->get('enable_caching')) {
+            $storage_cache  = 'db';
+            $messages_cache = true;
+        }
+
+        if ($storage_cache) {
+            $this->storage->set_caching($storage_cache);
+        }
+        if ($messages_cache) {
+            $this->storage->set_messages_caching(true);
+        }
+
+        // set pagesize from config
+        $pagesize = $this->config->get('mail_pagesize');
+        if (!$pagesize) {
+            $pagesize = $this->config->get('pagesize', 50);
+        }
+        $this->storage->set_pagesize($pagesize);
+
+        // set class options
+        $options = array(
+            'auth_type'   => $this->config->get("{$driver}_auth_type", 'check'),
+            'auth_cid'    => $this->config->get("{$driver}_auth_cid"),
+            'auth_pw'     => $this->config->get("{$driver}_auth_pw"),
+            'debug'       => (bool) $this->config->get("{$driver}_debug"),
+            'force_caps'  => (bool) $this->config->get("{$driver}_force_caps"),
+            'timeout'     => (int) $this->config->get("{$driver}_timeout"),
+            'skip_deleted' => (bool) $this->config->get('skip_deleted'),
+            'driver'      => $driver,
+        );
+
+        if (!empty($_SESSION['storage_host'])) {
+            $options['host']     = $_SESSION['storage_host'];
+            $options['user']     = $_SESSION['username'];
+            $options['port']     = $_SESSION['storage_port'];
+            $options['ssl']      = $_SESSION['storage_ssl'];
+            $options['password'] = $this->decrypt($_SESSION['password']);
+            $_SESSION[$driver.'_host'] = $_SESSION['storage_host'];
+        }
+
+        $options = $this->plugins->exec_hook("storage_init", $options);
+
+        // for backward compat. (deprecated, to be removed)
+        $options = $this->plugins->exec_hook("imap_init", $options);
+
+        $this->storage->set_options($options);
+        $this->set_storage_prop();
     }
-    if (isset($_SESSION['page'])) {
-      $storage->set_page($_SESSION['page']);
+
+
+    /**
+     * Set storage parameters.
+     * This must be done AFTER connecting to the server!
+     */
+    protected function set_storage_prop()
+    {
+        $storage = $this->get_storage();
+
+        $storage->set_charset($this->config->get('default_charset', RCMAIL_CHARSET));
+
+        if ($default_folders = $this->config->get('default_folders')) {
+            $storage->set_default_folders($default_folders);
+        }
+        if (isset($_SESSION['mbox'])) {
+            $storage->set_folder($_SESSION['mbox']);
+        }
+        if (isset($_SESSION['page'])) {
+            $storage->set_page($_SESSION['page']);
+        }
     }
-  }
 
 
     /**
@@ -397,12 +405,17 @@ class rcube
 
         $sess_name   = $this->config->get('session_name');
         $sess_domain = $this->config->get('session_domain');
+        $sess_path   = $this->config->get('session_path');
         $lifetime    = $this->config->get('session_lifetime', 0) * 60;
 
         // set session domain
         if ($sess_domain) {
             ini_set('session.cookie_domain', $sess_domain);
         }
+        // set session path
+        if ($sess_path) {
+            ini_set('session.cookie_path', $sess_path);
+        }
         // set session garbage collecting time according to session_lifetime
         if ($lifetime) {
             ini_set('session.gc_maxlifetime', $lifetime * 2);
@@ -492,433 +505,469 @@ class rcube
     }
 
 
-  /**
-   * Get localized text in the desired language
-   *
-   * @param mixed   $attrib  Named parameters array or label name
-   * @param string  $domain  Label domain (plugin) name
-   *
-   * @return string Localized text
-   */
-  public function gettext($attrib, $domain=null)
-  {
-    // load localization files if not done yet
-    if (empty($this->texts))
-      $this->load_language();
-
-    // extract attributes
-    if (is_string($attrib))
-      $attrib = array('name' => $attrib);
-
-    $name = $attrib['name'] ? $attrib['name'] : '';
-
-    // attrib contain text values: use them from now
-    if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us']))
-        $this->texts[$name] = $setval;
-
-    // check for text with domain
-    if ($domain && ($text = $this->texts[$domain.'.'.$name]))
-      ;
-    // text does not exist
-    else if (!($text = $this->texts[$name])) {
-      return "[$name]";
-    }
+    /**
+     * Get localized text in the desired language
+     *
+     * @param mixed   $attrib  Named parameters array or label name
+     * @param string  $domain  Label domain (plugin) name
+     *
+     * @return string Localized text
+     */
+    public function gettext($attrib, $domain=null)
+    {
+        // load localization files if not done yet
+        if (empty($this->texts)) {
+            $this->load_language();
+        }
 
-    // replace vars in text
-    if (is_array($attrib['vars'])) {
-      foreach ($attrib['vars'] as $var_key => $var_value)
-        $text = str_replace($var_key[0]!='$' ? '$'.$var_key : $var_key, $var_value, $text);
-    }
+        // extract attributes
+        if (is_string($attrib)) {
+            $attrib = array('name' => $attrib);
+        }
 
-    // format output
-    if (($attrib['uppercase'] && strtolower($attrib['uppercase']=='first')) || $attrib['ucfirst'])
-      return ucfirst($text);
-    else if ($attrib['uppercase'])
-      return mb_strtoupper($text);
-    else if ($attrib['lowercase'])
-      return mb_strtolower($text);
-
-    return strtr($text, array('\n' => "\n"));
-  }
-
-
-  /**
-   * Check if the given text label exists
-   *
-   * @param string  $name       Label name
-   * @param string  $domain     Label domain (plugin) name or '*' for all domains
-   * @param string  $ref_domain Sets domain name if label is found
-   *
-   * @return boolean True if text exists (either in the current language or in en_US)
-   */
-  public function text_exists($name, $domain = null, &$ref_domain = null)
-  {
-    // load localization files if not done yet
-    if (empty($this->texts))
-      $this->load_language();
-
-    if (isset($this->texts[$name])) {
-        $ref_domain = '';
-        return true;
-    }
+        $name = $attrib['name'] ? $attrib['name'] : '';
+
+        // attrib contain text values: use them from now
+        if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us'])) {
+            $this->texts[$name] = $setval;
+        }
 
-    // any of loaded domains (plugins)
-    if ($domain == '*') {
-      foreach ($this->plugins->loaded_plugins() as $domain)
-        if (isset($this->texts[$domain.'.'.$name])) {
-          $ref_domain = $domain;
-          return true;
+        // check for text with domain
+        if ($domain && ($text = $this->texts[$domain.'.'.$name])) {
+        }
+        // text does not exist
+        else if (!($text = $this->texts[$name])) {
+            return "[$name]";
+        }
+
+        // replace vars in text
+        if (is_array($attrib['vars'])) {
+            foreach ($attrib['vars'] as $var_key => $var_value) {
+                $text = str_replace($var_key[0]!='$' ? '$'.$var_key : $var_key, $var_value, $text);
+            }
         }
+
+        // format output
+        if (($attrib['uppercase'] && strtolower($attrib['uppercase'] == 'first')) || $attrib['ucfirst']) {
+            return ucfirst($text);
+        }
+        else if ($attrib['uppercase']) {
+            return mb_strtoupper($text);
+        }
+        else if ($attrib['lowercase']) {
+            return mb_strtolower($text);
+        }
+
+        return strtr($text, array('\n' => "\n"));
     }
-    // specified domain
-    else if ($domain) {
-      $ref_domain = $domain;
-      return isset($this->texts[$domain.'.'.$name]);
+
+
+    /**
+     * Check if the given text label exists
+     *
+     * @param string  $name       Label name
+     * @param string  $domain     Label domain (plugin) name or '*' for all domains
+     * @param string  $ref_domain Sets domain name if label is found
+     *
+     * @return boolean True if text exists (either in the current language or in en_US)
+     */
+    public function text_exists($name, $domain = null, &$ref_domain = null)
+    {
+        // load localization files if not done yet
+        if (empty($this->texts)) {
+            $this->load_language();
+        }
+
+        if (isset($this->texts[$name])) {
+            $ref_domain = '';
+            return true;
+        }
+
+        // any of loaded domains (plugins)
+        if ($domain == '*') {
+            foreach ($this->plugins->loaded_plugins() as $domain) {
+                if (isset($this->texts[$domain.'.'.$name])) {
+                    $ref_domain = $domain;
+                    return true;
+                }
+            }
+        }
+        // specified domain
+        else if ($domain) {
+            $ref_domain = $domain;
+            return isset($this->texts[$domain.'.'.$name]);
+        }
+
+        return false;
     }
 
-    return false;
-  }
 
-  /**
-   * Load a localization package
-   *
-   * @param string Language ID
-   */
-  public function load_language($lang = null, $add = array())
-  {
-    $lang = $this->language_prop(($lang ? $lang : $_SESSION['language']));
+    /**
+     * Load a localization package
+     *
+     * @param string Language ID
+     * @param array  Additional text labels/messages
+     */
+    public function load_language($lang = null, $add = array())
+    {
+        $lang = $this->language_prop(($lang ? $lang : $_SESSION['language']));
+
+        // load localized texts
+        if (empty($this->texts) || $lang != $_SESSION['language']) {
+            $this->texts = array();
 
-    // load localized texts
-    if (empty($this->texts) || $lang != $_SESSION['language']) {
-      $this->texts = array();
+            // handle empty lines after closing PHP tag in localization files
+            ob_start();
 
-      // handle empty lines after closing PHP tag in localization files
-      ob_start();
+            // get english labels (these should be complete)
+            @include(INSTALL_PATH . 'program/localization/en_US/labels.inc');
+            @include(INSTALL_PATH . 'program/localization/en_US/messages.inc');
 
-      // get english labels (these should be complete)
-      @include(INSTALL_PATH . 'program/localization/en_US/labels.inc');
-      @include(INSTALL_PATH . 'program/localization/en_US/messages.inc');
+            if (is_array($labels))
+                $this->texts = $labels;
+            if (is_array($messages))
+                $this->texts = array_merge($this->texts, $messages);
 
-      if (is_array($labels))
-        $this->texts = $labels;
-      if (is_array($messages))
-        $this->texts = array_merge($this->texts, $messages);
+            // include user language files
+            if ($lang != 'en' && $lang != 'en_US' && is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
+                include_once(INSTALL_PATH . 'program/localization/' . $lang . '/labels.inc');
+                include_once(INSTALL_PATH . 'program/localization/' . $lang . '/messages.inc');
 
-      // include user language files
-      if ($lang != 'en' && $lang != 'en_US' && is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
-        include_once(INSTALL_PATH . 'program/localization/' . $lang . '/labels.inc');
-        include_once(INSTALL_PATH . 'program/localization/' . $lang . '/messages.inc');
+                if (is_array($labels))
+                    $this->texts = array_merge($this->texts, $labels);
+                if (is_array($messages))
+                    $this->texts = array_merge($this->texts, $messages);
+            }
 
-        if (is_array($labels))
-          $this->texts = array_merge($this->texts, $labels);
-        if (is_array($messages))
-          $this->texts = array_merge($this->texts, $messages);
-      }
+            ob_end_clean();
 
-      ob_end_clean();
+            $_SESSION['language'] = $lang;
+        }
 
-      $_SESSION['language'] = $lang;
+        // append additional texts (from plugin)
+        if (is_array($add) && !empty($add)) {
+            $this->texts += $add;
+        }
     }
 
-    // append additional texts (from plugin)
-    if (is_array($add) && !empty($add))
-      $this->texts += $add;
-  }
-
-
-  /**
-   * Check the given string and return a valid language code
-   *
-   * @param string Language code
-   * @return string Valid language code
-   */
-  protected function language_prop($lang)
-  {
-    static $rcube_languages, $rcube_language_aliases;
-
-    // user HTTP_ACCEPT_LANGUAGE if no language is specified
-    if (empty($lang) || $lang == 'auto') {
-       $accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
-       $lang = str_replace('-', '_', $accept_langs[0]);
-     }
-
-    if (empty($rcube_languages)) {
-      @include(INSTALL_PATH . 'program/localization/index.inc');
-    }
 
-    // check if we have an alias for that language
-    if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang])) {
-      $lang = $rcube_language_aliases[$lang];
+    /**
+     * Check the given string and return a valid language code
+     *
+     * @param string Language code
+     *
+     * @return string Valid language code
+     */
+    protected function language_prop($lang)
+    {
+        static $rcube_languages, $rcube_language_aliases;
+
+        // user HTTP_ACCEPT_LANGUAGE if no language is specified
+        if (empty($lang) || $lang == 'auto') {
+            $accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+            $lang         = str_replace('-', '_', $accept_langs[0]);
+        }
+
+        if (empty($rcube_languages)) {
+            @include(INSTALL_PATH . 'program/localization/index.inc');
+        }
+
+        // check if we have an alias for that language
+        if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang])) {
+            $lang = $rcube_language_aliases[$lang];
+        }
+        // try the first two chars
+        else if (!isset($rcube_languages[$lang])) {
+            $short = substr($lang, 0, 2);
+
+            // check if we have an alias for the short language code
+            if (!isset($rcube_languages[$short]) && isset($rcube_language_aliases[$short])) {
+                $lang = $rcube_language_aliases[$short];
+            }
+            // expand 'nn' to 'nn_NN'
+            else if (!isset($rcube_languages[$short])) {
+                $lang = $short.'_'.strtoupper($short);
+            }
+        }
+
+        if (!isset($rcube_languages[$lang]) || !is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
+            $lang = 'en_US';
+        }
+
+        return $lang;
     }
-    // try the first two chars
-    else if (!isset($rcube_languages[$lang])) {
-      $short = substr($lang, 0, 2);
-
-      // check if we have an alias for the short language code
-      if (!isset($rcube_languages[$short]) && isset($rcube_language_aliases[$short])) {
-        $lang = $rcube_language_aliases[$short];
-      }
-      // expand 'nn' to 'nn_NN'
-      else if (!isset($rcube_languages[$short])) {
-        $lang = $short.'_'.strtoupper($short);
-      }
+
+
+    /**
+     * Read directory program/localization and return a list of available languages
+     *
+     * @return array List of available localizations
+     */
+    public function list_languages()
+    {
+        static $sa_languages = array();
+
+        if (!sizeof($sa_languages)) {
+            @include(INSTALL_PATH . 'program/localization/index.inc');
+
+            if ($dh = @opendir(INSTALL_PATH . 'program/localization')) {
+                while (($name = readdir($dh)) !== false) {
+                    if ($name[0] == '.' || !is_dir(INSTALL_PATH . 'program/localization/' . $name)) {
+                        continue;
+                    }
+
+                    if ($label = $rcube_languages[$name]) {
+                        $sa_languages[$name] = $label;
+                    }
+                }
+                closedir($dh);
+            }
+        }
+
+        return $sa_languages;
     }
 
-    if (!isset($rcube_languages[$lang]) || !is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
-      $lang = 'en_US';
+
+    /**
+     * Encrypt using 3DES
+     *
+     * @param string $clear clear text input
+     * @param string $key encryption key to retrieve from the configuration, defaults to 'des_key'
+     * @param boolean $base64 whether or not to base64_encode() the result before returning
+     *
+     * @return string encrypted text
+     */
+    public function encrypt($clear, $key = 'des_key', $base64 = true)
+    {
+        if (!$clear) {
+            return '';
+        }
+
+        /*-
+         * Add a single canary byte to the end of the clear text, which
+         * will help find out how much of padding will need to be removed
+         * upon decryption; see http://php.net/mcrypt_generic#68082
+         */
+        $clear = pack("a*H2", $clear, "80");
+
+        if (function_exists('mcrypt_module_open') &&
+            ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))
+        ) {
+            $iv = $this->create_iv(mcrypt_enc_get_iv_size($td));
+            mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv);
+            $cipher = $iv . mcrypt_generic($td, $clear);
+            mcrypt_generic_deinit($td);
+            mcrypt_module_close($td);
+        }
+        else {
+            @include_once 'des.inc';
+
+            if (function_exists('des')) {
+                $des_iv_size = 8;
+                $iv = $this->create_iv($des_iv_size);
+                $cipher = $iv . des($this->config->get_crypto_key($key), $clear, 1, 1, $iv);
+            }
+            else {
+                self::raise_error(array(
+                    'code' => 500, 'type' => 'php',
+                    'file' => __FILE__, 'line' => __LINE__,
+                    'message' => "Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available"
+                    ), true, true);
+            }
+        }
+
+        return $base64 ? base64_encode($cipher) : $cipher;
     }
 
-    return $lang;
-  }
 
+    /**
+     * Decrypt 3DES-encrypted string
+     *
+     * @param string $cipher encrypted text
+     * @param string $key encryption key to retrieve from the configuration, defaults to 'des_key'
+     * @param boolean $base64 whether or not input is base64-encoded
+     *
+     * @return string decrypted text
+     */
+    public function decrypt($cipher, $key = 'des_key', $base64 = true)
+    {
+        if (!$cipher) {
+            return '';
+        }
 
-  /**
-   * Read directory program/localization and return a list of available languages
-   *
-   * @return array List of available localizations
-   */
-  public function list_languages()
-  {
-    static $sa_languages = array();
+        $cipher = $base64 ? base64_decode($cipher) : $cipher;
 
-    if (!sizeof($sa_languages)) {
-      @include(INSTALL_PATH . 'program/localization/index.inc');
+        if (function_exists('mcrypt_module_open') &&
+            ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))
+        ) {
+            $iv_size = mcrypt_enc_get_iv_size($td);
+            $iv = substr($cipher, 0, $iv_size);
 
-      if ($dh = @opendir(INSTALL_PATH . 'program/localization')) {
-        while (($name = readdir($dh)) !== false) {
-          if ($name[0] == '.' || !is_dir(INSTALL_PATH . 'program/localization/' . $name))
-            continue;
+            // session corruption? (#1485970)
+            if (strlen($iv) < $iv_size) {
+                return '';
+            }
 
-          if ($label = $rcube_languages[$name])
-            $sa_languages[$name] = $label;
+            $cipher = substr($cipher, $iv_size);
+            mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv);
+            $clear = mdecrypt_generic($td, $cipher);
+            mcrypt_generic_deinit($td);
+            mcrypt_module_close($td);
+        }
+        else {
+            @include_once 'des.inc';
+
+            if (function_exists('des')) {
+                $des_iv_size = 8;
+                $iv = substr($cipher, 0, $des_iv_size);
+                $cipher = substr($cipher, $des_iv_size);
+                $clear = des($this->config->get_crypto_key($key), $cipher, 0, 1, $iv);
+            }
+            else {
+                self::raise_error(array(
+                    'code' => 500, 'type' => 'php',
+                    'file' => __FILE__, 'line' => __LINE__,
+                    'message' => "Could not perform decryption; make sure Mcrypt is installed or lib/des.inc is available"
+                    ), true, true);
+            }
         }
-        closedir($dh);
-      }
+
+        /*-
+         * Trim PHP's padding and the canary byte; see note in
+         * rcube::encrypt() and http://php.net/mcrypt_generic#68082
+         */
+        $clear = substr(rtrim($clear, "\0"), 0, -1);
+
+        return $clear;
     }
 
-    return $sa_languages;
-  }
-
-
-  /**
-   * Encrypt using 3DES
-   *
-   * @param string $clear clear text input
-   * @param string $key encryption key to retrieve from the configuration, defaults to 'des_key'
-   * @param boolean $base64 whether or not to base64_encode() the result before returning
-   *
-   * @return string encrypted text
-   */
-  public function encrypt($clear, $key = 'des_key', $base64 = true)
-  {
-    if (!$clear)
-      return '';
-
-    /*-
-     * Add a single canary byte to the end of the clear text, which
-     * will help find out how much of padding will need to be removed
-     * upon decryption; see http://php.net/mcrypt_generic#68082
+
+    /**
+     * Generates encryption initialization vector (IV)
+     *
+     * @param int Vector size
+     *
+     * @return string Vector string
      */
-    $clear = pack("a*H2", $clear, "80");
-
-    if (function_exists('mcrypt_module_open') &&
-        ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))) {
-      $iv = $this->create_iv(mcrypt_enc_get_iv_size($td));
-      mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv);
-      $cipher = $iv . mcrypt_generic($td, $clear);
-      mcrypt_generic_deinit($td);
-      mcrypt_module_close($td);
-    }
-    else {
-      @include_once 'des.inc';
-
-      if (function_exists('des')) {
-        $des_iv_size = 8;
-        $iv = $this->create_iv($des_iv_size);
-        $cipher = $iv . des($this->config->get_crypto_key($key), $clear, 1, 1, $iv);
-      }
-      else {
-        self::raise_error(array(
-          'code' => 500, 'type' => 'php',
-          'file' => __FILE__, 'line' => __LINE__,
-          'message' => "Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available"
-        ), true, true);
-      }
+    private function create_iv($size)
+    {
+        // mcrypt_create_iv() can be slow when system lacks entrophy
+        // we'll generate IV vector manually
+        $iv = '';
+        for ($i = 0; $i < $size; $i++) {
+            $iv .= chr(mt_rand(0, 255));
+        }
+
+        return $iv;
     }
 
-    return $base64 ? base64_encode($cipher) : $cipher;
-  }
-
-  /**
-   * Decrypt 3DES-encrypted string
-   *
-   * @param string $cipher encrypted text
-   * @param string $key encryption key to retrieve from the configuration, defaults to 'des_key'
-   * @param boolean $base64 whether or not input is base64-encoded
-   *
-   * @return string decrypted text
-   */
-  public function decrypt($cipher, $key = 'des_key', $base64 = true)
-  {
-    if (!$cipher)
-      return '';
-
-    $cipher = $base64 ? base64_decode($cipher) : $cipher;
-
-    if (function_exists('mcrypt_module_open') &&
-        ($td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_CBC, ""))) {
-      $iv_size = mcrypt_enc_get_iv_size($td);
-      $iv = substr($cipher, 0, $iv_size);
-
-      // session corruption? (#1485970)
-      if (strlen($iv) < $iv_size)
-        return '';
 
-      $cipher = substr($cipher, $iv_size);
-      mcrypt_generic_init($td, $this->config->get_crypto_key($key), $iv);
-      $clear = mdecrypt_generic($td, $cipher);
-      mcrypt_generic_deinit($td);
-      mcrypt_module_close($td);
-    }
-    else {
-      @include_once 'des.inc';
-
-      if (function_exists('des')) {
-        $des_iv_size = 8;
-        $iv = substr($cipher, 0, $des_iv_size);
-        $cipher = substr($cipher, $des_iv_size);
-        $clear = des($this->config->get_crypto_key($key), $cipher, 0, 1, $iv);
-      }
-      else {
-        self::raise_error(array(
-          'code' => 500, 'type' => 'php',
-          'file' => __FILE__, 'line' => __LINE__,
-          'message' => "Could not perform decryption; make sure Mcrypt is installed or lib/des.inc is available"
-        ), true, true);
-      }
+    /**
+     * Build a valid URL to this instance of Roundcube
+     *
+     * @param mixed Either a string with the action or url parameters as key-value pairs
+     * @return string Valid application URL
+     */
+    public function url($p)
+    {
+        // STUB: should be overloaded by the application
+        return '';
     }
 
-    /*-
-     * Trim PHP's padding and the canary byte; see note in
-     * rcube::encrypt() and http://php.net/mcrypt_generic#68082
+
+    /**
+     * Function to be executed in script shutdown
+     * Registered with register_shutdown_function()
      */
-    $clear = substr(rtrim($clear, "\0"), 0, -1);
-
-    return $clear;
-  }
-
-  /**
-   * Generates encryption initialization vector (IV)
-   *
-   * @param int Vector size
-   * @return string Vector string
-   */
-  private function create_iv($size)
-  {
-    // mcrypt_create_iv() can be slow when system lacks entrophy
-    // we'll generate IV vector manually
-    $iv = '';
-    for ($i = 0; $i < $size; $i++)
-        $iv .= chr(mt_rand(0, 255));
-    return $iv;
-  }
-
-
-  /**
-   * Build a valid URL to this instance of Roundcube
-   *
-   * @param mixed Either a string with the action or url parameters as key-value pairs
-   * @return string Valid application URL
-   */
-  public function url($p)
-  {
-      // STUB: should be overloaded by the application
-      return '';
-  }
-
-
-  /**
-   * Function to be executed in script shutdown
-   * Registered with register_shutdown_function()
-   */
-  public function shutdown()
-  {
-    foreach ($this->shutdown_functions as $function)
-      call_user_func($function);
-
-    if (is_object($this->smtp))
-      $this->smtp->disconnect();
-
-    foreach ($this->caches as $cache) {
-        if (is_object($cache))
-            $cache->close();
-    }
+    public function shutdown()
+    {
+        foreach ($this->shutdown_functions as $function) {
+            call_user_func($function);
+        }
+
+        if (is_object($this->smtp)) {
+            $this->smtp->disconnect();
+        }
+
+        foreach ($this->caches as $cache) {
+            if (is_object($cache)) {
+                $cache->close();
+            }
+        }
 
-    if (is_object($this->storage)) {
-      if ($this->expunge_cache)
-        $this->storage->expunge_cache();
-      $this->storage->close();
+        if (is_object($this->storage)) {
+            if ($this->expunge_cache) {
+                $this->storage->expunge_cache();
+            }
+            $this->storage->close();
+        }
     }
-  }
-
-
-  /**
-   * Registers shutdown function to be executed on shutdown.
-   * The functions will be executed before destroying any
-   * objects like smtp, imap, session, etc.
-   *
-   * @param callback Function callback
-   */
-  public function add_shutdown_function($function)
-  {
-    $this->shutdown_functions[] = $function;
-  }
-
-
-  /**
-   * Construct shell command, execute it and return output as string.
-   * Keywords {keyword} are replaced with arguments
-   *
-   * @param $cmd Format string with {keywords} to be replaced
-   * @param $values (zero, one or more arrays can be passed)
-   * @return output of command. shell errors not detectable
-   */
-  public static function exec(/* $cmd, $values1 = array(), ... */)
-  {
-    $args = func_get_args();
-    $cmd = array_shift($args);
-    $values = $replacements = array();
-
-    // merge values into one array
-    foreach ($args as $arg)
-      $values += (array)$arg;
-
-    preg_match_all('/({(-?)([a-z]\w*)})/', $cmd, $matches, PREG_SET_ORDER);
-    foreach ($matches as $tags) {
-      list(, $tag, $option, $key) = $tags;
-      $parts = array();
-
-      if ($option) {
-        foreach ((array)$values["-$key"] as $key => $value) {
-          if ($value === true || $value === false || $value === null)
-            $parts[] = $value ? $key : "";
-          else foreach ((array)$value as $val)
-            $parts[] = "$key " . escapeshellarg($val);
-        }
-      }
-      else {
-        foreach ((array)$values[$key] as $value)
-          $parts[] = escapeshellarg($value);
-      }
-
-      $replacements[$tag] = join(" ", $parts);
+
+
+    /**
+     * Registers shutdown function to be executed on shutdown.
+     * The functions will be executed before destroying any
+     * objects like smtp, imap, session, etc.
+     *
+     * @param callback Function callback
+     */
+    public function add_shutdown_function($function)
+    {
+        $this->shutdown_functions[] = $function;
     }
 
-    // use strtr behaviour of going through source string once
-    $cmd = strtr($cmd, $replacements);
 
-    return (string)shell_exec($cmd);
-  }
+    /**
+     * Construct shell command, execute it and return output as string.
+     * Keywords {keyword} are replaced with arguments
+     *
+     * @param $cmd Format string with {keywords} to be replaced
+     * @param $values (zero, one or more arrays can be passed)
+     *
+     * @return output of command. shell errors not detectable
+     */
+    public static function exec(/* $cmd, $values1 = array(), ... */)
+    {
+        $args   = func_get_args();
+        $cmd    = array_shift($args);
+        $values = $replacements = array();
+
+        // merge values into one array
+        foreach ($args as $arg) {
+            $values += (array)$arg;
+        }
+
+        preg_match_all('/({(-?)([a-z]\w*)})/', $cmd, $matches, PREG_SET_ORDER);
+        foreach ($matches as $tags) {
+            list(, $tag, $option, $key) = $tags;
+            $parts = array();
+
+            if ($option) {
+                foreach ((array)$values["-$key"] as $key => $value) {
+                    if ($value === true || $value === false || $value === null) {
+                        $parts[] = $value ? $key : "";
+                    }
+                    else {
+                        foreach ((array)$value as $val) {
+                            $parts[] = "$key " . escapeshellarg($val);
+                        }
+                    }
+                }
+            }
+            else {
+                foreach ((array)$values[$key] as $value) {
+                    $parts[] = escapeshellarg($value);
+                }
+            }
+
+            $replacements[$tag] = join(" ", $parts);
+        }
+
+        // use strtr behaviour of going through source string once
+        $cmd = strtr($cmd, $replacements);
+
+        return (string)shell_exec($cmd);
+    }
 
 
     /**
diff --git a/lib/ext/Roundcube/rcube_browser.php b/lib/ext/Roundcube/rcube_browser.php
index 06033e0..7cfae70 100644
--- a/lib/ext/Roundcube/rcube_browser.php
+++ b/lib/ext/Roundcube/rcube_browser.php
@@ -20,8 +20,6 @@
 */
 
 /**
- * rcube_browser
- *
  * Provide details about the client's browser based on the User-Agent header
  *
  * @package Core
diff --git a/lib/ext/Roundcube/rcube_cache.php b/lib/ext/Roundcube/rcube_cache.php
index cdb1dd5..4e60dea 100644
--- a/lib/ext/Roundcube/rcube_cache.php
+++ b/lib/ext/Roundcube/rcube_cache.php
@@ -254,7 +254,7 @@ class rcube_cache
             }
             else if ($this->type == 'apc') {
                 $data = apc_fetch($this->ckey($key));
-	        }
+            }
 
             if ($data) {
                 $md5sum = md5($data);
@@ -294,7 +294,7 @@ class rcube_cache
                 }
 
                 $this->cache[$key]      = $data;
-	            $this->cache_sums[$key] = $md5sum;
+                $this->cache_sums[$key] = $md5sum;
             }
             else {
                 $this->cache[$key] = null;
diff --git a/lib/ext/Roundcube/rcube_config.php b/lib/ext/Roundcube/rcube_config.php
index 2fe0d97..e299790 100644
--- a/lib/ext/Roundcube/rcube_config.php
+++ b/lib/ext/Roundcube/rcube_config.php
@@ -324,7 +324,7 @@ class rcube_config
         if (strlen($key) != 24) {
             rcube::raise_error(array(
                 'code' => 500, 'type' => 'php',
-	            'file' => __FILE__, 'line' => __LINE__,
+                'file' => __FILE__, 'line' => __LINE__,
                 'message' => "Configured crypto key '$key' is not exactly 24 bytes long"
             ), true, true);
         }
@@ -348,7 +348,7 @@ class rcube_config
             else
                 rcube::raise_error(array(
                     'code' => 500, 'type' => 'php',
-	                'file' => __FILE__, 'line' => __LINE__,
+                    'file' => __FILE__, 'line' => __LINE__,
                     'message' => "Invalid mail_header_delimiter setting"
                 ), true, false);
         }
diff --git a/lib/ext/Roundcube/rcube_db.php b/lib/ext/Roundcube/rcube_db.php
index 042ca15..f97d70a 100644
--- a/lib/ext/Roundcube/rcube_db.php
+++ b/lib/ext/Roundcube/rcube_db.php
@@ -576,6 +576,10 @@ class rcube_db
             return intval($input);
         }
 
+        if (is_null($input)) {
+            return 'NULL';
+        }
+
         // create DB handle if not available
         if (!$this->dbh) {
             $this->db_connect('r');
diff --git a/lib/ext/Roundcube/rcube_imap.php b/lib/ext/Roundcube/rcube_imap.php
index 4ab06cf..5dd9c12 100644
--- a/lib/ext/Roundcube/rcube_imap.php
+++ b/lib/ext/Roundcube/rcube_imap.php
@@ -359,11 +359,11 @@ class rcube_imap extends rcube_storage
 
         return array(
             $this->search_string,
-	        $this->search_set,
-        	$this->search_charset,
-        	$this->search_sort_field,
-        	$this->search_sorted,
-	    );
+            $this->search_set,
+            $this->search_charset,
+            $this->search_sort_field,
+            $this->search_sorted,
+        );
     }
 
 
@@ -2138,14 +2138,17 @@ class rcube_imap extends rcube_storage
 
     /**
      * Sends the whole message source to stdout
+     *
+     * @param int  $uid       Message UID
+     * @param bool $formatted Enables line-ending formatting
      */
-    public function print_raw_body($uid)
+    public function print_raw_body($uid, $formatted = true)
     {
         if (!$this->check_connection()) {
             return;
         }
 
-        $this->conn->handlePartBody($this->folder, $uid, true, NULL, NULL, true);
+        $this->conn->handlePartBody($this->folder, $uid, true, null, null, true, null, $formatted);
     }
 
 
@@ -3847,12 +3850,12 @@ class rcube_imap extends rcube_storage
     protected function rsort($folder, $delimiter, &$list, &$out)
     {
         while (list($key, $name) = each($list)) {
-	        if (strpos($name, $folder.$delimiter) === 0) {
-	            // set the type of folder name variable (#1485527)
-    	        $out[] = (string) $name;
-	            unset($list[$key]);
-	            $this->rsort($name, $delimiter, $list, $out);
-	        }
+            if (strpos($name, $folder.$delimiter) === 0) {
+                // set the type of folder name variable (#1485527)
+                $out[] = (string) $name;
+                unset($list[$key]);
+                $this->rsort($name, $delimiter, $list, $out);
+            }
         }
         reset($list);
     }
diff --git a/lib/ext/Roundcube/rcube_imap_generic.php b/lib/ext/Roundcube/rcube_imap_generic.php
index 8d956f2..915a11a 100644
--- a/lib/ext/Roundcube/rcube_imap_generic.php
+++ b/lib/ext/Roundcube/rcube_imap_generic.php
@@ -2377,7 +2377,7 @@ class rcube_imap_generic
         return $this->handlePartBody($mailbox, $id, $is_uid, $part);
     }
 
-    function handlePartBody($mailbox, $id, $is_uid=false, $part='', $encoding=NULL, $print=NULL, $file=NULL)
+    function handlePartBody($mailbox, $id, $is_uid=false, $part='', $encoding=NULL, $print=NULL, $file=NULL, $formatted=true)
     {
         if (!$this->select($mailbox)) {
             return false;
@@ -2494,7 +2494,7 @@ class rcube_imap_generic
                         continue;
                     $line = convert_uudecode($line);
                 // default
-                } else {
+                } else if ($formatted) {
                     $line = rtrim($line, "\t\r\n\0\x0B") . "\n";
                 }
 
diff --git a/lib/ext/Roundcube/rcube_ldap.php b/lib/ext/Roundcube/rcube_ldap.php
index 5561613..ad2ccdd 100644
--- a/lib/ext/Roundcube/rcube_ldap.php
+++ b/lib/ext/Roundcube/rcube_ldap.php
@@ -139,6 +139,11 @@ class rcube_ldap extends rcube_addressbook
                     unset($this->coltypes[$childcol]);  // remove address child col from global coltypes list
                 }
             }
+
+            // at least one address type must be specified
+            if (empty($this->coltypes['address']['subtypes'])) {
+                $this->coltypes['address']['subtypes'] = array('home');
+            }
         }
         else if ($this->coltypes['address']) {
             $this->coltypes['address'] += array('type' => 'textarea', 'childs' => null, 'size' => 40);
@@ -2027,12 +2032,12 @@ class rcube_ldap extends rcube_addressbook
         # a0 = type context-specific/constructed with a length of 06 (6) bytes following
         # 02 = type integer with 2 bytes following (offset): 01 01 (ie 1)
         # 02 = type integer with 2 bytes following (contentCount):  01 00
-        
+
         # whith a search string present:
         # 81 = type context-specific/constructed with a length of 04 (4) bytes following (the length will change here)
         # 81 indicates a user string is present where as a a0 indicates just a offset search
         # 81 = type context-specific/constructed with a length of 06 (6) bytes following
-        
+
         # the following info was taken from the ISO/IEC 8825-1:2003 x.690 standard re: the
         # encoding of integer values (note: these values are in
         # two-complement form so since offset will never be negative bit 8 of the
@@ -2042,7 +2047,7 @@ class rcube_ldap extends rcube_addressbook
         # of the second (to the left of first octet) octet:
         # a) shall not all be ones; and
         # b) shall not all be zero
-        
+
         if ($search)
         {
             $search = preg_replace('/[^-[:alpha:] ,.()0-9]+/', '', $search);
@@ -2062,7 +2067,7 @@ class rcube_ldap extends rcube_addressbook
             // now compute length over $str
             $str = self::_ber_addseq($str, 'a0');
         }
-        
+
         // now tack on records per page
         $str = "020100" . self::_ber_addseq(self::_ber_encode_int($rpp-1), '02') . $str;
 
diff --git a/lib/ext/Roundcube/rcube_message.php b/lib/ext/Roundcube/rcube_message.php
index f798468..f550b57 100644
--- a/lib/ext/Roundcube/rcube_message.php
+++ b/lib/ext/Roundcube/rcube_message.php
@@ -55,8 +55,8 @@ class rcube_message
     public $uid = null;
     public $headers;
     public $parts = array();
-    public $inline_parts = array();
     public $mime_parts = array();
+    public $inline_parts = array();
     public $attachments = array();
     public $subject = '';
     public $sender = null;
diff --git a/lib/ext/Roundcube/rcube_output_html.php b/lib/ext/Roundcube/rcube_output_html.php
index 30512d2..a071ee3 100644
--- a/lib/ext/Roundcube/rcube_output_html.php
+++ b/lib/ext/Roundcube/rcube_output_html.php
@@ -67,6 +67,11 @@ class rcube_output_html extends rcube_output
         $this->set_env('task', $task);
         $this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin'));
 
+        // add cookie info
+        $this->set_env('cookie_domain', ini_get('session.cookie_domain'));
+        $this->set_env('cookie_path', ini_get('session.cookie_path'));
+        $this->set_env('cookie_secure', ini_get('session.cookie_secure'));
+
         // load the correct skin (in case user-defined)
         $skin = $this->config->get('skin');
         $this->set_skin($skin);
@@ -1378,6 +1383,9 @@ class rcube_output_html extends rcube_output
         if (empty($url) && !preg_match('/_(task|action)=logout/', $_SERVER['QUERY_STRING']))
             $url = $_SERVER['QUERY_STRING'];
 
+        // Disable autocapitalization on iPad/iPhone (#1488609)
+        $attrib['autocapitalize'] = 'off';
+
         // set atocomplete attribute
         $user_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
         $host_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
diff --git a/lib/ext/Roundcube/rcube_plugin.php b/lib/ext/Roundcube/rcube_plugin.php
index b1ec32a..c103573 100644
--- a/lib/ext/Roundcube/rcube_plugin.php
+++ b/lib/ext/Roundcube/rcube_plugin.php
@@ -336,7 +336,7 @@ abstract class rcube_plugin
   public function local_skin_path()
   {
     $rcmail = rcube::get_instance();
-    foreach (array($rcmail->config->get('skin'),'default') as $skin) {
+    foreach (array($rcmail->config->get('skin'), 'larry') as $skin) {
       $skin_path = 'skins/' . $skin;
       if (is_dir(realpath(slashify($this->home) . $skin_path)))
         break;
diff --git a/lib/ext/Roundcube/rcube_plugin_api.php b/lib/ext/Roundcube/rcube_plugin_api.php
index 8c1e125..9ef68ca 100644
--- a/lib/ext/Roundcube/rcube_plugin_api.php
+++ b/lib/ext/Roundcube/rcube_plugin_api.php
@@ -32,12 +32,12 @@ if (!defined('RCMAIL_PLUGINS_DIR'))
 class rcube_plugin_api
 {
   static private $instance;
-  
+
   public $dir;
   public $url = 'plugins/';
   public $task = '';
   public $output;
-  
+
   public $handlers = array();
   private $plugins = array();
   private $tasks = array();
diff --git a/lib/ext/Roundcube/rcube_session.php b/lib/ext/Roundcube/rcube_session.php
index b6a0ccf..6192466 100644
--- a/lib/ext/Roundcube/rcube_session.php
+++ b/lib/ext/Roundcube/rcube_session.php
@@ -531,7 +531,7 @@ class rcube_session
   public function set_keep_alive($keep_alive)
   {
     $this->keep_alive = $keep_alive;
-    
+
     if ($this->lifetime < $keep_alive)
         $this->set_lifetime($keep_alive + 30);
   }
@@ -551,7 +551,7 @@ class rcube_session
   {
     return $this->ip;
   }
-  
+
   /**
    * Setter for cookie encryption secret
    */
@@ -568,7 +568,8 @@ class rcube_session
   {
     $this->ip_check = $check;
   }
-  
+
+
   /**
    * Setter for the cookie name used for session cookie
    */
@@ -605,7 +606,7 @@ class rcube_session
           $result = true;
         }
       }
-	}
+    }
 
     if (!$result)
       $this->log("Session authentication failed for " . $this->key . "; invalid auth cookie sent; timeslot = " . date('Y-m-d H:i:s', $prev));
@@ -637,7 +638,7 @@ class rcube_session
   }
 
   /**
-   * 
+   * Writes debug information to the log
    */
   function log($line)
   {
diff --git a/lib/ext/Roundcube/rcube_shared.inc b/lib/ext/Roundcube/rcube_shared.inc
index 85f2784..5b839d8 100644
--- a/lib/ext/Roundcube/rcube_shared.inc
+++ b/lib/ext/Roundcube/rcube_shared.inc
@@ -306,6 +306,29 @@ function format_email_recipient($email, $name = '')
 
 
 /**
+ * Format e-mail address
+ *
+ * @param string $email E-mail address
+ *
+ * @return string Formatted e-mail address
+ */
+function format_email($email)
+{
+    $email = trim($email);
+    $parts = explode('@', $email);
+    $count = count($parts);
+
+    if ($count > 1) {
+        $parts[$count-1] = mb_strtolower($parts[$count-1]);
+
+        $email = implode('@', $parts);
+    }
+
+    return $email;
+}
+
+
+/**
  * mbstring replacement functions
  */
 if (!extension_loaded('mbstring'))
diff --git a/lib/ext/Roundcube/rcube_smtp.php b/lib/ext/Roundcube/rcube_smtp.php
index e574824..b28be52 100644
--- a/lib/ext/Roundcube/rcube_smtp.php
+++ b/lib/ext/Roundcube/rcube_smtp.php
@@ -423,7 +423,7 @@ class rcube_smtp
         $lines[] = $key . ': ' . $value;
       }
     }
-    
+
     return array($from, join(SMTP_MIME_CRLF, $lines) . SMTP_MIME_CRLF);
   }
 
diff --git a/lib/ext/Roundcube/rcube_storage.php b/lib/ext/Roundcube/rcube_storage.php
index 1075b0f..768a26d 100644
--- a/lib/ext/Roundcube/rcube_storage.php
+++ b/lib/ext/Roundcube/rcube_storage.php
@@ -502,8 +502,11 @@ abstract class rcube_storage
 
     /**
      * Sends the whole message source to stdout
+     *
+     * @param int  $uid       Message UID
+     * @param bool $formatted Enables line-ending formatting
      */
-    abstract function print_raw_body($uid);
+    abstract function print_raw_body($uid, $formatted = true);
 
 
     /**
diff --git a/lib/ext/Roundcube/rcube_user.php b/lib/ext/Roundcube/rcube_user.php
index 644d24b..29eb0f2 100644
--- a/lib/ext/Roundcube/rcube_user.php
+++ b/lib/ext/Roundcube/rcube_user.php
@@ -443,7 +443,7 @@ class rcube_user
         }
 
         $data = $rcube->plugins->exec_hook('user_create',
-	        array('user'=>$user, 'user_name'=>$user_name, 'user_email'=>$user_email, 'host'=>$host));
+            array('user'=>$user, 'user_name'=>$user_name, 'user_email'=>$user_email, 'host'=>$host));
 
         // plugin aborted this operation
         if ($data['abort'])
diff --git a/lib/ext/Roundcube/rcube_utils.php b/lib/ext/Roundcube/rcube_utils.php
index 9344a92..9f18b79 100644
--- a/lib/ext/Roundcube/rcube_utils.php
+++ b/lib/ext/Roundcube/rcube_utils.php
@@ -84,9 +84,9 @@ class rcube_utils
 
         // from PEAR::Validate
         $regexp = '&^(?:
-	        ("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+")| 			 	            #1 quoted name
-	        ([-\w!\#\$%\&\'*+~/^`|{}=]+(?:\.[-\w!\#\$%\&\'*+~/^`|{}=]+)*)) 	#2 OR dot-atom (RFC5322)
-	        $&xi';
+            ("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+")|                             #1 quoted name
+            ([-\w!\#\$%\&\'*+~/^`|{}=]+(?:\.[-\w!\#\$%\&\'*+~/^`|{}=]+)*))  #2 OR dot-atom (RFC5322)
+            $&xi';
 
         if (!preg_match($regexp, $local_part)) {
             return false;
@@ -110,6 +110,11 @@ class rcube_utils
                 }
             }
 
+            // last domain part
+            if (preg_match('/[^a-zA-Z]/', array_pop($domain_array))) {
+                return false;
+            }
+
             $rcube = rcube::get_instance();
 
             if (!$dns_check || !$rcube->config->get('email_dns_check')) {
@@ -617,8 +622,8 @@ class rcube_utils
         // %n - host
         $n = preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME']);
         // %t - host name without first part, e.g. %n=mail.domain.tld, %t=domain.tld
-	$t = preg_replace('/^[^\.]+\./', '', $n);
-	// %d - domain name without first part
+        $t = preg_replace('/^[^\.]+\./', '', $n);
+        // %d - domain name without first part
         $d = preg_replace('/^[^\.]+\./', '', $_SERVER['HTTP_HOST']);
         // %h - IMAP host
         $h = $_SESSION['storage_host'] ? $_SESSION['storage_host'] : $host;


commit 4701c410d0f4e74a2259aec4ed5698e1f47fbc14
Author: Aleksander Machniak <alec at alec.pl>
Date:   Tue Aug 21 14:18:39 2012 +0200

    Update login_lc option handling

diff --git a/lib/kolab_sync.php b/lib/kolab_sync.php
index 741fb04..35f2f83 100644
--- a/lib/kolab_sync.php
+++ b/lib/kolab_sync.php
@@ -259,18 +259,20 @@ class kolab_sync extends rcube
         // Convert username to lowercase. If storage backend
         // is case-insensitive we need to store always the same username
         if ($login_lc) {
-            $username = mb_strtolower($username);
+            if ($login_lc == 2 || $login_lc === true) {
+                $username = mb_strtolower($username);
+            }
+            else if (strpos($username, '@')) {
+                // lowercase domain name
+                list($local, $domain) = explode('@', $username);
+                $username = $local . '@' . mb_strtolower($domain);
+            }
         }
 
         // Here we need IDNA ASCII
         // Only rcube_contacts class is using domain names in Unicode
-        $host = rcube_utils::idn_to_ascii($host);
-        if (strpos($username, '@')) {
-            // lowercase domain name
-            list($local, $domain) = explode('@', $username);
-            $username = $local . '@' . mb_strtolower($domain);
-            $username = rcube_utils::idn_to_ascii($username);
-        }
+        $host     = rcube_utils::idn_to_ascii($host);
+        $username = rcube_utils::idn_to_ascii($username);
 
         // user already registered?
         $user = rcube_user::query($username, $host);


commit 57eca016cbea5a062b763c259f56824c72ef8462
Author: Aleksander Machniak <alec at alec.pl>
Date:   Tue Aug 21 14:15:47 2012 +0200

    Cleanup, remove useless code

diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index b589714..0517e69 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -23,6 +23,9 @@
  +--------------------------------------------------------------------------+
 */
 
+/**
+ * Base class for Syncroton data backends
+ */
 abstract class kolab_sync_data implements Syncroton_Data_IData
 {
     /**
@@ -75,13 +78,6 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
     protected $folderType;
 
     /**
-     * Default namespace
-     *
-     * @var string
-    */
-    protected $defaultNS = 'Calendar';
-
-    /**
      * Internal cache for kolab_storage folder objects
      *
      * @var array
@@ -374,17 +370,6 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
      */
     public function updateEntry($folderId, $serverId, Syncroton_Model_IEntry $entry)
     {
-/* @TODO:
-    Certain in-schema properties remain untouched in the following three cases:
-
-        If there is only an email:Flag ([MS-ASEMAIL] section 2.2.2.27), email:Read ([MS-ASEMAIL] section 2.2.2.47), or email:Categories ([MS-ASEMAIL] section 2.2.2.9) change (that is, if only an email:Flag, email:Categories or email:Read element is present), all other properties will remain unchanged and the client SHOULD NOT send the other elements in the request. If all the other elements are sent, extra bandwidth is used, but no errors occur.
-
-        If a calendar:Exceptions ([MS-ASCAL] section 2.2.2.20) node is not specified, the properties for that calendar:Exceptions node will remain unchanged. If a calendar:Exception ([MS-ASCAL] section 2.2.2.19) node within the calendar:Exceptions node is not present, that particular exception will remain unchanged.
-
-        If the airsyncbase:Body, airsyncbase:Data, or contacts:Picture elements are not present, the corresponding properties will remain unchanged.
-
-    In all other cases, if an in-schema property is not specified in a change request, the property is actively deleted from the item on the server. A client MUST be aware of this when it is sending Sync requests; otherwise, data can be unintentionally removed.
-*/
         $oldEntry = $this->getObject($folderId, $serverId);
 
         if (empty($oldEntry)) {
@@ -488,19 +473,6 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
      */
     protected function filter($filter_type = 0)
     {
-    /*
-    From Syncroton_Command_Sync:
-        const FILTER_NOTHING        = 0;
-        const FILTER_1_DAY_BACK     = 1;
-        const FILTER_3_DAYS_BACK    = 2;
-        const FILTER_1_WEEK_BACK    = 3;
-        const FILTER_2_WEEKS_BACK   = 4;
-        const FILTER_1_MONTH_BACK   = 5;
-        const FILTER_3_MONTHS_BACK  = 6;
-        const FILTER_6_MONTHS_BACK  = 7;
-        const FILTER_INCOMPLETE     = 8;
-    Doc: MS-ASCMD 2.2.3.64.2 FilterType (Sync)
-    */
         // overwrite by child class according to specified type
         return array();
     }
@@ -528,7 +500,6 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
         return $result;
     }
 
-
     /**
      * get count of entries changed between two dates
      *
@@ -941,33 +912,6 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
         }
 
         return new Syncroton_Model_EmailBody($params);
-/*
-        // strip off any non printable control characters
-        $value = self::quote($value);
-
-        if ($this->asversion >= 12) {
-            $body = $domParent->appendChild(new DOMElement('Body', null, 'uri:AirSyncBase'));
-
-            $body->appendChild(new DOMElement('Type', 1, 'uri:AirSyncBase'));
-
-            $dataTag = new DOMElement('Data', null, 'uri:AirSyncBase');
-
-            // ... append it to parent node aka append it to the document ...
-            $body->appendChild($dataTag);
-
-            // ... and now add the content (DomText takes care of special chars)
-            $dataTag->appendChild(new DOMText($value));
-        } else {
-            // create a new DOMElement ...
-            $node = new DOMElement('Body', null, 'uri:' . $this->defaultNS);
-
-            // ... append it to parent node aka append it to the document ...
-            $domParent->appendChild($node);
-
-            // ... and now add the content (DomText takes care of special chars)
-            $node->appendChild(new DOMText($value));
-        }
-*/
     }
 
     /**
@@ -980,18 +924,6 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
         if ($data && $data->Data) {
             return $data->Data;
         }
-/*
-        if ($this->asversion >= 12) {
-            $airSyncBase = $data->children('uri:AirSyncBase');
-
-            if (isset($airSyncBase->Body)) {
-                return (string)$airSyncBase->Body->Data;
-            }
-        }
-        else if (isset($classData->Body)) {
-            return (string) $classData->Body;
-        }
-*/
     }
 
     /**
@@ -1249,7 +1181,6 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
         return $result;
     }
 
-
     /**
      * Convert bitmask used by ActiveSync to string of days (TU,TH)
      *
diff --git a/lib/kolab_sync_data_calendar.php b/lib/kolab_sync_data_calendar.php
index 2a3d66d..26e7975 100644
--- a/lib/kolab_sync_data_calendar.php
+++ b/lib/kolab_sync_data_calendar.php
@@ -24,7 +24,7 @@
 */
 
 /**
- *
+ * Calendar (Events) data class for Syncroton
  */
 class kolab_sync_data_calendar extends kolab_sync_data
 {
@@ -104,13 +104,6 @@ class kolab_sync_data_calendar extends kolab_sync_data
     protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_CALENDAR_USER_CREATED;
 
     /**
-     * Default namespace
-     *
-     * @var string
-     */
-    protected $defaultNS = 'Calendar';
-
-    /**
      * attendee status
      */
     const ATTENDEE_STATUS_UNKNOWN       = 0;
diff --git a/lib/kolab_sync_data_contacts.php b/lib/kolab_sync_data_contacts.php
index 37142c7..58adf36 100644
--- a/lib/kolab_sync_data_contacts.php
+++ b/lib/kolab_sync_data_contacts.php
@@ -24,7 +24,7 @@
 */
 
 /**
- *
+ * COntacts data class for Syncroton
  */
 class kolab_sync_data_contacts extends kolab_sync_data
 {
@@ -129,13 +129,6 @@ class kolab_sync_data_contacts extends kolab_sync_data
      */
     protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED;
 
-    /**
-     * Default namespace
-     *
-     * @var string
-     */
-    protected $defaultNS = 'Contacts';
-
 
     /**
      * Creates model object
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 582f171..f8b7df8 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -24,7 +24,7 @@
 */
 
 /**
- *
+ * Email data class for Syncroton
  */
 class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_IDataSearch
 {
@@ -79,13 +79,6 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
      */
     protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_MAIL_USER_CREATED;
 
-    /**
-     * Default namespace
-     *
-     * @var string
-     */
-    protected $defaultNS = 'Email';
-
 
     /**
      * the constructor
diff --git a/lib/kolab_sync_data_gal.php b/lib/kolab_sync_data_gal.php
index 66d06da..e830790 100644
--- a/lib/kolab_sync_data_gal.php
+++ b/lib/kolab_sync_data_gal.php
@@ -24,7 +24,7 @@
 */
 
 /**
- * GAL (Global Address List) data backend
+ * GAL (Global Address List) data backend for Syncroton
  */
 class kolab_sync_data_gal extends kolab_sync_data implements Syncroton_Data_IDataSearch
 {
@@ -89,14 +89,6 @@ class kolab_sync_data_gal extends kolab_sync_data implements Syncroton_Data_IDat
      */
     protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_CONTACT_USER_CREATED;
 
-    /**
-     * Default namespace
-     *
-     * @var string
-     */
-    protected $defaultNS = 'Contacts';
-
-
 
     /**
      * the constructor
diff --git a/lib/kolab_sync_data_tasks.php b/lib/kolab_sync_data_tasks.php
index 099150a..be94f59 100644
--- a/lib/kolab_sync_data_tasks.php
+++ b/lib/kolab_sync_data_tasks.php
@@ -24,7 +24,7 @@
 */
 
 /**
- *
+ * Tasks data class for Syncroton
  */
 class kolab_sync_data_tasks extends kolab_sync_data
 {
@@ -96,13 +96,6 @@ class kolab_sync_data_tasks extends kolab_sync_data
      */
     protected $folderType = Syncroton_Command_FolderSync::FOLDERTYPE_TASK_USER_CREATED;
 
-    /**
-     * Default namespace
-     *
-     * @var string
-     */
-    protected $defaultNS = 'Tasks';
-
 
     /**
      * Appends contact data to xml element


commit 19efc41f2ff5647e4f801daf1f29cc59390e75f3
Author: Aleksander Machniak <alec at alec.pl>
Date:   Tue Aug 21 11:58:24 2012 +0200

    Code cleanup, fixes in empty values handling

diff --git a/lib/kolab_sync_data_calendar.php b/lib/kolab_sync_data_calendar.php
index 9abc0d7..2a3d66d 100644
--- a/lib/kolab_sync_data_calendar.php
+++ b/lib/kolab_sync_data_calendar.php
@@ -406,6 +406,10 @@ class kolab_sync_data_calendar extends kolab_sync_data
 
             case 'description':
                 $value = $this->getBody($value);
+                // If description isn't specified keep old description
+                if ($value === null) {
+                    continue 2;
+                }
                 break;
             }
 
diff --git a/lib/kolab_sync_data_contacts.php b/lib/kolab_sync_data_contacts.php
index ff21b41..37142c7 100644
--- a/lib/kolab_sync_data_contacts.php
+++ b/lib/kolab_sync_data_contacts.php
@@ -60,11 +60,11 @@ class kolab_sync_data_contacts extends kolab_sync_data
         //'FileAs'                => 'fileas', //@TODO: ?
         'FirstName'             => 'firstname',
         //'Home2PhoneNumber'      => 'home2phonenumber',
-        'HomeAddressCity'              => 'address.home.locality',
-        'HomeAddressCountry'           => 'address.home.country',
-        'HomeAddressPostalCode'        => 'address.home.code',
-        'HomeAddressState'             => 'address.home.region',
-        'HomeAddressStreet'            => 'address.home.street',
+        'HomeAddressCity'       => 'address.home.locality',
+        'HomeAddressCountry'    => 'address.home.country',
+        'HomeAddressPostalCode' => 'address.home.code',
+        'HomeAddressState'      => 'address.home.region',
+        'HomeAddressStreet'     => 'address.home.street',
         'HomeFaxNumber'         => 'phone.homefax.number',
         'HomePhoneNumber'       => 'phone.home.number',
         'JobTitle'              => 'jobtitle',
@@ -89,16 +89,16 @@ class kolab_sync_data_contacts extends kolab_sync_data
         //'Rtf'                   => 'rtf',
         'Picture'               => 'photo',
         // Mapping from ActiveSync Contacts2 namespace fields
-        //'CustomerId'       => 'customerid',
-        //'GovernmentId'     => 'governmentid',
-        'IMAddress'        => 'im:0',
-        'IMAddress2'       => 'im:1',
-        'IMAddress3'       => 'im:2',
-        'ManagerName'      => 'manager:0',
-        //'CompanyMainPhone' => 'companymainphone',
-        //'AccountName'      => 'accountname',
-        'NickName'         => 'nickname',
-        //'MMS'              => 'mms',
+        //'CustomerId'            => 'customerid',
+        //'GovernmentId'          => 'governmentid',
+        'IMAddress'             => 'im:0',
+        'IMAddress2'            => 'im:1',
+        'IMAddress3'            => 'im:2',
+        'ManagerName'           => 'manager:0',
+        //'CompanyMainPhone'      => 'companymainphone',
+        //'AccountName'           => 'accountname',
+        'NickName'              => 'nickname',
+        //'MMS'                   => 'mms',
     );
 
     /**
@@ -226,6 +226,17 @@ class kolab_sync_data_contacts extends kolab_sync_data
 
             case 'notes':
                 $value = $this->getBody($value);
+                // If note isn't specified keep old note
+                if ($value === null) {
+                    continue 2;
+                }
+                break;
+
+            case 'photo':
+                // If photo isn't specified keep old photo
+                if ($value === null) {
+                    continue 2;
+                }
                 break;
             }
 
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 8804cd6..582f171 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -250,16 +250,6 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
         // Message body
         if ($airSyncBaseType == 4) {
             $messageBody = $this->storage->get_raw_body($message->uid);
-/*
-            if ($this->asversion < 12) {
-                // if the email contains non 7bit ascii characters we can't transfer
-                // them via MIMEData xml and we need to fall back to plain text
-                if (preg_match('/[^\x00-\x7F]/', $messageBody)) {
-                    $airSyncBaseType = 1;
-                    $messageBody     = $this->getMessageBody($message);
-                }
-            }
-*/
         }
         else {
             $messageBody = $this->getMessageBody($message, $airSyncBaseType == 2);
@@ -289,31 +279,6 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
             }
 
             $result['Body'] = $this->setBody($messageBody, $body_params);
-/*
-            if ($this->asversion >= 12) {
-                $body = $domParrent->appendChild(new DOMElement('Body', null, 'uri:AirSyncBase'));
-                $body->appendChild(new DOMElement('Type', $airSyncBaseType, 'uri:AirSyncBase'));
-                $body->appendChild(new DOMElement('Truncated', $isTruncacted, 'uri:AirSyncBase'));
-                $body->appendChild(new DOMElement('EstimatedDataSize', $data->size, 'uri:AirSyncBase'));
-
-                $dataTag = $body->appendChild(new DOMElement('Data', null, 'uri:AirSyncBase'));
-                $dataTag->appendChild(new DOMText($messageBody));
-            }
-            else {
-                if ($airSyncBaseType == 4) {
-                    $domParrent->appendChild(new DOMElement('MIMETruncated', $isTruncacted, 'uri:Email'));
-
-                    $body = $domParrent->appendChild(new DOMElement('MIMEData', null, 'uri:Email'));
-                    $body->appendChild(new DOMText($messageBody));
-                }
-                else {
-                    $domParrent->appendChild(new DOMElement('BodyTruncated', $isTruncacted, 'uri:Email'));
-
-                    $body = $domParrent->appendChild(new DOMElement('Body', null, 'uri:Email'));
-                    $body->appendChild(new DOMText($messageBody));
-                }
-            }
-*/
         }
 
         $result['NativeBodyType'] = intval($message->has_html_part(false));
diff --git a/lib/kolab_sync_data_tasks.php b/lib/kolab_sync_data_tasks.php
index 5e13945..099150a 100644
--- a/lib/kolab_sync_data_tasks.php
+++ b/lib/kolab_sync_data_tasks.php
@@ -196,6 +196,10 @@ class kolab_sync_data_tasks extends kolab_sync_data
 
             case 'description':
                 $value = $this->getBody($value);
+                // If description isn't specified keep old description
+                if ($value === null) {
+                    continue 2;
+                }
                 break;
 
             case 'priority':





More information about the commits mailing list