From d8335117e27e9a81caa5f655b2c6357960849418 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Sun, 17 Oct 2010 09:17:52 -0400
Subject: [PATCH] - Add LITERAL+ support (RFC2088)

---
 CHANGELOG                              |    1 
 program/include/rcube_imap_generic.php |   68 +++++++++++++++++++++++----------
 2 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 19290c7..037eec5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -30,6 +30,7 @@
 - Improve displaying of UI messages (#1486977)
 - Fix double e-mail filed in identity form (#1487054)
 - Display IMAP errors for LIST/THREAD/SEARCH commands (#1486905)
+- Add LITERAL+ (IMAP4 non-synchronizing literals) support (RFC2088)
 
 RELEASE 0.4.2
 -------------
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index ee5638e..80f25b9 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -158,15 +158,23 @@
 	    if ($parts = preg_split('/(\{[0-9]+\}\r\n)/m', $string, -1, PREG_SPLIT_DELIM_CAPTURE)) {
 		    for ($i=0, $cnt=count($parts); $i<$cnt; $i++) {
 			    if (preg_match('/^\{[0-9]+\}\r\n$/', $parts[$i+1])) {
+                    // LITERAL+ support
+                    if ($this->prefs['literal+'])
+                        $parts[$i+1] = preg_replace('/([0-9]+)/', '\\1+', $parts[$i+1]);
+                
 				    $bytes = $this->putLine($parts[$i].$parts[$i+1], false);
                     if ($bytes === false)
                         return false;
                     $res += $bytes;
-				    $line = $this->readLine(1000);
-				    // handle error in command
-				    if ($line[0] != '+')
-					    return false;
-				    $i++;
+
+                    // don't wait if server supports LITERAL+ capability
+                    if (!$this->prefs['literal+']) {
+				        $line = $this->readLine(1000);
+				        // handle error in command
+				        if ($line[0] != '+')
+					        return false;
+				    }
+                    $i++;
 			    }
 			    else {
 				    $bytes = $this->putLine($parts[$i], false);
@@ -348,7 +356,7 @@
 	    do {
 		    $line = trim($this->readLine(1024));
 	        if (preg_match('/^\* CAPABILITY (.+)/i', $line, $matches)) {
-		        $this->capability = explode(' ', strtoupper($matches[1]));
+		        $this->parseCapability($matches[1]);
 	        }
 	    } while (!$this->startsWith($line, 'cp01', true));
 
@@ -413,7 +421,7 @@
 
         // re-set capabilities list if untagged CAPABILITY response provided
 	    if (preg_match('/\* CAPABILITY (.+)/i', $untagged, $matches)) {
-		    $this->capability = explode(' ', strtoupper($matches[1]));
+		    $this->parseCapability($matches[1]);
 	    }
 
         // process result
@@ -624,7 +632,7 @@
 
 	    // RFC3501 [7.1] optional CAPABILITY response
 	    if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
-		    $this->capability = explode(' ', strtoupper($matches[1]));
+		    $this->parseCapability($matches[1]);
 	    }
 
 	    $this->message .= $line;
@@ -1989,15 +1997,19 @@
 		    return false;
 	    }
 
-	    $request = 'a APPEND "' . $this->escape($folder) .'" (\\Seen) {' . $len . '}';
+	    $request = sprintf("a APPEND \"%s\" (\\Seen) {%d%s}", $this->escape($folder),
+            $len, ($this->prefs['literal+'] ? '+' : ''));
 
 	    if ($this->putLine($request)) {
-		    $line = $this->readLine(512);
+            // Don't wait when LITERAL+ is supported
+            if (!$this->prefs['literal+']) {
+                $line = $this->readLine(512);
 
-    		if ($line[0] != '+') {
-	    		$this->parseResult($line, 'APPEND: ');
-			    return false;
-    		}
+    		    if ($line[0] != '+') {
+	    		    $this->parseResult($line, 'APPEND: ');
+			        return false;
+    		    }
+            }
 
 	    	if (!$this->putLine($message)) {
                 return false;
@@ -2045,14 +2057,19 @@
         }
 
     	// send APPEND command
-	    $request    = 'a APPEND "' . $this->escape($folder) . '" (\\Seen) {' . $len . '}';
-	    if ($this->putLine($request)) {
-		    $line = $this->readLine(512);
+	    $request = sprintf("a APPEND \"%s\" (\\Seen) {%d%s}", $this->escape($folder),
+            $len, ($this->prefs['literal+'] ? '+' : ''));
 
-		    if ($line[0] != '+') {
-			    $this->parseResult($line, 'APPEND: ');
-			    return false;
-		    }
+	    if ($this->putLine($request)) {
+            // Don't wait when LITERAL+ is supported
+            if (!$this->prefs['literal+']) {
+    		    $line = $this->readLine(512);
+
+	    	    if ($line[0] != '+') {
+		    	    $this->parseResult($line, 'APPEND: ');
+			        return false;
+		        }
+            }
 
             // send headers with body separator
             if ($headers) {
@@ -2241,6 +2258,15 @@
         return $data;
     }
 
+    private function parseCapability($str)
+    {
+        $this->capability = explode(' ', strtoupper($str));
+
+        if (!isset($this->prefs['literal+']) && in_array('LITERAL+', $this->capability)) {
+            $this->prefs['literal+'] = true;
+        }
+    }
+
     private function escape($string)
     {
 	    return strtr($string, array('"'=>'\\"', '\\' => '\\\\'));

--
Gitblit v1.9.1