From 2cdaa79dce689b2dc9ef5c7bf3dcbd9446d86c21 Mon Sep 17 00:00:00 2001
From: Paweł Słowik <pawel.slowik@iq.pl>
Date: Thu, 13 Sep 2012 08:24:01 -0400
Subject: [PATCH] Merge branch 'master' of https://github.com/roundcube/roundcubemail
---
program/include/rcube_imap.php | 607 ++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 445 insertions(+), 162 deletions(-)
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index fa3f60c..0b2f84d 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -19,9 +19,6 @@
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
-
- $Id$
-
*/
@@ -132,7 +129,7 @@
$this->options['ssl_mode'] = $use_ssl == 'imaps' ? 'ssl' : $use_ssl;
}
else if ($use_ssl) {
- raise_error(array('code' => 403, 'type' => 'imap',
+ rcube::raise_error(array('code' => 403, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
'message' => "OpenSSL not available"), true, false);
$port = 143;
@@ -154,7 +151,7 @@
$attempt = 0;
do {
- $data = rcmail::get_instance()->plugins->exec_hook('imap_connect',
+ $data = rcube::get_instance()->plugins->exec_hook('imap_connect',
array_merge($this->options, array('host' => $host, 'user' => $user,
'attempt' => ++$attempt)));
@@ -185,9 +182,9 @@
else if ($this->conn->error) {
if ($pass && $user) {
$message = sprintf("Login failed for %s from %s. %s",
- $user, rcmail_remote_ip(), $this->conn->error);
+ $user, rcube_utils::remote_ip(), $this->conn->error);
- raise_error(array('code' => 403, 'type' => 'imap',
+ rcube::raise_error(array('code' => 403, 'type' => 'imap',
'file' => __FILE__, 'line' => __LINE__,
'message' => $message), true, false);
}
@@ -212,6 +209,8 @@
/**
* Check connection state, connect if not connected.
+ *
+ * @return bool Connection state.
*/
public function check_connection()
{
@@ -360,11 +359,11 @@
return array(
$this->search_string,
- $this->search_set,
- $this->search_charset,
- $this->search_sort_field,
- $this->search_sorted,
- );
+ $this->search_set,
+ $this->search_charset,
+ $this->search_sort_field,
+ $this->search_sorted,
+ );
}
@@ -402,15 +401,56 @@
*/
public function check_permflag($flag)
{
- $flag = strtoupper($flag);
- $imap_flag = $this->conn->flags[$flag];
+ $flag = strtoupper($flag);
+ $imap_flag = $this->conn->flags[$flag];
+ $perm_flags = $this->get_permflags($this->folder);
- if ($this->folder !== null) {
- $this->check_connection();
+ return in_array_nocase($imap_flag, $perm_flags);
+ }
+
+
+ /**
+ * Returns PERMANENTFLAGS of the specified folder
+ *
+ * @param string $folder Folder name
+ *
+ * @return array Flags
+ */
+ public function get_permflags($folder)
+ {
+ if (!strlen($folder)) {
+ return array();
}
- // @TODO: cache permanent flags (?)
+/*
+ Checking PERMANENTFLAGS is rather rare, so we disable caching of it
+ Re-think when we'll use it for more than only MDNSENT flag
- return (in_array_nocase($imap_flag, $this->conn->data['PERMANENTFLAGS']));
+ $cache_key = 'mailboxes.permanentflags.' . $folder;
+ $permflags = $this->get_cache($cache_key);
+
+ if ($permflags !== null) {
+ return explode(' ', $permflags);
+ }
+*/
+ if (!$this->check_connection()) {
+ return array();
+ }
+
+ if ($this->conn->select($folder)) {
+ $permflags = $this->conn->data['PERMANENTFLAGS'];
+ }
+ else {
+ return array();
+ }
+
+ if (!is_array($permflags)) {
+ $permflags = array();
+ }
+/*
+ // Store permflags as string to limit cached object size
+ $this->update_cache($cache_key, implode(' ', $permflags));
+*/
+ return $permflags;
}
@@ -455,7 +495,7 @@
return;
}
- $config = rcmail::get_instance()->config;
+ $config = rcube::get_instance()->config;
$imap_personal = $config->get('imap_ns_personal');
$imap_other = $config->get('imap_ns_other');
$imap_shared = $config->get('imap_ns_shared');
@@ -544,7 +584,7 @@
$folder = $this->folder;
}
- return $this->messagecount($folder, $mode, $force, $status);
+ return $this->countmessages($folder, $mode, $force, $status);
}
@@ -560,12 +600,12 @@
* @return int Number of messages
* @see rcube_imap::count()
*/
- protected function messagecount($folder, $mode='ALL', $force=false, $status=true)
+ protected function countmessages($folder, $mode='ALL', $force=false, $status=true)
{
$mode = strtoupper($mode);
- // count search set
- if ($this->search_string && $folder == $this->folder && ($mode == 'ALL' || $mode == 'THREADS') && !$force) {
+ // count search set, assume search set is always up-to-date (don't check $force flag)
+ if ($this->search_string && $folder == $this->folder && ($mode == 'ALL' || $mode == 'THREADS')) {
if ($mode == 'ALL') {
return $this->search_set->count_messages();
}
@@ -832,8 +872,8 @@
* protected method for setting threaded messages flags:
* depth, has_children and unread_children
*
- * @param array $headers Reference to headers array indexed by message UID
- * @param rcube_imap_result $threads Threads data object
+ * @param array $headers Reference to headers array indexed by message UID
+ * @param rcube_result_thread $threads Threads data object
*
* @return array Message headers array indexed by message UID
*/
@@ -972,8 +1012,8 @@
$a_msg_headers, $this->sort_field, $this->sort_order);
// only return the requested part of the set
- $a_msg_headers = array_slice(array_values($a_msg_headers),
- $from, min($cnt-$to, $this->page_size));
+ $slice_length = min($this->page_size, $cnt - ($to > $cnt ? $from : $to));
+ $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length);
if ($slice) {
$a_msg_headers = array_slice($a_msg_headers, -$slice, $slice);
@@ -1046,7 +1086,7 @@
if ($sort) {
// use this class for message sorting
- $sorter = new rcube_header_sorter();
+ $sorter = new rcube_message_header_sorter();
$sorter->set_index($msgs);
$sorter->sort_headers($a_msg_headers);
}
@@ -1073,7 +1113,7 @@
$old = $this->get_folder_stats($folder);
// refresh message count -> will update
- $this->messagecount($folder, 'ALL', true);
+ $this->countmessages($folder, 'ALL', true);
$result = 0;
@@ -1211,7 +1251,9 @@
}
// use message index sort as default sorting
else if (!$sort_field) {
+ // use search result from count() if possible
if ($this->options['skip_deleted'] && !empty($this->icache['undeleted_idx'])
+ && $this->icache['undeleted_idx']->get_parameters('ALL') !== null
&& $this->icache['undeleted_idx']->get_parameters('MAILBOX') == $folder
) {
$index = $this->icache['undeleted_idx'];
@@ -1344,21 +1386,21 @@
*
* @return rcube_result_index Search result (UIDs)
*/
- public function search_once($mailbox = null, $str = 'ALL')
+ public function search_once($folder = null, $str = 'ALL')
{
if (!$str) {
return 'ALL';
}
- if (!strlen($mailbox)) {
- $mailbox = $this->mailbox;
+ if (!strlen($folder)) {
+ $folder = $this->folder;
}
if (!$this->check_connection()) {
return new rcube_result_index();
}
- $index = $this->conn->search($mailbox, $str, true);
+ $index = $this->conn->search($folder, $str, true);
return $index;
}
@@ -1392,6 +1434,12 @@
$criteria = 'UNDELETED '.$criteria;
}
+ // unset CHARSET if criteria string is ASCII, this way
+ // SEARCH won't be re-sent after "unsupported charset" response
+ if ($charset && $charset != 'US-ASCII' && is_ascii($criteria)) {
+ $charset = 'US-ASCII';
+ }
+
if ($this->threading) {
$threads = $this->conn->thread($folder, $this->threading, $criteria, true, $charset);
@@ -1423,7 +1471,7 @@
}
$messages = $this->conn->search($folder,
- ($charset ? "CHARSET $charset " : '') . $criteria, true);
+ ($charset && $charset != 'US-ASCII' ? "CHARSET $charset " : '') . $criteria, true);
// Error, try with US-ASCII (some servers may support only US-ASCII)
if ($messages->is_error() && $charset && $charset != 'US-ASCII') {
@@ -1454,7 +1502,7 @@
foreach ($matches[1] as $m) {
$string_offset = $m[1] + strlen($m[0]) + 4; // {}\r\n
$string = substr($str, $string_offset - 1, $m[0]);
- $string = rcube_charset_convert($string, $charset, $dest_charset);
+ $string = rcube_charset::convert($string, $charset, $dest_charset);
if ($string === false) {
continue;
}
@@ -1496,7 +1544,7 @@
* @param string $folder Folder to read from
* @param bool $force True to skip cache
*
- * @return rcube_mail_header Message headers
+ * @return rcube_message_header Message headers
*/
public function get_message_headers($uid, $folder = null, $force = false)
{
@@ -1527,7 +1575,7 @@
* @param int $uid Message UID to fetch
* @param string $folder Folder to read from
*
- * @return object rcube_mail_header Message data
+ * @return object rcube_message_header Message data
*/
public function get_message($uid, $folder = null)
{
@@ -1593,11 +1641,24 @@
$structure[1] = $m[2];
}
else {
- return $headers;
+ // Try to parse the message using Mail_mimeDecode package
+ // We need a better solution, Mail_mimeDecode parses message
+ // in memory, which wouldn't work for very big messages,
+ // (it uses up to 10x more memory than the message size)
+ // it's also buggy and not actively developed
+ if ($headers->size && rcube_utils::mem_check($headers->size * 10)) {
+ $raw_msg = $this->get_raw_body($uid);
+ $struct = rcube_mime::parse_message($raw_msg);
+ }
+ else {
+ return $headers;
+ }
}
}
- $struct = $this->structure_part($structure, 0, '', $headers);
+ if (empty($struct)) {
+ $struct = $this->structure_part($structure, 0, '', $headers);
+ }
// don't trust given content-type
if (empty($struct->parts) && !empty($headers->ctype)) {
@@ -1946,7 +2007,7 @@
$charset = $this->struct_charset;
}
else {
- $charset = rc_detect_encoding($filename_mime, $this->default_charset);
+ $charset = rcube_charset::detect($filename_mime, $this->default_charset);
}
$part->filename = rcube_mime::decode_mime_string($filename_mime, $charset);
@@ -1958,7 +2019,7 @@
$filename_encoded = $fmatches[2];
}
- $part->filename = rcube_charset_convert(urldecode($filename_encoded), $filename_charset);
+ $part->filename = rcube_charset::convert(urldecode($filename_encoded), $filename_charset);
}
}
@@ -2037,7 +2098,7 @@
$o_part->charset = $this->default_charset;
}
}
- $body = rcube_charset_convert($body, $o_part->charset);
+ $body = rcube_charset::convert($body, $o_part->charset);
}
}
@@ -2083,14 +2144,17 @@
/**
* Sends the whole message source to stdout
+ *
+ * @param int $uid Message UID
+ * @param bool $formatted Enables line-ending formatting
*/
- public function print_raw_body($uid)
+ public function print_raw_body($uid, $formatted = true)
{
if (!$this->check_connection()) {
return;
}
- $this->conn->handlePartBody($this->folder, $uid, true, NULL, NULL, true);
+ $this->conn->handlePartBody($this->folder, $uid, true, null, null, true, null, $formatted);
}
@@ -2164,6 +2228,10 @@
$folder = $this->folder;
}
+ if (!$this->check_connection()) {
+ return false;
+ }
+
// make sure folder exists
if ($this->folder_exists($folder)) {
if ($is_file) {
@@ -2225,7 +2293,7 @@
}
}
- $config = rcmail::get_instance()->config;
+ $config = rcube::get_instance()->config;
$to_trash = $to_mbox == $config->get('trash_mbox');
// flag messages as read before moving them
@@ -2464,7 +2532,16 @@
return $a_mboxes;
}
- $a_mboxes = $this->_list_folders_subscribed($root, $name, $filter, $rights);
+ // Give plugins a chance to provide a list of folders
+ $data = rcube::get_instance()->plugins->exec_hook('storage_folders',
+ array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LSUB'));
+
+ if (isset($data['folders'])) {
+ $a_mboxes = $data['folders'];
+ }
+ else {
+ $a_mboxes = $this->list_folders_subscribed_direct($root, $name);
+ }
if (!is_array($a_mboxes)) {
return array();
@@ -2493,74 +2570,74 @@
/**
- * protected method for folders listing (LSUB)
+ * Method for direct folders listing (LSUB)
*
* @param string $root Optional root folder
* @param string $name Optional name pattern
- * @param mixed $filter Optional filter
- * @param string $rights Optional ACL requirements
*
* @return array List of subscribed folders
* @see rcube_imap::list_folders_subscribed()
*/
- protected function _list_folders_subscribed($root='', $name='*', $filter=null, $rights=null)
+ public function list_folders_subscribed_direct($root='', $name='*')
{
- $a_defaults = $a_out = array();
-
- // Give plugins a chance to provide a list of folders
- $data = rcmail::get_instance()->plugins->exec_hook('storage_folders',
- array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LSUB'));
-
- if (isset($data['folders'])) {
- $a_folders = $data['folders'];
- }
- else if (!$this->check_connection()) {
+ if (!$this->check_connection()) {
return null;
}
- else {
- // Server supports LIST-EXTENDED, we can use selection options
- $config = rcmail::get_instance()->config;
- // #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED
- if (!$config->get('imap_force_lsub') && $this->get_capability('LIST-EXTENDED')) {
- // This will also set folder options, LSUB doesn't do that
- $a_folders = $this->conn->listMailboxes($root, $name,
- NULL, array('SUBSCRIBED'));
- // unsubscribe non-existent folders, remove from the list
- if (is_array($a_folders) && $name == '*') {
- foreach ($a_folders as $idx => $folder) {
- if ($this->conn->data['LIST'] && ($opts = $this->conn->data['LIST'][$folder])
- && in_array('\\NonExistent', $opts)
- ) {
+ $config = rcube::get_instance()->config;
+
+ // Server supports LIST-EXTENDED, we can use selection options
+ // #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED
+ $list_extended = !$config->get('imap_force_lsub') && $this->get_capability('LIST-EXTENDED');
+ if ($list_extended) {
+ // This will also set folder options, LSUB doesn't do that
+ $a_folders = $this->conn->listMailboxes($root, $name,
+ NULL, array('SUBSCRIBED'));
+ }
+ else {
+ // retrieve list of folders from IMAP server using LSUB
+ $a_folders = $this->conn->listSubscribed($root, $name);
+ }
+
+ if (!is_array($a_folders)) {
+ return array();
+ }
+
+ // #1486796: some server configurations doesn't return folders in all namespaces
+ if ($root == '' && $name == '*' && $config->get('imap_force_ns')) {
+ $this->list_folders_update($a_folders, ($list_extended ? 'ext-' : '') . 'subscribed');
+ }
+
+ if ($list_extended) {
+ // unsubscribe non-existent folders, remove from the list
+ // we can do this only when LIST response is available
+ if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) {
+ foreach ($a_folders as $idx => $folder) {
+ if (($opts = $this->conn->data['LIST'][$folder])
+ && in_array('\\NonExistent', $opts)
+ ) {
+ $this->conn->unsubscribe($folder);
+ unset($a_folders[$idx]);
+ }
+ }
+ }
+ }
+ else {
+ // unsubscribe non-existent folders, remove them from the list,
+ // we can do this only when LIST response is available
+ if (is_array($a_folders) && $name == '*' && !empty($this->conn->data['LIST'])) {
+ foreach ($a_folders as $idx => $folder) {
+ if (!isset($this->conn->data['LIST'][$folder])
+ || in_array('\\Noselect', $this->conn->data['LIST'][$folder])
+ ) {
+ // Some servers returns \Noselect for existing folders
+ if (!$this->folder_exists($folder)) {
$this->conn->unsubscribe($folder);
unset($a_folders[$idx]);
}
}
}
}
- // retrieve list of folders from IMAP server using LSUB
- else {
- $a_folders = $this->conn->listSubscribed($root, $name);
-
- // unsubscribe non-existent folders, remove from the list
- if (is_array($a_folders) && $name == '*') {
- foreach ($a_folders as $idx => $folder) {
- if ($this->conn->data['LIST'] && ($opts = $this->conn->data['LIST'][$folder])
- && in_array('\\Noselect', $opts)
- ) {
- // Some servers returns \Noselect for existing folders
- if (!$this->folder_exists($folder)) {
- $this->conn->unsubscribe($folder);
- unset($a_folders[$idx]);
- }
- }
- }
- }
- }
- }
-
- if (!is_array($a_folders) || !sizeof($a_folders)) {
- $a_folders = array();
}
return $a_folders;
@@ -2594,7 +2671,7 @@
}
// Give plugins a chance to provide a list of folders
- $data = rcmail::get_instance()->plugins->exec_hook('storage_folders',
+ $data = rcube::get_instance()->plugins->exec_hook('storage_folders',
array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST'));
if (isset($data['folders'])) {
@@ -2602,7 +2679,7 @@
}
else {
// retrieve list of folders from IMAP server
- $a_mboxes = $this->_list_folders($root, $name);
+ $a_mboxes = $this->list_folders_direct($root, $name);
}
if (!is_array($a_mboxes)) {
@@ -2637,7 +2714,7 @@
/**
- * protected method for folders listing (LIST)
+ * Method for direct folders listing (LIST)
*
* @param string $root Optional root folder
* @param string $name Optional name pattern
@@ -2645,7 +2722,7 @@
* @return array List of folders
* @see rcube_imap::list_folders()
*/
- protected function _list_folders($root='', $name='*')
+ public function list_folders_direct($root='', $name='*')
{
if (!$this->check_connection()) {
return null;
@@ -2657,50 +2734,71 @@
return array();
}
- // #1486796: some server configurations doesn't
- // return folders in all namespaces, we'll try to detect that situation
- // and ask for these namespaces separately
- if ($root == '' && $name == '*') {
- $delim = $this->get_hierarchy_delimiter();
- $namespace = $this->get_namespace();
- $search = array();
+ $config = rcube::get_instance()->config;
- // build list of namespace prefixes
- foreach ((array)$namespace as $ns) {
- if (is_array($ns)) {
- foreach ($ns as $ns_data) {
- if (strlen($ns_data[0])) {
- $search[] = $ns_data[0];
- }
- }
- }
- }
+ // #1486796: some server configurations doesn't return folders in all namespaces
+ if ($root == '' && $name == '*' && $config->get('imap_force_ns')) {
+ $this->list_folders_update($result);
+ }
- if (!empty($search)) {
- // go through all folders detecting namespace usage
- foreach ($result as $folder) {
- foreach ($search as $idx => $prefix) {
- if (strpos($folder, $prefix) === 0) {
- unset($search[$idx]);
- }
- }
- if (empty($search)) {
- break;
- }
- }
+ return $result;
+ }
- // get folders in hidden namespaces and add to the result
- foreach ($search as $prefix) {
- $list = $this->conn->listMailboxes($prefix, $name);
- if (!empty($list)) {
- $result = array_merge($result, $list);
+ /**
+ * Fix folders list by adding folders from other namespaces.
+ * Needed on some servers eg. Courier IMAP
+ *
+ * @param array $result Reference to folders list
+ * @param string $type Listing type (ext-subscribed, subscribed or all)
+ */
+ private function list_folders_update(&$result, $type = null)
+ {
+ $delim = $this->get_hierarchy_delimiter();
+ $namespace = $this->get_namespace();
+ $search = array();
+
+ // build list of namespace prefixes
+ foreach ((array)$namespace as $ns) {
+ if (is_array($ns)) {
+ foreach ($ns as $ns_data) {
+ if (strlen($ns_data[0])) {
+ $search[] = $ns_data[0];
}
}
}
}
- return $result;
+ if (!empty($search)) {
+ // go through all folders detecting namespace usage
+ foreach ($result as $folder) {
+ foreach ($search as $idx => $prefix) {
+ if (strpos($folder, $prefix) === 0) {
+ unset($search[$idx]);
+ }
+ }
+ if (empty($search)) {
+ break;
+ }
+ }
+
+ // get folders in hidden namespaces and add to the result
+ foreach ($search as $prefix) {
+ if ($type == 'ext-subscribed') {
+ $list = $this->conn->listMailboxes('', $prefix . '*', null, array('SUBSCRIBED'));
+ }
+ else if ($type == 'subscribed') {
+ $list = $this->conn->listSubscribed('', $prefix . '*');
+ }
+ else {
+ $list = $this->conn->listMailboxes('', $prefix . '*');
+ }
+
+ if (!empty($list)) {
+ $result = array_merge($result, $list);
+ }
+ }
+ }
}
@@ -2841,11 +2939,11 @@
// get list of subscribed folders
if ((strpos($folder, '%') === false) && (strpos($folder, '*') === false)) {
- $a_subscribed = $this->_list_folders_subscribed('', $folder . $delm . '*');
+ $a_subscribed = $this->list_folders_subscribed('', $folder . $delm . '*');
$subscribed = $this->folder_exists($folder, true);
}
else {
- $a_subscribed = $this->_list_folders_subscribed();
+ $a_subscribed = $this->list_folders_subscribed();
$subscribed = in_array($folder, $a_subscribed);
}
@@ -2913,7 +3011,7 @@
if (strpos($c_mbox, $folder.$delm) === 0) {
$this->conn->unsubscribe($c_mbox);
if ($this->conn->deleteFolder($c_mbox)) {
- $this->clear_message_cache($c_mbox);
+ $this->clear_message_cache($c_mbox);
}
}
}
@@ -3140,6 +3238,14 @@
return $this->icache['options'];
}
+ // get cached metadata
+ $cache_key = 'mailboxes.folder-info.' . $folder;
+ $cached = $this->get_cache($cache_key);
+
+ if (is_array($cached)) {
+ return $cached;
+ }
+
$acl = $this->get_capability('ACL');
$namespace = $this->get_namespace();
$options = array();
@@ -3175,10 +3281,9 @@
$options['name'] = $folder;
$options['attributes'] = $this->folder_attributes($folder, true);
$options['namespace'] = $this->folder_namespace($folder);
- $options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($folder) : array();
$options['special'] = in_array($folder, $this->default_folders);
- // Set 'noselect' and 'norename' flags
+ // Set 'noselect' flag
if (is_array($options['attributes'])) {
foreach ($options['attributes'] as $attrib) {
$attrib = strtolower($attrib);
@@ -3191,6 +3296,15 @@
$options['noselect'] = true;
}
+ // Get folder rights (MYRIGHTS)
+ if ($acl && !$options['noselect']) {
+ // skip shared roots
+ if (!$options['is_root'] || $options['namespace'] == 'personal') {
+ $options['rights'] = (array)$this->my_rights($folder);
+ }
+ }
+
+ // Set 'norename' flag
if (!empty($options['rights'])) {
$options['norename'] = !in_array('x', $options['rights']) && !in_array('d', $options['rights']);
@@ -3202,7 +3316,9 @@
$options['norename'] = $options['is_root'] || $options['namespace'] != 'personal';
}
+ // update caches
$this->icache['options'] = $options;
+ $this->update_cache($cache_key, $options);
return $options;
}
@@ -3267,6 +3383,8 @@
if (!$this->check_connection()) {
return false;
}
+
+ $this->clear_cache('mailboxes.folder-info.' . $folder);
return $this->conn->setACL($folder, $user, $acl);
}
@@ -3381,6 +3499,8 @@
return false;
}
+ $this->clear_cache('mailboxes.metadata.', true);
+
if ($this->get_capability('METADATA') ||
(!strlen($folder) && $this->get_capability('METADATA-SERVER'))
) {
@@ -3413,7 +3533,9 @@
return false;
}
- if ($this->get_capability('METADATA') ||
+ $this->clear_cache('mailboxes.metadata.', true);
+
+ if ($this->get_capability('METADATA') ||
(!strlen($folder) && $this->get_capability('METADATA-SERVER'))
) {
return $this->conn->deleteMetadata($folder, $entries);
@@ -3442,6 +3564,23 @@
*/
public function get_metadata($folder, $entries, $options=array())
{
+ $entries = (array)$entries;
+
+ // create cache key
+ // @TODO: this is the simplest solution, but we do the same with folders list
+ // maybe we should store data per-entry and merge on request
+ sort($options);
+ sort($entries);
+ $cache_key = 'mailboxes.metadata.' . $folder;
+ $cache_key .= '.' . md5(serialize($options).serialize($entries));
+
+ // get cached data
+ $cached_data = $this->get_cache($cache_key);
+
+ if (is_array($cached_data)) {
+ return $cached_data;
+ }
+
if (!$this->check_connection()) {
return null;
}
@@ -3449,14 +3588,14 @@
if ($this->get_capability('METADATA') ||
(!strlen($folder) && $this->get_capability('METADATA-SERVER'))
) {
- return $this->conn->getMetadata($folder, $entries, $options);
+ $res = $this->conn->getMetadata($folder, $entries, $options);
}
else if ($this->get_capability('ANNOTATEMORE') || $this->get_capability('ANNOTATEMORE2')) {
$queries = array();
$res = array();
// Convert entry names
- foreach ((array)$entries as $entry) {
+ foreach ($entries as $entry) {
list($ent, $attr) = $this->md2annotate($entry);
$queries[$attr][] = $ent;
}
@@ -3467,7 +3606,10 @@
$res = array_merge_recursive($res, $result);
}
}
+ }
+ if (isset($res)) {
+ $this->update_cache($cache_key, $res);
return $res;
}
@@ -3504,7 +3646,7 @@
/**
* Enable or disable indexes caching
*
- * @param string $type Cache type (@see rcmail::get_cache)
+ * @param string $type Cache type (@see rcube::get_cache)
*/
public function set_caching($type)
{
@@ -3526,9 +3668,9 @@
protected function get_cache_engine()
{
if ($this->caching && !$this->cache) {
- $rcmail = rcmail::get_instance();
- $ttl = $rcmail->config->get('message_cache_lifetime', '10d') - mktime();
- $this->cache = $rcmail->get_cache('IMAP', $this->caching, $ttl);
+ $rcube = rcube::get_instance();
+ $ttl = $rcube->config->get('message_cache_lifetime', '10d');
+ $this->cache = $rcube->get_cache('IMAP', $this->caching, $ttl);
}
return $this->cache;
@@ -3581,12 +3723,13 @@
public function expunge_cache()
{
if ($this->mcache) {
- $ttl = rcmail::get_instance()->config->get('message_cache_lifetime', '10d');
+ $ttl = rcube::get_instance()->config->get('message_cache_lifetime', '10d');
$this->mcache->expunge($ttl);
}
- if ($this->cache)
+ if ($this->cache) {
$this->cache->expunge();
+ }
}
@@ -3620,10 +3763,10 @@
protected function get_mcache_engine()
{
if ($this->messages_caching && !$this->mcache) {
- $rcmail = rcmail::get_instance();
- if ($dbh = $rcmail->get_dbh()) {
+ $rcube = rcube::get_instance();
+ if (($dbh = $rcube->get_dbh()) && ($userid = $rcube->get_user_id())) {
$this->mcache = new rcube_imap_cache(
- $dbh, $this, $rcmail->user->ID, $this->options['skip_deleted']);
+ $dbh, $this, $userid, $this->options['skip_deleted']);
}
}
@@ -3687,7 +3830,7 @@
$a_defaults[$p] = $folder;
}
else {
- $folders[$folder] = rcube_charset_convert($folder, 'UTF7-IMAP');
+ $folders[$folder] = rcube_charset::convert($folder, 'UTF7-IMAP');
}
}
@@ -3717,12 +3860,12 @@
protected function rsort($folder, $delimiter, &$list, &$out)
{
while (list($key, $name) = each($list)) {
- if (strpos($name, $folder.$delimiter) === 0) {
- // set the type of folder name variable (#1485527)
- $out[] = (string) $name;
- unset($list[$key]);
- $this->rsort($name, $delimiter, $list, $out);
- }
+ if (strpos($name, $folder.$delimiter) === 0) {
+ // set the type of folder name variable (#1485527)
+ $out[] = (string) $name;
+ unset($list[$key]);
+ $this->rsort($name, $delimiter, $list, $out);
+ }
}
reset($list);
}
@@ -3847,7 +3990,147 @@
*/
public function debug_handler(&$imap, $message)
{
- write_log('imap', $message);
+ rcube::write_log('imap', $message);
}
-} // end class rcube_imap
+
+ /**
+ * Deprecated methods (to be removed)
+ */
+
+ public function decode_address_list($input, $max = null, $decode = true, $fallback = null)
+ {
+ return rcube_mime::decode_address_list($input, $max, $decode, $fallback);
+ }
+
+ public function decode_header($input, $fallback = null)
+ {
+ return rcube_mime::decode_mime_string((string)$input, $fallback);
+ }
+
+ public static function decode_mime_string($input, $fallback = null)
+ {
+ return rcube_mime::decode_mime_string($input, $fallback);
+ }
+
+ public function mime_decode($input, $encoding = '7bit')
+ {
+ return rcube_mime::decode($input, $encoding);
+ }
+
+ public static function explode_header_string($separator, $str, $remove_comments = false)
+ {
+ return rcube_mime::explode_header_string($separator, $str, $remove_comments);
+ }
+
+ public function select_mailbox($mailbox)
+ {
+ // do nothing
+ }
+
+ public function set_mailbox($folder)
+ {
+ $this->set_folder($folder);
+ }
+
+ public function get_mailbox_name()
+ {
+ return $this->get_folder();
+ }
+
+ public function list_headers($folder='', $page=NULL, $sort_field=NULL, $sort_order=NULL, $slice=0)
+ {
+ return $this->list_messages($folder, $page, $sort_field, $sort_order, $slice);
+ }
+
+ public function get_headers($uid, $folder = null, $force = false)
+ {
+ return $this->get_message_headers($uid, $folder, $force);
+ }
+
+ public function mailbox_status($folder = null)
+ {
+ return $this->folder_status($folder);
+ }
+
+ public function message_index($folder = '', $sort_field = NULL, $sort_order = NULL)
+ {
+ return $this->index($folder, $sort_field, $sort_order);
+ }
+
+ public function message_index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true)
+ {
+ return $this->index_direct($folder, $sort_field, $sort_order, $skip_cache);
+ }
+
+ public function list_mailboxes($root='', $name='*', $filter=null, $rights=null, $skip_sort=false)
+ {
+ return $this->list_folders_subscribed($root, $name, $filter, $rights, $skip_sort);
+ }
+
+ public function list_unsubscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false)
+ {
+ return $this->list_folders($root, $name, $filter, $rights, $skip_sort);
+ }
+
+ public function get_mailbox_size($folder)
+ {
+ return $this->folder_size($folder);
+ }
+
+ public function create_mailbox($folder, $subscribe=false)
+ {
+ return $this->create_folder($folder, $subscribe);
+ }
+
+ public function rename_mailbox($folder, $new_name)
+ {
+ return $this->rename_folder($folder, $new_name);
+ }
+
+ function delete_mailbox($folder)
+ {
+ return $this->delete_folder($folder);
+ }
+
+ public function mailbox_exists($folder, $subscription=false)
+ {
+ return $this->folder_exists($folder, $subscription);
+ }
+
+ public function mailbox_namespace($folder)
+ {
+ return $this->folder_namespace($folder);
+ }
+
+ public function mod_mailbox($folder, $mode = 'out')
+ {
+ return $this->mod_folder($folder, $mode);
+ }
+
+ public function mailbox_attributes($folder, $force=false)
+ {
+ return $this->folder_attributes($folder, $force);
+ }
+
+ public function mailbox_data($folder)
+ {
+ return $this->folder_data($folder);
+ }
+
+ public function mailbox_info($folder)
+ {
+ return $this->folder_info($folder);
+ }
+
+ public function mailbox_sync($folder)
+ {
+ return $this->folder_sync($folder);
+ }
+
+ public function expunge($folder='', $clear_cache=true)
+ {
+ return $this->expunge_folder($folder, $clear_cache);
+ }
+
+}
--
Gitblit v1.9.1