summaryrefslogtreecommitdiff
path: root/program/include
diff options
context:
space:
mode:
authorthomascube <thomas@roundcube.net>2006-01-05 00:37:10 +0000
committerthomascube <thomas@roundcube.net>2006-01-05 00:37:10 +0000
commit15a9d1ce671fcbc44ea3e4858d7aa6f5b22300c9 (patch)
tree30e15c3f52ff435d5b08691424515995d8b077c9 /program/include
parent977a295eb1e97e0c230063da40b8296fca778814 (diff)
Optimized loading time; added periodic mail check; added EXPUNGE command
Diffstat (limited to 'program/include')
-rw-r--r--program/include/main.inc106
-rwxr-xr-xprogram/include/rcube_db.inc251
-rw-r--r--program/include/rcube_imap.inc289
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));
}