From 6e57fb6b4cc8c108b89458651dd525a0df950fdd Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Thu, 04 Jul 2013 02:45:41 -0400
Subject: [PATCH] Fix parsing of square bracket characters in IMAP response strings (#1489223)

---
 CHANGELOG                                    |    1 +
 tests/Framework/ImapGeneric.php              |   23 +++++++++++++++++++++++
 program/lib/Roundcube/rcube_imap_generic.php |   30 ++++++++++++++++--------------
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 00e65ce..94930bc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Fix parsing of square bracket characters in IMAP response strings (#1489223)
 - Don't clear References and in-Reply-To when a message is "edited as new" (#1489216)
 - Make possible to disable some (broken) IMAP extensions with imap_disable_caps option (#1489184)
 - Contacts drag-n-drop default action is to move contacts (#1488751)
diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php
index ae390a0..9b11624 100644
--- a/program/lib/Roundcube/rcube_imap_generic.php
+++ b/program/lib/Roundcube/rcube_imap_generic.php
@@ -2163,14 +2163,18 @@
                     else if ($name == 'RFC822') {
                         $result[$id]->body = $value;
                     }
-                    else if ($name == 'BODY') {
-                        $body = $this->tokenizeResponse($line, 1);
-                        if ($value[0] == 'HEADER.FIELDS')
-                            $headers = $body;
-                        else if (!empty($value))
-                            $result[$id]->bodypart[$value[0]] = $body;
+                    else if (stripos($name, 'BODY[') === 0) {
+                        $name = str_replace(']', '', substr($name, 5));
+
+                        if ($name == 'HEADER.FIELDS') {
+                            // skip ']' after headers list
+                            $this->tokenizeResponse($line, 1);
+                            $headers = $this->tokenizeResponse($line, 1);
+                        }
+                        else if (strlen($name))
+                            $result[$id]->bodypart[$name] = $value;
                         else
-                            $result[$id]->body = $body;
+                            $result[$id]->body = $value;
                     }
                 }
 
@@ -2515,8 +2519,7 @@
 
                 for ($i=0; $i<count($tokens); $i+=2) {
                     if (preg_match('/^(BODY|BINARY)/i', $tokens[$i])) {
-                        $i += 2; // skip BODY|BINARY and part number
-                        $result = $tokens[$i];
+                        $result = $tokens[$i+1];
                         $found  = true;
                         break;
                     }
@@ -3481,25 +3484,24 @@
 
             // Parenthesized list
             case '(':
-            case '[':
                 $str = substr($str, 1);
                 $result[] = self::tokenizeResponse($str);
                 break;
             case ')':
-            case ']':
                 $str = substr($str, 1);
                 return $result;
                 break;
 
-            // String atom, number, NIL, *, %
+            // String atom, number, astring, NIL, *, %
             default:
                 // empty string
                 if ($str === '' || $str === null) {
                     break 2;
                 }
 
-                // excluded chars: SP, CTL, ), [, ], DEL
-                if (preg_match('/^([^\x00-\x20\x29\x5B\x5D\x7F]+)/', $str, $m)) {
+                // excluded chars: SP, CTL, ), DEL
+                // we do not exclude [ and ] (#1489223)
+                if (preg_match('/^([^\x00-\x20\x29\x7F]+)/', $str, $m)) {
                     $result[] = $m[1] == 'NIL' ? NULL : $m[1];
                     $str = substr($str, strlen($m[1]));
                 }
diff --git a/tests/Framework/ImapGeneric.php b/tests/Framework/ImapGeneric.php
index 2f9b6d1..af73158 100644
--- a/tests/Framework/ImapGeneric.php
+++ b/tests/Framework/ImapGeneric.php
@@ -35,4 +35,27 @@
         $this->assertSame(array(1, 2, 3), $result);
         $this->assertCount(3, $result);
     }
+
+    /**
+     * Test for tokenizeResponse
+     */
+    function test_tokenizeResponse()
+    {
+        $response = "test brack[et] {1}\r\na {0}\r\n (item1 item2)";
+
+        $result = rcube_imap_generic::tokenizeResponse($response, 1);
+        $this->assertSame("test", $result);
+
+        $result = rcube_imap_generic::tokenizeResponse($response, 1);
+        $this->assertSame("brack[et]", $result);
+
+        $result = rcube_imap_generic::tokenizeResponse($response, 1);
+        $this->assertSame("a", $result);
+
+        $result = rcube_imap_generic::tokenizeResponse($response, 1);
+        $this->assertSame("", $result);
+
+        $result = rcube_imap_generic::tokenizeResponse($response, 1);
+        $this->assertSame(array('item1', 'item2'), $result);
+    }
 }

--
Gitblit v1.9.1