From 90f81a6c8de5aecfa36c54cc5260d25ba883aa51 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Wed, 08 Dec 2010 07:52:04 -0500
Subject: [PATCH] - 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

---
 program/include/rcube_imap_generic.php |   62 ++++++++++++++++++++++++++-----
 1 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 10bc6d0..b2346ba 100644
--- a/program/include/rcube_imap_generic.php
+++ b/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)
-                $this->error = $err_prefix ? $err_prefix.$str : $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:*');
 	    }
 
-        $res = $this->close();
-//	    $res = $this->expunge($mailbox);
+        if ($res) {
+            if ($this->selected == $mailbox)
+                $res = $this->close();
+            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);

--
Gitblit v1.9.1