diff options
-rw-r--r-- | program/include/bugs.inc | 7 | ||||
-rw-r--r-- | program/include/rcube_imap.inc | 146 | ||||
-rw-r--r-- | program/lib/imap.inc | 2 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 5 |
4 files changed, 122 insertions, 38 deletions
diff --git a/program/include/bugs.inc b/program/include/bugs.inc index c9116d5a2..bc1a2932d 100644 --- a/program/include/bugs.inc +++ b/program/include/bugs.inc @@ -97,7 +97,12 @@ function log_bug($arg_arr) // show error if debug_mode is on if ($CONFIG['debug_level'] & 4) { - print "<b>$program Error in $arg_arr[file] ($arg_arr[line]):</b> "; + print "<b>$program Error"; + + if (!empty($arg_arr['file']) && !empty($arg_arr['line'])) + print " in $arg_arr[file] ($arg_arr[line])"; + + print ":</b> "; print nl2br($arg_arr['message']); print '<br />'; flush(); diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index ed7c3edcd..cc30b3fe4 100644 --- a/program/include/rcube_imap.inc +++ b/program/include/rcube_imap.inc @@ -35,6 +35,8 @@ class rcube_imap var $mailbox = 'INBOX'; var $list_page = 1; var $page_size = 10; + var $sort_field = 'date'; + var $sort_order = 'DESC'; var $delimiter = NULL; var $caching_enabled = FALSE; var $default_folders = array('inbox', 'drafts', 'sent', 'junk', 'trash'); @@ -279,19 +281,30 @@ class rcube_imap // return cached value if (!$force && is_array($a_mailbox_cache[$mailbox]) && isset($a_mailbox_cache[$mailbox][$mode])) - return $a_mailbox_cache[$mailbox][$mode]; + return $a_mailbox_cache[$mailbox][$mode]; + + $search_str = "ALL UNDELETED"; // get message count and store in cache if ($mode == 'UNSEEN') - $count = iil_C_CountUnseen($this->conn, $mailbox); - else - $count = iil_C_CountMessages($this->conn, $mailbox); + $search_str .= " UNSEEN"; + + // get message count using SEARCH + // not very performant but more precise (using UNDELETED) + $count = 0; + $index = $this->_search_index($mailbox, $search_str); + if (is_array($index)) + { + $str = implode(",", $index); + if (!empty($str)) + $count = count($index); + } if (is_array($a_mailbox_cache[$mailbox])) $a_mailbox_cache[$mailbox] = array(); $a_mailbox_cache[$mailbox][$mode] = (int)$count; - + // write back to cache $this->update_cache('messagecount', $a_mailbox_cache); @@ -301,7 +314,7 @@ class rcube_imap // public method for listing headers // convert mailbox name with root dir first - function list_headers($mbox='', $page=NULL, $sort_field='date', $sort_order='DESC') + function list_headers($mbox='', $page=NULL, $sort_field=NULL, $sort_order=NULL) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; return $this->_list_headers($mailbox, $page, $sort_field, $sort_order); @@ -309,10 +322,15 @@ class rcube_imap // private method for listing message header - function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') + function _list_headers($mailbox='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $recursive=FALSE) { if (!strlen($mailbox)) return array(); + + if ($sort_field!=NULL) + $this->sort_field = $sort_field; + if ($sort_order!=NULL) + $this->sort_order = strtoupper($sort_order); $max = $this->_messagecount($mailbox); $start_msg = ($this->list_page-1) * $this->page_size; @@ -322,7 +340,7 @@ class rcube_imap $begin = 0; $end = $max; } - else if ($sort_order=='DESC') + else if ($this->sort_order=='DESC') { $begin = $max - $this->page_size - $start_msg; $end = $max - $start_msg; @@ -348,20 +366,20 @@ class rcube_imap // cache is OK, we can get all messages from local cache if ($cache_status>0) { - $a_msg_headers = $this->get_message_cache($cache_key, $start_msg, $start_msg+$this->page_size, $sort_field, $sort_order); + $a_msg_headers = $this->get_message_cache($cache_key, $start_msg, $start_msg+$this->page_size, $this->sort_field, $this->sort_order); $headers_sorted = TRUE; } else { // retrieve headers from IMAP - if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $sort_field))) + if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field))) { //console("$mailbox: ".count($msg_index)); $msgs = $msg_index[$begin]; for ($i=$begin; $i < $end; $i++) { - if ($sort_order == 'DESC') + if ($this->sort_order == 'DESC') $msgs = $msg_index[$i].','.$msgs; else $msgs = $msgs.','.$msg_index[$i]; @@ -377,10 +395,10 @@ class rcube_imap // cache is dirty, sync it - if ($this->caching_enabled && $cache_status==-1) + if ($this->caching_enabled && $cache_status==-1 && !$recursive) { $this->sync_header_index($mailbox); - return $this->_list_headers($mailbox, $page, $sort_field, $sort_order); + return $this->_list_headers($mailbox, $page, $this->sort_field, $this->sort_order, TRUE); } @@ -390,7 +408,7 @@ class rcube_imap // fetch reuested headers from server $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs); $a_msg_headers = array(); - + $deleted_count = 0; if (!empty($a_header_index)) { @@ -402,6 +420,7 @@ class rcube_imap if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid) $this->remove_message_cache($cache_key, $headers->id); + $deleted_count++; continue; } @@ -417,7 +436,11 @@ class rcube_imap $this->clear_message_cache($cache_key, $max); + // fetch more headers of there were any deleted messages + // ... + // kick child process to sync cache + // ... } @@ -429,26 +452,70 @@ class rcube_imap // if not already sorted if (!$headers_sorted) - $a_msg_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order); + $a_msg_headers = iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order); return array_values($a_msg_headers); } // return sorted array of message UIDs - function message_index($mbox='', $sort_field='date', $sort_order='DESC') + function message_index($mbox='', $sort_field=NULL, $sort_order=NULL) { + if ($sort_field!=NULL) + $this->sort_field = $sort_field; + if ($sort_order!=NULL) + $this->sort_order = strtoupper($sort_order); + $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; - $a_out = array(); + $key = "$mbox:".$this->sort_field.":".$this->sort_order.".msgi"; - // get array of message headers - $a_headers = $this->_list_headers($mailbox, 'all', $sort_field, $sort_order); + // have stored it in RAM + if (isset($this->cache[$key])) + return $this->cache[$key]; - if (is_array($a_headers)) - foreach ($a_headers as $header) - $a_out[] = $header->uid; + // check local cache + $cache_key = $mailbox.'.msg'; + $cache_status = $this->check_cache_status($mailbox, $cache_key); - return $a_out; + // cache is OK + if ($cache_status>0) + { + $a_index = get_message_cache_index($cache_key, FALSE, $this->sort_field); + return array_values($a_index); + } + + + // fetch complete message index + $msg_count = $this->_messagecount($mailbox); + if ($this->get_capability('sort') && ($a_index = iil_C_Sort($this->conn, $mailbox, $this->sort_field))) + { + $a_uids = iil_C_FetchUIDs($this->conn, $mailbox); + + if ($this->sort_order == 'DESC') + $a_index = array_reverse($a_index); + + $i = 0; + $this->cache[$key] = array(); + foreach ($a_index as $index => $value) + $this->cache[$key][$i++] = $a_uids[$value]; + } + else + { + $a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, "1:$msg_count", $this->sort_field); + $a_uids = iil_C_FetchUIDs($this->conn, $mailbox); + + if ($this->sort_order=="ASC") + asort($a_index); + else if ($this->sort_order=="DESC") + arsort($a_index); + + $i = 0; + $this->cache[$key] = array(); + foreach ($a_index as $index => $value) + $this->cache[$key][$i++] = $a_uids[$index]; + } + + return $this->cache[$key]; } @@ -506,6 +573,12 @@ class rcube_imap function search($mbox='', $criteria='ALL') { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; + return $this->_search_index($mailbox, $criteria); + } + + + function _search_index($mailbox, $criteria='ALL') + { $a_messages = iil_C_Search($this->conn, $mailbox, $criteria); return $a_messages; } @@ -570,20 +643,20 @@ class rcube_imap $uids = array($uids); foreach ($uids as $uid) - $msg_ids[] = $this->_uid2id($uid); + $msg_ids[$uid] = $this->_uid2id($uid); if ($flag=='UNSEEN') - $result = iil_C_Unseen($this->conn, $this->mailbox, join(',', $msg_ids)); + $result = iil_C_Unseen($this->conn, $this->mailbox, join(',', array_values($msg_ids))); else - $result = iil_C_Flag($this->conn, $this->mailbox, join(',', $msg_ids), $flag); + $result = iil_C_Flag($this->conn, $this->mailbox, join(',', array_values($msg_ids)), $flag); // reload message headers if cached $cache_key = $this->mailbox.'.msg'; if ($this->caching_enabled) { - foreach ($msg_ids as $id) + foreach ($msg_ids as $uid => $id) { - if ($cached_headers = $this->get_cached_message($cache_key, $id)) + if ($cached_headers = $this->get_cached_message($cache_key, $uid)) { $this->remove_message_cache($cache_key, $id); //$this->get_headers($uid); @@ -596,7 +669,7 @@ class rcube_imap } // set nr of messages that were flaged - $count = sizeof($msg_ids); + $count = count($msg_ids); // clear message count cache if ($result && $flag=='SEEN') @@ -1160,7 +1233,7 @@ class rcube_imap } - function get_message_cache_index($key, $force=FALSE) + function get_message_cache_index($key, $force=FALSE, $sort_col='idx') { static $sa_message_index = array(); @@ -1173,7 +1246,7 @@ class rcube_imap FROM ".get_table_name('messages')." WHERE user_id=? AND cache_key=? - ORDER BY idx ASC", + ORDER BY ".$sort_col." ASC", $_SESSION['user_id'], $key); @@ -1186,6 +1259,9 @@ class rcube_imap function add_message_cache($key, $index, $headers) { + if (!is_object($headers) || empty($headers->uid)) + return; + $this->db->query( "INSERT INTO ".get_table_name('messages')." (user_id, del, cache_key, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers) @@ -1198,7 +1274,7 @@ class rcube_imap $this->decode_header($headers->from, TRUE), $this->decode_header($headers->to, TRUE), $this->decode_header($headers->cc, TRUE), - $headers->size, + (int)$headers->size, serialize($headers)); } @@ -1268,7 +1344,7 @@ class rcube_imap function decode_header($input, $remove_quotes=FALSE) { - $str = $this->decode_mime_string($input); + $str = $this->decode_mime_string((string)$input); if ($str{0}=='"' && $remove_quotes) { $str = str_replace('"', '', $str); @@ -1518,6 +1594,10 @@ class rcube_imap // add incremental value to messagecount $a_mailbox_cache[$mailbox][$mode] += $increment; + + // there's something wrong, delete from cache + if ($a_mailbox_cache[$mailbox][$mode] < 0) + unset($a_mailbox_cache[$mailbox][$mode]); // write back to cache $this->update_cache('messagecount', $a_mailbox_cache); diff --git a/program/lib/imap.inc b/program/lib/imap.inc index 6ca522084..a1dbd7b98 100644 --- a/program/lib/imap.inc +++ b/program/lib/imap.inc @@ -618,7 +618,7 @@ function iil_C_Sort(&$conn, $mailbox, $field){ if (!$fields[$field]) return false; $fp = $conn->fp; - $command = 's SORT ('.$field.') US-ASCII ALL'."\r\n"; + $command = 's SORT ('.$field.') US-ASCII ALL UNDELETED'."\r\n"; $line = $data = ''; if (!fputs($fp, $command)) return false; diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index c81dd2fd2..74a967870 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -528,12 +528,11 @@ function rcmail_get_messagecount_text() if (isset($MESSAGE['index'])) { - $a_msg_index = $IMAP->message_index(); return rcube_label(array('name' => 'messagenrof', 'vars' => array('nr' => $MESSAGE['index']+1, - 'count' => sizeof($a_msg_index)))); + 'count' => $IMAP->messagecount()))); } - + $start_msg = ($IMAP->list_page-1) * $IMAP->page_size + 1; $max = $IMAP->messagecount(); |