summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2010-12-03 12:25:49 +0000
committeralecpl <alec@alec.pl>2010-12-03 12:25:49 +0000
commite232acbfde30e27101f84da7f0a617f8a8522512 (patch)
treeebc5aee2db28601d4a62a3412d02c3c711e13330
parentc0c0c03d97c7d7d7157c34c17f2fcddbb2533d32 (diff)
- Improve performance of moving or copying of all messages in a folder (use CLOSE intead of EXPUNGE)
- Code cleanup + added more phpdoc comments
-rw-r--r--CHANGELOG2
-rw-r--r--program/include/rcube_imap.php15
-rw-r--r--program/include/rcube_imap_generic.php228
3 files changed, 170 insertions, 75 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 6044c02ac..8f9b0b5a1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -12,6 +12,8 @@ CHANGELOG Roundcube Webmail
- Fix invalid Request when creating a folder (#1487443)
- Add folder size and quota indicator in folder manager (#1485780)
- Add possibility to move a subfolder into root folder (#1486791)
+- Fix copying all messages in a folder copies only messages from current page
+- Improve performance of moving or copying of all messages in a folder
RELEASE 0.5-BETA
----------------
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index dd9f81b86..bf88c2991 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -185,7 +185,7 @@ class rcube_imap
*/
function close()
{
- $this->conn->close();
+ $this->conn->closeConnection();
$this->write_cache();
}
@@ -198,7 +198,7 @@ class rcube_imap
*/
function reconnect()
{
- $this->close();
+ $this->closeConnection();
$this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl);
// issue SELECT command to restore connection status
@@ -617,7 +617,7 @@ class rcube_imap
}
// RECENT count is fetched a bit different
else if ($mode == 'RECENT') {
- $count = $this->conn->checkForRecent($mailbox);
+ $count = $this->conn->countRecent($mailbox);
}
// use SEARCH for message counting
else if ($this->skip_deleted) {
@@ -2582,6 +2582,7 @@ class rcube_imap
// send expunge command in order to have the moved message
// really deleted from the source mailbox
+$aa = rcube_timer();
if ($moved) {
$this->_expunge($from_mbox, false, $uids);
$this->_clear_messagecount($from_mbox);
@@ -2591,7 +2592,7 @@ class rcube_imap
else if ($config->get('delete_always', false) && $tbox == $config->get('trash_mbox')) {
$moved = $this->delete_message($uids, $fbox);
}
-
+rcube_print_time($aa);
if ($moved) {
// unset threads internal cache
unset($this->icache['threads']);
@@ -2774,7 +2775,11 @@ class rcube_imap
else
$a_uids = NULL;
- $result = $this->conn->expunge($mailbox, $a_uids);
+ // CLOSE(+SELECT) should be faster than EXPUNGE
+ if (empty($a_uids) || $a_uids == '1:*')
+ $result = $this->conn->close();
+ else
+ $result = $this->conn->expunge($mailbox, $a_uids);
if ($result && $clear_cache) {
$this->clear_message_cache($mailbox.'.msg');
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 16c9d4a64..d3742fe8e 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -683,7 +683,7 @@ class rcube_imap_generic
$error = sprintf("Empty startup greeting (%s:%d)", $host, $this->prefs['port']);
$this->setError(self::ERROR_BAD, $error);
- $this->close();
+ $this->closeConnection();
return false;
}
@@ -700,13 +700,13 @@ class rcube_imap_generic
$res = $this->execute('STARTTLS');
if ($res[0] != self::ERROR_OK) {
- $this->close();
+ $this->closeConnection();
return false;
}
if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
$this->setError(self::ERROR_BAD, "Unable to negotiate TLS");
- $this->close();
+ $this->closeConnection();
return false;
}
@@ -738,7 +738,7 @@ class rcube_imap_generic
// Prevent from sending credentials in plain text when connection is not secure
if ($auth_method == 'LOGIN' && $this->getCapability('LOGINDISABLED')) {
$this->setError(self::ERROR_BAD, "Login disabled by IMAP server");
- $this->close();
+ $this->closeConnection();
return false;
}
// replace AUTH with CRAM-MD5 for backward compat.
@@ -778,8 +778,7 @@ class rcube_imap_generic
return true;
}
- // Close connection
- $this->close();
+ $this->closeConnection();
return false;
}
@@ -789,7 +788,7 @@ class rcube_imap_generic
return ($this->fp && $this->logged) ? true : false;
}
- function close()
+ function closeConnection()
{
if ($this->putLine($this->nextTag() . ' LOGOUT')) {
$this->readReply();
@@ -799,6 +798,14 @@ class rcube_imap_generic
$this->fp = false;
}
+ /**
+ * Executes SELECT command (if mailbox is already not in selected state)
+ *
+ * @param string $mailbox Mailbox name
+ *
+ * @return boolean True on success, false on error
+ * @access public
+ */
function select($mailbox)
{
if (!strlen($mailbox)) {
@@ -842,7 +849,7 @@ class rcube_imap_generic
}
/**
- * Executes STATUS comand
+ * Executes STATUS command
*
* @param string $mailbox Mailbox name
* @param array $items Additional requested item names. By default
@@ -887,21 +894,133 @@ class rcube_imap_generic
return false;
}
- function checkForRecent($mailbox)
+ /**
+ * Executes EXPUNGE command
+ *
+ * @param string $mailbox Mailbox name
+ * @param string $messages Message UIDs to expunge
+ *
+ * @return boolean True on success, False on error
+ * @access public
+ */
+ function expunge($mailbox, $messages=NULL)
{
- if (!strlen($mailbox)) {
- $mailbox = 'INBOX';
- }
+ if (!$this->select($mailbox)) {
+ return false;
+ }
- $this->select($mailbox);
+ // Clear internal status cache
+ unset($this->data['STATUS:'.$mailbox]);
- if ($this->selected == $mailbox) {
- return $this->data['RECENT'];
- }
+ if ($messages)
+ $result = $this->execute('UID EXPUNGE', array($messages), self::COMMAND_NORESPONSE);
+ else
+ $result = $this->execute('EXPUNGE', null, self::COMMAND_NORESPONSE);
+
+ if ($result == self::ERROR_OK) {
+ $this->selected = ''; // state has changed, need to reselect
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Executes CLOSE command
+ *
+ * @return boolean True on success, False on error
+ * @access public
+ * @since 0.5
+ */
+ function close()
+ {
+ $result = $this->execute('CLOSE', NULL, self::COMMAND_NORESPONSE);
+
+ if ($result == self::ERROR_OK) {
+ $this->selected = '';
+ return true;
+ }
return false;
}
+ /**
+ * Executes SUBSCRIBE command
+ *
+ * @param string $mailbox Mailbox name
+ *
+ * @return boolean True on success, False on error
+ * @access public
+ */
+ function subscribe($mailbox)
+ {
+ $result = $this->execute('SUBSCRIBE', array($this->escape($mailbox)),
+ self::COMMAND_NORESPONSE);
+
+ return ($result == self::ERROR_OK);
+ }
+
+ /**
+ * Executes UNSUBSCRIBE command
+ *
+ * @param string $mailbox Mailbox name
+ *
+ * @return boolean True on success, False on error
+ * @access public
+ */
+ function unsubscribe($mailbox)
+ {
+ $result = $this->execute('UNSUBSCRIBE', array($this->escape($mailbox)),
+ self::COMMAND_NORESPONSE);
+
+ return ($result == self::ERROR_OK);
+ }
+
+ /**
+ * Executes DELETE command
+ *
+ * @param string $mailbox Mailbox name
+ *
+ * @return boolean True on success, False on error
+ * @access public
+ */
+ function deleteFolder($mailbox)
+ {
+ $result = $this->execute('DELETE', array($this->escape($mailbox)),
+ self::COMMAND_NORESPONSE);
+
+ return ($result == self::ERROR_OK);
+ }
+
+ /**
+ * Removes all messages in a folder
+ *
+ * @param string $mailbox Mailbox name
+ *
+ * @return boolean True on success, False on error
+ * @access public
+ */
+ function clearFolder($mailbox)
+ {
+ $num_in_trash = $this->countMessages($mailbox);
+ if ($num_in_trash > 0) {
+ $this->delete($mailbox, '1:*');
+ }
+
+ $res = $this->close();
+// $res = $this->expunge($mailbox);
+
+ return $res;
+ }
+
+ /**
+ * Returns count of all messages in a folder
+ *
+ * @param string $mailbox Mailbox name
+ *
+ * @return int Number of messages, False on error
+ * @access public
+ */
function countMessages($mailbox, $refresh = false)
{
if ($refresh) {
@@ -928,6 +1047,29 @@ class rcube_imap_generic
}
/**
+ * Returns count of messages with \Recent flag in a folder
+ *
+ * @param string $mailbox Mailbox name
+ *
+ * @return int Number of messages, False on error
+ * @access public
+ */
+ function countRecent($mailbox)
+ {
+ if (!strlen($mailbox)) {
+ $mailbox = 'INBOX';
+ }
+
+ $this->select($mailbox);
+
+ if ($this->selected == $mailbox) {
+ return $this->data['RECENT'];
+ }
+
+ return false;
+ }
+
+ /**
* Returns count of messages without \Seen flag in a specified folder
*
* @param string $mailbox Mailbox name
@@ -1565,27 +1707,6 @@ class rcube_imap_generic
return $result;
}
- function expunge($mailbox, $messages=NULL)
- {
- if (!$this->select($mailbox)) {
- return false;
- }
-
- // Clear internal status cache
- unset($this->data['STATUS:'.$mailbox]);
-
- if ($messages)
- $result = $this->execute('UID EXPUNGE', array($messages), self::COMMAND_NORESPONSE);
- else
- $result = $this->execute('EXPUNGE', null, self::COMMAND_NORESPONSE);
-
- if ($result == self::ERROR_OK) {
- $this->selected = ''; // state has changed, need to reselect
- return true;
- }
-
- return false;
- }
function modFlag($mailbox, $messages, $flag, $mod)
{
@@ -2153,39 +2274,6 @@ class rcube_imap_generic
return ($result == self::ERROR_OK);
}
- function deleteFolder($mailbox)
- {
- $result = $this->execute('DELETE', array($this->escape($mailbox)),
- self::COMMAND_NORESPONSE);
-
- return ($result == self::ERROR_OK);
- }
-
- function clearFolder($mailbox)
- {
- $num_in_trash = $this->countMessages($mailbox);
- if ($num_in_trash > 0) {
- $this->delete($mailbox, '1:*');
- }
- return ($this->expunge($mailbox) >= 0);
- }
-
- function subscribe($mailbox)
- {
- $result = $this->execute('SUBSCRIBE', array($this->escape($mailbox)),
- self::COMMAND_NORESPONSE);
-
- return ($result == self::ERROR_OK);
- }
-
- function unsubscribe($mailbox)
- {
- $result = $this->execute('UNSUBSCRIBE', array($this->escape($mailbox)),
- self::COMMAND_NORESPONSE);
-
- return ($result == self::ERROR_OK);
- }
-
function append($mailbox, &$message)
{
if (!$mailbox) {