| | |
| | | protected $search_sort_field = ''; |
| | | protected $search_threads = false; |
| | | protected $search_sorted = false; |
| | | protected $options = array('auth_method' => 'check'); |
| | | protected $options = array('auth_type' => 'check'); |
| | | protected $caching = false; |
| | | protected $messages_caching = false; |
| | | protected $threading = false; |
| | |
| | | */ |
| | | public function set_folder($folder) |
| | | { |
| | | if ($this->folder == $folder) { |
| | | return; |
| | | } |
| | | |
| | | $this->folder = $folder; |
| | | |
| | | // clear messagecount cache for this folder |
| | | $this->clear_messagecount($folder); |
| | | } |
| | | |
| | | |
| | |
| | | public function check_permflag($flag) |
| | | { |
| | | $flag = strtoupper($flag); |
| | | $imap_flag = $this->conn->flags[$flag]; |
| | | $perm_flags = $this->get_permflags($this->folder); |
| | | $imap_flag = $this->conn->flags[$flag]; |
| | | |
| | | return in_array_nocase($imap_flag, $perm_flags); |
| | | return $imap_flag && !empty($perm_flags) && in_array_nocase($imap_flag, $perm_flags); |
| | | } |
| | | |
| | | |
| | |
| | | if (!strlen($folder)) { |
| | | return array(); |
| | | } |
| | | /* |
| | | Checking PERMANENTFLAGS is rather rare, so we disable caching of it |
| | | Re-think when we'll use it for more than only MDNSENT flag |
| | | |
| | | $cache_key = 'mailboxes.permanentflags.' . $folder; |
| | | $permflags = $this->get_cache($cache_key); |
| | | |
| | | if ($permflags !== null) { |
| | | return explode(' ', $permflags); |
| | | } |
| | | */ |
| | | if (!$this->check_connection()) { |
| | | 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; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if ($mode == 'THREADS') { |
| | | $res = $this->fetch_threads($folder, $force); |
| | | $res = $this->threads($folder); |
| | | $count = $res->count(); |
| | | |
| | | if ($status) { |
| | |
| | | $keys[] = 'ALL'; |
| | | } |
| | | if ($status) { |
| | | $keys[] = 'MAX'; |
| | | $keys[] = 'MAX'; |
| | | } |
| | | } |
| | | |
| | | // @TODO: if $force==false && $mode == 'ALL' we could try to use cache index here |
| | | // @TODO: if $mode == 'ALL' we could try to use cache index here |
| | | |
| | | // get message count using (E)SEARCH |
| | | // not very performant but more precise (using UNDELETED) |
| | |
| | | $threads = $mcache->get_thread($folder); |
| | | } |
| | | else { |
| | | $threads = $this->fetch_threads($folder); |
| | | $threads = $this->threads($folder); |
| | | } |
| | | |
| | | return $this->fetch_thread_headers($folder, $threads, $page, $slice); |
| | |
| | | /** |
| | | * Method for fetching threads data |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param bool $force Use IMAP server, no cache |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return rcube_imap_thread Thread data object |
| | | */ |
| | | function fetch_threads($folder, $force = false) |
| | | function threads($folder) |
| | | { |
| | | if (!$force && ($mcache = $this->get_mcache_engine())) { |
| | | if ($mcache = $this->get_mcache_engine()) { |
| | | // don't store in self's internal cache, cache has it's own internal cache |
| | | return $mcache->get_thread($folder); |
| | | } |
| | | |
| | | if (empty($this->icache['threads'])) { |
| | | if (!$this->check_connection()) { |
| | | return new rcube_result_thread(); |
| | | if (!empty($this->icache['threads'])) { |
| | | if ($this->icache['threads']->get_parameters('MAILBOX') == $folder) { |
| | | return $this->icache['threads']; |
| | | } |
| | | |
| | | // get all threads |
| | | $result = $this->conn->thread($folder, $this->threading, |
| | | $this->options['skip_deleted'] ? 'UNDELETED' : '', true); |
| | | |
| | | // add to internal (fast) cache |
| | | $this->icache['threads'] = $result; |
| | | } |
| | | |
| | | return $this->icache['threads']; |
| | | // get all threads |
| | | $result = $this->threads_direct($folder); |
| | | |
| | | // add to internal (fast) cache |
| | | return $this->icache['threads'] = $result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Method for direct fetching of threads data |
| | | * |
| | | * @param string $folder Folder name |
| | | * |
| | | * @return rcube_imap_thread Thread data object |
| | | */ |
| | | function threads_direct($folder) |
| | | { |
| | | if (!$this->check_connection()) { |
| | | return new rcube_result_thread(); |
| | | } |
| | | |
| | | // get all threads |
| | | return $this->conn->thread($folder, $this->threading, |
| | | $this->options['skip_deleted'] ? 'UNDELETED' : '', true); |
| | | } |
| | | |
| | | |
| | |
| | | // use memory less expensive (and quick) method for big result set |
| | | $index = clone $this->index('', $this->sort_field, $this->sort_order); |
| | | // get messages uids for one page... |
| | | $index->slice($start_msg, min($cnt-$from, $this->page_size)); |
| | | $index->slice($from, min($cnt-$from, $this->page_size)); |
| | | |
| | | if ($slice) { |
| | | $index->slice(-$slice, $slice); |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns current status of folder |
| | | * Returns current status of a folder (compared to the last time use) |
| | | * |
| | | * We compare the maximum UID to determine the number of |
| | | * new messages because the RECENT flag is not reliable. |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param array $diff Difference data |
| | | * |
| | | * @return int Folder status |
| | | * @return int Folder status |
| | | */ |
| | | public function folder_status($folder = null) |
| | | public function folder_status($folder = null, &$diff = array()) |
| | | { |
| | | if (!strlen($folder)) { |
| | | $folder = $this->folder; |
| | |
| | | // got new messages |
| | | if ($new['maxuid'] > $old['maxuid']) { |
| | | $result += 1; |
| | | // get new message UIDs range, that can be used for example |
| | | // to get the data of these messages |
| | | $diff['new'] = ($old['maxuid'] + 1 < $new['maxuid'] ? ($old['maxuid']+1).':' : '') . $new['maxuid']; |
| | | } |
| | | // some messages has been deleted |
| | | if ($new['cnt'] < $old['cnt']) { |
| | |
| | | * @param string $folder Folder to get index from |
| | | * @param string $sort_field Sort column |
| | | * @param string $sort_order Sort order [ASC, DESC] |
| | | * @param bool $no_threads Get not threaded index |
| | | * @param bool $no_search Get index not limited to search result (optionally) |
| | | * |
| | | * @return rcube_result_index|rcube_result_thread List of messages (UIDs) |
| | | */ |
| | | public function index($folder = '', $sort_field = NULL, $sort_order = NULL) |
| | | { |
| | | if ($this->threading) { |
| | | public function index($folder = '', $sort_field = NULL, $sort_order = NULL, |
| | | $no_threads = false, $no_search = false |
| | | ) { |
| | | if (!$no_threads && $this->threading) { |
| | | return $this->thread_index($folder, $sort_field, $sort_order); |
| | | } |
| | | |
| | |
| | | |
| | | // we have a saved search result, get index from there |
| | | if ($this->search_string) { |
| | | if ($this->search_threads) { |
| | | $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); |
| | | if ($this->search_set->is_empty()) { |
| | | return new rcube_result_index($folder, '* SORT'); |
| | | } |
| | | |
| | | // use message index sort as default sorting |
| | | if (!$this->sort_field || $this->search_sorted) { |
| | | if ($this->sort_field && $this->search_sort_field != $this->sort_field) { |
| | | $this->search($folder, $this->search_string, $this->search_charset, $this->sort_field); |
| | | } |
| | | // search result is an index with the same sorting? |
| | | if (($this->search_set instanceof rcube_result_index) |
| | | && ((!$this->sort_field && !$this->search_sorted) || |
| | | ($this->search_sorted && $this->search_sort_field == $this->sort_field)) |
| | | ) { |
| | | $index = $this->search_set; |
| | | } |
| | | else if (!$this->check_connection()) { |
| | | return new rcube_result_index(); |
| | | } |
| | | else { |
| | | $index = $this->conn->index($folder, $this->search_set->get(), |
| | | $this->sort_field, $this->options['skip_deleted'], true, true); |
| | | // $no_search is enabled when we are not interested in |
| | | // fetching index for search result, e.g. to sort |
| | | // threaded search result we can use full mailbox index. |
| | | // This makes possible to use index from cache |
| | | else if (!$no_search) { |
| | | if (!$this->sort_field) { |
| | | // No sorting needed, just build index from the search result |
| | | // @TODO: do we need to sort by UID here? |
| | | $search = $this->search_set->get_compressed(); |
| | | $index = new rcube_result_index($folder, '* ESEARCH ALL ' . $search); |
| | | } |
| | | else { |
| | | $index = $this->index_direct($folder, $this->search_charset, |
| | | $this->sort_field, $this->search_set); |
| | | } |
| | | } |
| | | |
| | | if ($this->sort_order != $index->get_parameters('ORDER')) { |
| | | $index->revert(); |
| | | } |
| | | if (isset($index)) { |
| | | if ($this->sort_order != $index->get_parameters('ORDER')) { |
| | | $index->revert(); |
| | | } |
| | | |
| | | return $index; |
| | | return $index; |
| | | } |
| | | } |
| | | |
| | | // check local cache |
| | | if ($mcache = $this->get_mcache_engine()) { |
| | | $index = $mcache->get_index($folder, $this->sort_field, $this->sort_order); |
| | | } |
| | | // fetch from IMAP server |
| | | else { |
| | | $index = $this->index_direct( |
| | | $folder, $this->sort_field, $this->sort_order); |
| | | return $mcache->get_index($folder, $this->sort_field, $this->sort_order); |
| | | } |
| | | |
| | | return $index; |
| | | // fetch from IMAP server |
| | | return $this->index_direct($folder, $this->sort_field, $this->sort_order); |
| | | } |
| | | |
| | | |
| | |
| | | * Return sorted list of message UIDs ignoring current search settings. |
| | | * Doesn't uses cache by default. |
| | | * |
| | | * @param string $folder Folder to get index from |
| | | * @param string $sort_field Sort column |
| | | * @param string $sort_order Sort order [ASC, DESC] |
| | | * @param bool $skip_cache Disables cache usage |
| | | * @param string $folder Folder to get index from |
| | | * @param string $sort_field Sort column |
| | | * @param string $sort_order Sort order [ASC, DESC] |
| | | * @param rcube_result_* $search Optional messages set to limit the result |
| | | * |
| | | * @return rcube_result_index Sorted list of message UIDs |
| | | */ |
| | | public function index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true) |
| | | public function index_direct($folder, $sort_field = null, $sort_order = null, $search = null) |
| | | { |
| | | if (!$skip_cache && ($mcache = $this->get_mcache_engine())) { |
| | | $index = $mcache->get_index($folder, $sort_field, $sort_order); |
| | | if (!empty($search)) { |
| | | $search = $this->search_set->get_compressed(); |
| | | } |
| | | |
| | | // use message index sort as default sorting |
| | | else if (!$sort_field) { |
| | | if (!$sort_field) { |
| | | // use search result from count() if possible |
| | | if ($this->options['skip_deleted'] && !empty($this->icache['undeleted_idx']) |
| | | if (empty($search) && $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 |
| | | ) { |
| | |
| | | return new rcube_result_index(); |
| | | } |
| | | else { |
| | | $index = $this->conn->search($folder, |
| | | 'ALL' .($this->options['skip_deleted'] ? ' UNDELETED' : ''), true); |
| | | $query = $this->options['skip_deleted'] ? 'UNDELETED' : ''; |
| | | if ($search) { |
| | | $query = trim($query . ' UID ' . $search); |
| | | } |
| | | |
| | | $index = $this->conn->search($folder, $query, true); |
| | | } |
| | | } |
| | | else if (!$this->check_connection()) { |
| | |
| | | // fetch complete message index |
| | | else { |
| | | if ($this->get_capability('SORT')) { |
| | | $index = $this->conn->sort($folder, $sort_field, |
| | | $this->options['skip_deleted'] ? 'UNDELETED' : '', true); |
| | | $query = $this->options['skip_deleted'] ? 'UNDELETED' : ''; |
| | | if ($search) { |
| | | $query = trim($query . ' UID ' . $search); |
| | | } |
| | | |
| | | $index = $this->conn->sort($folder, $sort_field, $query, true); |
| | | } |
| | | |
| | | if (empty($index) || $index->is_error()) { |
| | | $index = $this->conn->index($folder, "1:*", $sort_field, |
| | | $this->options['skip_deleted'], false, true); |
| | | $index = $this->conn->index($folder, $search ? $search : "1:*", |
| | | $sort_field, $this->options['skip_deleted'], |
| | | $search ? true : false, true); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | else { |
| | | // get all threads (default sort order) |
| | | $threads = $this->fetch_threads($folder); |
| | | $threads = $this->threads($folder); |
| | | } |
| | | |
| | | $this->set_sort_order($sort_field, $sort_order); |
| | |
| | | |
| | | |
| | | /** |
| | | * Sort threaded result, using THREAD=REFS method |
| | | * Sort threaded result, using THREAD=REFS method if available. |
| | | * If not, use any method and re-sort the result in THREAD=REFS way. |
| | | * |
| | | * @param rcube_result_thread $threads Threads result set |
| | | * @param rcube_result_thread $threads Threads result set |
| | | */ |
| | | protected function sort_threads($threads) |
| | | { |
| | |
| | | // THREAD=REFERENCES: sorting by sent date of root message |
| | | // THREAD=REFS: sorting by the most recent date in each thread |
| | | |
| | | if ($this->sort_field && ($this->sort_field != 'date' || $this->get_capability('THREAD') != 'REFS')) { |
| | | $index = $this->index_direct($this->folder, $this->sort_field, $this->sort_order, false); |
| | | if ($this->threading != 'REFS' || ($this->sort_field && $this->sort_field != 'date')) { |
| | | $sortby = $this->sort_field ? $this->sort_field : 'date'; |
| | | $index = $this->index($this->folder, $sortby, $this->sort_order, true, true); |
| | | |
| | | if (!$index->is_empty()) { |
| | | $threads->sort($index); |
| | | } |
| | | } |
| | | else { |
| | | if ($this->sort_order != $threads->get_parameters('ORDER')) { |
| | | $threads->revert(); |
| | | } |
| | | else if ($this->sort_order != $threads->get_parameters('ORDER')) { |
| | | $threads->revert(); |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | protected function search_index($folder, $criteria='ALL', $charset=NULL, $sort_field=NULL) |
| | | { |
| | | $orig_criteria = $criteria; |
| | | |
| | | if (!$this->check_connection()) { |
| | | if ($this->threading) { |
| | | return new rcube_result_thread(); |
| | |
| | | // Example of structure for malformed MIME message: |
| | | // ("text" "plain" NIL NIL NIL "7bit" 2154 70 NIL NIL NIL) |
| | | if ($headers->ctype && !is_array($structure[0]) && $headers->ctype != 'text/plain' |
| | | && strtolower($structure[0].'/'.$structure[1]) == 'text/plain') { |
| | | && strtolower($structure[0].'/'.$structure[1]) == 'text/plain' |
| | | ) { |
| | | // A special known case "Content-type: text" (#1488968) |
| | | if ($headers->ctype == 'text') { |
| | | $structure[1] = 'plain'; |
| | | $headers->ctype = 'text/plain'; |
| | | } |
| | | // we can handle single-part messages, by simple fix in structure (#1486898) |
| | | if (preg_match('/^(text|application)\/(.*)/', $headers->ctype, $m)) { |
| | | else if (preg_match('/^(text|application)\/(.*)/', $headers->ctype, $m)) { |
| | | $structure[0] = $m[1]; |
| | | $structure[1] = $m[2]; |
| | | } |
| | |
| | | $struct = $this->structure_part($structure, 0, '', $headers); |
| | | } |
| | | |
| | | // don't trust given content-type |
| | | if (empty($struct->parts) && !empty($headers->ctype)) { |
| | | $struct->mime_id = '1'; |
| | | $struct->mimetype = strtolower($headers->ctype); |
| | | list($struct->ctype_primary, $struct->ctype_secondary) = explode('/', $struct->mimetype); |
| | | // some workarounds on simple messages... |
| | | if (empty($struct->parts)) { |
| | | // ...don't trust given content-type |
| | | if (!empty($headers->ctype)) { |
| | | $struct->mime_id = '1'; |
| | | $struct->mimetype = strtolower($headers->ctype); |
| | | list($struct->ctype_primary, $struct->ctype_secondary) = explode('/', $struct->mimetype); |
| | | } |
| | | |
| | | // ...and charset (there's a case described in #1488968 where invalid content-type |
| | | // results in invalid charset in BODYSTRUCTURE) |
| | | if (!empty($headers->charset) && $headers->charset != $struct->ctype_parameters['charset']) { |
| | | $struct->charset = $headers->charset; |
| | | $struct->ctype_parameters['charset'] = $headers->charset; |
| | | } |
| | | } |
| | | |
| | | $headers->structure = $struct; |
| | |
| | | /** |
| | | * Fetch message body of a specific message from the server |
| | | * |
| | | * @param int $uid Message UID |
| | | * @param string $part Part number |
| | | * @param rcube_message_part $o_part Part object created by get_structure() |
| | | * @param mixed $print True to print part, ressource to write part contents in |
| | | * @param resource $fp File pointer to save the message part |
| | | * @param boolean $skip_charset_conv Disables charset conversion |
| | | * @param int $max_bytes Only read this number of bytes |
| | | * @param int Message UID |
| | | * @param string Part number |
| | | * @param rcube_message_part Part object created by get_structure() |
| | | * @param mixed True to print part, resource to write part contents in |
| | | * @param resource File pointer to save the message part |
| | | * @param boolean Disables charset conversion |
| | | * @param int Only read this number of bytes |
| | | * @param boolean Enables formatting of text/* parts bodies |
| | | * |
| | | * @return string Message/part body if not printed |
| | | */ |
| | | public function get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false, $max_bytes=0) |
| | | public function get_message_part($uid, $part=1, $o_part=NULL, $print=NULL, $fp=NULL, $skip_charset_conv=false, $max_bytes=0, $formatted=true) |
| | | { |
| | | if (!$this->check_connection()) { |
| | | return null; |
| | |
| | | } |
| | | |
| | | if ($o_part && $o_part->size) { |
| | | $formatted = $formatted && $o_part->ctype_primary == 'text'; |
| | | $body = $this->conn->handlePartBody($this->folder, $uid, true, |
| | | $part ? $part : 'TEXT', $o_part->encoding, $print, $fp, $o_part->ctype_primary == 'text', $max_bytes); |
| | | $part ? $part : 'TEXT', $o_part->encoding, $print, $fp, $formatted, $max_bytes); |
| | | } |
| | | |
| | | if ($fp || $print) { |
| | |
| | | /** |
| | | * Append a mail message (source) to a specific folder |
| | | * |
| | | * @param string $folder Target folder |
| | | * @param string $message The message source string or filename |
| | | * @param string $headers Headers string if $message contains only the body |
| | | * @param boolean $is_file True if $message is a filename |
| | | * @param array $flags Message flags |
| | | * @param mixed $date Message internal date |
| | | * @param bool $binary Enables BINARY append |
| | | * @param string $folder Target folder |
| | | * @param string|array $message The message source string or filename |
| | | * or array (of strings and file pointers) |
| | | * @param string $headers Headers string if $message contains only the body |
| | | * @param boolean $is_file True if $message is a filename |
| | | * @param array $flags Message flags |
| | | * @param mixed $date Message internal date |
| | | * @param bool $binary Enables BINARY append |
| | | * |
| | | * @return int|bool Appended message UID or True on success, False on error |
| | | */ |
| | |
| | | // move messages |
| | | $moved = $this->conn->move($uids, $from_mbox, $to_mbox); |
| | | |
| | | // send expunge command in order to have the moved message |
| | | // really deleted from the source folder |
| | | if ($moved) { |
| | | $this->expunge_message($uids, $from_mbox, false); |
| | | $this->clear_messagecount($from_mbox); |
| | | $this->clear_messagecount($to_mbox); |
| | | } |
| | |
| | | |
| | | 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]) |
| | |
| | | } |
| | | } |
| | | 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]); |
| | | } |
| | | } |
| | | // unsubscribe non-existent folders, remove them from the list |
| | | if (is_array($a_folders) && !empty($a_folders) && $name == '*') { |
| | | $existing = $this->list_folders($root, $name); |
| | | $nonexisting = array_diff($a_folders, $existing); |
| | | $a_folders = array_diff($a_folders, $nonexisting); |
| | | |
| | | foreach ($nonexisting as $folder) { |
| | | $this->conn->unsubscribe($folder); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | // filter folders list according to rights requirements |
| | | if ($rights && $this->get_capability('ACL')) { |
| | | $a_folders = $this->filter_rights($a_folders, $rights); |
| | | $a_mboxes = $this->filter_rights($a_mboxes, $rights); |
| | | } |
| | | |
| | | // filter folders and sort them |
| | |
| | | */ |
| | | private function list_folders_update(&$result, $type = null) |
| | | { |
| | | $delim = $this->get_hierarchy_delimiter(); |
| | | $namespace = $this->get_namespace(); |
| | | $search = array(); |
| | | |
| | |
| | | { |
| | | if (!empty($this->options['fetch_headers'])) { |
| | | $headers = explode(' ', $this->options['fetch_headers']); |
| | | $headers = array_map('strtoupper', $headers); |
| | | } |
| | | else { |
| | | $headers = array(); |
| | |
| | | $headers = array_merge($headers, $this->all_headers); |
| | | } |
| | | |
| | | return implode(' ', array_unique($headers)); |
| | | return $headers; |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | if ($this->caching && !$this->cache) { |
| | | $rcube = rcube::get_instance(); |
| | | $ttl = $rcube->config->get('message_cache_lifetime', '10d'); |
| | | $ttl = $rcube->config->get('imap_cache_ttl', '10d'); |
| | | $this->cache = $rcube->get_cache('IMAP', $this->caching, $ttl); |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Delete outdated cache entries |
| | | */ |
| | | public function expunge_cache() |
| | | { |
| | | if ($this->mcache) { |
| | | $ttl = rcube::get_instance()->config->get('message_cache_lifetime', '10d'); |
| | | $this->mcache->expunge($ttl); |
| | | } |
| | | |
| | | if ($this->cache) { |
| | | $this->cache->expunge(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /* -------------------------------- |
| | | * message caching methods |
| | |
| | | /** |
| | | * Enable or disable messages caching |
| | | * |
| | | * @param boolean $set Flag |
| | | * @param boolean $set Flag |
| | | * @param int $mode Cache mode |
| | | */ |
| | | public function set_messages_caching($set) |
| | | public function set_messages_caching($set, $mode = null) |
| | | { |
| | | if ($set) { |
| | | $this->messages_caching = true; |
| | | |
| | | if ($mode && ($cache = $this->get_mcache_engine())) { |
| | | $cache->set_mode($mode); |
| | | } |
| | | } |
| | | else { |
| | | if ($this->mcache) { |
| | |
| | | if ($this->messages_caching && !$this->mcache) { |
| | | $rcube = rcube::get_instance(); |
| | | if (($dbh = $rcube->get_dbh()) && ($userid = $rcube->get_user_id())) { |
| | | $ttl = $rcube->config->get('messages_cache_ttl', '10d'); |
| | | $threshold = $rcube->config->get('messages_cache_threshold', 50); |
| | | $this->mcache = new rcube_imap_cache( |
| | | $dbh, $this, $userid, $this->options['skip_deleted']); |
| | | $dbh, $this, $userid, $this->options['skip_deleted'], $ttl, $threshold); |
| | | } |
| | | } |
| | | |
| | |
| | | * Clears the messages cache. |
| | | * |
| | | * @param string $folder Folder name |
| | | * @param array $uids Optional message UIDs to remove from cache |
| | | * @param array $uids Optional message UIDs to remove from cache |
| | | */ |
| | | protected function clear_message_cache($folder = null, $uids = null) |
| | | { |
| | | if ($mcache = $this->get_mcache_engine()) { |
| | | $mcache->clear($folder, $uids); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Delete outdated cache entries |
| | | */ |
| | | function cache_gc() |
| | | { |
| | | rcube_imap_cache::gc(); |
| | | } |
| | | |
| | | |
| | |
| | | $delimiter = $this->get_hierarchy_delimiter(); |
| | | |
| | | // find default folders and skip folders starting with '.' |
| | | foreach ($a_folders as $i => $folder) { |
| | | foreach ($a_folders as $folder) { |
| | | if ($folder[0] == '.') { |
| | | continue; |
| | | } |
| | |
| | | return $this->index($folder, $sort_field, $sort_order); |
| | | } |
| | | |
| | | public function message_index_direct($folder, $sort_field = null, $sort_order = null, $skip_cache = true) |
| | | public function message_index_direct($folder, $sort_field = null, $sort_order = null) |
| | | { |
| | | return $this->index_direct($folder, $sort_field, $sort_order, $skip_cache); |
| | | return $this->index_direct($folder, $sort_field, $sort_order); |
| | | } |
| | | |
| | | public function list_mailboxes($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) |