From 2727053c61cac4a37a76b9e58e607acff7fc8dfb Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Tue, 07 Oct 2008 02:24:18 -0400
Subject: [PATCH] - #1485471: fix drafts saving

---
 program/lib/imap.inc |  228 +++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 135 insertions(+), 93 deletions(-)

diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index e3df356..7c257de 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -52,8 +52,6 @@
 		- $ICL_SSL is not boolean anymore but contains the connection schema (ssl or tls)
 		- Removed some debuggers (echo ...)
 		File altered by Aleksander Machniak <alec@alec.pl>
-		- RFC3501 [7.1] don't call CAPABILITY if was returned in server 
-		  optional resposne in iil_Connect()
 		- trim(chop()) replaced by trim()
 		- added iil_Escape() with support for " and \ in folder names
 		- support \ character in username in iil_C_Login()
@@ -62,6 +60,12 @@
 		- removed hardcoded data size in iil_ReadLine() 
 		- added iil_PutLine() wrapper for fputs()
 		- code cleanup and identation fixes
+		- removed flush() calls in iil_C_HandlePartBody() to prevent from memory leak (#1485187)
+		- don't return "??" from iil_C_GetQuota()
+		- RFC3501 [7.1] don't call CAPABILITY if was returned in server 
+		  optional resposne in iil_Connect(), added iil_C_GetCapability()
+		- remove 'undisclosed-recipients' string from 'To' header
+		- iil_C_HandlePartBody(): added 6th argument and fixed endless loop
 
 ********************************************************/
 
@@ -90,6 +94,16 @@
 
 $GLOBALS['IMAP_SERVER_TZ'] = date('Z');
 
+$GLOBALS['IMAP_FLAGS'] = array(
+    'SEEN'     => '\\Seen',
+    'DELETED'  => '\\Deleted',
+    'RECENT'   => '\\Recent',
+    'ANSWERED' => '\\Answered',
+    'DRAFT'    => '\\Draft',
+    'FLAGGED'  => '\\Flagged',
+    'FORWARDED' => '$Forwarded',
+    'MDNSENT'  => '$MDNSent');
+
 $iil_error;
 $iil_errornum;
 $iil_selected;
@@ -113,6 +127,8 @@
 	var $rootdir;
 	var $delimiter;
 	var $capability = array();
+	var $permanentflags = array();
+	var $capability_readed = false;
 }
 
 /**
@@ -142,7 +158,7 @@
 	var $priority;
 	var $mdn_to;
 	var $mdn_sent = false;
-	var $is_reply = false;
+	var $is_draft = false;
 	var $seen = false;
 	var $deleted = false;
 	var $recent = false;
@@ -281,6 +297,40 @@
 	return strtr($string, array('"'=>'\\"', '\\' => '\\\\')); 
 }
 
+function iil_C_GetCapability(&$conn, $name)
+{
+	if (in_array($name, $conn->capability)) {
+		return true;
+	}
+	else if ($conn->capability_readed) {
+		return false;
+	}
+
+	// get capabilities (only once) because initial 
+	// optional CAPABILITY response may differ
+	$conn->capability = array();
+
+	iil_PutLine($conn->fp, "cp01 CAPABILITY");
+	do {
+		$line = trim(iil_ReadLine($conn->fp, 1024));
+		$a = explode(' ', $line);
+		if ($line[0] == '*') {
+			while (list($k, $w) = each($a)) {
+				if ($w != '*' && $w != 'CAPABILITY')
+    					$conn->capability[] = strtoupper($w);
+			}
+		}
+	} while ($a[0] != 'cp01');
+	
+	$conn->capability_readed = true;
+
+	if (in_array($name, $conn->capability)) {
+		return true;
+	}
+
+	return false;
+}
+
 function iil_C_Authenticate(&$conn, $user, $pass, $encChallenge) {
     
     $ipad = '';
@@ -385,7 +435,7 @@
 function iil_C_NameSpace(&$conn) {
 	global $my_prefs;
 	
-	if (!in_array('NAMESPACE', $conn->capability)) {
+	if (!iil_C_GetCapability($conn, 'NAMESPACE')) {
 	    return false;
 	}
     
@@ -500,42 +550,24 @@
 	}
 
 	$iil_error .= "Socket connection established\r\n";
-	$line       = iil_ReadLine($conn->fp, 1024);
+	$line       = iil_ReadLine($conn->fp, 4096);
 
 	// RFC3501 [7.1] optional CAPABILITY response
-	// commented out, because it's not working always as should
-//	if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
-//		$conn->capability = explode(' ', $matches[1]);
-//	} else {
-		iil_PutLine($conn->fp, "cp01 CAPABILITY");
-		do {
-			$line = trim(iil_ReadLine($conn->fp, 1024));
+	if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
+		$conn->capability = explode(' ', strtoupper($matches[1]));
+	}
 
-			$conn->message .= "$line\n";
-
-			$a = explode(' ', $line);
-			if ($line[0] == '*') {
-				while (list($k, $w) = each($a)) {
-					if ($w != '*' && $w != 'CAPABILITY')
-    					$conn->capability[] = $w;
-				}
-			}
-		} while ($a[0] != 'cp01');
-//	}
+	$conn->message .= $line;
 
 	if (strcasecmp($auth_method, "check") == 0) {
 		//check for supported auth methods
-		
-		//default to plain text auth
-		$auth_method = 'plain';
-			
-		//check for CRAM-MD5
-		foreach ($conn->capability as $c)
-			if (strcasecmp($c, 'AUTH=CRAM_MD5') == 0 ||
-				strcasecmp($c, 'AUTH=CRAM-MD5') == 0) {
-				$auth_method = 'auth';
-				break;
-			}
+		if (iil_C_GetCapability($conn, 'AUTH=CRAM-MD5') || iil_C_GetCapability($conn, 'AUTH=CRAM_MD5')) {
+			$auth_method = 'auth';
+		}
+		else {
+			//default to plain text auth
+			$auth_method = 'plain';
+		}
 	}
 
 	if (strcasecmp($auth_method, 'auth') == 0) {
@@ -668,15 +700,15 @@
 }
 
 function iil_ExplodeQuotedString($delimiter, $string) {
-	$quotes=explode('"', $string);
+	$quotes = explode('"', $string);
 	while ( list($key, $val) = each($quotes)) {
 		if (($key % 2) == 1) {
 			$quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
     		}
 	}
-	$string=implode('"', $quotes);
+	$string = implode('"', $quotes);
 	
-	$result=explode($delimiter, $string);
+	$result = explode($delimiter, $string);
 	while ( list($key, $val) = each($result) ) {
 		$result[$key] = str_replace('_!@!_', $delimiter, $result[$key]);
 	}
@@ -716,7 +748,7 @@
 		return false;
 	}
 	if (strcmp($conn->selected, $mailbox) == 0) {
-    		return true;
+		return true;
 	}
     
 	iil_C_LoadCache($conn, $mailbox);
@@ -729,9 +761,12 @@
 				if (strcasecmp($a[2], 'EXISTS') == 0) {
 					$conn->exists = (int) $a[1];
 				}
-            			if (strcasecmp($a[2], 'RECENT') == 0) {
-                			$conn->recent = (int) $a[1];
-            			}
+				if (strcasecmp($a[2], 'RECENT') == 0) {
+					$conn->recent = (int) $a[1];
+				}
+			}
+			else if (preg_match('/\[?PERMANENTFLAGS\s+\(([^\)]+)\)\]/U', $line, $match)) {
+				$conn->permanentflags = explode(' ', $match[1]);
 			}
 		} while (!iil_StartsWith($line, 'sel1'));
 
@@ -1643,7 +1678,7 @@
 						$result[$id]->from = $string;
 						break;
 					case 'to':
-						$result[$id]->to = $string;
+						$result[$id]->to = preg_replace('/undisclosed-recipients:[;,]*/', '', $string);
 						break;
 					case 'subject':
 						$result[$id]->subject = $string;
@@ -1757,6 +1792,8 @@
 							    $result[$id]->answered = true;
 							} else if (strcasecmp($val, '$Forwarded') == 0) {
 							    $result[$id]->forwarded = true;
+							} else if (strcasecmp($val, 'Draft') == 0) {
+							    $result[$id]->is_draft = true;
 							} else if (strcasecmp($val, '$MDNSent') == 0) {
 							    $result[$id]->mdn_sent = true;
 							} else if (strcasecmp($val, 'Flagged') == 0) {
@@ -1909,15 +1946,7 @@
 	}
     
 	$fp    = $conn->fp;
-	$flags = array(
-        'SEEN'     => '\\Seen',
-        'DELETED'  => '\\Deleted',
-        'RECENT'   => '\\Recent',
-        'ANSWERED' => '\\Answered',
-        'DRAFT'    => '\\Draft',
-        'FLAGGED'  => '\\Flagged',
-        'FORWARDED' => '$Forwarded',
-        'MDNSENT'  => '$MDNSent');
+	$flags = $GLOBALS['IMAP_FLAGS'];
         
 	$flag = strtoupper($flag);
 	$flag = $flags[$flag];
@@ -1990,11 +2019,9 @@
 function iil_C_CountUnseen(&$conn, $folder) {
 	$index = iil_C_Search($conn, $folder, 'ALL UNSEEN');
 	if (is_array($index)) {
-		$str = implode(',', $index);
-		if (empty($str)) {
-		    return false;
-    		}
-		return count($index);
+		if (($cnt = count($index)) && $index[0] != '') {
+			return $cnt;
+		}
 	}
 	return false;
 }
@@ -2002,11 +2029,7 @@
 function iil_C_UID2ID(&$conn, $folder, $uid) {
 	if ($uid > 0) {
 		$id_a = iil_C_Search($conn, $folder, "UID $uid");
-		if (is_array($id_a)) {
-			$count = count($id_a);
-			if ($count > 1) {
-			    return false;
-        		}
+		if (is_array($id_a) && count($id_a) == 1) {
 			return $id_a[0];
 		}
 	}
@@ -2325,19 +2348,19 @@
 	return $result;
 }
 
-function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part, $mode) {
+function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part, $mode, $file=NULL) {
 	/* modes:
-        1: return string
+        1: return string (or write to $file pointer)
         2: print
-        3: base64 and print
+        3: base64 and print (or write to $file pointer)
 	*/
 	
 	$fp     = $conn->fp;
 	$result = false;
 	if (($part == 0) || empty($part)) {
-	    $part = 'TEXT';
+		$part = 'TEXT';
 	}
-    
+	
 	if (iil_C_Select($conn, $mailbox)) {
     		$reply_key = '* ' . $id;
         
@@ -2371,8 +2394,11 @@
 	                if ($mode == 2) {
         		        echo $result;
 	                } else if ($mode == 3) {
-        		        echo base64_decode($result);
-	                }
+				if ($file)
+					fwrite($file, base64_decode($result));
+        		    	else
+					echo base64_decode($result);
+			}			     
     		} else if ($line[$len-1] == '}') {
 	                //multi-line request, find sizes of content and receive that many bytes
         		$from     = strpos($line, '{') + 1;
@@ -2380,34 +2406,47 @@
         		$len      = $to - $from;
 	                $sizeStr  = substr($line, $from, $len);
         		$bytes    = (int)$sizeStr;
-	                $received = 0;
 
-        		while ($received < $bytes) {
-            			$remaining = $bytes - $received;
-		                $line      = iil_ReadLine($fp, 1024);
+        		while ($bytes > 0) {
+    		                $line      = iil_ReadLine($fp, 1024);
             			$len       = strlen($line);
                 
-		                if ($len > $remaining) {
-            			        $line = substr($line, 0, $remaining);
+		                if ($len > $bytes) {
+            			        $line = substr($line, 0, $bytes);
 		                }
-            			$received += strlen($line);
+            			$bytes -= strlen($line);
+
 		                if ($mode == 1) {
-            			        $result .= rtrim($line, "\t\r\n\0\x0B") . "\n";
+					if ($file)
+						fwrite($file, rtrim($line, "\t\r\n\0\x0B") . "\n");
+            			        else
+						$result .= rtrim($line, "\t\r\n\0\x0B") . "\n";
 		                } else if ($mode == 2) {
-            			        echo rtrim($line, "\t\r\n\0\x0B") . "\n"; flush();
+            			        echo rtrim($line, "\t\r\n\0\x0B") . "\n";
 		                } else if ($mode == 3) {
-            				echo base64_decode($line); flush();
-            			}
+					if ($file)
+						fwrite($file, base64_decode($line));
+            				else
+						echo base64_decode($line);
+				}
         		}
     		}
-	        // read in anything up until 'til last line
+	        // read in anything up until last line
 		do {
         		$line = iil_ReadLine($fp, 1024);
 		} while (!iil_StartsWith($line, $key));
         
+		if ($mode == 3 && $file) {
+			return true;
+		}
+	
     		if ($result) {
 	    		$result = rtrim($result, "\t\r\n\0\x0B");
-        		return $result; // substr($result, 0, strlen($result)-1);
+			if ($file) {
+				fwrite($file, $result);
+				return true;
+			}	
+			return $result; // substr($result, 0, strlen($result)-1);
     		}
     		
 		return false;
@@ -2416,13 +2455,18 @@
 	}
     
 	if ($mode==1) {
+		if ($file) {
+			fwrite($file, $result);
+			return true;
+		}
     		return $result;
 	}
-	return $received;
+	
+	return false;
 }
 
-function iil_C_FetchPartBody(&$conn, $mailbox, $id, $part) {
-	return iil_C_HandlePartBody($conn, $mailbox, $id, $part, 1);
+function iil_C_FetchPartBody(&$conn, $mailbox, $id, $part, $file=NULL) {
+	return iil_C_HandlePartBody($conn, $mailbox, $id, $part, 1, $file);
 }
 
 function iil_C_PrintPartBody(&$conn, $mailbox, $id, $part) {
@@ -2562,12 +2606,14 @@
 	
 	if (iil_C_Select($conn, $folder)) {
 		$key = 'F1247';
-        
+
 		if (iil_PutLine($fp, "$key FETCH $id (BODYSTRUCTURE)")) {
 			do {
 				$line = iil_ReadLine($fp, 5000);
 				$line = iil_MultLine($fp, $line);
-				$result .= $line;
+				list(, $index, $cmd, $rest) = explode(' ', $line);
+				if ($cmd != 'FETCH' || $index == $id || preg_match("/^$key/", $line))
+					$result .= $line;
 			} while (!preg_match("/^$key/", $line));
 
 			$result = trim(substr($result, strpos($result, 'BODYSTRUCTURE')+13, -(strlen($result)-strrpos($result, $key)+1)));
@@ -2610,13 +2656,9 @@
 		$parts        = explode(' ', $quota_line);
 		$storage_part = array_search('STORAGE', $parts);
 		if ($storage_part > 0) {
-			$result = array();
-			$used   = $parts[$storage_part+1];
-			$total  = $parts[$storage_part+2];
-            
-			$result['used']    = $used;
-			$result['total']   = (empty($total)?"??":$total);
-			$result['percent'] = (empty($total)?"??":round(($used/$total)*100));
+			$result['used']    = intval($parts[$storage_part+1]);
+			$result['total']   = intval($parts[$storage_part+2]);
+			$result['percent'] = min(100, round(($result['used']/max(1,$result['total']))*100));
 			$result['free']    = 100 - $result['percent'];
 		}
 	}

--
Gitblit v1.9.1