From cff88617c0010a827daafae21cc1a2cab1b5d4eb Mon Sep 17 00:00:00 2001 From: alecpl Date: Wed, 24 Mar 2010 11:27:44 +0000 Subject: [PATCH] - small backend cleanup + support for operations on ALL messages in a folder --- program/include/rcube_imap.php | 148 ++++++++++++++++++++------------- program/lib/imap.inc | 69 +++++++-------- 2 files changed, 121 insertions(+), 96 deletions(-) diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 26646f07f..64b300c65 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -2104,42 +2104,42 @@ class rcube_imap /** * 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); + 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); - - // reload message headers if cached - if ($this->caching_enabled && !$skip_cache) { - $cache_key = $mailbox.'.msg'; - $this->remove_message_cache($cache_key, $uids); + $result = iil_C_Flag($this->conn, $mailbox, $uids, $flag); + + 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; } @@ -2147,10 +2147,10 @@ class rcube_imap /** * 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) @@ -2197,7 +2197,7 @@ class rcube_imap /** * 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 @@ -2209,11 +2209,10 @@ class rcube_imap $to_mbox = $this->mod_mailbox($to_mbox); $from_mbox = $from_mbox ? $this->mod_mailbox($from_mbox) : $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); // exit if no message uids are specified - if (!is_array($a_uids) || empty($a_uids)) + if (empty($uids)) return false; // make sure mailbox exists @@ -2233,19 +2232,19 @@ class rcube_imap } // 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) { @@ -2255,10 +2254,11 @@ class rcube_imap // 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); } @@ -2266,9 +2266,9 @@ class rcube_imap // 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); } } @@ -2279,7 +2279,7 @@ class rcube_imap /** * Copy a message from one mailbox to another * - * @param string List of UIDs to copy, 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 @@ -2291,11 +2291,10 @@ class rcube_imap $to_mbox = $this->mod_mailbox($to_mbox); $from_mbox = $from_mbox ? $this->mod_mailbox($from_mbox) : $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); // exit if no message uids are specified - if (!is_array($a_uids) || empty($a_uids)) + if (empty($uids)) return false; // make sure mailbox exists @@ -2308,7 +2307,7 @@ class rcube_imap } // copy messages - $iil_copy = iil_C_Copy($this->conn, join(',', $a_uids), $from_mbox, $to_mbox); + $iil_copy = iil_C_Copy($this->conn, $uids, $from_mbox, $to_mbox); $copied = !($iil_copy === false || $iil_copy < 0); if ($copied) { @@ -2322,7 +2321,7 @@ class rcube_imap /** * 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 */ @@ -2330,19 +2329,18 @@ class rcube_imap { $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); + // 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]); @@ -2352,10 +2350,11 @@ class rcube_imap // 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); } @@ -2363,9 +2362,9 @@ class rcube_imap // 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); } } @@ -2421,12 +2420,12 @@ class rcube_imap /** * 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) { @@ -2447,11 +2446,35 @@ class rcube_imap } + /** + * Parse message UIDs input + * + * @param mixed UIDs array or comma-separated list or '*' or '1:*' + * @return array Two elements array with UIDs converted to list and ALL flag + * @access private + */ + private function _parse_uids($uids) + { + if ($uids === '*' || $uids === '1:*') { + $uids = '1:*'; + $all = true; + } + 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 * @@ -3148,6 +3171,13 @@ class rcube_imap 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')." diff --git a/program/lib/imap.inc b/program/lib/imap.inc index d77a226d8..d87747038 100644 --- a/program/lib/imap.inc +++ b/program/lib/imap.inc @@ -389,7 +389,7 @@ function iil_C_GetCapability(&$conn, $name) return false; } -function iil_C_ClearCapability(&$conn) +function iil_ClearCapability() { $conn->capability = array(); $conn->capability_readed = false; @@ -660,7 +660,7 @@ function iil_Connect($host, $user, $password, $options=null) { } // Now we're authenticated, capabilities need to be reread - iil_C_ClearCapability($conn); + iil_ClearCapability(); } } @@ -1425,10 +1425,10 @@ function iil_C_Expunge(&$conn, $mailbox, $messages=NULL) { iil_PutLine($conn->fp, "exp1 $command"); do { - $line=chop(iil_ReadLine($conn->fp, 100)); + $line = iil_ReadLine($conn->fp, 100); if ($line[0] == '*') { - $c++; - } + $c++; + } } while (!iil_StartsWith($line, 'exp1', true)); if (iil_ParseResult($line) == 0) { @@ -1447,29 +1447,27 @@ function iil_C_ModFlag(&$conn, $mailbox, $messages, $flag, $mod) { return -1; } - $fp = $conn->fp; $flags = $GLOBALS['IMAP_FLAGS']; - - $flag = strtoupper($flag); - $flag = $flags[$flag]; + $flag = $flags[strtoupper($flag)]; - if (iil_C_Select($conn, $mailbox)) { - $c = 0; - iil_PutLine($fp, "flg UID STORE $messages " . $mod . "FLAGS (" . $flag . ")"); - do { - $line=chop(iil_ReadLine($fp, 100)); - if ($line[0] == '*') { - $c++; - } - } while (!iil_StartsWith($line, 'flg', true)); + if (!iil_C_Select($conn, $mailbox)) { + return -1; + } + + $c = 0; + iil_PutLine($conn->fp, "flg UID STORE $messages " . $mod . "FLAGS (" . $flag . ")"); + do { + $line = iil_ReadLine($conn->fp, 1000); + if ($line[0] == '*') { + $c++; + } + } while (!iil_StartsWith($line, 'flg', true)); - if (iil_ParseResult($line) == 0) { - return $c; - } - $conn->error = $line; - return -1; + if (iil_ParseResult($line) == 0) { + return $c; } - $conn->error = 'Select failed'; + + $conn->error = $line; return -1; } @@ -1486,28 +1484,25 @@ function iil_C_Delete(&$conn, $mailbox, $messages) { } function iil_C_Copy(&$conn, $messages, $from, $to) { - $fp = $conn->fp; if (empty($from) || empty($to)) { return -1; } - if (iil_C_Select($conn, $from)) { - $c=0; - - iil_PutLine($fp, "cpy1 UID COPY $messages \"".iil_Escape($to)."\""); - $line = iil_ReadReply($fp); - return iil_ParseResult($line); - } else { - return -1; + if (!iil_C_Select($conn, $from)) { + return -1; } + + iil_PutLine($conn->fp, "cpy1 UID COPY $messages \"".iil_Escape($to)."\""); + $line = iil_ReadReply($conn->fp); + return iil_ParseResult($line); } function iil_C_CountUnseen(&$conn, $folder) { - $index = iil_C_Search($conn, $folder, 'ALL UNSEEN'); - if (is_array($index)) - return count($index); - return false; + $index = iil_C_Search($conn, $folder, 'ALL UNSEEN'); + if (is_array($index)) + return count($index); + return false; } function iil_C_UID2ID(&$conn, $folder, $uid) {