lib/kolab_sync_data_email.php lib/kolab_sync_data.php lib/plugins

Aleksander Machniak machniak at kolabsys.com
Thu Jan 2 13:30:58 CET 2014


 lib/kolab_sync_data.php                          |   87 +++++++++++++++--------
 lib/kolab_sync_data_email.php                    |   11 ++
 lib/plugins/libkolab/lib/kolab_storage_cache.php |   25 +++++-
 3 files changed, 88 insertions(+), 35 deletions(-)

New commits:
commit e46f49b16a35c3cd01c492d022f6965be3fe408e
Author: Aleksander Machniak <alec at alec.pl>
Date:   Thu Jan 2 13:30:31 2014 +0100

    Improve errors handling to prevent removing all objects from the device (Bug #2698)

diff --git a/lib/kolab_sync_data.php b/lib/kolab_sync_data.php
index eae8630..15db5bd 100644
--- a/lib/kolab_sync_data.php
+++ b/lib/kolab_sync_data.php
@@ -536,6 +536,7 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
         }
 
         $result = $result_type == self::RESULT_COUNT ? 0 : array();
+        $found  = 0;
 
         foreach ($folders as $folderid) {
             $foldername = $this->backend->folder_id2name($folderid, $this->device->deviceid);
@@ -550,23 +551,51 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
                 continue;
             }
 
+            $found++;
+            $error = false;
+
             switch ($result_type) {
             case self::RESULT_COUNT:
-                $result += (int) $folder->count($filter);
+                $count = $folder->count($filter);
+
+                if ($count === null || $count === false) {
+                    $error = true;
+                }
+                else {
+                    $result += (int) count;
+                }
                 break;
 
             case self::RESULT_UID:
-                if ($uids = $folder->get_uids($filter)) {
+                $uids = $folder->get_uids($filter);
+
+                if (!is_array($uids)) {
+                    $error = true;
+                }
+                else {
                     $result = array_merge($result, $uids);
                 }
                 break;
 
             case self::RESULT_OBJECT:
             default:
-                if ($objects = $folder->select($filter)) {
+                $objects = $folder->select($filter);
+
+                if (!is_array($objects)) {
+                    $error = true;
+                }
+                else {
                     $result = array_merge($result, $objects);
                 }
             }
+
+            if ($error) {
+                throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
+            }
+        }
+
+        if (!$found) {
+            throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
         }
 
         return $result;
@@ -586,58 +615,54 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
     }
 
     /**
-     * get all entries changed between to dates
+     * get all entries changed between two dates
      *
-     * @param string $folderId
+     * @param string   $folderId
      * @param DateTime $start
      * @param DateTime $end
-     * @param int $filterType
+     * @param int      $filterType
      *
      * @return array
      */
     public function getChangedEntries($folderId, DateTime $start, DateTime $end = null, $filter_type = null)
     {
-        $filter = $this->filter($filter_type);
+        $filter   = $this->filter($filter_type);
         $filter[] = array('changed', '>', $start);
 
         if ($end) {
             $filter[] = array('changed', '<=', $end);
         }
 
-        $result = $this->searchEntries($folderId, $filter, self::RESULT_UID);
-
-        return $result;
+        return $this->searchEntries($folderId, $filter, self::RESULT_UID);
     }
 
     /**
      * get count of entries changed between two dates
      *
-     * @param string $folderId
+     * @param string   $folderId
      * @param DateTime $start
      * @param DateTime $end
-     * @param int $filterType
+     * @param int      $filterType
      *
      * @return int
      */
     public function getChangedEntriesCount($folderId, DateTime $start, DateTime $end = null, $filter_type = null)
     {
-        $filter = $this->filter($filter_type);
+        $filter   = $this->filter($filter_type);
         $filter[] = array('changed', '>', $start);
 
         if ($end) {
             $filter[] = array('changed', '<=', $end);
         }
 
-        $result = $this->searchEntries($folderId, $filter, self::RESULT_COUNT);
-
-        return $result;
+        return $this->searchEntries($folderId, $filter, self::RESULT_COUNT);
     }
 
     /**
      * get id's of all entries available on the server
      *
      * @param string $folderId
-     * @param int $filterType
+     * @param int    $filterType
      *
      * @return array
      */
@@ -696,21 +721,27 @@ abstract class kolab_sync_data implements Syncroton_Data_IData
      */
     public function hasChanges(Syncroton_Backend_IContent $contentBackend, Syncroton_Model_IFolder $folder, Syncroton_Model_ISyncState $syncState)
     {
-        if ($this->getChangedEntriesCount($folder->serverId, $syncState->lastsync, null, $folder->lastfiltertype)) {
-            return true;
-        }
+        try {
+            if ($this->getChangedEntriesCount($folder->serverId, $syncState->lastsync, null, $folder->lastfiltertype)) {
+                return true;
+            }
 
-        $allClientEntries = $contentBackend->getFolderState($this->device, $folder);
+            $allClientEntries = $contentBackend->getFolderState($this->device, $folder);
 
-        // @TODO: Consider looping over all folders here, not in getServerEntries() and
-        // getChangedEntriesCount(). This way we could break the loop and not check all folders
-        // or at least skip redundant cache sync of the same folder
-        $allServerEntries = $this->getServerEntries($folder->serverId, $folder->lastfiltertype);
+            // @TODO: Consider looping over all folders here, not in getServerEntries() and
+            // getChangedEntriesCount(). This way we could break the loop and not check all folders
+            // or at least skip redundant cache sync of the same folder
+            $allServerEntries = $this->getServerEntries($folder->serverId, $folder->lastfiltertype);
 
-        $addedEntries   = array_diff($allServerEntries, $allClientEntries);
-        $deletedEntries = array_diff($allClientEntries, $allServerEntries);
+            $addedEntries   = array_diff($allServerEntries, $allClientEntries);
+            $deletedEntries = array_diff($allClientEntries, $allServerEntries);
 
-        return count($addedEntries) > 0 || count($deletedEntries) > 0;
+            return count($addedEntries) > 0 || count($deletedEntries) > 0;
+        }
+        catch (Exception $e) {
+            // return "no changes" if something failed
+            return false;
+        }
     }
 
     /**
diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php
index 18b8b54..3d7f835 100644
--- a/lib/kolab_sync_data_email.php
+++ b/lib/kolab_sync_data_email.php
@@ -779,6 +779,7 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
         $result = $result_type == self::RESULT_COUNT ? 0 : array();
         // no sorting for best performance
         $sort_by = null;
+        $found   = 0;
 
         foreach ($folders as $folder_id) {
             $foldername = $this->backend->folder_id2name($folder_id, $this->device->deviceid);
@@ -787,6 +788,8 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
                 continue;
             }
 
+            $found++;
+
             $this->storage->set_folder($foldername);
 
             // Syncronize folder (if it wasn't synced in this request already)
@@ -837,8 +840,8 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
 
             $search = $this->storage->search_once($foldername, $filter_str);
 
-            if (!($search instanceof rcube_result_index)) {
-                continue;
+            if (!($search instanceof rcube_result_index) || $search->is_error()) {
+                throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
             }
 
             switch ($result_type) {
@@ -864,6 +867,10 @@ class kolab_sync_data_email extends kolab_sync_data implements Syncroton_Data_ID
             }
         }
 
+        if (!$found) {
+            throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
+        }
+
         if (!empty($modseq_update)) {
             $this->backend->modseq_set($this->device->id, $folderid,
                 $this->syncTimeStamp, $modseq_data);
diff --git a/lib/plugins/libkolab/lib/kolab_storage_cache.php b/lib/plugins/libkolab/lib/kolab_storage_cache.php
index 651dc18..732ce8f 100644
--- a/lib/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/lib/plugins/libkolab/lib/kolab_storage_cache.php
@@ -411,6 +411,10 @@ class kolab_storage_cache
                 $this->folder_id
             );
 
+            if ($this->db->is_error($sql_result)) {
+                return null;
+            }
+
             while ($sql_arr = $this->db->fetch_assoc($sql_result)) {
                 if ($uids) {
                     $this->uid2msg[$sql_arr['uid']] = $sql_arr['msguid'];
@@ -431,7 +435,11 @@ class kolab_storage_cache
             }
             else {  // search by object type
                 $search = 'UNDELETED HEADER X-Kolab-Type ' . kolab_format::KTYPE_PREFIX . $filter['type'];
-                $index = $this->imap->search_once($this->folder->name, $search)->get();
+                $index  = $this->imap->search_once($this->folder->name, $search)->get();
+            }
+
+            if ($index->is_error()) {
+                return null;
             }
 
             // fetch all messages in $index from IMAP
@@ -461,8 +469,6 @@ class kolab_storage_cache
      */
     public function count($query = array())
     {
-        $count = 0;
-
         // cache is in sync, we can count records in local DB
         if ($this->synched) {
             $this->_read_folder_data();
@@ -473,14 +479,23 @@ class kolab_storage_cache
                 $this->folder_id
             );
 
+            if ($this->db->is_error($sql_result)) {
+                return null;
+            }
+
             $sql_arr = $this->db->fetch_assoc($sql_result);
-            $count = intval($sql_arr['numrows']);
+            $count   = intval($sql_arr['numrows']);
         }
         else {
             // search IMAP by object type
             $filter = $this->_query2assoc($query);
             $ctype  = kolab_format::KTYPE_PREFIX . $filter['type'];
-            $index = $this->imap->search_once($this->folder->name, 'UNDELETED HEADER X-Kolab-Type ' . $ctype);
+            $index  = $this->imap->search_once($this->folder->name, 'UNDELETED HEADER X-Kolab-Type ' . $ctype);
+
+            if ($index->is_error()) {
+                return null;
+            }
+
             $count = $index->count();
         }
 




More information about the commits mailing list