From 745b1466fc76d5ded589e2469328086002430c1c Mon Sep 17 00:00:00 2001 From: thomascube <thomas@roundcube.net> Date: Wed, 22 Feb 2006 16:58:00 -0500 Subject: [PATCH] Updated localizations --- program/include/rcube_imap.inc | 496 +++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 392 insertions(+), 104 deletions(-) diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index ed7c3ed..71a5cb6 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,33 +59,53 @@ 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; // 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; } @@ -84,7 +119,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 +149,12 @@ } + /** + * Close IMAP connection + * Usually done on script shutdown + * + * @access public + */ function close() { if ($this->conn) @@ -121,6 +162,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 +175,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 +196,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 +219,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 +241,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 +291,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 +308,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 +337,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 +376,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,20 +456,39 @@ } - // 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 header + * + * @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; @@ -322,7 +498,7 @@ $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; @@ -330,7 +506,7 @@ else { $begin = $start_msg; - $end = $start_msg + $this->page_size; + $end = $start_msg + $this->page_size; } if ($begin < 0) $begin = 0; @@ -348,22 +524,22 @@ // 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++) + for ($i=$begin+1; $i < $end; $i++) { - if ($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]; } @@ -377,47 +553,24 @@ // 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 + // ... } @@ -429,26 +582,117 @@ // 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') + /** + * 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) + { + 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 = $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))) + { + $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,20 +750,26 @@ 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; } - 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 +820,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 +846,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 +865,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 +885,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 +984,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 +1059,22 @@ // 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); + return sprintf("%.2fMB / %.2fMB (%.0f%%)", $result["used"] / 1000.0, $result["total"] / 1000.0, $result["percent"]); + } + else + return 'unknown'; } @@ -1160,7 +1441,7 @@ } - 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(); @@ -1173,7 +1454,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 +1467,22 @@ 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) - 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 +1552,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 +1607,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 +1658,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; } @@ -1518,6 +1802,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 +1936,4 @@ return trim($output); } -?> +?> \ No newline at end of file -- Gitblit v1.9.1