From 32ca1f9fc8a78e092565b51cc97faa724bb4e6cf Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Sat, 30 May 2009 05:09:57 -0400
Subject: [PATCH] - css fixes (#1485869)

---
 program/lib/imap.inc |  636 ++++++++++++++++++++++++---------------------------------
 1 files changed, 267 insertions(+), 369 deletions(-)

diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index cca499b..2954ecf 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -68,7 +68,7 @@
 		- iil_C_HandlePartBody(): added 6th argument and fixed endless loop
 		- added iil_PutLineC() 
 		- fixed iil_C_Sort() to support very long and/or divided responses
-		- added BYE response simple support for endless loop prevention
+		- added BYE/BAD response simple support for endless loop prevention
 		- added 3rd argument in iil_StartsWith* functions
 		- fix iil_C_FetchPartHeader() in some cases by use of iil_C_HandlePartBody()
 		- allow iil_C_HandlePartBody() to fetch whole message
@@ -78,6 +78,12 @@
 		- support multiquota result
 		- include BODYSTRUCTURE in iil_C_FetchHeaders()
 		- added iil_C_FetchMIMEHeaders() function
+		- added \* flag support 
+		- use PREG instead of EREG
+		- removed caching functions
+		- handling connection startup response
+		- added UID EXPUNGE support
+		- fixed problem with double quotes and spaces in folder names in LIST and LSUB 
 
 ********************************************************/
 
@@ -88,9 +94,6 @@
  * @todo Refactor code.
  * @todo Replace echo-debugging (make it adhere to config setting and log)
  */
-
-// changed path to work within roundcube webmail
-include_once 'lib/icl_commons.inc';
 
 
 if (!isset($IMAP_USE_HEADER_DATE) || !$IMAP_USE_HEADER_DATE) {
@@ -114,7 +117,9 @@
     'DRAFT'    => '\\Draft',
     'FLAGGED'  => '\\Flagged',
     'FORWARDED' => '$Forwarded',
-    'MDNSENT'  => '$MDNSent');
+    'MDNSENT'  => '$MDNSent',
+    '*'        => '\\*',
+);
 
 $iil_error;
 $iil_errornum;
@@ -131,9 +136,6 @@
 	var $selected;
 	var $message;
 	var $host;
-	var $cache;
-	var $uid_cache;
-	var $do_cache;
 	var $exists;
 	var $recent;
 	var $rootdir;
@@ -179,6 +181,7 @@
 	var $forwarded = false;
 	var $junk = false;
 	var $flagged = false;
+	var $others = array();
 }
 
 /**
@@ -217,6 +220,9 @@
 			if(preg_match('/^\{[0-9]+\}\r\n$/', $parts[$i+1])) {
 				$res += iil_PutLine($fp, $parts[$i].$parts[$i+1], false);
 				$line = iil_ReadLine($fp, 1000);
+				// handle error in command
+				if ($line[0] != '+')
+					return false;
 				$i++;
 			}
 			else
@@ -226,7 +232,7 @@
 	return $res;
 }
 
-function iil_ReadLine($fp, $size) {
+function iil_ReadLine($fp, $size=1024) {
 	$line = '';
 
 	if (!$fp) {
@@ -249,9 +255,9 @@
 	return $line;
 }
 
-function iil_MultLine($fp, $line) {
+function iil_MultLine($fp, $line, $escape=false) {
 	$line = chop($line);
-	if (ereg('\{[0-9]+\}$', $line)) {
+	if (preg_match('/\{[0-9]+\}$/', $line)) {
 		$out = '';
         
 		preg_match_all('/(.*)\{([0-9]+)\}$/', $line, $a);
@@ -260,7 +266,8 @@
 			$line = iil_ReadBytes($fp, $bytes); 
 			$out .= $line;
 		}
-		$line = $a[1][0] . "\"$out\"";
+
+		$line = $a[1][0] . '"' . ($escape ? iil_Escape($out) : $out) . '"';
 //		console('[...] '. $out);
 	}
 	return $line;
@@ -289,7 +296,7 @@
 }
 
 function iil_ParseResult($string) {
-	$a=explode(' ', $string);
+	$a = explode(' ', $string);
 	if (count($a) > 2) {
 		if (strcasecmp($a[1], 'OK') == 0) {
 			return 0;
@@ -304,8 +311,8 @@
 	return -4;
 }
 
-// check if $string starts with $match
-function iil_StartsWith($string, $match, $bye=false) {
+// check if $string starts with $match (or * BYE/BAD)
+function iil_StartsWith($string, $match, $error=false) {
 	$len = strlen($match);
 	if ($len == 0) {
 		return false;
@@ -313,7 +320,7 @@
 	if (strncmp($string, $match, $len) == 0) {
 		return true;
 	}
-	if ($bye && strncmp($string, '* BYE ', 6) == 0) {
+	if ($error && preg_match('/^\* (BYE|BAD) /i', $string)) {
 		return true;
 	}
 	return false;
@@ -329,6 +336,7 @@
 	}
 	if ($bye && strncmp($string, '* BYE ', 6) == 0) {
 		return true;
+
 	}
 	return false;
 }
@@ -375,6 +383,12 @@
 	}
 
 	return false;
+}
+
+function iil_C_ClearCapability(&$conn)
+{
+	$conn->capability = array();
+	$conn->capability_readed = false;
 }
 
 function iil_C_Authenticate(&$conn, $user, $pass, $encChallenge) {
@@ -532,7 +546,6 @@
 function iil_Connect($host, $user, $password, $options=null) {	
 	global $iil_error, $iil_errornum;
 	global $ICL_SSL, $ICL_PORT;
-	global $IMAP_NO_CACHE;
 	global $my_prefs, $IMAP_USE_INTERNAL_DATE;
 	
 	$iil_error = '';
@@ -558,16 +571,13 @@
 		
 	$result = false;
 	
-	//initialize connection
+	// initialize connection
 	$conn              = new iilConnection;
 	$conn->error       = '';
 	$conn->errorNum    = 0;
 	$conn->selected    = '';
 	$conn->user        = $user;
 	$conn->host        = $host;
-	$conn->cache       = array();
-	$conn->do_cache    = (function_exists("cache_write")&&!$IMAP_NO_CACHE);
-	$conn->cache_dirty = array();
 	
 	if ($my_prefs['sort_field'] == 'INTERNALDATE') {
 		$IMAP_USE_INTERNAL_DATE = true;
@@ -592,16 +602,15 @@
 		$iil_errornum = -1;
 		return false;
 	}
+
 	if (!$ICL_PORT) {
 		$ICL_PORT = 143;
 	}
-    
 	//check for SSL
-	if ($ICL_SSL) {
+	if ($ICL_SSL && $ICL_SSL != 'tls') {
 		$host = $ICL_SSL . '://' . $host;
 	}
-	
-	//open socket connection
+
 	$conn->fp = fsockopen($host, $ICL_PORT, $errno, $errstr, 10);
 	if (!$conn->fp) {
     		$iil_error = "Could not connect to $host at port $ICL_PORT: $errstr";
@@ -609,15 +618,48 @@
 		return false;
 	}
 
-	$iil_error .= "Socket connection established\r\n";
-	$line       = iil_ReadLine($conn->fp, 4096);
+	stream_set_timeout($conn->fp, 10);
+	$line = stream_get_line($conn->fp, 8192, "\r\n");
 
+	// Connected to wrong port or connection error?
+	if (!preg_match('/^\* (OK|PREAUTH)/i', $line)) {
+		if ($line)
+			$iil_error = "Wrong startup greeting ($host:$ICL_PORT): $line";
+		else
+			$iil_error = "Empty startup greeting ($host:$ICL_PORT)";
+	        $iil_errornum = -2;
+	        return false;
+	}
+	
 	// RFC3501 [7.1] optional CAPABILITY response
 	if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) {
 		$conn->capability = explode(' ', strtoupper($matches[1]));
 	}
 
 	$conn->message .= $line;
+
+	// TLS connection
+	if ($ICL_SSL == 'tls' && iil_C_GetCapability($conn, 'STARTTLS')) {
+        	if (version_compare(PHP_VERSION, '5.1.0', '>=')) {
+               		iil_PutLine($conn->fp, 'stls000 STARTTLS');
+
+			$line = iil_ReadLine($conn->fp, 4096);
+                	if (!iil_StartsWith($line, 'stls000 OK')) {
+				$iil_error = "Server responded to STARTTLS with: $line";
+				$iil_errornum = -2;
+                    		return false;
+                	}
+
+			if (!stream_socket_enable_crypto($conn->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
+				$iil_error = "Unable to negotiate TLS";
+				$iil_errornum = -2;
+				return false;
+			}
+			
+			// Now we're authenticated, capabilities need to be reread
+			iil_C_ClearCapability($conn);
+        	}
+	}
 
 	if (strcasecmp($auth_method, "check") == 0) {
 		//check for supported auth methods
@@ -677,7 +719,6 @@
 }
 
 function iil_Close(&$conn) {
-	iil_C_WriteCache($conn);
 	if (iil_PutLine($conn->fp, "I LOGOUT")) {
 		fgets($conn->fp, 1024);
 		fclose($conn->fp);
@@ -685,100 +726,21 @@
 	}
 }
 
-function iil_ClearCache($user, $host) {
-}
-
-function iil_C_WriteCache(&$conn) {
-	//echo "<!-- doing iil_C_WriteCache //-->\n";
-	if (!$conn->do_cache) return false;
-	
-	if (is_array($conn->cache)) {
-		while (list($folder,$data)=each($conn->cache)) {
-			if ($folder && is_array($data) && $conn->cache_dirty[$folder]) {
-				$key = $folder.".imap";
-				$result = cache_write($conn->user, $conn->host, $key, $data, true);
-				//echo "<!-- writing $key $data: $result //-->\n";
-			}
-		}
-	}
-}
-
-function iil_C_EnableCache(&$conn) {
-	$conn->do_cache = true;
-}
-
-function iil_C_DisableCache(&$conn) {
-	$conn->do_cache = false;
-}
-
-function iil_C_LoadCache(&$conn, $folder) {
-	if (!$conn->do_cache) {
-	    return false;
-	}
-    
-	$key = $folder.'.imap';
-	if (!is_array($conn->cache[$folder])) {
-		$conn->cache[$folder]       = cache_read($conn->user, $conn->host, $key);
-		$conn->cache_dirty[$folder] = false;
-	}
-}
-
-function iil_C_ExpireCachedItems(&$conn, $folder, $message_set) {
-	
-	if (!$conn->do_cache) {
-		return;	//caching disabled
-	}
-	if (!is_array($conn->cache[$folder])) {
-    		return;	//cache not initialized|empty
-	}
-	if (count($conn->cache[$folder]) == 0) {
-    		return;	//cache not initialized|empty
-	}
-    
-	$uids = iil_C_FetchHeaderIndex($conn, $folder, $message_set, 'UID');
-	$num_removed = 0;
-	if (is_array($uids)) {
-		//echo "<!-- unsetting: ".implode(",",$uids)." //-->\n";
-		while (list($n,$uid)=each($uids)) {
-			unset($conn->cache[$folder][$uid]);
-			//$conn->cache[$folder][$uid] = false;
-			//$num_removed++;
-		}
-		$conn->cache_dirty[$folder] = true;
-
-		//echo '<!--'."\n";
-		//print_r($conn->cache);
-		//echo "\n".'//-->'."\n";
-	} else {
-		echo "<!-- failed to get uids: $message_set //-->\n";
-	}
-	
-	/*
-	if ($num_removed>0) {
-		$new_cache;
-		reset($conn->cache[$folder]);
-		while (list($uid,$item)=each($conn->cache[$folder])) {
-			if ($item) $new_cache[$uid] = $conn->cache[$folder][$uid];
-		}
-		$conn->cache[$folder] = $new_cache;
-	}
-	*/
-}
-
 function iil_ExplodeQuotedString($delimiter, $string) {
-	$quotes = explode('"', $string);
-	while ( list($key, $val) = each($quotes)) {
-		if (($key % 2) == 1) {
-			$quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
-    		}
+	$result = array();
+	$strlen = strlen($string);
+	  
+	for ($q=$p=$i=0; $i < $strlen; $i++) {
+	        if ($string[$i] == "\"" && $string[$i-1] != "\\") {
+			$q = $q ? false : true;
+		}
+		else if (!$q && preg_match("/$delimiter/", $string[$i])) {
+			$result[] = substr($string, $p, $i - $p);
+			$p = $i + 1;
+		}
 	}
-	$string = implode('"', $quotes);
-	
-	$result = explode($delimiter, $string);
-	while ( list($key, $val) = each($result) ) {
-		$result[$key] = str_replace('_!@!_', $delimiter, $result[$key]);
-	}
-    
+
+	$result[] = substr($string, $p);
 	return $result;
 }
 
@@ -817,8 +779,6 @@
 		return true;
 	}
     
-	iil_C_LoadCache($conn, $mailbox);
-	
 	if (iil_PutLine($conn->fp, "sel1 SELECT \"".iil_Escape($mailbox).'"')) {
 		do {
 			$line = chop(iil_ReadLine($conn->fp, 300));
@@ -1249,50 +1209,7 @@
 	}
 	$message_set = '1' . ($num>1?':' . $num:'');
 	
-	//if cache not enabled, just call iil_C_FetchHeaderIndex on 'UID' field
-	if (!$conn->do_cache)
-		return iil_C_FetchHeaderIndex($conn, $mailbox, $message_set, 'UID');
-
-	//otherwise, let's check cache first
-	$key        = $mailbox.'.uids';
-	$cache_good = true;
-	if ($conn->uid_cache) {
-	    $data = $conn->uid_cache;
-	} else {
-	    $data = cache_read($conn->user, $conn->host, $key);
-	}
-    
-	//was anything cached at all?
-	if ($data === false) {
-	    $cache_good = -1;
-	}
-    
-	//make sure number of messages were the same
-	if ($cache_good > 0 && $data['n'] != $num) {
-	    $cache_good = -2;
-	}
-    
-	//if everything's okay so far...
-	if ($cache_good > 0) {
-		//check UIDs of highest mid with current and cached
-		$temp = iil_C_Search($conn, $mailbox, 'UID ' . $data['d'][$num]);
-		if (!$temp || !is_array($temp) || $temp[0] != $num) {
-		    $cache_good = -3;
-    		}
-	}
-
-	//if cached data's good, return it
-	if ($cache_good > 0) {
-		return $data['d'];
-	}
-
-	//otherwise, we need to fetch it
-	$data      = array('n' => $num, 'd' => array());
-	$data['d'] = iil_C_FetchHeaderIndex($conn, $mailbox, $message_set, 'UID');
-    
-	cache_write($conn->user, $conn->host, $key, $data);
-	$conn->uid_cache = $data;
-	return $data['d'];
+	return iil_C_FetchHeaderIndex($conn, $mailbox, $message_set, 'UID');
 }
 
 function iil_SortThreadHeaders($headers, $index_a, $uids) {
@@ -1319,30 +1236,7 @@
 	$uids   = iil_C_FetchUIDs($conn, $mailbox);
 	$debug  = false;
 	
-	/* Get cached records where possible */
-	if ($conn->do_cache) {
-		$cached = cache_read($conn->user, $conn->host, $mailbox.'.thhd');
-		if ($cached && is_array($uids) && count($uids)>0) {
-			$needed_set = '';
-			foreach ($uids as $id=>$uid) {
-				if ($cached[$uid]) {
-					$result[$uid]     = $cached[$uid];
-					$result[$uid]->id = $id;
-				} else {
-				    $needed_set .= ($needed_set ? ',' : '') . $id;
-            			}
-			}
-			if ($needed_set) {
-			    $message_set = $needed_set;
-			} else {
-			    $message_set = '';
-        		}
-		}
-	}
 	$message_set = iil_CompressMessageSet($message_set);
-	if ($debug) {
-	    echo "Still need: ".$message_set;
-	}
     
 	/* if we're missing any, get them */
 	if ($message_set) {
@@ -1360,7 +1254,7 @@
 			if ($debug) {
 			    echo $line . "\n";
         		}
-			if (ereg('\{[0-9]+\}$', $line)) {
+			if (preg_match('/\{[0-9]+\}$/', $line)) {
 				$a 	 = explode(' ', $line);
 				$new = array();
 
@@ -1378,7 +1272,7 @@
 
 						$new[strtoupper($field_name)] = trim($field_val);
 
-					} else if (ereg('^[[:space:]]', $line)) {
+					} else if (preg_match('/^\s+/', $line)) {
 						$new[strtoupper($field_name)] .= trim($line);
 					}
 				} while ($line[0] != ')');
@@ -1395,13 +1289,6 @@
 	/* sort headers */
 	if (is_array($index_a)) {
 		$result = iil_SortThreadHeaders($result, $index_a, $uids);	
-	}
-	
-	/* write new set to cache */
-	if ($conn->do_cache) {
-		if (count($result)!=count($cached)) {
-			cache_write($conn->user, $conn->host, $mailbox . '.thhd', $result);
-    		}
 	}
 	
 	//echo 'iil_FetchThreadHeaders:'."\n";
@@ -1428,7 +1315,7 @@
 	$fp        = $conn->fp;
 	$debug     = false;
 	
-	$sbj_filter_pat = '[a-zA-Z]{2,3}(\[[0-9]*\])?:([[:space:]]*)';
+	$sbj_filter_pat = '/[a-z]{2,3}(\[[0-9]*\])?:(\s*)/i';
 	
 	/*  Do "SELECT" command */
 	if (!iil_C_Select($conn, $mailbox)) {
@@ -1465,18 +1352,18 @@
 		}
         
 		/* if subject contains 'RE:' or has in-reply-to header, it's a reply */
-		$sbj_pre ='';
+		$sbj_pre = '';
 		$has_re = false;
-		if (eregi($sbj_filter_pat, $new['SUBJECT'])) {
+		if (preg_match($sbj_filter_pat, $new['SUBJECT'])) {
 		    $has_re = true;
 		}
-    		if ($has_re||$new['IN-REPLY-TO']) {
+    		if ($has_re || $new['IN-REPLY-TO']) {
         	    $sbj_pre = 'RE:';
 		}
         
 		/* strip out 're:', 'fw:' etc */
 		if ($has_re) {
-		    $sbj = ereg_replace($sbj_filter_pat, '', $new['SUBJECT']);
+		    $sbj = preg_replace($sbj_filter_pat, '', $new['SUBJECT']);
 		} else {
 		    $sbj = $new['SUBJECT'];
 		}
@@ -1626,7 +1513,7 @@
 	return $t_index;
 }
 
-function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false)
+function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false, $add='')
 {
 	global $IMAP_USE_INTERNAL_DATE;
 	
@@ -1644,28 +1531,9 @@
 		$conn->error = "Couldn't select $mailbox";
 		return false;
 	}
-		
-	/* Get cached records where possible */
-	if ($conn->do_cache) {
-		$uids = iil_C_FetchHeaderIndex($conn, $mailbox, $message_set, "UID");
-		if (is_array($uids) && count($conn->cache[$mailbox]>0)) {
-			$needed_set = '';
-			while (list($id,$uid)=each($uids)) {
-				if ($conn->cache[$mailbox][$uid]) {
-					$result[$id]     = $conn->cache[$mailbox][$uid];
-					$result[$id]->id = $id;
-				} else {
-				    $needed_set.=($needed_set ? ',': '') . $id;
-				}
-			}
-			//echo "<!-- iil_C_FetchHeader\nMessage Set: $message_set\nNeeded Set:$needed_set\n//-->\n";
-			if ($needed_set) {
-				$message_set = iil_CompressMessageSet($needed_set);
-			} else {
-				return $result;
-			}
-		}
-	}
+
+	if ($add)
+		$add = ' '.strtoupper(trim($add));
 
 	/* FETCH uid, size, flags and headers */
 	$key  	  = 'FH12';
@@ -1676,7 +1544,7 @@
 	$request .= "BODY.PEEK[HEADER.FIELDS ";
 	$request .= "(DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC ";
 	$request .= "CONTENT-TRANSFER-ENCODING CONTENT-TYPE MESSAGE-ID ";
-	$request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY)])";
+	$request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY".$add.")])";
 
 	if (!iil_PutLine($fp, $request)) {
 		return false;
@@ -1684,7 +1552,7 @@
 	do {
 		$line = iil_ReadLine($fp, 1024);
 		$line = iil_MultLine($fp, $line);
-		
+
 		$a    = explode(' ', $line);
 		if (($line[0] == '*') && ($a[2] == 'FETCH')) {
 			$id = $a[1];
@@ -1707,12 +1575,12 @@
 				$str = $matches[1];
 
 				// swap parents with quotes, then explode
-				$str = eregi_replace("[()]", "\"", $str);
+				$str = preg_replace('/[()]/', '"', $str);
 				$a = iil_ExplodeQuotedString(' ', $str);
 
 				// did we get the right number of replies?
 				$parts_count = count($a);
-				if ($parts_count>=8) {
+				if ($parts_count>=6) {
 					for ($i=0; $i<$parts_count; $i=$i+2) {
 						if (strcasecmp($a[$i],'UID') == 0)
 							$result[$id]->uid = $a[$i+1];
@@ -1722,34 +1590,6 @@
 							$time_str = $a[$i+1];
 						else if (strcasecmp($a[$i],'FLAGS') == 0)
 							$flags_str = $a[$i+1];
-					}
-
-					// process flags
-					$flags_str = eregi_replace('[\\\"]', '', $flags_str);
-					$flags_a   = explode(' ', $flags_str);
-					
-					if (is_array($flags_a)) {
-						reset($flags_a);
-						while (list(,$val)=each($flags_a)) {
-							if (strcasecmp($val,'Seen') == 0) {
-							    $result[$id]->seen = true;
-							} else if (strcasecmp($val, 'Deleted') == 0) {
-							    $result[$id]->deleted=true;
-							} else if (strcasecmp($val, 'Recent') == 0) {
-							    $result[$id]->recent = true;
-							} else if (strcasecmp($val, 'Answered') == 0) {
-							    $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) {
-							     $result[$id]->flagged = true;
-							}
-						}
-						$result[$id]->flags = $flags_a;
 					}
 
 					$time_str = str_replace('"', '', $time_str);
@@ -1794,7 +1634,7 @@
 				// re-parse (see below)
 				foreach ($reslines as $line) {
 					if (ord($line[0])<=32) {
-					    $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
+						$lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
 					} else {
 						$lines[++$ln] = trim($line);
 					}
@@ -1811,23 +1651,28 @@
 			do {
 				$line = chop(iil_ReadLine($fp, 300), "\r\n");
 
-				if (ord($line[0])<=32) {
-				    $lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
-				} else {
-					$lines[++$ln] = trim($line);
-				}
-				/* 
-					The preg_match below works around communigate imap, which outputs " UID <number>)".
-					Without this, the while statement continues on and gets the "FH0 OK completed" message.
-					If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.  
-					This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing
-					If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin
-					An alternative might be:
-					if (!preg_match("/:/",$line) && preg_match("/\)$/",$line)) break;
-					however, unsure how well this would work with all imap clients.
-				*/
+				// The preg_match below works around communigate imap, which outputs " UID <number>)".
+				// Without this, the while statement continues on and gets the "FH0 OK completed" message.
+				// If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.  
+				// This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing
+				// If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin
+				// An alternative might be:
+				// if (!preg_match("/:/",$line) && preg_match("/\)$/",$line)) break;
+				// however, unsure how well this would work with all imap clients.
 				if (preg_match("/^\s*UID [0-9]+\)$/", $line)) {
 				    break;
+				}
+
+				// handle FLAGS reply after headers (AOL, Zimbra?)
+				if (preg_match('/\s+FLAGS \((.*)\)\)$/', $line, $matches)) {
+					$flags_str = $matches[1];
+					break;
+				}
+
+				if (ord($line[0])<=32) {
+					$lines[$ln] .= (empty($lines[$ln])?'':"\n").trim($line);
+				} else {
+					$lines[++$ln] = trim($line);
 				}
 			// patch from "Maksim Rubis" <siburny@hotmail.com>
 			} while (trim($line[0]) != ')' && strncmp($line, $key, strlen($key)));
@@ -1847,7 +1692,7 @@
 					list($field, $string) = iil_SplitHeaderLine($str);
 					
 					$field  = strtolower($field);
-                                        $string = ereg_replace("\n[[:space:]]*"," ",$string); 
+					$string = preg_replace('/\n\s*/', ' ', $string);
 					
 					switch ($field) {
 					case 'date';
@@ -1888,7 +1733,7 @@
 						}
 						break;
 					case 'in-reply-to':
-						$result[$id]->in_reply_to = ereg_replace("[\n<>]", '', $string);
+						$result[$id]->in_reply_to = preg_replace('/[\n<>]/', '', $string);
 						break;
 					case 'references':
 						$result[$id]->references = $string;
@@ -1905,16 +1750,44 @@
 						if (preg_match('/^(\d+)/', $string, $matches))
 							$result[$id]->priority = intval($matches[1]);
 						break;
+					default:
+						if (strlen($field) > 2)
+							$result[$id]->others[$field] = $string;
+						break;
 					} // end switch ()
 				} // end while ()
-		
-				if ($conn->do_cache) {
-					$uid = $result[$id]->uid;
-					$conn->cache[$mailbox][$uid] = $result[$id];
-					$conn->cache_dirty[$mailbox] = true;
-				}
 			} else {
 				$a = explode(' ', $line);
+			}
+
+			// process flags
+			if (!empty($flags_str)) {
+				$flags_str = preg_replace('/[\\\"]/', '', $flags_str);
+				$flags_a   = explode(' ', $flags_str);
+					
+				if (is_array($flags_a)) {
+					reset($flags_a);
+					while (list(,$val)=each($flags_a)) {
+						if (strcasecmp($val,'Seen') == 0) {
+						    $result[$id]->seen = true;
+						} else if (strcasecmp($val, 'Deleted') == 0) {
+						    $result[$id]->deleted=true;
+						} else if (strcasecmp($val, 'Recent') == 0) {
+						    $result[$id]->recent = true;
+						} else if (strcasecmp($val, 'Answered') == 0) {
+							$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) {
+						         $result[$id]->flagged = true;
+						}
+					}
+					$result[$id]->flags = $flags_a;
+				}
 			}
 		}
 	} while (strcmp($a[0], $key) != 0);
@@ -1922,9 +1795,9 @@
 	return $result;
 }
 
-function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false) {
+function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false, $add='') {
 
-	$a  = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr);
+	$a  = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr, $add);
 	if (is_array($a)) {
 		return array_shift($a);
 	}
@@ -1994,11 +1867,13 @@
 	return $result;
 }
 
-function iil_C_Expunge(&$conn, $mailbox) {
+function iil_C_Expunge(&$conn, $mailbox, $messages=NULL) {
 
 	if (iil_C_Select($conn, $mailbox)) {
 		$c = 0;
-		iil_PutLine($conn->fp, "exp1 EXPUNGE");
+		$command = $messages ? "UID EXPUNGE $messages" : "EXPUNGE";
+
+		iil_PutLine($conn->fp, "exp1 $command");
 		do {
 			$line=chop(iil_ReadLine($conn->fp, 100));
 			if ($line[0] == '*') {
@@ -2030,7 +1905,7 @@
     
 	if (iil_C_Select($conn, $mailbox)) {
 		$c = 0;
-		iil_PutLine($fp, "flg STORE $messages " . $mod . "FLAGS (" . $flag . ")");
+		iil_PutLine($fp, "flg UID STORE $messages " . $mod . "FLAGS (" . $flag . ")");
 		do {
 			$line=chop(iil_ReadLine($fp, 100));
 			if ($line[0] == '*') {
@@ -2039,7 +1914,6 @@
 		} while (!iil_StartsWith($line, 'flg', true));
 
 		if (iil_ParseResult($line) == 0) {
-			iil_C_ExpireCachedItems($conn, $mailbox, $messages);
 			return $c;
 		}
 		$conn->error = $line;
@@ -2079,7 +1953,7 @@
 	if (iil_C_Select($conn, $from)) {
 		$c=0;
 		
-		iil_PutLine($fp, "cpy1 COPY $messages \"".iil_Escape($to)."\"");
+		iil_PutLine($fp, "cpy1 UID COPY $messages \"".iil_Escape($to)."\"");
 		$line=iil_ReadReply($fp);
 		return iil_ParseResult($line);
 	} else {
@@ -2124,7 +1998,7 @@
 		if (iil_PutLine($fp, "$key FETCH $id (UID)")) {
 			do {
 				$line=chop(iil_ReadLine($fp, 1024));
-				if (eregi("^\* $id FETCH \(UID (.*)\)", $line, $r)) {
+				if (preg_match("/^\* $id FETCH \(UID (.*)\)/i", $line, $r)) {
 					$result = $r[1];
 				}
 			} while (!preg_match("/^$key/", $line));
@@ -2139,10 +2013,12 @@
 		$c = 0;
 		
 		$query = 'srch1 SEARCH ' . chop($criteria);
-		iil_PutLineC($fp, $query);
+		if (!iil_PutLineC($fp, $query)) {
+			return false;
+		}
 		do {
 			$line=trim(iil_ReadLine($fp, 10000));
-			if (eregi("^\* SEARCH", $line)) {
+			if (preg_match('/^\* SEARCH/i', $line)) {
 				$str = trim(substr($line, 8));
 				$messages = explode(' ', $str);
 			}
@@ -2160,12 +2036,13 @@
 }
 
 function iil_C_Move(&$conn, $messages, $from, $to) {
-    $fp = $conn->fp;
 
     if (!$from || !$to) {
         return -1;
     }
-    $r = iil_C_Copy($conn, $messages, $from,$to);
+    
+    $r = iil_C_Copy($conn, $messages, $from, $to);
+
     if ($r==0) {
         return iil_C_Delete($conn, $from, $messages);
     }
@@ -2274,7 +2151,7 @@
 	// get folder list
 	do {
 		$line = iil_ReadLine($fp, 500);
-		$line = iil_MultLine($fp, $line);
+		$line = iil_MultLine($fp, $line, true);
 
 		$a = explode(' ', $line);
 		if (($line[0] == '*') && ($a[1] == 'LIST')) {
@@ -2282,10 +2159,10 @@
         		// split one line
 			$a = iil_ExplodeQuotedString(' ', $line);
         		// last string is folder name
-			$folder = trim($a[count($a)-1], '"');
+			$folder = preg_replace(array('/^"/', '/"$/'), '', iil_UnEscape($a[count($a)-1]));
             
         		if (empty($ignore) || (!empty($ignore)
-            			&& !eregi($ignore, $folder))) {
+            			&& !preg_match('/'.preg_quote(ignore, '/').'/i', $folder))) {
             			$folders[$i] = $folder;
         		}
             
@@ -2339,7 +2216,7 @@
 	// get folder list
 	do {
 		$line = iil_ReadLine($fp, 500);
-		$line = iil_MultLine($fp, $line);
+		$line = iil_MultLine($fp, $line, true);
 		$a    = explode(' ', $line);
         
 		if (($line[0] == '*') && ($a[1] == 'LSUB' || $a[1] == 'LIST')) {
@@ -2347,13 +2224,11 @@
             
         		// split one line
 			$a = iil_ExplodeQuotedString(' ', $line);
-            
         		// last string is folder name
-        		//$folder = UTF7DecodeString(str_replace('"', '', $a[count($a)-1]));
-        		$folder = trim($a[count($a)-1], '"');
-            
+    			$folder = preg_replace(array('/^"/', '/"$/'), '', iil_UnEscape($a[count($a)-1]));
+        
 			if ((!in_array($folder, $folders)) && (empty($ignore)
-            			|| (!empty($ignore) && !eregi($ignore, $folder)))) {
+            			|| (!empty($ignore) && !preg_match('/'.preg_quote(ignore, '/').'/i', $folder)))) {
 			    $folders[$i] = $folder;
         		}
             
@@ -2418,7 +2293,7 @@
 
 	// format request
 	foreach($parts as $part)
-		$peeks[] = "BODY[$part.MIME]";
+		$peeks[] = "BODY.PEEK[$part.MIME]";
 	
 	$request = "$key FETCH $id (" . implode(' ', $peeks) . ')';
 
@@ -2446,35 +2321,47 @@
 
 	$part = empty($part) ? 'HEADER' : $part.'.MIME';
 
-        return iil_C_HandlePartBody($conn, $mailbox, $id, $part, 1);
+        return iil_C_HandlePartBody($conn, $mailbox, $id, $part);
 }
 
-function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part='', $mode=1, $file=NULL) {
-	/* modes:
-        1: return string (or write to $file pointer)
-        2: print
-        3: base64 and print (or write to $file pointer)
-	*/
+function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part='', $encoding=NULL, $print=NULL, $file=NULL) {
 	
 	$fp     = $conn->fp;
 	$result = false;
 	
+	switch ($encoding) {
+		case 'base64':
+			$mode = 1;
+		break;
+		case 'quoted-printable':
+			$mode = 2;
+		break;
+		case 'x-uuencode':
+		case 'x-uue':
+		case 'uue':
+		case 'uuencode':
+			$mode = 3;
+		break;
+		default:
+			$mode = 0;
+	}
+	
 	if (iil_C_Select($conn, $mailbox)) {
     		$reply_key = '* ' . $id;
-        
+
     		// format request
-		$key     = 'ftch' . ($c++) . ' ';
-		$request = $key . "FETCH $id (BODY.PEEK[$part])";
+		$key     = 'ftch0';
+		$request = $key . " FETCH $id (BODY.PEEK[$part])";
     		// send request
 		if (!iil_PutLine($fp, $request)) {
 		    return false;
     		}
-        
+
     		// receive reply line
     		do {
         		$line = chop(iil_ReadLine($fp, 1000));
         		$a    = explode(' ', $line);
-    		} while ($a[2] != 'FETCH');
+    		} while (!($end = iil_StartsWith($line, $key, true)) && $a[2] != 'FETCH');
     		$len = strlen($line);
 
 		// handle empty "* X FETCH ()" response
@@ -2490,14 +2377,13 @@
 				$result = substr($line, $from, $len);
 			}
 	    
-	                if ($mode == 2) {
-        		        echo $result;
-	                } else if ($mode == 3) {
-				if ($file)
-					fwrite($file, base64_decode($result));
-        		    	else
-					echo base64_decode($result);
-			}			     
+        		if ($mode == 1)
+				$result = base64_decode($result);
+			else if ($mode == 2)
+				$result = quoted_printable_decode($result);
+			else if ($mode == 3)
+				$result = convert_uudecode($result);
+
     		} else if ($line[$len-1] == '}') {
 	                //multi-line request, find sizes of content and receive that many bytes
         		$from     = strpos($line, '{') + 1;
@@ -2505,7 +2391,8 @@
         		$len      = $to - $from;
 	                $sizeStr  = substr($line, $from, $len);
         		$bytes    = (int)$sizeStr;
-
+			$prev	  = '';
+			
         		while ($bytes > 0) {
     		                $line      = iil_ReadLine($fp, 1024);
             			$len       = strlen($line);
@@ -2516,64 +2403,82 @@
             			$bytes -= strlen($line);
 
 		                if ($mode == 1) {
-					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";
-		                } else if ($mode == 3) {
+					$line = rtrim($line, "\t\r\n\0\x0B");
+					// create chunks with proper length for base64 decoding
+					$line = $prev.$line;
+					$length = strlen($line);
+					if ($length % 4) {
+						$length = floor($length / 4) * 4;
+						$prev = substr($line, $length);
+						$line = substr($line, 0, $length);
+					}
+					else
+						$prev = '';
+
 					if ($file)
 						fwrite($file, base64_decode($line));
-            				else
+            				else if ($print)
 						echo base64_decode($line);
+					else
+						$result .= base64_decode($line);
+				} else if ($mode == 2) {
+					$line = rtrim($line, "\t\r\0\x0B");
+					if ($file)
+						fwrite($file, quoted_printable_decode($line));
+            				else if ($print)
+						echo quoted_printable_decode($line);
+					else
+						$result .= quoted_printable_decode($line);
+				} else if ($mode == 3) {
+					$line = rtrim($line, "\t\r\n\0\x0B");
+					if ($line == 'end' || preg_match('/^begin\s+[0-7]+\s+.+$/', $line))
+						continue;
+					if ($file)
+						fwrite($file, convert_uudecode($line));
+            				else if ($print)
+						echo convert_uudecode($line);
+					else
+						$result .= convert_uudecode($line);
+				} else {
+					$line = rtrim($line, "\t\r\n\0\x0B");
+					if ($file)
+						fwrite($file, $line . "\n");
+            			        else if ($print)
+						echo $line . "\n";
+					else
+						$result .= $line . "\n";
 				}
         		}
     		}
+
 	        // read in anything up until last line
-		do {
-        		$line = iil_ReadLine($fp, 1024);
-		} while (!iil_StartsWith($line, $key, true));
+		if (!$end)
+			do {
+        			$line = iil_ReadLine($fp, 1024);
+			} while (!iil_StartsWith($line, $key, true));
         
-		if ($mode == 3 && $file) {
-			return true;
-		}
-	
     		if ($result) {
 	    		$result = rtrim($result, "\t\r\n\0\x0B");
 			if ($file) {
 				fwrite($file, $result);
-				return true;
-			}	
-			return $result; // substr($result, 0, strlen($result)-1);
+			} else if ($print) {
+				echo $result;
+			} else
+				return $result; // substr($result, 0, strlen($result)-1);
     		}
     		
-		return false;
-	} else {
-		echo 'Select failed.';
+		return true;
 	}
     
-	if ($mode==1) {
-		if ($file) {
-			fwrite($file, $result);
-			return true;
-		}
-    		return $result;
-	}
-	
 	return false;
 }
 
 function iil_C_FetchPartBody(&$conn, $mailbox, $id, $part, $file=NULL) {
-	return iil_C_HandlePartBody($conn, $mailbox, $id, $part, 1, $file);
+	return iil_C_HandlePartBody($conn, $mailbox, $id, $part, NULL, NULL, $file);
 }
 
 function iil_C_PrintPartBody(&$conn, $mailbox, $id, $part) {
-	iil_C_HandlePartBody($conn, $mailbox, $id, $part, 2);
-}
-
-function iil_C_PrintBase64Body(&$conn, $mailbox, $id, $part) {
-	iil_C_HandlePartBody($conn, $mailbox, $id, $part, 3);
+	iil_C_HandlePartBody($conn, $mailbox, $id, $part, NULL, true, NULL);
 }
 
 function iil_C_CreateFolder(&$conn, $folder) {
@@ -2721,13 +2626,6 @@
 	return $result;
 }
 
-function iil_C_PrintSource(&$conn, $folder, $id, $part) {
-	$header = iil_C_FetchPartHeader($conn, $folder, $id, $part);
-	//echo str_replace("\r", '', $header);
-	echo $header;
-	echo iil_C_PrintPartBody($conn, $folder, $id, $part);
-}
-
 function iil_C_GetQuota(&$conn) {
 /*
  * GETQUOTAROOT "INBOX"
@@ -2752,7 +2650,7 @@
 	// return false if not found, parse if found
 	$min_free = PHP_INT_MAX;
 	foreach ($quota_lines as $key => $quota_line) {
-		$quota_line   = eregi_replace('[()]', '', $quota_line);
+		$quota_line   = preg_replace('/[()]/', '', $quota_line);
 		$parts        = explode(' ', $quota_line);
 		$storage_part = array_search('STORAGE', $parts);
 		
@@ -2777,7 +2675,7 @@
 function iil_C_ClearFolder(&$conn, $folder) {
 	$num_in_trash = iil_C_CountMessages($conn, $folder);
 	if ($num_in_trash > 0) {
-		iil_C_Delete($conn, $folder, '1:' . $num_in_trash);
+		iil_C_Delete($conn, $folder, '1:*');
 	}
 	return (iil_C_Expunge($conn, $folder) >= 0);
 }

--
Gitblit v1.9.1