diff options
author | thomascube <thomas@roundcube.net> | 2006-01-05 00:37:10 +0000 |
---|---|---|
committer | thomascube <thomas@roundcube.net> | 2006-01-05 00:37:10 +0000 |
commit | 15a9d1ce671fcbc44ea3e4858d7aa6f5b22300c9 (patch) | |
tree | 30e15c3f52ff435d5b08691424515995d8b077c9 /program/include | |
parent | 977a295eb1e97e0c230063da40b8296fca778814 (diff) |
Optimized loading time; added periodic mail check; added EXPUNGE command
Diffstat (limited to 'program/include')
-rw-r--r-- | program/include/main.inc | 106 | ||||
-rwxr-xr-x | program/include/rcube_db.inc | 251 | ||||
-rw-r--r-- | program/include/rcube_imap.inc | 289 |
3 files changed, 513 insertions, 133 deletions
diff --git a/program/include/main.inc b/program/include/main.inc index 4cfb5b270..24110d343 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -146,6 +146,9 @@ function rcmail_imap_init($connect=FALSE) global $CONFIG, $DB, $IMAP; $IMAP = new rcube_imap($DB); + $IMAP->debug_level = $CONFIG['debug_level']; + $IMAP->skip_deleted = $CONFIG['skip_deleted']; + // connect with stored session data if ($connect) @@ -591,14 +594,25 @@ function decrypt_passwd($cypher) // send correct response on a remote request -function rcube_remote_response($js_code) +function rcube_remote_response($js_code, $flush=FALSE) { - send_nocacheing_headers(); - header('Content-Type: application/x-javascript'); + static $s_header_sent = FALSE; + + if (!$s_header_sent) + { + $s_header_sent = TRUE; + send_nocacheing_headers(); + header('Content-Type: application/x-javascript'); + print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n"; + } - print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n"; + // send response code print $js_code; - exit; + + if ($flush) // flush the output buffer + flush(); + else // terminate script + exit; } @@ -879,8 +893,13 @@ function rcube_xml_command($command, $str_attrib, $a_attrib=NULL) $object = strtolower($attrib['name']); $object_handlers = array( + // GENERAL + 'loginform' => 'rcmail_login_form', + 'username' => 'rcmail_current_username', + // MAIL 'mailboxlist' => 'rcmail_mailbox_list', + 'message' => 'rcmail_message_container', 'messages' => 'rcmail_message_list', 'messagecountdisplay' => 'rcmail_messagecount_display', 'messageheaders' => 'rcmail_message_headers', @@ -916,32 +935,28 @@ function rcube_xml_command($command, $str_attrib, $a_attrib=NULL) 'composebody' => 'rcmail_compose_body' ); - if ($object=='loginform') - return rcmail_login_form($attrib); - - else if ($object=='message') - return rcmail_message_container($attrib); // execute object handler function - else if ($object_handlers[$object] && function_exists($object_handlers[$object])) + if ($object_handlers[$object] && function_exists($object_handlers[$object])) return call_user_func($object_handlers[$object], $attrib); else if ($object=='pagetitle') { $task = $GLOBALS['_task']; + $title = !empty($CONFIG['product_name']) ? $CONFIG['product_name'].' :: ' : ''; + if ($task=='mail' && isset($GLOBALS['MESSAGE']['subject'])) - return rep_specialchars_output("RoundCube|Mail :: ".$GLOBALS['MESSAGE']['subject']); + $title .= $GLOBALS['MESSAGE']['subject']; else if (isset($GLOBALS['PAGE_TITLE'])) - return rep_specialchars_output("RoundCube|Mail :: ".$GLOBALS['PAGE_TITLE']); + $title .= $GLOBALS['PAGE_TITLE']; else if ($task=='mail' && ($mbox_name = $IMAP->get_mailbox_name())) - return "RoundCube|Mail :: ".rep_specialchars_output(UTF7DecodeString($mbox_name), 'html', 'all'); + $title .= UTF7DecodeString($mbox_name); else - return "RoundCube|Mail :: $task"; + $title .= $task; + + return rep_specialchars_output($title, 'html', 'all'); } - else if ($object=='about') - return ''; - break; } @@ -1266,6 +1281,38 @@ function rcmail_message_container($attrib) } +// return the IMAP username of the current session +function rcmail_current_username($attrib) + { + global $DB; + static $s_username; + + // alread fetched + if (!empty($s_username)) + return $s_username; + + // get e-mail address form default identity + $sql_result = $DB->query("SELECT email AS mailto + FROM ".get_table_name('identities')." + WHERE user_id=? + AND standard=1 + AND del<>1", + $_SESSION['user_id']); + + if ($DB->num_rows($sql_result)) + { + $sql_arr = $DB->fetch_assoc($sql_result); + $s_username = $sql_arr['mailto']; + } + else if (strstr($_SESSION['username'], '@')) + $s_username = $_SESSION['username']; + else + $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host']; + + return $s_username; + } + + // return code for the webmail login form function rcmail_login_form($attrib) { @@ -1373,4 +1420,27 @@ function rcmail_charset_selector($attrib) } + +function rcube_timer() + { + list($usec, $sec) = explode(" ", microtime()); + return ((float)$usec + (float)$sec); + } + + +function rcube_print_time($timer, $label='Timer') + { + static $print_count = 0; + + $print_count++; + $now = rcube_timer(); + $diff = $now-$timer; + + if (empty($label)) + $label = 'Timer '.$print_count; + + console(sprintf("%s: %0.4f sec", $label, $diff)); + } + + ?>
\ No newline at end of file diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.inc index acb13ce37..e54dcc989 100755 --- a/program/include/rcube_db.inc +++ b/program/include/rcube_db.inc @@ -20,8 +20,24 @@ */ + +/** + * Obtain the PEAR::DB class that is used for abstraction + */ require_once('DB.php'); + +/** + * Database independent query interface + * + * This is a wrapper for the PEAR::DB class + * + * @package RoundCube Webmail + * @author David Saez Padros <david@ols.es> + * @author Thomas Bruederli <roundcube@gmail.com> + * @version 1.14 + * @link http://pear.php.net/package/DB + */ class rcube_db { var $db_dsnw; // DSN for write operations @@ -34,8 +50,13 @@ class rcube_db var $last_res_id = 0; - // PHP 5 constructor - function __construct($db_dsnw,$db_dsnr='') + /** + * Object constructor + * + * @param string DSN for read/write operations + * @param string Optional DSN for read only operations + */ + function __construct($db_dsnw, $db_dsnr='') { if ($db_dsnr=='') $db_dsnr=$db_dsnw; @@ -48,25 +69,44 @@ class rcube_db } - // PHP 4 compatibility + /** + * PHP 4 object constructor + * + * @see rcube_db::__construct + */ function rcube_db($db_dsnw,$db_dsnr='') { $this->__construct($db_dsnw,$db_dsnr); } - // Connect to specific database + /** + * Object destructor + */ + function __destruct() + { + // before closing the database connection, write session data + session_write_close(); + } + + + /** + * Connect to specific database + * + * @param string DSN for DB connections + * @return object PEAR database handle + * @access private + */ function dsn_connect($dsn) { // Use persistent connections if available $dbh = DB::connect($dsn, array('persistent' => TRUE)); if (DB::isError($dbh)) - raise_error(array('code' => 500, - 'type' => 'db', - 'line' => __LINE__, - 'file' => __FILE__, + { + raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $dbh->getMessage()), TRUE, FALSE); + } else if ($this->db_provider=='sqlite') { @@ -79,8 +119,14 @@ class rcube_db } - // Connect to appropiate databse - function db_connect ($mode) + /** + * Connect to appropiate databse + * depending on the operation + * + * @param string Connection mode (r|w) + * @access public + */ + function db_connect($mode) { $this->db_mode = $mode; @@ -99,7 +145,7 @@ class rcube_db if ($this->db_mode==$mode) return; } - + if ($mode=='r') $dsn = $this->db_dsnr; else @@ -110,7 +156,14 @@ class rcube_db } - // Query database + /** + * Execute a SQL query + * + * @param string SQL query to execute + * @param mixed Values to be inserted in query + * @return number Query handle identifier + * @access public + */ function query() { $params = func_get_args(); @@ -120,7 +173,16 @@ class rcube_db } - // Query with limits + /** + * Execute a SQL query with limits + * + * @param string SQL query to execute + * @param number Offset for LIMIT statement + * @param number Number of rows for LIMIT statement + * @param mixed Values to be inserted in query + * @return number Query handle identifier + * @access public + */ function limitquery() { $params = func_get_args(); @@ -132,6 +194,16 @@ class rcube_db } + /** + * Execute a SQL query with limits + * + * @param string SQL query to execute + * @param number Offset for LIMIT statement + * @param number Number of rows for LIMIT statement + * @param array Values to be inserted in query + * @return number Query handle identifier + * @access private + */ function _query($query, $offset, $numrows, $params) { // Read or write ? @@ -155,6 +227,14 @@ class rcube_db } + /** + * Get number of rows for a SQL query + * If no query handle is specified, the last query will be taken as reference + * + * @param number Optional query handle identifier + * @return mixed Number of rows or FALSE on failure + * @access public + */ function num_rows($res_id=NULL) { if (!$this->db_handle) @@ -167,7 +247,13 @@ class rcube_db } - function affected_rows($res_id=NULL) + /** + * Get number of affected rows fort he last query + * + * @return mixed Number of rows or FALSE on failure + * @access public + */ + function affected_rows() { if (!$this->db_handle) return FALSE; @@ -176,6 +262,14 @@ class rcube_db } + /** + * Get last inserted record ID + * For Postgres databases, a sequence name is required + * + * @param string Sequence name for increment + * @return mixed ID or FALSE on failure + * @access public + */ function insert_id($sequence = '') { if (!$this->db_handle || $this->db_mode=='r') @@ -185,10 +279,12 @@ class rcube_db { case 'pgsql': // PostgreSQL uses sequences - $result =& $this->db_handle->getOne("SELECT CURRVAL('$sequence')"); + $result = &$this->db_handle->getOne("SELECT CURRVAL('$sequence')"); if (DB::isError($result)) + { raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $result->getMessage()), TRUE, FALSE); + } return $result; @@ -207,6 +303,14 @@ class rcube_db } + /** + * Get an associative array for one row + * If no query handle is specified, the last query will be taken as reference + * + * @param number Optional query handle identifier + * @return mixed Array with col values or FALSE on failure + * @access public + */ function fetch_assoc($res_id=NULL) { $result = $this->_get_result($res_id); @@ -222,30 +326,66 @@ class rcube_db } - function quote($input, $type=null) + /** + * Formats input so it can be safely used in a query + * + * @param mixed Value to quote + * @return string Quoted/converted string for use in query + * @access public + */ + function quote($input) { + // create DB handle if not available if (!$this->db_handle) $this->db_connect('r'); - - return $this->db_handle->quote($input); + + // escape pear identifier chars + $rep_chars = array('?' => '\?', + '!' => '\!', + '&' => '\&'); + + return $this->db_handle->quoteSmart(strtr($input, $rep_chars)); } + /** + * Quotes a string so it can be safely used as a table or column name + * + * @param string Value to quote + * @return string Quoted string for use in query + * @deprecated Replaced by rcube_db::quote_identifier + * @see rcube_db::quote_identifier + * @access public + */ function quoteIdentifier($str) { - if (!$this->db_handle) - $this->db_connect('r'); - - return $this->db_handle->quoteIdentifier($str); + return $this->quote_identifier($str); } + /** + * Quotes a string so it can be safely used as a table or column name + * + * @param string Value to quote + * @return string Quoted string for use in query + * @access public + */ function quote_identifier($str) { - return $this->quoteIdentifier($str); + if (!$this->db_handle) + $this->db_connect('r'); + + return $this->db_handle->quoteIdentifier($str); } + /** + * Return SQL statement to convert a field value into a unix timestamp + * + * @param string Field name + * @return string SQL statement to use in query + * @access public + */ function unixtimestamp($field) { switch($this->db_provider) @@ -260,6 +400,13 @@ class rcube_db } + /** + * Return SQL statement to convert from a unix timestamp + * + * @param string Field name + * @return string SQL statement to use in query + * @access public + */ function fromunixtime($timestamp) { switch($this->db_provider) @@ -275,13 +422,20 @@ class rcube_db } + /** + * Adds a query result and returns a handle ID + * + * @param object Query handle + * @return mixed Handle ID or FALE on failure + * @access private + */ function _add_result($res) { // sql error occured if (DB::isError($res)) { raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 1024)), TRUE, FALSE); + 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)), TRUE, FALSE); return FALSE; } else @@ -294,7 +448,15 @@ class rcube_db } - function _get_result($res_id) + /** + * Resolves a given handle ID and returns the according query handle + * If no ID is specified, the last ressource handle will be returned + * + * @param number Handle ID + * @return mixed Ressource handle or FALE on failure + * @access private + */ + function _get_result($res_id=NULL) { if ($res_id==NULL) $res_id = $this->last_res_id; @@ -306,16 +468,22 @@ class rcube_db } - // create a sqlite database from a file - function _sqlite_create_database($dbh, $fileName) + /** + * Create a sqlite database from a file + * + * @param object SQLite database handle + * @param string File path to use for DB creation + * @access private + */ + function _sqlite_create_database($dbh, $file_name) { - if (empty($fileName) || !is_string($fileName)) - return ; + if (empty($file_name) || !is_string($file_name)) + return; $data = ''; - if ($fd = fopen($fileName, 'r')) + if ($fd = fopen($file_name, 'r')) { - $data = fread($fd, filesize($fileName)); + $data = fread($fd, filesize($file_name)); fclose($fd); } @@ -323,6 +491,13 @@ class rcube_db sqlite_exec($dbh->connection, $data); } + + /** + * Add some proprietary database functions to the current SQLite handle + * in order to make it MySQL compatible + * + * @access private + */ function _sqlite_prepare() { include_once('include/rcube_sqlite.inc'); @@ -334,21 +509,7 @@ class rcube_db sqlite_create_function($this->db_handle->connection, "md5", "rcube_sqlite_md5"); } -/* - // transform a query so that it is sqlite2 compliant - function _sqlite_prepare_query($query) - { - if (!is_string($query)) - return ($query); - - - $search = array('/NOW\(\)/i', '/`/'); - $replace = array("datetime('now')", '"'); - $query = preg_replace($search, $replace, $query); - return ($query); - } -*/ } // end class rcube_db ?>
\ No newline at end of file diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index 593225da2..7b71dc09c 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; @@ -46,33 +59,53 @@ class rcube_imap 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; } - // 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; // 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; } @@ -86,7 +119,7 @@ class rcube_imap $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 @@ -116,6 +149,12 @@ class rcube_imap } + /** + * Close IMAP connection + * Usually done on script shutdown + * + * @access public + */ function close() { if ($this->conn) @@ -123,6 +162,12 @@ class rcube_imap } + /** + * 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(); @@ -130,6 +175,15 @@ class rcube_imap } + /** + * 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)==='/') @@ -142,6 +196,12 @@ class rcube_imap } + /** + * 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)) @@ -159,6 +219,14 @@ class rcube_imap } + /** + * 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); @@ -173,24 +241,49 @@ class rcube_imap } + /** + * 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); @@ -198,6 +291,12 @@ class rcube_imap } + /** + * 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)) @@ -209,8 +308,17 @@ class rcube_imap 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(); @@ -229,7 +337,14 @@ class rcube_imap 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(); @@ -261,7 +376,7 @@ class rcube_imap } - // get message count for a specific mailbox; acceptes modes are: ALL, UNSEEN + // get message count for a specific mailbox; acceptes modes are: ALL, UNSEEN, RECENT function messagecount($mbox='', $mode='ALL', $force=FALSE) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; @@ -274,7 +389,7 @@ class rcube_imap $a_mailbox_cache = FALSE; $mode = strtoupper($mode); - if (!$mailbox) + if (empty($mailbox)) $mailbox = $this->mailbox; $a_mailbox_cache = $this->get_cache('messagecount'); @@ -282,22 +397,37 @@ 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]; - - $search_str = "ALL UNDELETED"; - // get message count and store in cache - if ($mode == 'UNSEEN') - $search_str .= " UNSEEN"; + // RECENT count is fetched abit different + if ($mode == 'RECENT') + $count = iil_C_CheckForRecent($this->conn, $mailbox); - // 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)) + // use SEARCH for message counting + else if ($this->skip_deleted) { - $str = implode(",", $index); - if (!empty($str)) - $count = count($index); + $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 + { + 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])) @@ -348,7 +478,7 @@ class rcube_imap else { $begin = $start_msg; - $end = $start_msg + $this->page_size; + $end = $start_msg + $this->page_size; } if ($begin < 0) $begin = 0; @@ -372,16 +502,16 @@ class rcube_imap else { // retrieve headers from IMAP - if ($this->get_capability('sort') && ($msg_index = iil_C_Sort($this->conn, $mailbox, $this->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++) + for ($i=$begin+1; $i < $end; $i++) { - if ($this->sort_order == 'DESC') - $msgs = $msg_index[$i].','.$msgs; - else + //if ($this->sort_order == 'DESC') + // $msgs = $msg_index[$i].','.$msgs; + //else $msgs = $msgs.','.$msg_index[$i]; } @@ -401,44 +531,16 @@ class rcube_imap 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(); - $deleted_count = 0; - - 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); - - $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; - } - } + $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); - - // fetch more headers of there were any deleted messages - // ... - + // kick child process to sync cache // ... @@ -458,6 +560,53 @@ class rcube_imap } + /** + * Fetches message headers + * Used for loop + * + * @param string Mailbox name + * @param string Message indey 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) { @@ -584,7 +733,7 @@ class rcube_imap } - function get_headers($uid, $mbox=NULL) + function get_headers($id, $mbox=NULL, $is_uid=TRUE) { $mailbox = $mbox ? $this->_mod_mailbox($mbox) : $this->mailbox; @@ -592,7 +741,7 @@ class rcube_imap if ($headers = $this->get_cached_message($mailbox.'.msg', $uid)) 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 @@ -802,9 +951,9 @@ class rcube_imap // 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) @@ -1270,10 +1419,10 @@ class rcube_imap $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), + substr($this->decode_header($headers->subject, TRUE), 0, 128), + substr($this->decode_header($headers->from, TRUE), 0, 128), + substr($this->decode_header($headers->to, TRUE), 0, 128), + substr($this->decode_header($headers->cc, TRUE), 0, 128), (int)$headers->size, serialize($headers)); } |