From c309cd8928af861637996f5c5490a2db0dc626dc Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Fri, 29 Oct 2010 08:18:05 -0400
Subject: [PATCH] - Improve performance of setting IMAP flags using .SILENT suffix

---
 CHANGELOG                              |    1 
 program/include/rcube_imap.php         |   30 +++++++++------
 program/steps/mail/mark.inc            |    4 +-
 program/include/rcube_imap_generic.php |   71 +++++++++++++----------------------
 4 files changed, 48 insertions(+), 58 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 802eb2a..94d6d04 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -56,6 +56,7 @@
 - Add SORT=DISPLAY support (RFC 5957)
 - Plugin API: add possibility to disable plugin in AJAX mode, 'noajax' property
 - Plugin API: add possibility to disable plugin in framed mode, 'noframe' property
+- Improve performance of setting IMAP flags using .SILENT suffix
 
 RELEASE 0.4.2
 -------------
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 3fd9e1a..d085542 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -2353,7 +2353,7 @@
      * @param string  $flag       Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT
      * @param string  $mbox_name  Folder name
      * @param boolean $skip_cache True to skip message cache clean up
-     * @return int    Number of flagged messages, -1 on failure
+     * @return boolean  Operation status
      */
     function set_flag($uids, $flag, $mbox_name=NULL, $skip_cache=false)
     {
@@ -2367,7 +2367,7 @@
         else
             $result = $this->conn->flag($mailbox, $uids, $flag);
 
-        if ($result >= 0) {
+        if ($result) {
             // reload message headers if cached
             if ($this->caching_enabled && !$skip_cache) {
                 $cache_key = $mailbox.'.msg';
@@ -2376,13 +2376,15 @@
                 else
                     $this->remove_message_cache($cache_key, explode(',', $uids));
             }
-            // update counters
-            if ($flag=='SEEN')
-                $this->_set_messagecount($mailbox, 'UNSEEN', $result*(-1));
-            else if ($flag=='UNSEEN')
-                $this->_set_messagecount($mailbox, 'UNSEEN', $result);
-            else if ($flag=='DELETED')
-                $this->_set_messagecount($mailbox, 'ALL', $result*(-1));
+
+            // clear cached counters
+            if ($flag == 'SEEN' || $flag == 'UNSEEN') {
+                $this->_clear_messagecount($mailbox, 'SEEN');
+                $this->_clear_messagecount($mailbox, 'UNSEEN');
+            }
+            else if ($flag == 'DELETED') {
+                $this->_clear_messagecount($mailbox, 'DELETED');
+            }
         }
 
         return $result;
@@ -4425,15 +4427,19 @@
      * Remove messagecount of a specific mailbox from cache
      * @access private
      */
-    private function _clear_messagecount($mbox_name='')
+    private function _clear_messagecount($mbox_name='', $mode=null)
     {
-        $a_mailbox_cache = false;
         $mailbox = $mbox_name ? $mbox_name : $this->mailbox;
 
         $a_mailbox_cache = $this->get_cache('messagecount');
 
         if (is_array($a_mailbox_cache[$mailbox])) {
-            unset($a_mailbox_cache[$mailbox]);
+            if ($mode) {
+                unset($a_mailbox_cache[$mailbox][$mode]);
+            }
+            else {
+                unset($a_mailbox_cache[$mailbox]);
+            }
             $this->update_cache('messagecount', $a_mailbox_cache);
         }
     }
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 0383543..e9a5a2d 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -1007,11 +1007,6 @@
 	        return false;
 	    }
 
-        // RFC 5957: SORT=DISPLAY
-        if (($field == 'FROM' || $field == 'TO') && $this->getCapability('SORT=DISPLAY')) {
-            $field = 'DISPLAY' . $field;
-        }
-
 	    // message IDs
 	    if (is_array($add))
 		    $add = $this->compressMessageSet(join(',', $add));
@@ -1155,29 +1150,32 @@
 	    return $result;
     }
 
-    private function compressMessageSet($message_set, $force=false)
+    private function compressMessageSet($messages, $force=false)
     {
 	    // given a comma delimited list of independent mid's,
 	    // compresses by grouping sequences together
 
-	    // if less than 255 bytes long, let's not bother
-	    if (!$force && strlen($message_set)<255) {
-	        return $message_set;
-	    }
+        if (!is_array($message_set)) {
+	        // if less than 255 bytes long, let's not bother
+	        if (!$force && strlen($messages)<255) {
+	            return $messages;
+	        }
 
-	    // see if it's already been compressed
-	    if (strpos($message_set, ':') !== false) {
-	        return $message_set;
-	    }
+    	    // see if it's already been compressed
+	        if (strpos($messages, ':') !== false) {
+	            return $messages;
+	        }
 
-	    // separate, then sort
-	    $ids = explode(',', $message_set);
-	    sort($ids);
+	        // separate, then sort
+	        $messages = explode(',', $messages);
+        }
+
+	    sort($messages);
 
 	    $result = array();
-	    $start  = $prev = $ids[0];
+	    $start  = $prev = $messages[0];
 
-	    foreach ($ids as $id) {
+	    foreach ($messages as $id) {
 		    $incr = $id - $prev;
 		    if ($incr > 1) {			//found a gap
 			    if ($start == $prev) {
@@ -1191,7 +1189,7 @@
 	    }
 
 	    // handle the last sequence/id
-	    if ($start==$prev) {
+	    if ($start == $prev) {
 	        $result[] = $prev;
 	    } else {
     	    $result[] = $start.':'.$prev;
@@ -1587,35 +1585,19 @@
     function modFlag($mailbox, $messages, $flag, $mod)
     {
 	    if ($mod != '+' && $mod != '-') {
-	        return -1;
+            $mod = '+';
 	    }
-
-	    $flag = $this->flags[strtoupper($flag)];
 
 	    if (!$this->select($mailbox)) {
-	        return -1;
+	        return false;
 	    }
 
-        $c = 0;
-        $key = $this->next_tag();
-        $command = "$key UID STORE $messages {$mod}FLAGS ($flag)";
-	    if (!$this->putLine($command)) {
-            $this->set_error(self::ERROR_COMMAND, "Unable to send command: $command");
-            return -1;
-        }
+	    $flag   = $this->flags[strtoupper($flag)];
+        $result = $this->execute('UID STORE', array(
+            $this->compressMessageSet($messages), $mod . 'FLAGS.SILENT', "($flag)"),
+            self::COMMAND_NORESPONSE);
 
-	    do {
-		    $line = $this->readLine();
-		    if ($line[0] == '*') {
-		        $c++;
-            }
-	    } while (!$this->startsWith($line, $key, true, true));
-
-	    if ($this->parseResult($line, 'STORE: ') == self::ERROR_OK) {
-		    return $c;
-	    }
-
-	    return -1;
+	    return ($result == self::ERROR_OK);
     }
 
     function flag($mailbox, $messages, $flag) {
@@ -1640,7 +1622,8 @@
             return -1;
 	    }
 
-        $result = $this->execute('UID COPY', array($messages, $this->escape($to)),
+        $result = $this->execute('UID COPY', array(
+            $this->compressMessageSet($messages), $this->escape($to)),
             self::COMMAND_NORESPONSE);
 
 	    return $result;
diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc
index 9266cf4..57eae64 100644
--- a/program/steps/mail/mark.inc
+++ b/program/steps/mail/mark.inc
@@ -43,7 +43,7 @@
 
   $marked = $IMAP->set_flag($uids, $flag);
 
-  if ($marked == -1) {
+  if (!$marked) {
     // send error message
     if ($_POST['_from'] != 'show')
       $OUTPUT->command('list_mailbox');
@@ -56,7 +56,7 @@
     $ruids = get_input_value('_ruid', RCUBE_INPUT_POST);
     $read = $IMAP->set_flag($ruids, 'SEEN');
 
-    if ($read != -1 && !$CONFIG['skip_deleted'])
+    if ($read && !$CONFIG['skip_deleted'])
       $OUTPUT->command('flag_deleted_as_read', $ruids);
   }
 

--
Gitblit v1.9.1