From e48f8945b32ab5b67f1cdeb53a37d3d196e31e4d Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Fri, 20 May 2016 05:19:01 -0400
Subject: [PATCH] Fix bug where message list columns could be in wrong order after column drag-n-drop and list sorting

---
 program/lib/Roundcube/rcube_imap.php |   72 +++++++++++++++++++-----------------
 1 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php
index d1d1fbf..ea5e717 100644
--- a/program/lib/Roundcube/rcube_imap.php
+++ b/program/lib/Roundcube/rcube_imap.php
@@ -57,7 +57,6 @@
     protected $icache = array();
 
     protected $plugins;
-    protected $list_page = 1;
     protected $delimiter;
     protected $namespace;
     protected $sort_field = '';
@@ -583,27 +582,30 @@
 
 
     /**
-     * protected method for getting nr of messages
+     * Protected method for getting number of messages
      *
-     * @param string  $folder  Folder name
-     * @param string  $mode    Mode for count [ALL|THREADS|UNSEEN|RECENT|EXISTS]
-     * @param boolean $force   Force reading from server and update cache
-     * @param boolean $status  Enables storing folder status info (max UID/count),
-     *                         required for folder_status()
+     * @param string  $folder    Folder name
+     * @param string  $mode      Mode for count [ALL|THREADS|UNSEEN|RECENT|EXISTS]
+     * @param boolean $force     Force reading from server and update cache
+     * @param boolean $status    Enables storing folder status info (max UID/count),
+     *                           required for folder_status()
+     * @param boolean $no_search Ignore current search result
      *
      * @return int Number of messages
      * @see rcube_imap::count()
      */
-    protected function countmessages($folder, $mode='ALL', $force=false, $status=true)
+    protected function countmessages($folder, $mode = 'ALL', $force = false, $status = true, $no_search = false)
     {
         $mode = strtoupper($mode);
 
-        // count search set, assume search set is always up-to-date (don't check $force flag)
-        if ($this->search_string && $folder == $this->folder && ($mode == 'ALL' || $mode == 'THREADS')) {
+        // Count search set, assume search set is always up-to-date (don't check $force flag)
+        // @TODO: this could be handled in more reliable way, e.g. a separate method
+        //        maybe in rcube_imap_search
+        if (!$no_search && $this->search_string && $folder == $this->folder) {
             if ($mode == 'ALL') {
                 return $this->search_set->count_messages();
             }
-            else {
+            else if ($mode == 'THREADS') {
                 return $this->search_set->count();
             }
         }
@@ -1232,7 +1234,7 @@
         $old = $this->get_folder_stats($folder);
 
         // refresh message count -> will update
-        $this->countmessages($folder, 'ALL', true);
+        $this->countmessages($folder, 'ALL', true, true, true);
 
         $result = 0;
 
@@ -1801,10 +1803,10 @@
 
     /**
      * Fetch message headers and body structure from the IMAP server and build
-     * an object structure similar to the one generated by PEAR::Mail_mimeDecode
+     * an object structure.
      *
-     * @param int     $uid      Message UID to fetch
-     * @param string  $folder   Folder to read from
+     * @param int    $uid    Message UID to fetch
+     * @param string $folder Folder to read from
      *
      * @return object rcube_message_header Message data
      */
@@ -1883,8 +1885,8 @@
                 $structure[1] = $m[2];
             }
             else {
-                // Try to parse the message using Mail_mimeDecode package
-                // We need a better solution, Mail_mimeDecode parses message
+                // Try to parse the message using rcube_mime_decode.
+                // We need a better solution, it parses message
                 // in memory, which wouldn't work for very big messages,
                 // (it uses up to 10x more memory than the message size)
                 // it's also buggy and not actively developed
@@ -2811,7 +2813,7 @@
         }
 
         // INBOX should always be available
-        if ((!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
+        if (!strlen($root) && (!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
             array_unshift($a_mboxes, 'INBOX');
         }
 
@@ -2871,7 +2873,7 @@
             if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) {
                 foreach ($a_folders as $idx => $folder) {
                     if (($opts = $this->conn->data['LIST'][$folder])
-                        && in_array('\\NonExistent', $opts)
+                        && in_array_nocase('\\NonExistent', $opts)
                     ) {
                         $this->conn->unsubscribe($folder);
                         unset($a_folders[$idx]);
@@ -2939,7 +2941,7 @@
         }
 
         // INBOX should always be available
-        if ((!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
+        if (!strlen($root) && (!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
             array_unshift($a_mboxes, 'INBOX');
         }
 
@@ -3165,16 +3167,6 @@
 
         $result = $this->conn->createFolder($folder, $type ? array("\\" . ucfirst($type)) : null);
 
-        // it's quite often situation that we're trying to create and subscribe
-        // a folder that already exist, but is unsubscribed
-        if (!$result) {
-            if ($this->get_response_code() == rcube_storage::ALREADYEXISTS
-                || preg_match('/already exists/i', $this->get_error_str())
-            ) {
-                $result = true;
-            }
-        }
-
         // try to subscribe it
         if ($result) {
             // clear cache
@@ -3303,6 +3295,12 @@
     public function get_special_folders($forced = false)
     {
         $result = parent::get_special_folders();
+        $rcube  = rcube::get_instance();
+
+        // Lock SPECIAL-USE after user preferences change (#4782)
+        if ($rcube->config->get('lock_special_folders')) {
+            return $result;
+        }
 
         if (isset($this->icache['special-use'])) {
             return array_merge($result, $this->icache['special-use']);
@@ -3408,7 +3406,7 @@
         if ($subscription) {
             // It's possible we already called LIST command, check LIST data
             if (!empty($this->conn->data['LIST']) && !empty($this->conn->data['LIST'][$folder])
-                && in_array('\\Subscribed', $this->conn->data['LIST'][$folder])
+                && in_array_nocase('\\Subscribed', $this->conn->data['LIST'][$folder])
             ) {
                 $a_folders = array($folder);
             }
@@ -3951,9 +3949,15 @@
 
             // @TODO: Honor MAXSIZE and DEPTH options
             foreach ($queries as $attrib => $entry) {
-                if ($result = $this->conn->getAnnotation($folder, $entry, $attrib)) {
-                    foreach ($result as $folder => $data) {
-                        $res[$folder] = array_merge((array) $res[$folder], $data);
+                $result = $this->conn->getAnnotation($folder, $entry, $attrib);
+
+                // an error, invalidate any previous getAnnotation() results
+                if (!is_array($result)) {
+                    return null;
+                }
+                else {
+                    foreach ($result as $fldr => $data) {
+                        $res[$fldr] = array_merge((array) $res[$fldr], $data);
                     }
                 }
             }

--
Gitblit v1.9.1