alecpl
2010-12-08 90f81a6c8de5aecfa36c54cc5260d25ba883aa51
- Better support for READ-ONLY and NOPERM responses handling (#1487083)
- Add confirmation message on purge/expunge commands response
- Fix CLOSE was called on unselected mailbox


13 files modified
237 ■■■■ changed files
CHANGELOG 2 ●●●●● patch | view | raw | blame | history
program/include/main.inc 32 ●●●●● patch | view | raw | blame | history
program/include/rcube_imap.php 72 ●●●●● patch | view | raw | blame | history
program/include/rcube_imap_generic.php 58 ●●●● patch | view | raw | blame | history
program/localization/en_US/messages.inc 3 ●●●●● patch | view | raw | blame | history
program/localization/pl_PL/messages.inc 3 ●●●●● patch | view | raw | blame | history
program/steps/mail/copy.inc 4 ●●● patch | view | raw | blame | history
program/steps/mail/folders.inc 36 ●●●●● patch | view | raw | blame | history
program/steps/mail/list.inc 3 ●●●● patch | view | raw | blame | history
program/steps/mail/mark.inc 2 ●●● patch | view | raw | blame | history
program/steps/mail/move_del.inc 4 ●●●● patch | view | raw | blame | history
program/steps/mail/search.inc 3 ●●●● patch | view | raw | blame | history
program/steps/settings/folders.inc 15 ●●●●● patch | view | raw | blame | history
CHANGELOG
@@ -16,6 +16,8 @@
- Improve performance of moving or copying of all messages in a folder
- Fix plaintext versions of HTML messages don't contain placeholders for emotions (#1485206)
- Improve performance of folder rename and delete actions
- Better support for READ-ONLY and NOPERM responses handling (#1487083)
- Add confirmation message on purge/expunge command response
RELEASE 0.5-BETA
----------------
program/include/main.inc
@@ -1616,6 +1616,38 @@
/**
 * Outputs error message according to server error/response codes
 *
 * @param string Fallback message label
 * @param string Fallback message label arguments
 *
 * @return void
 */
function rcmail_display_server_error($fallback=null, $fallback_args=null)
{
    global $RCMAIL;
    $err_code = $RCMAIL->imap->get_error_code();
    $res_code = $RCMAIL->imap->get_response_code();
    if ($res_code == rcube_imap::NOPERM) {
        $RCMAIL->output->show_message('errornoperm', 'error');
    }
    else if ($res_code == rcube_imap::READONLY) {
        $RCMAIL->output->show_message('errorreadonly', 'error');
    }
    else if ($err_code && ($err_str = $RCMAIL->imap->get_error_str())) {
        $RCMAIL->output->show_message('servererrormsg', 'error', array('msg' => $err_str));
    }
    else if ($fallback) {
        $RCMAIL->output->show_message($fallback, 'error', $fallback_args);
    }
    return true;
}
/**
 * Output HTML editor scripts
 *
 * @param string Editor mode
program/include/rcube_imap.php
@@ -100,6 +100,16 @@
        'RETURN-PATH',
    );
    const UNKNOWN       = 0;
    const NOPERM        = 1;
    const READONLY      = 2;
    const TRYCREATE     = 3;
    const INUSE         = 4;
    const OVERQUOTA     = 5;
    const ALREADYEXISTS = 6;
    const NONEXISTENT   = 7;
    const CONTACTADMIN  = 8;
    /**
     * Object constructor
@@ -220,7 +230,51 @@
     */
    function get_error_str()
    {
        return ($this->conn) ? $this->conn->error : '';
        return ($this->conn) ? $this->conn->error : null;
    }
    /**
     * Returns code of last command response
     *
     * @return int Response code
     */
    function get_response_code()
    {
        if (!$this->conn)
            return self::UNKNOWN;
        switch ($this->conn->resultcode) {
            case 'NOPERM':
                return self::NOPERM;
            case 'READ-ONLY':
                return self::READONLY;
            case 'TRYCREATE':
                return self::TRYCREATE;
            case 'INUSE':
                return self::INUSE;
            case 'OVERQUOTA':
                return self::OVERQUOTA;
            case 'ALREADYEXISTS':
                return self::ALREADYEXISTS;
            case 'NONEXISTENT':
                return self::NONEXISTENT;
            case 'CONTACTADMIN':
                return self::CONTACTADMIN;
            default:
                return self::UNKNOWN;
        }
    }
    /**
     * Returns last command response
     *
     * @return string Response
     */
    function get_response_str()
    {
        return ($this->conn) ? $this->conn->result : null;
    }
@@ -295,9 +349,9 @@
     * @param  string $mailbox Mailbox/Folder name
     * @access public
     */
    function select_mailbox($mailbox)
    function select_mailbox($mailbox=null)
    {
        $mailbox = $this->mod_mailbox($mailbox);
        $mailbox = strlen($mailbox) ? $this->mod_mailbox($mailbox) : $this->mailbox;
        $selected = $this->conn->select($mailbox);
@@ -2769,6 +2823,18 @@
        else
            $a_uids = NULL;
        // force mailbox selection and check if mailbox is writeable
        // to prevent a situation when CLOSE is executed on closed
        // or EXPUNGE on read-only mailbox
        $result = $this->conn->select($mailbox);
        if (!$result) {
            return false;
        }
        if (!$this->conn->data['READ-WRITE']) {
            $this->conn->setError(rcube_imap_generic::ERROR_READONLY, "Mailbox is read-only");
            return false;
        }
        // CLOSE(+SELECT) should be faster than EXPUNGE
        if (empty($a_uids) || $a_uids == '1:*')
            $result = $this->conn->close();
program/include/rcube_imap_generic.php
@@ -85,6 +85,8 @@
{
    public $error;
    public $errornum;
    public $result;
    public $resultcode;
    public $data = array();
    public $flags = array(
        'SEEN'     => '\\Seen',
@@ -112,8 +114,9 @@
    const ERROR_NO = -1;
    const ERROR_BAD = -2;
    const ERROR_BYE = -3;
    const ERROR_COMMAND = -5;
    const ERROR_UNKNOWN = -4;
    const ERROR_COMMAND = -5;
    const ERROR_READONLY = -6;
    const COMMAND_NORESPONSE = 1;
    const COMMAND_CAPABILITY = 2;
@@ -302,7 +305,7 @@
            $str = trim($matches[2]);
            if ($res == 'OK') {
                return $this->errornum = self::ERROR_OK;
                $this->errornum = self::ERROR_OK;
            } else if ($res == 'NO') {
                $this->errornum = self::ERROR_NO;
            } else if ($res == 'BAD') {
@@ -313,15 +316,29 @@
                $this->errornum = self::ERROR_BYE;
            }
            if ($str)
            if ($str) {
                $str = trim($str);
                // get response string and code (RFC5530)
                if (preg_match("/^\[([a-z-]+)\]/i", $str, $m)) {
                    $this->resultcode = strtoupper($m[1]);
                    $str = trim(substr($str, strlen($m[1]) + 2));
                }
                else {
                    $this->resultcode = null;
                }
                $this->result = $str;
                if ($this->errornum != self::ERROR_OK) {
                $this->error = $err_prefix ? $err_prefix.$str : $str;
                }
            }
            return $this->errornum;
        }
        return self::ERROR_UNKNOWN;
    }
    private function setError($code, $msg='')
    function setError($code, $msg='')
    {
        $this->errornum = $code;
        $this->error    = $msg;
@@ -838,6 +855,8 @@
                }
            }
            $this->data['READ-WRITE'] = $this->resultcode != 'READ-ONLY';
            $this->selected = $mailbox;
            return true;
        }
@@ -903,6 +922,11 @@
    function expunge($mailbox, $messages=NULL)
    {
        if (!$this->select($mailbox)) {
            return false;
        }
        if (!$this->data['READ-WRITE']) {
            $this->setError(self::ERROR_READONLY, "Mailbox is read-only", 'EXPUNGE');
            return false;
        }
@@ -1001,11 +1025,15 @@
    {
        $num_in_trash = $this->countMessages($mailbox);
        if ($num_in_trash > 0) {
            $this->delete($mailbox, '1:*');
            $res = $this->delete($mailbox, '1:*');
        }
        if ($res) {
            if ($this->selected == $mailbox)
        $res = $this->close();
//        $res = $this->expunge($mailbox);
            else
                $res = $this->expunge($mailbox);
        }
        return $res;
    }
@@ -1715,6 +1743,11 @@
            return false;
        }
        if (!$this->data['READ-WRITE']) {
            $this->setError(self::ERROR_READONLY, "Mailbox is read-only", 'STORE');
            return false;
        }
        // Clear internal status cache
        if ($flag == 'SEEN') {
            unset($this->data['STATUS:'.$mailbox]['UNSEEN']);
@@ -1758,6 +1791,15 @@
    function move($messages, $from, $to)
    {
        if (!$this->select($from)) {
            return false;
        }
        if (!$this->data['READ-WRITE']) {
            $this->setError(self::ERROR_READONLY, "Mailbox is read-only", 'STORE');
            return false;
        }
        $r = $this->copy($messages, $from, $to);
        if ($r) {
@@ -2963,9 +3005,9 @@
            $this->parseCapability($matches[1], true);
        }
        // return last line only (without command tag and result)
        // return last line only (without command tag, result and response code)
        if ($line && ($options & self::COMMAND_LASTLINE)) {
            $response = preg_replace("/^$tag (OK|NO|BAD|BYE|PREAUTH)?\s*/i", '', trim($line));
            $response = preg_replace("/^$tag (OK|NO|BAD|BYE|PREAUTH)?\s*(\[[a-z-]+\])?\s*/i", '', trim($line));
        }
        return $noresp ? $code : array($code, $response);
program/localization/en_US/messages.inc
@@ -24,6 +24,8 @@
$messages['imaperror'] = 'Connection to IMAP server failed';
$messages['servererror'] = 'Server Error!';
$messages['servererrormsg'] = 'Server Error: $msg';
$messages['errorreadonly'] = 'Unable to perform operation. Folder is read-only';
$messages['errornoperm'] = 'Unable to perform operation. Permission denied';
$messages['invalidrequest'] = 'Invalid request! No data was saved.';
$messages['nomessagesfound'] = 'No messages found in this mailbox';
$messages['loggedout'] = 'You have successfully terminated the session. Good bye!';
@@ -81,6 +83,7 @@
$messages['foldersubscribed'] = 'Folder successfully subscribed';
$messages['folderunsubscribed'] = 'Folder successfully unsubscribed';
$messages['folderpurged'] = 'Folder successfully purged';
$messages['folderexpunged'] = 'Folder successfully emptied';
$messages['deletedsuccessfully'] = 'Successfully deleted';
$messages['converting'] = 'Removing formatting...';
$messages['messageopenerror'] = 'Could not load message from server';
program/localization/pl_PL/messages.inc
@@ -135,9 +135,12 @@
$messages['foldersubscribed'] = 'Folder pomyślnie zasubskrybowany';
$messages['folderunsubscribed'] = 'Folder pomyślnie odsubskrybowany';
$messages['folderpurged'] = 'Folder pomyślnie wyczyszczony';
$messages['folderexpunged'] = 'Folder pomyślnie opróżniony';
$messages['namecannotbeempty'] = 'Nazwa nie może być pusta';
$messages['nametoolong'] = 'Name jest zbyt długa';
$messages['folderupdated'] = 'Folder pomyślnie zaktualizowany';
$messages['foldercreated'] = 'Folder pomyślnie utworzony';
$messages['errorreadonly'] = 'Nie można wykonać operacji. Folder tylko do odczytu';
$messages['errornoperm'] = 'Nie można wykonać operacji. Brak uprawnień';
?>
program/steps/mail/copy.inc
@@ -33,7 +33,7 @@
    if (!$copied) {
        // send error message
        $OUTPUT->show_message('errorcopying', 'error');
        rcmail_display_server_error('errorcopying');
        $OUTPUT->send();
        exit;
    }
@@ -52,5 +52,3 @@
// send response
$OUTPUT->send();
program/steps/mail/folders.inc
@@ -25,20 +25,24 @@
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST, true);
// send EXPUNGE command
if ($RCMAIL->action=='expunge')
{
if ($RCMAIL->action == 'expunge') {
  $success = $IMAP->expunge($mbox);
  // reload message list if current mailbox
  if ($success && !empty($_REQUEST['_reload']))
  {
    if ($success) {
        $OUTPUT->show_message('folderexpunged', 'confirmation');
        if (!empty($_REQUEST['_reload'])) {
    $OUTPUT->command('set_quota', rcmail_quota_content());
    $OUTPUT->command('message_list.clear');
    $RCMAIL->action = 'list';
    return;
  }
  else
    $commands = "// expunged: $success\n";
    }
    else {
        rcmail_display_server_error();
    }
}
// clear mailbox
@@ -50,12 +54,14 @@
  // we should only be purging trash and junk (or their subfolders)
  if ($mbox == $CONFIG['trash_mbox'] || $mbox == $CONFIG['junk_mbox']
    || preg_match($trash_regexp, $mbox) || preg_match($junk_regexp, $mbox))
  {
        || preg_match($trash_regexp, $mbox) || preg_match($junk_regexp, $mbox)
    ) {
    $success = $IMAP->clear_mailbox($mbox);
    if ($success && !empty($_REQUEST['_reload']))
    {
        if ($success) {
            $OUTPUT->show_message('folderpurged', 'confirmation');
            if (!empty($_REQUEST['_reload'])) {
      $OUTPUT->set_env('messagecount', 0);
      $OUTPUT->set_env('pagecount', 0);
      $OUTPUT->command('message_list.clear');
@@ -64,11 +70,11 @@
      $OUTPUT->command('set_quota', rcmail_quota_content());
      rcmail_set_unseen_count($mbox, 0);
    }
    else
      $commands = "// purged: $success";
        }
        else {
            rcmail_display_server_error();
        }
  }
}
$OUTPUT->send($commands);
$OUTPUT->send();
program/steps/mail/list.inc
@@ -106,8 +106,7 @@
else {
  // handle IMAP errors (e.g. #1486905)
  if ($err_code = $IMAP->get_error_code()) {
    $err_str = $IMAP->get_error_str();
    $OUTPUT->show_message('servererrormsg', 'error', array('msg' => $err_str));
    rcmail_display_server_error();
  }
  else if ($search_request)
    $OUTPUT->show_message('searchnomatch', 'notice');
program/steps/mail/mark.inc
@@ -47,7 +47,7 @@
    // send error message
    if ($_POST['_from'] != 'show')
      $OUTPUT->command('list_mailbox');
    $OUTPUT->show_message('errormarking', 'error');
    rcmail_display_server_error('errormarking');
    $OUTPUT->send();
    exit;
  }
program/steps/mail/move_del.inc
@@ -39,7 +39,7 @@
        // send error message
        if ($_POST['_from'] != 'show')
            $OUTPUT->command('list_mailbox');
        $OUTPUT->show_message('errormoving', 'error');
        rcmail_display_server_error('errormoving');
        $OUTPUT->send();
        exit;
    }
@@ -60,7 +60,7 @@
        // send error message
        if ($_POST['_from'] != 'show')
            $OUTPUT->command('list_mailbox');
        $OUTPUT->show_message('errordeleting', 'error');
        rcmail_display_server_error('errordeleting');
        $OUTPUT->send();
        exit;
    }
program/steps/mail/search.inc
@@ -124,8 +124,7 @@
}
// handle IMAP errors (e.g. #1486905)
else  if ($err_code = $IMAP->get_error_code()) {
  $err_str = $IMAP->get_error_str();
  $OUTPUT->show_message('servererrormsg', 'error', array('msg' => $err_str));
  rcmail_display_server_error();
}
else {
  $OUTPUT->show_message('searchnomatch', 'notice');
program/steps/settings/folders.inc
@@ -34,7 +34,7 @@
        // Handle virtual (non-existing) folders
        if (!$result && $IMAP->get_error_code() == -1 &&
            strpos($IMAP->get_error_str(), '[TRYCREATE]')
            $IMAP->get_response_code() == rcube_imap::TRYCREATE
        ) {
            $result = $IMAP->create_mailbox($mbox, true);
            if ($result) {
@@ -45,7 +45,7 @@
        if ($result)
            $OUTPUT->show_message('foldersubscribed', 'confirmation');
        else
            $OUTPUT->show_message('errorsaving', 'error');
            rcmail_display_server_error('errorsaving');
    }
}
@@ -58,7 +58,7 @@
        if ($result)
            $OUTPUT->show_message('folderunsubscribed', 'confirmation');
        else
            $OUTPUT->show_message('errorsaving', 'error');
            rcmail_display_server_error('errorsaving');
    }
}
@@ -92,7 +92,7 @@
        $OUTPUT->command('set_quota', rcmail_quota_content());
    }
    else if (!$deleted) {
        $OUTPUT->show_message('errorsaving', 'error');
        rcmail_display_server_error('errorsaving');
    }
}
@@ -141,7 +141,7 @@
            rcube_charset_convert($name, 'UTF7-IMAP'), $display_rename, $before);
    }
    else if (!$rename) {
        $OUTPUT->show_message('errorsaving', 'error');
        rcmail_display_server_error('errorsaving');
    }
}
@@ -179,7 +179,7 @@
        $OUTPUT->command('show_folder', $mbox_utf8, null, true);
    }
    else {
        $OUTPUT->show_message('errorsaving', 'error');
        rcmail_display_server_error('errorsaving');
    }
}
@@ -195,6 +195,9 @@
    if ($size !== false) {
        $OUTPUT->command('folder_size_update', show_bytes($size));
    }
    else {
        rcmail_display_server_error();
    }
}
if ($OUTPUT->ajax_call)