diff options
-rw-r--r-- | CHANGELOG | 4 | ||||
-rw-r--r-- | program/include/rcube_imap.php | 120 | ||||
-rw-r--r-- | program/lib/imap.inc | 6 | ||||
-rw-r--r-- | program/steps/mail/search.inc | 7 |
4 files changed, 80 insertions, 57 deletions
@@ -1,6 +1,10 @@ CHANGELOG RoundCube Webmail --------------------------- +2008/11/12 (alec) +---------- +- Use SORT for searching on servers with SORT capability + 2008/11/06 (alec) ---------- - Fix empty file sending (#1485389) diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index b0a6ed9d4..2ccaf7750 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -64,6 +64,7 @@ class rcube_imap var $search_subject = ''; var $search_string = ''; var $search_charset = ''; + var $search_sort_field = ''; var $debug_level = 1; var $error_code = 0; @@ -285,10 +286,10 @@ class rcube_imap * @param string Search string * @param array List of message ids or NULL if empty */ - function set_search_set($subject, $str=null, $msgs=null, $charset=null, $sorted=null) + function set_search_set($subject, $str=null, $msgs=null, $charset=null, $sort_field=null) { if (is_array($subject) && $str == null && $msgs == null) - list($subject, $str, $msgs, $charset, $sorted) = $subject; + list($subject, $str, $msgs, $charset, $sort_field) = $subject; if ($msgs != null && !is_array($msgs)) $msgs = split(',', $msgs); @@ -296,6 +297,7 @@ class rcube_imap $this->search_string = $str; $this->search_set = (array)$msgs; $this->search_charset = $charset; + $this->search_sort_field = $sort_field; } @@ -305,7 +307,7 @@ class rcube_imap */ function get_search_set() { - return array($this->search_subject, $this->search_string, $this->search_set, $this->search_charset); + return array($this->search_subject, $this->search_string, $this->search_set, $this->search_charset, $this->search_sort_field); } @@ -544,7 +546,7 @@ class rcube_imap // use saved message set if ($this->search_string && $mailbox == $this->mailbox) - return $this->_list_header_set($mailbox, $this->search_set, $page, $sort_field, $sort_order); + return $this->_list_header_set($mailbox, $page, $sort_field, $sort_order); $this->_set_sort_order($sort_field, $sort_order); @@ -626,62 +628,74 @@ class rcube_imap } - /** - * Public method for listing a specific set of headers - * convert mailbox name with root dir first + * Private method for listing a set of message headers (search results) * * @param string Mailbox/folder name - * @param array List of message ids to list * @param int Current page to list * @param string Header field to sort by * @param string Sort order [ASC|DESC] * @return array Indexed array with message header objects - * @access public - */ - function list_header_set($mbox_name='', $msgs, $page=NULL, $sort_field=NULL, $sort_order=NULL) - { - $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox; - return $this->_list_header_set($mailbox, $msgs, $page, $sort_field, $sort_order); - } - - - /** - * Private method for listing a set of message headers - * * @access private * @see rcube_imap::list_header_set() */ - function _list_header_set($mailbox, $msgs, $page=NULL, $sort_field=NULL, $sort_order=NULL) + function _list_header_set($mailbox, $page=NULL, $sort_field=NULL, $sort_order=NULL) { - if (!strlen($mailbox) || empty($msgs)) + if (!strlen($mailbox) || empty($this->search_set)) return array(); - // also accept a comma-separated list of message ids - if (is_array ($msgs)) { - $max = count ($msgs); - $msgs = join (',', $msgs); - } else { - $max = count(split(',', $msgs)); - } + $msgs = $this->search_set; + $a_msg_headers = array(); + $start_msg = ($this->list_page-1) * $this->page_size; $this->_set_sort_order($sort_field, $sort_order); - $start_msg = ($this->list_page-1) * $this->page_size; + // sorted messages, so we can first slice array and then fetch only wanted headers + if ($this->get_capability('sort')) // SORT searching result + { + // reset search set if sorting field has been changed + if ($sort_field && $this->search_sort_field != $sort_field) + { + $msgs = $this->search('', $this->search_subject, $this->search_string, $this->search_charset, $sort_field); + } - // fetch reuested headers from server - $a_msg_headers = array(); - $this->_fetch_headers($mailbox, $msgs, $a_msg_headers, NULL); + // return empty array if no messages found + if (empty($msgs)) + return array(); - // return empty array if no messages found - if (!is_array($a_msg_headers) || empty($a_msg_headers)) - return array(); + if ($sort_order == 'DESC') + $msgs = array_reverse($msgs); - // if not already sorted - $a_msg_headers = iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order); + // get messages uids for one page + $msgs = array_slice(array_values($msgs), $start_msg, min(count($msgs)-$start_msg, $this->page_size)); + + // fetch headers + $this->_fetch_headers($mailbox, join(',',$msgs), $a_msg_headers, NULL); + + $sorter = new rcube_header_sorter(); + $sorter->set_sequence_numbers($msgs); + $sorter->sort_headers($a_msg_headers); + + return array_values($a_msg_headers); + } + else { // SEARCH searching result + // not sorted, so we must fetch headers for all messages + // TODO: to minimize big memory consumption on servers without SORT + // capability, we should fetch only headers used for sorting, and then + // fetch all headers needed for displaying one page of messages list. + // Of course it has sense only for big results if count($msgs) > $this->pagesize + $this->_fetch_headers($mailbox, join(',', $msgs), $a_msg_headers, NULL); + + // return empty array if no messages found + if (!is_array($a_msg_headers) || empty($a_msg_headers)) + return array(); - // only return the requested part of the set - return array_slice(array_values($a_msg_headers), $start_msg, min($max-$start_msg, $this->page_size)); + // if not already sorted + $a_msg_headers = iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order); + + // only return the requested part of the set + return array_slice(array_values($a_msg_headers), $start_msg, min(count($msgs)-$start_msg, $this->page_size)); + } } @@ -894,16 +908,18 @@ class rcube_imap * @param string mailbox name to search in * @param string search criteria (ALL, TO, FROM, SUBJECT, etc) * @param string search string + * @param string search string charset + * @param string header field to sort by * @return array search results as list of message ids * @access public */ - function search($mbox_name='', $criteria='ALL', $str=NULL, $charset=NULL) + function search($mbox_name='', $criteria='ALL', $str=NULL, $charset=NULL, $sort_field=NULL) { $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox; $search = ''; // have an array of criterias => create search string - if (is_array($criteria)) + if (is_array($criteria) && count($criteria) > 1) $search .= 'OR'; $criteria = (array) $criteria; @@ -913,13 +929,14 @@ class rcube_imap else $search .= '('. $crit .')'; - $results = $this->_search_index($mailbox, (!empty($charset) ? "CHARSET $charset " : '') . $search); + $results = $this->_search_index($mailbox, $search, $charset, $sort_field); // try search with ISO charset (should be supported by server) if (empty($results) && !empty($charset) && $charset!='ISO-8859-1') - $results = $this->search($mbox_name, $criteria, rcube_charset_convert($str, $charset, 'ISO-8859-1'), 'ISO-8859-1'); + $results = $this->search($mbox_name, $criteria, rcube_charset_convert($str, $charset, 'ISO-8859-1'), 'ISO-8859-1', $sort_field); + + $this->set_search_set($criteria, $str, $results, $charset, $sort_field); - $this->set_search_set($criteria, $str, $results, $charset); return $results; } @@ -931,9 +948,12 @@ class rcube_imap * @access private * @see rcube_imap::search() */ - function _search_index($mailbox, $criteria='ALL') + function _search_index($mailbox, $criteria='ALL', $charset='', $sort_field='') { - $a_messages = iil_C_Search($this->conn, $mailbox, $criteria); + if ($this->get_capability('sort')) + $a_messages = iil_C_Sort($this->conn, $mailbox, $sort_field, $criteria, FALSE, $charset); + else + $a_messages = iil_C_Search($this->conn, $mailbox, ($charset ? "CHARSET $charset " : '') . $criteria); // clean message list (there might be some empty entries) if (is_array($a_messages)) @@ -955,7 +975,7 @@ class rcube_imap function refresh_search() { if (!empty($this->search_subject) && !empty($this->search_string)) - $this->search_set = $this->search('', $this->search_subject, $this->search_string, $this->search_charset); + $this->search_set = $this->search('', $this->search_subject, $this->search_string, $this->search_charset, $this->search_sort_field); return $this->get_search_set(); } @@ -2245,7 +2265,7 @@ class rcube_imap /** * @access private */ - function get_message_cache_index($key, $force=FALSE, $sort_col='idx', $sort_order='ASC') + function get_message_cache_index($key, $force=FALSE, $sort_field='idx', $sort_order='ASC') { static $sa_message_index = array(); @@ -2262,7 +2282,7 @@ class rcube_imap FROM ".get_table_name('messages')." WHERE user_id=? AND cache_key=? - ORDER BY ".$this->db->quote_identifier($sort_col)." ".$sort_order, + ORDER BY ".$this->db->quote_identifier($sort_field)." ".$sort_order, $_SESSION['user_id'], $key); diff --git a/program/lib/imap.inc b/program/lib/imap.inc index 24abd697d..8cbb0e02b 100644 --- a/program/lib/imap.inc +++ b/program/lib/imap.inc @@ -838,7 +838,7 @@ function iil_C_CheckForRecent(&$conn, $mailbox) { function iil_C_CountMessages(&$conn, $mailbox, $refresh = false) { if ($refresh) { - $conn->selected= ''; + $conn->selected = ''; } iil_C_Select($conn, $mailbox); @@ -926,10 +926,10 @@ function iil_C_Sort(&$conn, $mailbox, $field, $add='', $is_uid=FALSE, $fp = $conn->fp; $command = 's ' . $is_uid . 'SORT (' . $field . ') '; - $command .= $encoding . ' ALL' . $add; + $command .= $encoding . ' ALL ' . $add; $line = $data = ''; - if (!iil_PutLine($fp, $command)) { + if (!iil_PutLineC($fp, $command)) { return false; } do { diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc index 44f58b1e1..6f3676891 100644 --- a/program/steps/mail/search.inc +++ b/program/steps/mail/search.inc @@ -69,16 +69,15 @@ else $search = trim($str); } - // execute IMAP search -$result = $IMAP->search($mbox, $subject, $search, $imap_charset); +$result = $IMAP->search($mbox, $subject, $search, $imap_charset, $_SESSION['sort_col']); $count = 0; - + // Make sure our $result is legit.. if (is_array($result) && $result[0] != '') { // Get the headers - $result_h = $IMAP->list_header_set($mbox, $result, 1, $_SESSION['sort_col'], $_SESSION['sort_order']); + $result_h = $IMAP->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']); $count = $IMAP->messagecount(); // save search results in session |