diff options
Diffstat (limited to 'program/lib/Roundcube/rcube_imap.php')
-rw-r--r-- | program/lib/Roundcube/rcube_imap.php | 139 |
1 files changed, 79 insertions, 60 deletions
diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php index 3ca8a07c9..b60aefc5f 100644 --- a/program/lib/Roundcube/rcube_imap.php +++ b/program/lib/Roundcube/rcube_imap.php @@ -1189,11 +1189,13 @@ class rcube_imap extends rcube_storage * @param string $sort_field Sort column * @param string $sort_order Sort order [ASC, DESC] * @param bool $no_threads Get not threaded index + * @param bool $no_search Get index not limited to search result (optionally) * * @return rcube_result_index|rcube_result_thread List of messages (UIDs) */ - public function index($folder = '', $sort_field = NULL, $sort_order = NULL, $no_threads = false) - { + public function index($folder = '', $sort_field = NULL, $sort_order = NULL, + $no_threads = false, $no_search = false + ) { if (!$no_threads && $this->threading) { return $this->thread_index($folder, $sort_field, $sort_order); } @@ -1206,43 +1208,50 @@ class rcube_imap extends rcube_storage // we have a saved search result, get index from there if ($this->search_string) { - if ($this->search_threads) { - $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); + if ($this->search_set->is_empty()) { + return new rcube_result_index($folder, '* SORT'); } - // use message index sort as default sorting - if (!$this->sort_field || $this->search_sorted) { - if ($this->sort_field && $this->search_sort_field != $this->sort_field) { - $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); - } + // search result is an index with the same sorting? + if (($this->search_set instanceof rcube_result_index) + && ((!$this->sort_field && !$this->search_sorted) || + ($this->search_sorted && $this->search_sort_field == $this->sort_field)) + ) { $index = $this->search_set; } - else if (!$this->check_connection()) { - return new rcube_result_index(); - } - else { - $index = $this->conn->index($folder, $this->search_set->get(), - $this->sort_field, $this->options['skip_deleted'], true, true); + // $no_search is enabled when we are not interested in + // fetching index for search result, e.g. to sort + // threaded search result we can use full mailbox index. + // This makes possible to use index from cache + else if (!$no_search) { + if (!$this->sort_field) { + // No sorting needed, just build index from the search result + // @TODO: do we need to sort by UID here? + $search = $this->search_set->get_compressed(); + $index = new rcube_result_index($folder, '* ESEARCH ALL ' . $search); + } + else { + $index = $this->index_direct($folder, $this->search_charset, + $this->sort_field, $this->search_set); + } } - if ($this->sort_order != $index->get_parameters('ORDER')) { - $index->revert(); - } + if (isset($index)) { + if ($this->sort_order != $index->get_parameters('ORDER')) { + $index->revert(); + } - return $index; + return $index; + } } // check local cache if ($mcache = $this->get_mcache_engine()) { - $index = $mcache->get_index($folder, $this->sort_field, $this->sort_order); - } - // fetch from IMAP server - else { - $index = $this->index_direct( - $folder, $this->sort_field, $this->sort_order); + return $mcache->get_index($folder, $this->sort_field, $this->sort_order); } - return $index; + // fetch from IMAP server + return $this->index_direct($folder, $this->sort_field, $this->sort_order); } @@ -1250,18 +1259,24 @@ class rcube_imap extends rcube_storage * Return sorted list of message UIDs ignoring current search settings. * Doesn't uses cache by default. * - * @param string $folder Folder to get index from - * @param string $sort_field Sort column - * @param string $sort_order Sort order [ASC, DESC] + * @param string $folder Folder to get index from + * @param string $sort_field Sort column + * @param string $sort_order Sort order [ASC, DESC] + * @param rcube_result_* $search Optional messages set to limit the result * * @return rcube_result_index Sorted list of message UIDs */ - public function index_direct($folder, $sort_field = null, $sort_order = null) + public function index_direct($folder, $sort_field = null, $sort_order = null, $search = null) { + if (!empty($search)) { + $search = $this->search_set->get_compressed(); + } + // use message index sort as default sorting if (!$sort_field) { // use search result from count() if possible - if ($this->options['skip_deleted'] && !empty($this->icache['undeleted_idx']) + if (empty($search) && $this->options['skip_deleted'] + && !empty($this->icache['undeleted_idx']) && $this->icache['undeleted_idx']->get_parameters('ALL') !== null && $this->icache['undeleted_idx']->get_parameters('MAILBOX') == $folder ) { @@ -1271,8 +1286,12 @@ class rcube_imap extends rcube_storage return new rcube_result_index(); } else { - $index = $this->conn->search($folder, - 'ALL' .($this->options['skip_deleted'] ? ' UNDELETED' : ''), true); + $query = $this->options['skip_deleted'] ? 'UNDELETED' : ''; + if ($search) { + $query = trim($query . ' UID ' . $search); + } + + $index = $this->conn->search($folder, $query, true); } } else if (!$this->check_connection()) { @@ -1281,13 +1300,18 @@ class rcube_imap extends rcube_storage // fetch complete message index else { if ($this->get_capability('SORT')) { - $index = $this->conn->sort($folder, $sort_field, - $this->options['skip_deleted'] ? 'UNDELETED' : '', true); + $query = $this->options['skip_deleted'] ? 'UNDELETED' : ''; + if ($search) { + $query = trim($query . ' UID ' . $search); + } + + $index = $this->conn->sort($folder, $sort_field, $query, true); } if (empty($index) || $index->is_error()) { - $index = $this->conn->index($folder, "1:*", $sort_field, - $this->options['skip_deleted'], false, true); + $index = $this->conn->index($folder, $search ? $search : "1:*", + $sort_field, $this->options['skip_deleted'], + $search ? true : false, true); } } @@ -1346,9 +1370,9 @@ class rcube_imap extends rcube_storage // THREAD=REFERENCES: sorting by sent date of root message // THREAD=REFS: sorting by the most recent date in each thread - if ($this->get_capability('THREAD') != 'REFS') { + if ($this->threading != 'REFS' || ($this->sort_field && $this->sort_field != 'date')) { $sortby = $this->sort_field ? $this->sort_field : 'date'; - $index = $this->index($this->folder, $sortby, $this->sort_order, true); + $index = $this->index($this->folder, $sortby, $this->sort_order, true, true); if (!$index->is_empty()) { $threads->sort($index); @@ -2243,13 +2267,14 @@ class rcube_imap extends rcube_storage /** * Append a mail message (source) to a specific folder * - * @param string $folder Target folder - * @param string $message The message source string or filename - * @param string $headers Headers string if $message contains only the body - * @param boolean $is_file True if $message is a filename - * @param array $flags Message flags - * @param mixed $date Message internal date - * @param bool $binary Enables BINARY append + * @param string $folder Target folder + * @param string|array $message The message source string or filename + * or array (of strings and file pointers) + * @param string $headers Headers string if $message contains only the body + * @param boolean $is_file True if $message is a filename + * @param array $flags Message flags + * @param mixed $date Message internal date + * @param bool $binary Enables BINARY append * * @return int|bool Appended message UID or True on success, False on error */ @@ -2642,7 +2667,6 @@ class rcube_imap extends rcube_storage if ($list_extended) { // unsubscribe non-existent folders, remove from the list - // we can do this only when LIST response is available if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) { foreach ($a_folders as $idx => $folder) { if (($opts = $this->conn->data['LIST'][$folder]) @@ -2655,19 +2679,14 @@ class rcube_imap extends rcube_storage } } else { - // unsubscribe non-existent folders, remove them from the list, - // we can do this only when LIST response is available - if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) { - foreach ($a_folders as $idx => $folder) { - if (!isset($this->conn->data['LIST'][$folder]) - || in_array('\\Noselect', $this->conn->data['LIST'][$folder]) - ) { - // Some servers returns \Noselect for existing folders - if (!$this->folder_exists($folder)) { - $this->conn->unsubscribe($folder); - unset($a_folders[$idx]); - } - } + // unsubscribe non-existent folders, remove them from the list + if (is_array($a_folders) && !empty($a_folders) && $name == '*') { + $existing = $this->list_folders($root, $name); + $nonexisting = array_diff($a_folders, $existing); + $a_folders = array_diff($a_folders, $nonexisting); + + foreach ($nonexisting as $folder) { + $this->conn->unsubscribe($folder); } } } |