- Improve performance of moving or copying of all messages in a folder (use CLOSE intead of EXPUNGE)

- Code cleanup + added more phpdoc comments
release-0.6
alecpl 14 years ago
parent c0c0c03d97
commit e232acbfde

@ -12,6 +12,8 @@ CHANGELOG Roundcube Webmail
- Fix invalid Request when creating a folder (#1487443) - Fix invalid Request when creating a folder (#1487443)
- Add folder size and quota indicator in folder manager (#1485780) - Add folder size and quota indicator in folder manager (#1485780)
- Add possibility to move a subfolder into root folder (#1486791) - 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 RELEASE 0.5-BETA
---------------- ----------------

@ -185,7 +185,7 @@ class rcube_imap
*/ */
function close() function close()
{ {
$this->conn->close(); $this->conn->closeConnection();
$this->write_cache(); $this->write_cache();
} }
@ -198,7 +198,7 @@ class rcube_imap
*/ */
function reconnect() function reconnect()
{ {
$this->close(); $this->closeConnection();
$this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl); $this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl);
// issue SELECT command to restore connection status // issue SELECT command to restore connection status
@ -617,7 +617,7 @@ class rcube_imap
} }
// RECENT count is fetched a bit different // RECENT count is fetched a bit different
else if ($mode == 'RECENT') { else if ($mode == 'RECENT') {
$count = $this->conn->checkForRecent($mailbox); $count = $this->conn->countRecent($mailbox);
} }
// use SEARCH for message counting // use SEARCH for message counting
else if ($this->skip_deleted) { else if ($this->skip_deleted) {
@ -2582,6 +2582,7 @@ class rcube_imap
// send expunge command in order to have the moved message // send expunge command in order to have the moved message
// really deleted from the source mailbox // really deleted from the source mailbox
$aa = rcube_timer();
if ($moved) { if ($moved) {
$this->_expunge($from_mbox, false, $uids); $this->_expunge($from_mbox, false, $uids);
$this->_clear_messagecount($from_mbox); $this->_clear_messagecount($from_mbox);
@ -2591,7 +2592,7 @@ class rcube_imap
else if ($config->get('delete_always', false) && $tbox == $config->get('trash_mbox')) { else if ($config->get('delete_always', false) && $tbox == $config->get('trash_mbox')) {
$moved = $this->delete_message($uids, $fbox); $moved = $this->delete_message($uids, $fbox);
} }
rcube_print_time($aa);
if ($moved) { if ($moved) {
// unset threads internal cache // unset threads internal cache
unset($this->icache['threads']); unset($this->icache['threads']);
@ -2774,6 +2775,10 @@ class rcube_imap
else else
$a_uids = NULL; $a_uids = NULL;
// 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); $result = $this->conn->expunge($mailbox, $a_uids);
if ($result && $clear_cache) { if ($result && $clear_cache) {

@ -683,7 +683,7 @@ class rcube_imap_generic
$error = sprintf("Empty startup greeting (%s:%d)", $host, $this->prefs['port']); $error = sprintf("Empty startup greeting (%s:%d)", $host, $this->prefs['port']);
$this->setError(self::ERROR_BAD, $error); $this->setError(self::ERROR_BAD, $error);
$this->close(); $this->closeConnection();
return false; return false;
} }
@ -700,13 +700,13 @@ class rcube_imap_generic
$res = $this->execute('STARTTLS'); $res = $this->execute('STARTTLS');
if ($res[0] != self::ERROR_OK) { if ($res[0] != self::ERROR_OK) {
$this->close(); $this->closeConnection();
return false; return false;
} }
if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
$this->setError(self::ERROR_BAD, "Unable to negotiate TLS"); $this->setError(self::ERROR_BAD, "Unable to negotiate TLS");
$this->close(); $this->closeConnection();
return false; return false;
} }
@ -738,7 +738,7 @@ class rcube_imap_generic
// Prevent from sending credentials in plain text when connection is not secure // Prevent from sending credentials in plain text when connection is not secure
if ($auth_method == 'LOGIN' && $this->getCapability('LOGINDISABLED')) { if ($auth_method == 'LOGIN' && $this->getCapability('LOGINDISABLED')) {
$this->setError(self::ERROR_BAD, "Login disabled by IMAP server"); $this->setError(self::ERROR_BAD, "Login disabled by IMAP server");
$this->close(); $this->closeConnection();
return false; return false;
} }
// replace AUTH with CRAM-MD5 for backward compat. // replace AUTH with CRAM-MD5 for backward compat.
@ -778,8 +778,7 @@ class rcube_imap_generic
return true; return true;
} }
// Close connection $this->closeConnection();
$this->close();
return false; return false;
} }
@ -789,7 +788,7 @@ class rcube_imap_generic
return ($this->fp && $this->logged) ? true : false; return ($this->fp && $this->logged) ? true : false;
} }
function close() function closeConnection()
{ {
if ($this->putLine($this->nextTag() . ' LOGOUT')) { if ($this->putLine($this->nextTag() . ' LOGOUT')) {
$this->readReply(); $this->readReply();
@ -799,6 +798,14 @@ class rcube_imap_generic
$this->fp = false; $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) function select($mailbox)
{ {
if (!strlen($mailbox)) { if (!strlen($mailbox)) {
@ -842,7 +849,7 @@ class rcube_imap_generic
} }
/** /**
* Executes STATUS comand * Executes STATUS command
* *
* @param string $mailbox Mailbox name * @param string $mailbox Mailbox name
* @param array $items Additional requested item names. By default * @param array $items Additional requested item names. By default
@ -887,21 +894,133 @@ class rcube_imap_generic
return false; 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)) { if (!$this->select($mailbox)) {
$mailbox = 'INBOX'; return false;
} }
$this->select($mailbox); // Clear internal status cache
unset($this->data['STATUS:'.$mailbox]);
if ($this->selected == $mailbox) { if ($messages)
return $this->data['RECENT']; $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; 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) function countMessages($mailbox, $refresh = false)
{ {
if ($refresh) { if ($refresh) {
@ -927,6 +1046,29 @@ class rcube_imap_generic
return false; return false;
} }
/**
* 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 * Returns count of messages without \Seen flag in a specified folder
* *
@ -1565,27 +1707,6 @@ class rcube_imap_generic
return $result; 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) function modFlag($mailbox, $messages, $flag, $mod)
{ {
@ -2153,39 +2274,6 @@ class rcube_imap_generic
return ($result == self::ERROR_OK); 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) function append($mailbox, &$message)
{ {
if (!$mailbox) { if (!$mailbox) {

Loading…
Cancel
Save