From 6204390af16bcf50f82da61a1aefc2ad0c0adf94 Mon Sep 17 00:00:00 2001 From: thomascube <thomas@roundcube.net> Date: Mon, 01 May 2006 10:47:27 -0400 Subject: [PATCH] Applied patch for requesting receipts by Salvatore Ansani --- program/include/rcube_imap.inc | 661 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 547 insertions(+), 114 deletions(-) diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index ed7c3ed..c818fa0 100644 --- a/program/include/rcube_imap.inc +++ b/program/include/rcube_imap.inc @@ -21,11 +21,24 @@ */ +/** + * Obtain classes from the Iloha IMAP library + */ require_once('lib/imap.inc'); require_once('lib/mime.inc'); require_once('lib/utf7.inc'); +/** + * Interface class for accessing an IMAP server + * + * This is a wrapper that implements the Iloha IMAP Library (IIL) + * + * @package RoundCube Webmail + * @author Thomas Bruederli <roundcube@gmail.com> + * @version 1.22 + * @link http://ilohamail.org + */ class rcube_imap { var $db; @@ -35,6 +48,8 @@ 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'); @@ -44,38 +59,60 @@ var $uid_id_map = array(); var $msg_headers = array(); var $capabilities = array(); + var $skip_deleted = FALSE; + var $debug_level = 1; - // PHP 5 constructor + /** + * Object constructor + * + * @param object Database connection + */ function __construct($db_conn) { - $this->db = $db_conn; + $this->db = $db_conn; } - // PHP 4 compatibility + + /** + * PHP 4 object constructor + * + * @see rcube_imap::__construct + */ function rcube_imap($db_conn) { $this->__construct($db_conn); } + /** + * Connect to an IMAP server + * + * @param string Host to connect + * @param string Username for IMAP account + * @param string Password for IMAP account + * @param number Port to connect to + * @param boolean Use SSL connection + * @return boolean TRUE on success, FALSE on failure + * @access public + */ function connect($host, $user, $pass, $port=143, $use_ssl=FALSE) { - global $ICL_SSL, $ICL_PORT, $CONFIG; + global $ICL_SSL, $ICL_PORT, $IMAP_USE_INTERNAL_DATE; // check for Open-SSL support in PHP build if ($use_ssl && in_array('openssl', get_loaded_extensions())) $ICL_SSL = TRUE; else if ($use_ssl) { - raise_error(array('code' => 403, - 'type' => 'imap', - 'file' => __FILE__, + raise_error(array('code' => 403, 'type' => 'imap', 'file' => __FILE__, 'message' => 'Open SSL not available;'), TRUE, FALSE); $port = 143; } $ICL_PORT = $port; + $IMAP_USE_INTERNAL_DATE = false; + $this->conn = iil_Connect($host, $user, $pass, array('imap' => 'check')); $this->host = $host; $this->user = $user; @@ -84,7 +121,7 @@ $this->ssl = $use_ssl; // print trace mesages - if ($this->conn && ($CONFIG['debug_level'] & 8)) + if ($this->conn && ($this->debug_level & 8)) console($this->conn->message); // write error log @@ -114,6 +151,12 @@ } + /** + * Close IMAP connection + * Usually done on script shutdown + * + * @access public + */ function close() { if ($this->conn) @@ -121,6 +164,12 @@ } + /** + * Close IMAP connection and re-connect + * This is used to avoid some strange socket errors when talking to Courier IMAP + * + * @access public + */ function reconnect() { $this->close(); @@ -128,6 +177,15 @@ } + /** + * Set a root folder for the IMAP connection. + * + * Only folders within this root folder will be displayed + * and all folder paths will be translated using this folder name + * + * @param string Root folder + * @access public + */ function set_rootdir($root) { if (ereg('[\.\/]$', $root)) //(substr($root, -1, 1)==='/') @@ -140,6 +198,12 @@ } + /** + * This list of folders will be listed above all other folders + * + * @param array Indexed list of folder names + * @access public + */ function set_default_mailboxes($arr) { if (is_array($arr)) @@ -157,6 +221,14 @@ } + /** + * Set internal mailbox reference. + * + * All operations will be perfomed on this mailbox/folder + * + * @param string Mailbox/Folder name + * @access public + */ function set_mailbox($mbox) { $mailbox = $this->_mod_mailbox($mbox); @@ -171,24 +243,49 @@ } + /** + * Set internal list page + * + * @param number Page number to list + * @access public + */ function set_page($page) { $this->list_page = (int)$page; } + /** + * Set internal page size + * + * @param number Number of messages to display on one page + * @access public + */ function set_pagesize($size) { $this->page_size = (int)$size; } + /** + * Returns the currently used mailbox name + * + * @return string Name of the mailbox/folder + * @access public + */ function get_mailbox_name() { return $this->conn ? $this->_mod_mailbox($this->mailbox, 'out') : ''; } + /** + * Returns the IMAP server's capability + * + * @param string Capability name + * @return mixed Capability value or TRUE if supported, FALSE if not + * @access public + */ function get_capability($cap) { $cap = strtoupper($cap); @@ -196,6 +293,12 @@ } + /** + * Returns the delimiter that is used by the IMAP server for folder separation + * + * @return string Delimiter string + * @access public + */ function get_hierarchy_delimiter() { if ($this->conn && empty($this->delimiter)) @@ -207,8 +310,17 @@ return $this->delimiter; } - // public method for mailbox listing - // convert mailbox name with root dir first + + /** + * Public method for mailbox listing. + * + * Converts mailbox name with root dir first + * + * @param string Optional root folder + * @param string Optional filter for mailbox listing + * @return array List of mailboxes/folders + * @access public + */ function list_mailboxes($root='', $filter='*') { $a_out = array(); @@ -227,7 +339,14 @@ return $a_out; } - // private method for mailbox listing + + /** + * Private method for mailbox listing + * + * @return array List of mailboxes/folders + * @access private + * @see rcube_imap::list_mailboxes + */ function _list_mailboxes($root='', $filter='*') { $a_defaults = $a_out = array(); @@ -259,39 +378,79 @@ } - // get message count for a specific mailbox; acceptes modes are: ALL, UNSEEN + /** + * Get message count for a specific mailbox + * + * @param string Mailbox/folder name + * @param string Mode for count [ALL|UNSEEN|RECENT] + * @param boolean Force reading from server and update cache + * @return number Number of messages + * @access public + */ function messagecount($mbox='', $mode='ALL', $force=FALSE) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; return $this->_messagecount($mailbox, $mode, $force); } - // private method for getting nr of mesages + + /** + * Private method for getting nr of messages + * + * @access private + * @see rcube_imap::messagecount + */ function _messagecount($mailbox='', $mode='ALL', $force=FALSE) { $a_mailbox_cache = FALSE; $mode = strtoupper($mode); - if (!$mailbox) + if (empty($mailbox)) $mailbox = $this->mailbox; $a_mailbox_cache = $this->get_cache('messagecount'); // 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]; - // get message count and store in cache - if ($mode == 'UNSEEN') - $count = iil_C_CountUnseen($this->conn, $mailbox); + // RECENT count is fetched abit different + if ($mode == 'RECENT') + $count = iil_C_CheckForRecent($this->conn, $mailbox); + + // use SEARCH for message counting + else if ($this->skip_deleted) + { + $search_str = "ALL UNDELETED"; + + // get message count and store in cache + if ($mode == 'UNSEEN') + $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); + } + } else - $count = iil_C_CountMessages($this->conn, $mailbox); + { + if ($mode == 'UNSEEN') + $count = iil_C_CountUnseen($this->conn, $mailbox); + else + $count = iil_C_CountMessages($this->conn, $mailbox); + } - if (is_array($a_mailbox_cache[$mailbox])) + 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); @@ -299,30 +458,52 @@ } - // public method for listing headers - // convert mailbox name with root dir first - function list_headers($mbox='', $page=NULL, $sort_field='date', $sort_order='DESC') + /** + * Public method for listing headers + * convert mailbox name with root dir first + * + * @param string Mailbox/folder name + * @param number 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_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); } - // private method for listing message header - function _list_headers($mailbox='', $page=NULL, $sort_field='date', $sort_order='DESC') + /** + * Private method for listing message headers + * + * @access private + * @see rcube_imap::list_headers + */ + 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; + list($begin, $end) = $this->_get_message_range($max, $page); + + /* if ($page=='all') { $begin = 0; $end = $max; } - else if ($sort_order=='DESC') + else if (!$this->get_capability('sort') && $this->sort_order=='DESC') { $begin = $max - $this->page_size - $start_msg; $end = $max - $start_msg; @@ -330,13 +511,14 @@ else { $begin = $start_msg; - $end = $start_msg + $this->page_size; + $end = $start_msg + $this->page_size; } if ($begin < 0) $begin = 0; if ($end < 0) $end = $max; if ($end > $max) $end = $max; - + */ + //console("fetch headers $start_msg to ".($start_msg+$this->page_size)." (msg $begin to $end)"); $headers_sorted = FALSE; @@ -348,24 +530,19 @@ // 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, $this->skip_deleted ? 'UNDELETED' : ''))) { -//console("$mailbox: ".count($msg_index)); +//console("$mailbox: ".join(',', $msg_index)); $msgs = $msg_index[$begin]; - for ($i=$begin; $i < $end; $i++) - { - if ($sort_order == 'DESC') - $msgs = $msg_index[$i].','.$msgs; - else - $msgs = $msgs.','.$msg_index[$i]; - } + for ($i=$begin+1; $i < $end; $i++) + $msgs = $msgs.','.$msg_index[$i]; $sorted = TRUE; } @@ -377,47 +554,23 @@ // 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); } - - // cache is incomplete - $cache_index = $this->get_message_cache_index($cache_key); // fetch reuested headers from server - $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs); $a_msg_headers = array(); - - - if (!empty($a_header_index)) - { - foreach ($a_header_index as $i => $headers) - { - if ($headers->deleted) - { - // delete from cache - if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid) - $this->remove_message_cache($cache_key, $headers->id); - - continue; - } - - // add message to cache - if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid) - $this->add_message_cache($cache_key, $headers->id, $headers); - - $a_msg_headers[$headers->uid] = $headers; - } - } + $deleted_count = $this->_fetch_headers($mailbox, $msgs, $a_msg_headers, $cache_key); // delete cached messages with a higher index than $max $this->clear_message_cache($cache_key, $max); - + // kick child process to sync cache + // ... } @@ -428,27 +581,213 @@ // if not already sorted - if (!$headers_sorted) - $a_msg_headers = iil_SortHeaders($a_msg_headers, $sort_field, $sort_order); +// if (!$headers_sorted) +// $a_msg_headers = iil_SortHeaders($a_msg_headers, $this->sort_field, $this->sort_order); + + + if (!$headers_sorted && $this->sort_order == 'DESC') + $a_msg_headers = array_reverse($a_msg_headers); + return array_values($a_msg_headers); } + - - // return sorted array of message UIDs - function message_index($mbox='', $sort_field='date', $sort_order='DESC') + /** + * Public method for listing a specific set of headers + * convert mailbox name with root dir first + * + * @param string Mailbox/folder name + * @param array List of message ids to list + * @param number 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='', $msgs, $page=NULL, $sort_field=NULL, $sort_order=NULL) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; - $a_out = array(); + return $this->_list_header_set($mailbox, $msgs, $page, $sort_field, $sort_order); + } + - // get array of message headers - $a_headers = $this->_list_headers($mailbox, 'all', $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) + { + // also accept a comma-separated list of message ids + if (is_string($msgs)) + $msgs = split(',', $msgs); + + if (!strlen($mailbox) || empty($msgs)) + return array(); - if (is_array($a_headers)) - foreach ($a_headers as $header) - $a_out[] = $header->uid; + if ($sort_field!=NULL) + $this->sort_field = $sort_field; + if ($sort_order!=NULL) + $this->sort_order = strtoupper($sort_order); - return $a_out; + $max = count($msgs); + $start_msg = ($this->list_page-1) * $this->page_size; + + // fetch reuested headers from server + $a_msg_headers = array(); + $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(); + + // 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($max-$start_msg, $this->page_size)); + } + + + /** + * Helper function to get first and last index of the requested set + * + * @param number message count + * @param mixed page number to show, or string 'all' + * @return array array with two values: first index, last index + * @access private + */ + function _get_message_range($max, $page) + { + $start_msg = ($this->list_page-1) * $this->page_size; + + if ($page=='all') + { + $begin = 0; + $end = $max; + } + else if ($this->sort_order=='DESC') + { + $begin = $max - $this->page_size - $start_msg; + $end = $max - $start_msg; + } + else + { + $begin = $start_msg; + $end = $start_msg + $this->page_size; + } + + if ($begin < 0) $begin = 0; + if ($end < 0) $end = $max; + if ($end > $max) $end = $max; + + return array($begin, $end); + } + + + + /** + * Fetches message headers + * Used for loop + * + * @param string Mailbox name + * @param string Message index to fetch + * @param array Reference to message headers array + * @param array Array with cache index + * @return number Number of deleted messages + * @access private + */ + function _fetch_headers($mailbox, $msgs, &$a_msg_headers, $cache_key) + { + // cache is incomplete + $cache_index = $this->get_message_cache_index($cache_key); + + // fetch reuested headers from server + $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs); + $deleted_count = 0; + + if (!empty($a_header_index)) + { + foreach ($a_header_index as $i => $headers) + { + if ($headers->deleted && $this->skip_deleted) + { + // delete from cache + if ($cache_index[$headers->id] && $cache_index[$headers->id] == $headers->uid) + $this->remove_message_cache($cache_key, $headers->id); + + $deleted_count++; + continue; + } + + // add message to cache + if ($this->caching_enabled && $cache_index[$headers->id] != $headers->uid) + $this->add_message_cache($cache_key, $headers->id, $headers); + + $a_msg_headers[$headers->uid] = $headers; + } + } + + return $deleted_count; + } + + + // return sorted array of message UIDs + 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; + $key = "$mbox:".$this->sort_field.":".$this->sort_order.".msgi"; + + // have stored it in RAM + if (isset($this->cache[$key])) + return $this->cache[$key]; + + // check local cache + $cache_key = $mailbox.'.msg'; + $cache_status = $this->check_cache_status($mailbox, $cache_key); + + // cache is OK + if ($cache_status>0) + { + $a_index = $this->get_message_cache_index($cache_key, TRUE, $this->sort_field, $this->sort_order); + 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, '', TRUE))) + { + if ($this->sort_order == 'DESC') + $a_index = array_reverse($a_index); + + $this->cache[$key] = $a_index; + + } + 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]; } @@ -503,23 +842,57 @@ } - function search($mbox='', $criteria='ALL') + /** + * Invoke search request to IMAP server + * + * @param string mailbox name to search in + * @param string search criteria (ALL, TO, FROM, SUBJECT, etc) + * @param string search string + * @return array search results as list of message ids + * @access public + */ + function search($mbox='', $criteria='ALL', $str=NULL) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; + if ($str && $criteria) + { + $criteria .= " \"$str\""; + return $this->_search_index($mailbox, $criteria); + } + else + return $this->_search_index($mailbox, $criteria); + } + + + /** + * Private search method + * + * @return array search results as list of message ids + * @access private + * @see rcube_imap::search() + */ + function _search_index($mailbox, $criteria='ALL') + { $a_messages = iil_C_Search($this->conn, $mailbox, $criteria); + + // clean message list (there might be some empty entries) + foreach ($a_messages as $i => $val) + if (empty($val)) + unset($a_messages[$i]); + return $a_messages; } - function get_headers($uid, $mbox=NULL) + function get_headers($id, $mbox=NULL, $is_uid=TRUE) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; // get cached headers - if ($headers = $this->get_cached_message($mailbox.'.msg', $uid)) + if ($is_uid && ($headers = $this->get_cached_message($mailbox.'.msg', $id))) return $headers; - $msg_id = $this->_uid2id($uid); + $msg_id = $is_uid ? $this->_uid2id($id) : $id; $headers = iil_C_FetchHeader($this->conn, $mailbox, $msg_id); // write headers cache @@ -570,20 +943,20 @@ $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 +969,7 @@ } // set nr of messages that were flaged - $count = sizeof($msg_ids); + $count = count($msg_ids); // clear message count cache if ($result && $flag=='SEEN') @@ -615,7 +988,7 @@ { $mailbox = $this->_mod_mailbox($mbox); - // make shure mailbox exists + // make sure mailbox exists if (in_array($mailbox, $this->_list_mailboxes())) $saved = iil_C_Append($this->conn, $mailbox, $message); @@ -635,10 +1008,15 @@ $to_mbox = $this->_mod_mailbox($to_mbox); $from_mbox = $from_mbox ? $this->_mod_mailbox($from_mbox) : $this->mailbox; - // make shure mailbox exists + // make sure mailbox exists if (!in_array($to_mbox, $this->_list_mailboxes())) - return FALSE; - + { + if (in_array(strtolower($to_mbox), $this->default_folders)) + $this->create_mailbox($to_mbox, TRUE); + else + return FALSE; + } + // convert the list of uids to array $a_uids = is_string($uids) ? explode(',', $uids) : (is_array($uids) ? $uids : NULL); @@ -729,15 +1107,25 @@ // clear all messages in a specific mailbox - function clear_mailbox($mbox) + function clear_mailbox($mbox=NULL) { - $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; + $mailbox = !empty($mbox) ? $this->_mod_mailbox($mbox) : $this->mailbox; $msg_count = $this->_messagecount($mailbox, 'ALL'); if ($msg_count>0) { - $this->clear_message_cache($mailbox.'.msg'); - return iil_C_ClearFolder($this->conn, $mailbox); + $cleared = iil_C_ClearFolder($this->conn, $mailbox); + + // make sure the message count cache is cleared as well + if ($cleared) + { + $this->clear_message_cache($mailbox.'.msg'); + $a_mailbox_cache = $this->get_cache('messagecount'); + unset($a_mailbox_cache[$mailbox]); + $this->update_cache('messagecount', $a_mailbox_cache); + } + + return $cleared; } else return 0; @@ -794,6 +1182,23 @@ // filter folders and sort them $sa_unsubscribed = $this->_sort_mailbox_list($a_folders); return $sa_unsubscribed; + } + + + /** + * Get quota + * added by Nuny + */ + function get_quota() + { + if ($this->get_capability('QUOTA')) + { + $result = iil_C_GetQuota($this->conn); + if ($result["total"]) + return sprintf("%.2fMB / %.2fMB (%.0f%%)", $result["used"] / 1000.0, $result["total"] / 1000.0, $result["percent"]); + } + + return FALSE; } @@ -1074,14 +1479,14 @@ $header = iil_C_FetchHeader($this->conn, $mailbox, "$msg_count"); $cache_uid = array_pop($cache_index); - // uids of highes message matches -> cache seems OK + // uids of highest message matches -> cache seems OK if ($cache_uid == $header->uid) return 1; // cache is dirty return -1; } - // if cache count differs less that 10% report as dirty + // if cache count differs less than 10% report as dirty else if (abs($msg_count - $cache_count) < $msg_count/10) return -1; else @@ -1160,9 +1565,13 @@ } - function get_message_cache_index($key, $force=FALSE) + function get_message_cache_index($key, $force=FALSE, $sort_col='idx', $sort_order='ASC') { static $sa_message_index = array(); + + // empty key -> empty array + if (empty($key)) + return array(); if (!empty($sa_message_index[$key]) && !$force) return $sa_message_index[$key]; @@ -1173,7 +1582,7 @@ FROM ".get_table_name('messages')." WHERE user_id=? AND cache_key=? - ORDER BY idx ASC", + ORDER BY ".$this->db->quote_identifier($sort_col)." ".$sort_order, $_SESSION['user_id'], $key); @@ -1186,19 +1595,22 @@ function add_message_cache($key, $index, $headers) { + if (!$key || !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) - VALUES (?, 0, ?, ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?)", + (user_id, del, cache_key, created, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers) + VALUES (?, 0, ?, now(), ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?)", $_SESSION['user_id'], $key, $index, $headers->uid, - $this->decode_header($headers->subject, TRUE), - $this->decode_header($headers->from, TRUE), - $this->decode_header($headers->to, TRUE), - $this->decode_header($headers->cc, TRUE), - $headers->size, + (string)substr($this->decode_header($headers->subject, TRUE), 0, 128), + (string)substr($this->decode_header($headers->from, TRUE), 0, 128), + (string)substr($this->decode_header($headers->to, TRUE), 0, 128), + (string)substr($this->decode_header($headers->cc, TRUE), 0, 128), + (int)$headers->size, serialize($headers)); } @@ -1268,7 +1680,7 @@ 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); @@ -1323,10 +1735,10 @@ $rest = quoted_printable_decode($rest); } - return decode_specialchars($rest, $a[0]); + return rcube_charset_convert($rest, $a[0]); } else - return $str; //we dont' know what to do with this + return $str; // we dont' know what to do with this } @@ -1374,7 +1786,7 @@ function charset_decode($body, $ctype_param) { if (is_array($ctype_param) && !empty($ctype_param['charset'])) - return decode_specialchars($body, $ctype_param['charset']); + return rcube_charset_convert($body, $ctype_param['charset']); return $body; } @@ -1423,6 +1835,15 @@ return array_merge($a_defaults, $a_out); } + function get_id($uid) + { + return $this->_uid2id($uid); + } + + function get_uid($id) + { + return $this->_id2uid($id); + } function _uid2id($uid, $mbox=NULL) { @@ -1433,6 +1854,14 @@ $this->uid_id_map[$mbox][$uid] = iil_C_UID2ID($this->conn, $mbox, $uid); return $this->uid_id_map[$mbox][$uid]; + } + + function _id2uid($id, $mbox=NULL) + { + if (!$mbox) + $mbox = $this->mailbox; + + return iil_C_ID2UID($this->conn, $mbox, $id); } @@ -1518,6 +1947,10 @@ // 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); @@ -1648,4 +2081,4 @@ return trim($output); } -?> +?> \ No newline at end of file -- Gitblit v1.9.1