| | |
| | | * Get message count for a specific mailbox |
| | | * |
| | | * @param string Mailbox/folder name |
| | | * @param string Mode for count [ALL|UNSEEN|RECENT] |
| | | * @param string Mode for count [ALL|THREADS|UNSEEN|RECENT] |
| | | * @param boolean Force reading from server and update cache |
| | | * @return int Number of messages |
| | | * @access public |
| | |
| | | if (!is_array($a_mailbox_cache[$mailbox])) |
| | | $a_mailbox_cache[$mailbox] = array(); |
| | | |
| | | if ($mode == 'THREADS') |
| | | $count = $this->_threadcount($mailbox); |
| | | |
| | | if ($mode == 'THREADS') { |
| | | $count = $this->_threadcount($mailbox, $msg_count); |
| | | $_SESSION['maxuid'][$mailbox] = $msg_count ? $this->_id2uid($msg_count) : 0; |
| | | } |
| | | // RECENT count is fetched a bit different |
| | | else if ($mode == 'RECENT') |
| | | else if ($mode == 'RECENT') { |
| | | $count = iil_C_CheckForRecent($this->conn, $mailbox); |
| | | |
| | | } |
| | | // use SEARCH for message counting |
| | | else if ($this->skip_deleted) |
| | | { |
| | | else if ($this->skip_deleted) { |
| | | $search_str = "ALL UNDELETED"; |
| | | |
| | | // get message count and store in cache |
| | |
| | | |
| | | // get message count using SEARCH |
| | | // not very performant but more precise (using UNDELETED) |
| | | // disable THREADS for this request |
| | | $threads = $this->threading; |
| | | $this->threading = false; |
| | | $index = $this->_search_index($mailbox, $search_str); |
| | | $this->threading = $threads; |
| | | |
| | | $count = is_array($index) ? count($index) : 0; |
| | | |
| | | if ($mode == 'ALL') |
| | |
| | | * @access private |
| | | * @see rcube_imap::messagecount() |
| | | */ |
| | | private function _threadcount($mailbox) |
| | | private function _threadcount($mailbox, &$msg_count) |
| | | { |
| | | if (!empty($this->icache['threads'])) |
| | | return count($this->icache['threads']['tree']); |
| | | |
| | | list ($thread_tree, $msg_depth, $has_children) = $this->_fetch_threads($mailbox); |
| | | |
| | | $msg_count = count($msg_depth); |
| | | |
| | | // $this->update_thread_cache($mailbox, $thread_tree, $msg_depth, $has_children); |
| | | return count($thread_tree); |
| | |
| | | /** |
| | | * Set message flag to one or several messages |
| | | * |
| | | * @param mixed Message UIDs as array or as comma-separated string |
| | | * @param string Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT |
| | | * @param string Folder name |
| | | * @param mixed Message UIDs as array or comma-separated string, or '*' |
| | | * @param string Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT |
| | | * @param string Folder name |
| | | * @param boolean True to skip message cache clean up |
| | | * @return boolean True on success, False on failure |
| | | * @return int Number of flagged messages, -1 on failure |
| | | */ |
| | | function set_flag($uids, $flag, $mbox_name=NULL, $skip_cache=false) |
| | | { |
| | | $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox; |
| | | |
| | | $flag = strtoupper($flag); |
| | | if (!is_array($uids)) |
| | | $uids = explode(',',$uids); |
| | | |
| | | list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox); |
| | | |
| | | if (strpos($flag, 'UN') === 0) |
| | | $result = iil_C_UnFlag($this->conn, $mailbox, join(',', $uids), substr($flag, 2)); |
| | | $result = iil_C_UnFlag($this->conn, $mailbox, $uids, substr($flag, 2)); |
| | | else |
| | | $result = iil_C_Flag($this->conn, $mailbox, join(',', $uids), $flag); |
| | | $result = iil_C_Flag($this->conn, $mailbox, $uids, $flag); |
| | | |
| | | // reload message headers if cached |
| | | if ($this->caching_enabled && !$skip_cache) { |
| | | $cache_key = $mailbox.'.msg'; |
| | | $this->remove_message_cache($cache_key, $uids); |
| | | if ($result >= 0) { |
| | | // reload message headers if cached |
| | | if ($this->caching_enabled && !$skip_cache) { |
| | | $cache_key = $mailbox.'.msg'; |
| | | if ($all_mode) |
| | | $this->clear_message_cache($cache_key); |
| | | else |
| | | $this->remove_message_cache($cache_key, explode(',', $uids)); |
| | | } |
| | | // update counters |
| | | if ($flag=='SEEN') |
| | | $this->_set_messagecount($mailbox, 'UNSEEN', $result*(-1)); |
| | | else if ($flag=='UNSEEN') |
| | | $this->_set_messagecount($mailbox, 'UNSEEN', $result); |
| | | else if ($flag=='DELETED') |
| | | $this->_set_messagecount($mailbox, 'ALL', $result*(-1)); |
| | | } |
| | | |
| | | // set nr of messages that were flaged |
| | | $count = count($uids); |
| | | |
| | | // clear message count cache |
| | | if ($result && $flag=='SEEN') |
| | | $this->_set_messagecount($mailbox, 'UNSEEN', $count*(-1)); |
| | | else if ($result && $flag=='UNSEEN') |
| | | $this->_set_messagecount($mailbox, 'UNSEEN', $count); |
| | | else if ($result && $flag=='DELETED') |
| | | $this->_set_messagecount($mailbox, 'ALL', $count*(-1)); |
| | | |
| | | return $result; |
| | | } |
| | |
| | | /** |
| | | * Remove message flag for one or several messages |
| | | * |
| | | * @param mixed Message UIDs as array or as comma-separated string |
| | | * @param mixed Message UIDs as array or comma-separated string, or '*' |
| | | * @param string Flag to unset: SEEN, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT |
| | | * @param string Folder name |
| | | * @return boolean True on success, False on failure |
| | | * @return int Number of flagged messages, -1 on failure |
| | | * @see set_flag |
| | | */ |
| | | function unset_flag($uids, $flag, $mbox_name=NULL) |
| | |
| | | $mailbox = $this->mod_mailbox($mbox_name); |
| | | |
| | | // make sure mailbox exists |
| | | if ($mailbox == 'INBOX' || $this->mailbox_exists($mbox_name)) { |
| | | if ($this->mailbox_exists($mbox_name, true)) { |
| | | if ($is_file) { |
| | | $separator = rcmail::get_instance()->config->header_delimiter(); |
| | | $saved = iil_C_AppendFromFile($this->conn, $mailbox, $message, |
| | |
| | | /** |
| | | * Move a message from one mailbox to another |
| | | * |
| | | * @param string List of UIDs to move, separated by comma |
| | | * @param mixed Message UIDs as array or comma-separated string, or '*' |
| | | * @param string Target mailbox |
| | | * @param string Source mailbox |
| | | * @return boolean True on success, False on error |
| | |
| | | $to_mbox = $this->mod_mailbox($to_mbox); |
| | | $from_mbox = $from_mbox ? $this->mod_mailbox($from_mbox) : $this->mailbox; |
| | | |
| | | list($uids, $all_mode) = $this->_parse_uids($uids, $from_mbox); |
| | | |
| | | // exit if no message uids are specified |
| | | if (empty($uids)) |
| | | return false; |
| | | |
| | | // make sure mailbox exists |
| | | if ($to_mbox != 'INBOX' && !$this->mailbox_exists($tbox)) |
| | | if ($to_mbox != 'INBOX' && !$this->mailbox_exists($tbox, true)) |
| | | { |
| | | if (in_array($tbox, $this->default_folders)) |
| | | $this->create_mailbox($tbox, true); |
| | | else |
| | | return false; |
| | | } |
| | | |
| | | // convert the list of uids to array |
| | | $a_uids = is_string($uids) ? explode(',', $uids) : (is_array($uids) ? $uids : NULL); |
| | | |
| | | // exit if no message uids are specified |
| | | if (!is_array($a_uids) || empty($a_uids)) |
| | | return false; |
| | | |
| | | // flag messages as read before moving them |
| | | $config = rcmail::get_instance()->config; |
| | |
| | | } |
| | | |
| | | // move messages |
| | | $iil_move = iil_C_Move($this->conn, join(',', $a_uids), $from_mbox, $to_mbox); |
| | | $iil_move = iil_C_Move($this->conn, $uids, $from_mbox, $to_mbox); |
| | | $moved = !($iil_move === false || $iil_move < 0); |
| | | |
| | | // send expunge command in order to have the moved message |
| | | // really deleted from the source mailbox |
| | | if ($moved) { |
| | | $this->_expunge($from_mbox, false, $a_uids); |
| | | $this->_expunge($from_mbox, false, $uids); |
| | | $this->_clear_messagecount($from_mbox); |
| | | $this->_clear_messagecount($to_mbox); |
| | | } |
| | | // moving failed |
| | | else if ($config->get('delete_always', false) && $tbox == $config->get('trash_mbox')) { |
| | | $moved = $this->delete_message($a_uids, $fbox); |
| | | $moved = $this->delete_message($uids, $fbox); |
| | | } |
| | | |
| | | if ($moved) { |
| | |
| | | // remove message ids from search set |
| | | if ($this->search_set && $from_mbox == $this->mailbox) { |
| | | // threads are too complicated to just remove messages from set |
| | | if ($this->search_threads) |
| | | if ($this->search_threads || $all_mode) |
| | | $this->refresh_search(); |
| | | else { |
| | | foreach ($a_uids as $uid) |
| | | $uids = explode(',', $uids); |
| | | foreach ($uids as $uid) |
| | | $a_mids[] = $this->_uid2id($uid, $from_mbox); |
| | | $this->search_set = array_diff($this->search_set, $a_mids); |
| | | } |
| | |
| | | |
| | | // update cached message headers |
| | | $cache_key = $from_mbox.'.msg'; |
| | | if ($start_index = $this->get_message_cache_index_min($cache_key, $a_uids)) { |
| | | if ($all_mode || ($start_index = $this->get_message_cache_index_min($cache_key, $uids))) { |
| | | // clear cache from the lowest index on |
| | | $this->clear_message_cache($cache_key, $start_index); |
| | | $this->clear_message_cache($cache_key, $all_mode ? 1 : $start_index); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Copy a message from one mailbox to another |
| | | * |
| | | * @param mixed Message UIDs as array or comma-separated string, or '*' |
| | | * @param string Target mailbox |
| | | * @param string Source mailbox |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | function copy_message($uids, $to_mbox, $from_mbox='') |
| | | { |
| | | $fbox = $from_mbox; |
| | | $tbox = $to_mbox; |
| | | $to_mbox = $this->mod_mailbox($to_mbox); |
| | | $from_mbox = $from_mbox ? $this->mod_mailbox($from_mbox) : $this->mailbox; |
| | | |
| | | list($uids, $all_mode) = $this->_parse_uids($uids, $from_mbox); |
| | | |
| | | // exit if no message uids are specified |
| | | if (empty($uids)) |
| | | return false; |
| | | |
| | | // make sure mailbox exists |
| | | if ($to_mbox != 'INBOX' && !$this->mailbox_exists($tbox, true)) |
| | | { |
| | | if (in_array($tbox, $this->default_folders)) |
| | | $this->create_mailbox($tbox, true); |
| | | else |
| | | return false; |
| | | } |
| | | |
| | | // copy messages |
| | | $iil_copy = iil_C_Copy($this->conn, $uids, $from_mbox, $to_mbox); |
| | | $copied = !($iil_copy === false || $iil_copy < 0); |
| | | |
| | | if ($copied) { |
| | | $this->_clear_messagecount($to_mbox); |
| | | } |
| | | |
| | | return $copied; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Mark messages as deleted and expunge mailbox |
| | | * |
| | | * @param string List of UIDs to move, separated by comma |
| | | * @param mixed Message UIDs as array or comma-separated string, or '*' |
| | | * @param string Source mailbox |
| | | * @return boolean True on success, False on error |
| | | */ |
| | |
| | | { |
| | | $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox; |
| | | |
| | | // convert the list of uids to array |
| | | $a_uids = is_string($uids) ? explode(',', $uids) : (is_array($uids) ? $uids : NULL); |
| | | |
| | | list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox); |
| | | |
| | | // exit if no message uids are specified |
| | | if (!is_array($a_uids) || empty($a_uids)) |
| | | if (empty($uids)) |
| | | return false; |
| | | |
| | | $deleted = iil_C_Delete($this->conn, $mailbox, join(',', $a_uids)); |
| | | $deleted = iil_C_Delete($this->conn, $mailbox, $uids); |
| | | |
| | | if ($deleted) { |
| | | // send expunge command in order to have the deleted message |
| | | // really deleted from the mailbox |
| | | $this->_expunge($mailbox, false, $a_uids); |
| | | $this->_expunge($mailbox, false, $uids); |
| | | $this->_clear_messagecount($mailbox); |
| | | unset($this->uid_id_map[$mailbox]); |
| | | |
| | |
| | | // remove message ids from search set |
| | | if ($this->search_set && $mailbox == $this->mailbox) { |
| | | // threads are too complicated to just remove messages from set |
| | | if ($this->search_threads) |
| | | if ($this->search_threads || $all_mode) |
| | | $this->refresh_search(); |
| | | else { |
| | | foreach ($a_uids as $uid) |
| | | $uids = explode(',', $uids); |
| | | foreach ($uids as $uid) |
| | | $a_mids[] = $this->_uid2id($uid, $mailbox); |
| | | $this->search_set = array_diff($this->search_set, $a_mids); |
| | | } |
| | |
| | | |
| | | // remove deleted messages from cache |
| | | $cache_key = $mailbox.'.msg'; |
| | | if ($start_index = $this->get_message_cache_index_min($cache_key, $a_uids)) { |
| | | if ($all_mode || ($start_index = $this->get_message_cache_index_min($cache_key, $uids))) { |
| | | // clear cache from the lowest index on |
| | | $this->clear_message_cache($cache_key, $start_index); |
| | | $this->clear_message_cache($cache_key, $all_mode ? 1 : $start_index); |
| | | } |
| | | } |
| | | |
| | |
| | | /** |
| | | * Send IMAP expunge command and clear cache |
| | | * |
| | | * @see rcube_imap::expunge() |
| | | * @param string Mailbox name |
| | | * @param boolean False if cache should not be cleared |
| | | * @param string List of UIDs to remove, separated by comma |
| | | * @param string Mailbox name |
| | | * @param boolean False if cache should not be cleared |
| | | * @param mixed Message UIDs as array or comma-separated string, or '*' |
| | | * @return boolean True on success |
| | | * @access private |
| | | * @see rcube_imap::expunge() |
| | | */ |
| | | private function _expunge($mailbox, $clear_cache=true, $uids=NULL) |
| | | { |
| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Parse message UIDs input |
| | | * |
| | | * @param mixed UIDs array or comma-separated list or '*' or '1:*' |
| | | * @param string Mailbox name |
| | | * @return array Two elements array with UIDs converted to list and ALL flag |
| | | * @access private |
| | | */ |
| | | private function _parse_uids($uids, $mailbox) |
| | | { |
| | | if ($uids === '*' || $uids === '1:*') { |
| | | if (empty($this->search_set)) { |
| | | $uids = '1:*'; |
| | | $all = true; |
| | | } |
| | | // get UIDs from current search set |
| | | // @TODO: skip iil_C_FetchUIDs() and work with IDs instead of UIDs (?) |
| | | else { |
| | | if ($this->search_threads) |
| | | $uids = iil_C_FetchUIDs($this->conn, $mailbox, array_keys($this->search_set['depth'])); |
| | | else |
| | | $uids = iil_C_FetchUIDs($this->conn, $mailbox, $this->search_set); |
| | | |
| | | // save ID-to-UID mapping in local cache |
| | | if (is_array($uids)) |
| | | foreach ($uids as $id => $uid) |
| | | $this->uid_id_map[$mailbox][$uid] = $id; |
| | | |
| | | $uids = join(',', $uids); |
| | | } |
| | | } |
| | | else { |
| | | if (is_array($uids)) |
| | | $uids = join(',', $uids); |
| | | |
| | | if (preg_match('/[^0-9,]/', $uids)) |
| | | $uids = ''; |
| | | } |
| | | |
| | | return array($uids, (bool) $all); |
| | | } |
| | | |
| | | |
| | | /* -------------------------------- |
| | | * folder managment |
| | | * --------------------------------*/ |
| | | |
| | | |
| | | /** |
| | | * Get a list of all folders available on the IMAP server |
| | |
| | | { |
| | | $mailbox = $this->mod_mailbox($mbox_name); |
| | | $sub_mboxes = iil_C_ListMailboxes($this->conn, $this->mod_mailbox(''), |
| | | $mailbox . $this->delimiter . '*'); |
| | | $mbox_name . $this->delimiter . '*'); |
| | | |
| | | // unsubscribe mailbox before deleting |
| | | iil_C_UnSubscribe($this->conn, $mailbox); |
| | |
| | | |
| | | foreach ($sub_mboxes as $c_mbox) |
| | | if ($c_mbox != 'INBOX') { |
| | | iil_C_UnSubscribe($this->conn, $c_mbox); |
| | | $result = iil_C_DeleteFolder($this->conn, $c_mbox); |
| | | if ($result >= 0) { |
| | | $deleted = true; |
| | | $this->clear_message_cache($c_mbox.'.msg'); |
| | | iil_C_UnSubscribe($this->conn, $c_mbox); |
| | | $result = iil_C_DeleteFolder($this->conn, $c_mbox); |
| | | if ($result >= 0) { |
| | | $deleted = true; |
| | | $this->clear_message_cache($c_mbox.'.msg'); |
| | | } |
| | | } |
| | | } |
| | |
| | | if ($mbox_name == 'INBOX') |
| | | return true; |
| | | |
| | | $mbox = $this->mod_mailbox($mbox_name); |
| | | |
| | | if ($subscription) { |
| | | if ($a_folders = iil_C_ListSubscribed($this->conn, $this->mod_mailbox(''), $mbox)) |
| | | if ($a_folders = iil_C_ListSubscribed($this->conn, $this->mod_mailbox(''), $mbox_name)) |
| | | return true; |
| | | } |
| | | else { |
| | | $a_folders = iil_C_ListMailboxes($this->conn, $this->mod_mailbox(''), $mbox); |
| | | $a_folders = iil_C_ListMailboxes($this->conn, $this->mod_mailbox(''), $mbox_mbox); |
| | | |
| | | if (is_array($a_folders) && in_array($mbox, $a_folders)) |
| | | if (is_array($a_folders) && in_array($this->mod_mailbox($mbox_name), $a_folders)) |
| | | return true; |
| | | } |
| | | } |
| | |
| | | if (!$this->caching_enabled) |
| | | return; |
| | | |
| | | if (!empty($uids) && !is_array($uids)) { |
| | | if ($uids == '*' || $uids == '1:*') |
| | | $uids = NULL; |
| | | else |
| | | $uids = explode(',', $uids); |
| | | } |
| | | |
| | | $sql_result = $this->db->query( |
| | | "SELECT MIN(idx) AS minidx |
| | | FROM ".get_table_name('messages')." |