From d0b973cf6aed4a7cb705f706624d25b31d19ed52 Mon Sep 17 00:00:00 2001
From: svncommit <devs@roundcube.net>
Date: Thu, 18 Sep 2008 07:54:14 -0400
Subject: [PATCH] Bind cookie gotten over HTTPS to HTTPS only (#1485336).

---
 program/lib/imap.inc |  957 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 503 insertions(+), 454 deletions(-)

diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index 0f3ac98..17197d8 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -52,14 +52,20 @@
 		- $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()
 		- fixed iil_MultLine(): use iil_ReadBytes() instead of iil_ReadLine()
 		- fixed iil_C_FetchStructureString() to handle many literal strings in response
 		- 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
 
 ********************************************************/
 
@@ -88,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;
@@ -111,6 +127,8 @@
 	var $rootdir;
 	var $delimiter;
 	var $capability = array();
+	var $permanentflags = array();
+	var $capability_readed = false;
 }
 
 /**
@@ -140,12 +158,14 @@
 	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;
 	var $answered = false;
+	var $forwarded = false;
 	var $junk = false;
+	var $flagged = false;
 }
 
 /**
@@ -159,34 +179,41 @@
 	var $mid;
 }
 
-
 function iil_xor($string, $string2) {
-    $result = '';
-    $size = strlen($string);
-    for ($i=0; $i<$size; $i++) {
-    	$result .= chr(ord($string[$i]) ^ ord($string2[$i]));
-    }
-    return $result;
+	$result = '';
+	$size = strlen($string);
+	for ($i=0; $i<$size; $i++) {
+    		$result .= chr(ord($string[$i]) ^ ord($string2[$i]));
+	}
+	return $result;
+}
+
+function iil_PutLine($fp, $string, $endln=true) {
+//	console('C: '. $string);
+	return fputs($fp, $string . ($endln ? "\r\n" : ''));
 }
 
 function iil_ReadLine($fp, $size) {
-    $line = '';
-    if (!$fp) {
-        return $line;
-    }
+	$line = '';
+
+	if (!$fp) {
+    		return $line;
+	}
     
-    if (!$size) {
-	$size = 1024;
-    }
+	if (!$size) {
+		$size = 1024;
+	}
     
-    do {
-        $buffer = fgets($fp, $size);
-        if ($buffer === false) {
-            break;
-        }
-        $line .= $buffer;
-    } while ($buffer[strlen($buffer)-1] != "\n");
-    return $line;
+	do {
+    		$buffer = fgets($fp, $size);
+    		if ($buffer === false) {
+        		break;
+    		}
+//		console('S: '. chop($buffer));
+    		$line .= $buffer;
+	} while ($buffer[strlen($buffer)-1] != "\n");
+	
+	return $line;
 }
 
 function iil_MultLine($fp, $line) {
@@ -197,25 +224,27 @@
 		preg_match_all('/(.*)\{([0-9]+)\}$/', $line, $a);
 		$bytes = $a[2][0];
 		while (strlen($out) < $bytes) {
-		    $line = iil_ReadBytes($fp, $bytes); 
-		    $out .= $line;
+			$line = iil_ReadBytes($fp, $bytes); 
+			$out .= $line;
 		}
 		$line = $a[1][0] . "\"$out\"";
+//		console('[...] '. $out);
 	}
 	return $line;
 }
 
 function iil_ReadBytes($fp, $bytes) {
-    $data = '';
-    $len  = 0;
-    do {
-        $data .= fread($fp, $bytes-$len);
-        if ($len == strlen($data)) {
-            break; //nothing was read -> exit to avoid apache lockups
-        }
-        $len = strlen($data);
-    } while ($len < $bytes);
-    return $data;
+	$data = '';
+	$len  = 0;
+	do {
+    		$data .= fread($fp, $bytes-$len);
+		if ($len == strlen($data)) {
+    		        break; //nothing was read -> exit to avoid apache lockups
+    		}
+    		$len = strlen($data);
+	} while ($len < $bytes);
+	
+	return $data;
 }
 
 function iil_ReadReply($fp) {
@@ -230,43 +259,76 @@
 	$a=explode(' ', $string);
 	if (count($a) > 2) {
 		if (strcasecmp($a[1], 'OK') == 0) {
-		    return 0;
+			return 0;
 		} else if (strcasecmp($a[1], 'NO') == 0) {
-		    return -1;
+			return -1;
 		} else if (strcasecmp($a[1], 'BAD') == 0) {
-		    return -2;
-        }
+			return -2;
+    		}
 	}
-    return -3;
+	return -3;
 }
 
 // check if $string starts with $match
 function iil_StartsWith($string, $match) {
 	$len = strlen($match);
 	if ($len == 0) {
-	    return false;
-    }
+		return false;
+	}
 	if (strncmp($string, $match, $len) == 0) {
-	    return true;
-    }
+		return true;
+	}
 	return false;
 }
 
 function iil_StartsWithI($string, $match) {
 	$len = strlen($match);
 	if ($len == 0) {
-	    return false;
-    }
+		return false;
+	}
 	if (strncasecmp($string, $match, $len) == 0) {
-	    return true;
-    }
+		return true;
+	}
 	return false;
 }
 
-
 function iil_Escape($string)
 {
-    return strtr($string, array('"'=>'\\"', '\\' => '\\\\')); 
+	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) {
@@ -279,6 +341,7 @@
         $ipad .= chr(0x36);
         $opad .= chr(0x5C);
     }
+
     // pad $pass so it's 64 bytes
     $padLen = 64 - strlen($pass);
     for ($i=0;$i<$padLen;$i++) {
@@ -286,15 +349,13 @@
     }
     
     // generate hash
-    $hash  = iil_xor($pass,$opad);
-    $hash .= pack("H*", md5(iil_xor($pass, $ipad) . base64_decode($encChallenge)));
-    $hash  = md5($hash);
+    $hash  = md5(iil_xor($pass,$opad) . pack("H*", md5(iil_xor($pass, $ipad) . base64_decode($encChallenge))));
     
     // generate reply
-    $reply = base64_encode('"' . $user . '" "' . $hash . '"');
+    $reply = base64_encode($user . ' ' . $hash);
     
     // send result, get reply
-    fputs($conn->fp, $reply . "\r\n");
+    iil_PutLine($conn->fp, $reply);
     $line = iil_ReadLine($conn->fp, 1024);
     
     // process result
@@ -311,7 +372,7 @@
 
 function iil_C_Login(&$conn, $user, $password) {
 
-    fputs($conn->fp, 'a001 LOGIN "'.iil_Escape($user).'" "'.iil_Escape($password)."\"\r\n");
+    iil_PutLine($conn->fp, 'a001 LOGIN "'.iil_Escape($user).'" "'.iil_Escape($password).'"');
 
     do {
         $line = iil_ReadReply($conn->fp);
@@ -339,10 +400,10 @@
 function iil_ParseNamespace2($str, &$i, $len=0, $l) {
 	if (!$l) {
 	    $str = str_replace('NIL', '()', $str);
-    }
+	}
 	if (!$len) {
 	    $len = strlen($str);
-    }
+	}
 	$data      = array();
 	$in_quotes = false;
 	$elem      = 0;
@@ -353,17 +414,17 @@
 			$data[$elem] = iil_ParseNamespace2($str, $i, $len, $l++);
 			$elem++;
 		} else if ($c == ')' && !$in_quotes) {
-		    return $data;
-        } else if ($c == '\\') {
+			return $data;
+    		} else if ($c == '\\') {
 			$i++;
 			if ($in_quotes) {
-			    $data[$elem] .= $c.$str[$i];
-            }
+				$data[$elem] .= $c.$str[$i];
+        		}
 		} else if ($c == '"') {
 			$in_quotes = !$in_quotes;
 			if (!$in_quotes) {
-			    $elem++;
-            }
+				$elem++;
+        		}
 		} else if ($in_quotes) {
 			$data[$elem].=$c;
 		}
@@ -374,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;
 	}
     
@@ -382,7 +443,7 @@
 	    return true;
 	}
     
-	fputs($conn->fp, "ns1 NAMESPACE\r\n");
+	iil_PutLine($conn->fp, "ns1 NAMESPACE");
 	do {
 		$line = iil_ReadLine($conn->fp, 1024);
 		if (iil_StartsWith($line, '* NAMESPACE')) {
@@ -410,11 +471,10 @@
 	$my_prefs["rootdir"] = substr($conn->rootdir, 0, -1);
 	
 	return true;
-
 }
 
 function iil_Connect($host, $user, $password) {	
-    global $iil_error, $iil_errornum;
+	global $iil_error, $iil_errornum;
 	global $ICL_SSL, $ICL_PORT;
 	global $IMAP_NO_CACHE;
 	global $my_prefs, $IMAP_USE_INTERNAL_DATE;
@@ -431,11 +491,11 @@
 	if (func_num_args() >= 4) {
 		$auth_array = func_get_arg(3);
 		if (is_array($auth_array)) {
-		    $auth_method = $auth_array['imap'];
-        }
+			$auth_method = $auth_array['imap'];
+    		}
 		if (empty($auth_method)) {
-            $auth_method = "plain";
-        }
+        		$auth_method = "plain";
+    		}
 	}
 	$message = "INITIAL: $auth_method\n";
 		
@@ -453,27 +513,27 @@
 	$conn->cache_dirty = array();
 	
 	if ($my_prefs['sort_field'] == 'INTERNALDATE') {
-	    $IMAP_USE_INTERNAL_DATE = true;
-    } else if ($my_prefs['sort_field'] == 'DATE') {
-        $IMAP_USE_INTERNAL_DATE = false;
-    }
+		$IMAP_USE_INTERNAL_DATE = true;
+	} else if ($my_prefs['sort_field'] == 'DATE') {
+    		$IMAP_USE_INTERNAL_DATE = false;
+	}
 	//echo '<!-- conn sort_field: '.$my_prefs['sort_field'].' //-->';
 	
 	//check input
 	if (empty($host)) {
-	    $iil_error .= "Invalid host\n";
-    }
+		$iil_error .= "Invalid host\n";
+	}
 	if (empty($user)) {
-	    $iil_error .= "Invalid user\n";
-    }
+		$iil_error .= "Invalid user\n";
+	}
 	if (empty($password)) {
-	    $iil_error .= "Invalid password\n";
-    }
+		$iil_error .= "Invalid password\n";
+	}
 	if (!empty($iil_error)) {
-	    return false;
-    }
+		return false;
+	}
 	if (!$ICL_PORT) {
-	    $ICL_PORT = 143;
+		$ICL_PORT = 143;
 	}
     
 	//check for SSL
@@ -484,59 +544,41 @@
 	//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";
-        $iil_errornum = -1;
+    		$iil_error = "Could not connect to $host at port $ICL_PORT: $errstr";
+    		$iil_errornum = -1;
 		return false;
 	}
 
 	$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 {
-		fputs($conn->fp, "cp01 CAPABILITY\r\n");
-		do {
-			$line = trim(iil_ReadLine($conn->fp, 100));
+	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) {
 		$conn->message .= "Trying CRAM-MD5\n";
 
 		//do CRAM-MD5 authentication
-		fputs($conn->fp, "a000 AUTHENTICATE CRAM-MD5\r\n");
+		iil_PutLine($conn->fp, "a000 AUTHENTICATE CRAM-MD5");
 		$line = trim(iil_ReadLine($conn->fp, 1024));
-        
+
 		$conn->message .= "$line\n";
-        
+
 		if ($line[0] == '+') {
 			$conn->message .= 'Got challenge: ' . htmlspecialchars($line) . "\n";
 
@@ -546,8 +588,7 @@
 			$conn->message .= "Tried CRAM-MD5: $result \n";
 		} else {
 			$conn->message .='No challenge ('.htmlspecialchars($line)."), try plain\n";
-			
-            $auth = 'plain';            
+			$auth = 'plain';
 		}
 	}
 		
@@ -571,7 +612,7 @@
 
 function iil_Close(&$conn) {
 	iil_C_WriteCache($conn);
-	if (fputs($conn->fp, "I LOGOUT\r\n")) {
+	if (iil_PutLine($conn->fp, "I LOGOUT")) {
 		fgets($conn->fp, 1024);
 		fclose($conn->fp);
 		$conn->fp = false;
@@ -580,7 +621,6 @@
 
 function iil_ClearCache($user, $host) {
 }
-
 
 function iil_C_WriteCache(&$conn) {
 	//echo "<!-- doing iil_C_WriteCache //-->\n";
@@ -620,14 +660,14 @@
 function iil_C_ExpireCachedItems(&$conn, $folder, $message_set) {
 	
 	if (!$conn->do_cache) {
-	    return;	//caching disabled
+		return;	//caching disabled
 	}
-    if (!is_array($conn->cache[$folder])) {
-        return;	//cache not initialized|empty
+	if (!is_array($conn->cache[$folder])) {
+    		return;	//cache not initialized|empty
 	}
-    if (count($conn->cache[$folder]) == 0) {
-        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;
@@ -664,8 +704,8 @@
 	while ( list($key, $val) = each($quotes)) {
 		if (($key % 2) == 1) {
 			$quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
-        }
-    }
+    		}
+	}
 	$string=implode('"', $quotes);
 	
 	$result=explode($delimiter, $string);
@@ -678,13 +718,13 @@
 
 function iil_CheckForRecent($host, $user, $password, $mailbox) {
 	if (empty($mailbox)) {
-	    $mailbox = 'INBOX';
+		$mailbox = 'INBOX';
 	}
     
 	$conn = iil_Connect($host, $user, $password, 'plain');
 	$fp   = $conn->fp;
 	if ($fp) {
-		fputs($fp, "a002 EXAMINE \"".iil_Escape($mailbox)."\"\r\n");
+		iil_PutLine($fp, "a002 EXAMINE \"".iil_Escape($mailbox)."\"");
 		do {
 			$line=chop(iil_ReadLine($fp, 300));
 			$a=explode(' ', $line);
@@ -693,7 +733,7 @@
             }
 		} while (!iil_StartsWith($a[0], 'a002'));
 
-		fputs($fp, "a003 LOGOUT\r\n");
+		iil_PutLine($fp, "a003 LOGOUT");
 		fclose($fp);
 	} else {
 	    $result = -2;
@@ -703,57 +743,60 @@
 }
 
 function iil_C_Select(&$conn, $mailbox) {
-	$fp = $conn->fp;
-	
+
 	if (empty($mailbox)) {
-	    return false;
+		return false;
 	}
-    if (strcmp($conn->selected, $mailbox) == 0) {
-        return true;
+	if (strcmp($conn->selected, $mailbox) == 0) {
+		return true;
 	}
     
 	iil_C_LoadCache($conn, $mailbox);
 	
-	if (fputs($fp, "sel1 SELECT \"".iil_Escape($mailbox)."\"\r\n")) {
+	if (iil_PutLine($conn->fp, "sel1 SELECT \"".iil_Escape($mailbox).'"')) {
 		do {
-			$line=chop(iil_ReadLine($fp, 300));
-			$a=explode(' ', $line);
+			$line = chop(iil_ReadLine($conn->fp, 300));
+			$a = explode(' ', $line);
 			if (count($a) == 3) {
 				if (strcasecmp($a[2], 'EXISTS') == 0) {
-				    $conn->exists = (int) $a[1];
+					$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'));
 
-		$a=explode(' ', $line);
+		$a = explode(' ', $line);
 
 		if (strcasecmp($a[1], 'OK') == 0) {
 			$conn->selected = $mailbox;
 			return true;
 		}
 	}
-    return false;
+	return false;
 }
 
 function iil_C_CheckForRecent(&$conn, $mailbox) {
 	if (empty($mailbox)) {
-	    $mailbox = 'INBOX';
+		$mailbox = 'INBOX';
 	}
     
 	iil_C_Select($conn, $mailbox);
 	if ($conn->selected == $mailbox) {
-	    return $conn->recent;
+		return $conn->recent;
 	}
-    return false;
+	return false;
 }
 
 function iil_C_CountMessages(&$conn, $mailbox, $refresh = false) {
 	if ($refresh) {
 		$conn->selected= '';
 	}
+	
 	iil_C_Select($conn, $mailbox);
 	if ($conn->selected == $mailbox) {
 		return $conn->exists;
@@ -768,16 +811,16 @@
 		$res[1] = trim(substr($string, $pos+1));
 		return $res;
 	}
-    return $string;
+	return $string;
 }
 
 function iil_StrToTime($str) {
 	$IMAP_MONTHS    = $GLOBALS['IMAP_MONTHS'];
-    $IMAP_SERVER_TZ = $GLOBALS['IMAP_SERVER_TR'];
+	$IMAP_SERVER_TZ = $GLOBALS['IMAP_SERVER_TR'];
 		
 	if ($str) {
-        $time1 = strtotime($str);
-    }
+    	    $time1 = strtotime($str);
+	}
 	if ($time1 && $time1 != -1) {
 	    return $time1-$IMAP_SERVER_TZ;
 	}
@@ -791,7 +834,7 @@
 	$pos = strpos($str, ' ');
 	if (!is_numeric(substr($str, 0, $pos))) {
 	    $str = substr($str, $pos+1);
-    }
+	}
 	//explode, take good parts
 	$a = explode(' ', $str);
 
@@ -822,7 +865,8 @@
 	$field = strtoupper($field);
 	if ($field == 'INTERNALDATE') {
 	    $field = 'ARRIVAL';
-    }
+	}
+	
 	$fields = array('ARRIVAL' => 1,'CC' => 1,'DATE' => 1,
         'FROM' => 1, 'SIZE' => 1, 'SUBJECT' => 1, 'TO' => 1);
 	
@@ -834,21 +878,21 @@
 	
 	if (!empty($add)) {
 	    $add = " $add";
-    }
+	}
 
 	$fp       = $conn->fp;
 	$command  = 's ' . $is_uid . 'SORT (' . $field . ') ';
-	$command .= $encoding . ' ALL' . "$add\r\n";
+	$command .= $encoding . ' ALL' . $add;
 	$line     = $data = '';
 	
-	if (!fputs($fp, $command)) {
+	if (!iil_PutLine($fp, $command)) {
 	    return false;
 	}
 	do {
 		$line = chop(iil_ReadLine($fp, 1024));
 		if (iil_StartsWith($line, '* SORT')) {
-		    $data .= ($data?' ':'') . substr($line, 7);
-        }
+			$data .= ($data?' ':'') . substr($line, 7);
+    		}
 	} while ($line[0]!='s');
 	
 	if (empty($data)) {
@@ -870,14 +914,14 @@
 		
 	if (empty($index_field)) {
 	    $index_field = 'DATE';
-    }
+	}
 	$index_field = strtoupper($index_field);
 	
 	list($from_idx, $to_idx) = explode(':', $message_set);
 	if (empty($message_set) || (isset($to_idx)
-        && (int)$from_idx > (int)$to_idx)) {
+    	    && (int)$from_idx > (int)$to_idx)) {
 		return false;
-    }
+	}
 	
 	//$fields_a['DATE'] = ($IMAP_USE_INTERNAL_DATE?6:1);
 	$fields_a['DATE']         = 1;
@@ -901,21 +945,21 @@
 	/*  Do "SELECT" command */
 	if (!iil_C_Select($conn, $mailbox)) {
 	    return false;
-    }
+	}
     
 	/* FETCH date,from,subject headers */
 	if ($mode == 1) {
 		$key     = 'fhi' . ($c++);
-		$request = $key . " FETCH $message_set (BODY.PEEK[HEADER.FIELDS ($index_field)])\r\n";
-		if (!fputs($fp, $request)) {
+		$request = $key . " FETCH $message_set (BODY.PEEK[HEADER.FIELDS ($index_field)])";
+		if (!iil_PutLine($fp, $request)) {
 		    return false;
-        }
+    		}
 		do {
 			
 			$line=chop(iil_ReadLine($fp, 200));
 			$a=explode(' ', $line);
 			if (($line[0] == '*') && ($a[2] == 'FETCH')
-                && ($line[strlen($line)-1] != ')')) {
+            		    && ($line[strlen($line)-1] != ')')) {
 				$id=$a[1];
 
 				$str=$line=chop(iil_ReadLine($fp, 300));
@@ -934,7 +978,7 @@
 								$result[$id] = str_replace('"', '', $string);
 								if ($normalize) {
 								    $result[$id] = strtoupper($result[$id]);
-                                }
+                            					}
 							}
 							$str=$line;
 						}
@@ -954,9 +998,9 @@
 					$line      = chop($line);
 					
 					if ($received>$bytes) {
-                        break;
+                    				break;
 					} else if (!$line) {
-                        continue;
+                    				continue;
 					}
 
 					list($field, $string) = explode(': ', $line);
@@ -965,7 +1009,7 @@
 						$result[$id] = iil_StrToTime($string);
 					} else if ($index_field != 'DATE') {
 						$result[$id]=strtoupper(str_replace('"', '', $string));
-                    }
+                			}
 				} while ($line[0] != ')');
 			} else {
 				//one line response, not expected so ignore				
@@ -976,10 +1020,10 @@
 	}else if ($mode == 6) {
 
 		$key     = 'fhi' . ($c++);
-		$request = $key . " FETCH $message_set (INTERNALDATE)\r\n";
-		if (!fputs($fp, $request)) {
+		$request = $key . " FETCH $message_set (INTERNALDATE)";
+		if (!iil_PutLine($fp, $request)) {
 		    return false;
-        }
+    		}
 		do {
 			$line=chop(iil_ReadLine($fp, 200));
 			if ($line[0] == '*') {
@@ -1010,15 +1054,15 @@
 		    $field_name = 'RFC822.SIZE';
 		} else {
 		    $field_name = $index_field;
-        }
+    		}
         
 		/* 			FETCH uid, size, flags		*/
 		$key     = 'fhi' .($c++);
-		$request = $key . " FETCH $message_set ($field_name)\r\n";
+		$request = $key . " FETCH $message_set ($field_name)";
 
-		if (!fputs($fp, $request)) {
+		if (!iil_PutLine($fp, $request)) {
 		    return false;
-        }
+    		}
 		do {
 			$line=chop(iil_ReadLine($fp, 200));
 			$a = explode(' ', $line);
@@ -1032,9 +1076,9 @@
 				if (isset($result[$id])) {
 				    continue; //if we already got the data, skip forward
 				}
-                if ($a[3]!=$field_name) {
-                    continue;  //make sure it's returning what we requested
-			    }
+            			if ($a[3]!=$field_name) {
+                			continue;  //make sure it's returning what we requested
+				}
                 
 				/*  Caution, bad assumptions, next several lines */
 				if ($mode == 2) {
@@ -1056,10 +1100,10 @@
 		//if we have less, try and fill in the "gaps"
 		if (count($result) < $should_have) {
 			for ($i=$start_mid; $i<=$end_mid; $i++) {
-			    if (!isset($result[$i])) {
-			        $result[$i] = '';
-                }
-            }
+				if (!isset($result[$i])) {
+			    		$result[$i] = '';
+            			}
+        		}
 		}
 	}
 	return $result;	
@@ -1094,16 +1138,17 @@
 			} else {
 			    $result[] = $start . ':' . $prev;   //push sequence as start_id:end_id
 			}
-            $start = $id;							//start of new sequence
+        		$start = $id;			//start of new sequence
 		}
 		$prev = $id;
 	}
+
 	//handle the last sequence/id
 	if ($start==$prev) {
 	    $result[] = $prev;
-    } else {
-        $result[] = $start.':'.$prev;
-    }
+	} else {
+    	    $result[] = $start.':'.$prev;
+	}
     
 	//return as comma separated string
 	return implode(',', $result);
@@ -1112,7 +1157,7 @@
 function iil_C_UIDsToMIDs(&$conn, $mailbox, $uids) {
 	if (!is_array($uids) || count($uids) == 0) {
 	    return array();
-    }
+	}
 	return iil_C_Search($conn, $mailbox, 'UID ' . implode(',', $uids));
 }
 
@@ -1121,7 +1166,7 @@
 	if (count($result) == 1) {
 	    return $result[0];
 	}
-    return false;
+        return false;
 }
 
 function iil_C_FetchUIDs(&$conn,$mailbox) {
@@ -1130,7 +1175,7 @@
 	$num = iil_C_CountMessages($conn, $mailbox);
 	if ($num == 0) {
 	    return array();
-    }
+	}
 	$message_set = '1' . ($num>1?':' . $num:'');
 	
 	//if cache not enabled, just call iil_C_FetchHeaderIndex on 'UID' field
@@ -1162,7 +1207,7 @@
 		$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
@@ -1197,7 +1242,7 @@
 	if (empty($message_set) || (isset($to_idx)
         && (int)$from_idx > (int)$to_idx)) {
 		return false;
-    }
+	}
 
 	$result = array();
 	$uids   = iil_C_FetchUIDs($conn, $mailbox);
@@ -1214,13 +1259,13 @@
 					$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);
@@ -1234,16 +1279,16 @@
 		$key        = 'fh';
 		$fp         = $conn->fp;
 		$request    = $key . " FETCH $message_set ";
-        $request   .= "(BODY.PEEK[HEADER.FIELDS (SUBJECT MESSAGE-ID IN-REPLY-TO)])\r\n";
+    		$request   .= "(BODY.PEEK[HEADER.FIELDS (SUBJECT MESSAGE-ID IN-REPLY-TO)])";
 		$mid_to_id  = array();
-		if (!fputs($fp, $request)) {
+		if (!iil_PutLine($fp, $request)) {
 		    return false;
-        }
+    		}
 		do {
 			$line = chop(iil_ReadLine($fp, 1024));
 			if ($debug) {
 			    echo $line . "\n";
-            }
+        		}
 			if (ereg('\{[0-9]+\}$', $line)) {
 				$a 	 = explode(' ', $line);
 				$new = array();
@@ -1253,8 +1298,8 @@
 				do {
 					$line = chop(iil_ReadLine($fp, 1024), "\r\n");
 					if (iil_StartsWithI($line, 'Message-ID:')
-                        || (iil_StartsWithI($line,'In-Reply-To:'))
-                        || (iil_StartsWithI($line,'SUBJECT:'))) {
+                    				|| (iil_StartsWithI($line,'In-Reply-To:'))
+                    				|| (iil_StartsWithI($line,'SUBJECT:'))) {
 
 						$pos        = strpos($line, ':');
 						$field_name = substr($line, 0, $pos);
@@ -1285,7 +1330,7 @@
 	if ($conn->do_cache) {
 		if (count($result)!=count($cached)) {
 			cache_write($conn->user, $conn->host, $mailbox . '.thhd', $result);
-        }
+    		}
 	}
 	
 	//echo 'iil_FetchThreadHeaders:'."\n";
@@ -1299,7 +1344,7 @@
 
 	list($from_idx, $to_idx) = explode(':', $message_set);
 	if (empty($message_set) || (isset($to_idx)
-        && (int)$from_idx > (int)$to_idx)) {
+    		&& (int)$from_idx > (int)$to_idx)) {
 		return false;
 	}
     
@@ -1317,7 +1362,7 @@
 	/*  Do "SELECT" command */
 	if (!iil_C_Select($conn, $mailbox)) {
 	    return false;
-    }
+	}
     
 	/* FETCH date,from,subject headers */
 	$mid_to_id = array();
@@ -1338,7 +1383,7 @@
 		//			'IN-REPLY-TO'=>$header['r'], 'SUBJECT'=>$header['s']);
 		$id  = $header->id;
 		$new = array('id' => $id, 'MESSAGE-ID' => $header->mid, 
-            'IN-REPLY-TO' => $header->irt, 'SUBJECT' => $header->sbj);
+        		'IN-REPLY-TO' => $header->irt, 'SUBJECT' => $header->sbj);
 
 		/* add to message-id -> mid lookup table */
 		$mid_to_id[$new['MESSAGE-ID']] = $id;
@@ -1354,8 +1399,8 @@
 		if (eregi($sbj_filter_pat, $new['SUBJECT'])) {
 		    $has_re = true;
 		}
-        if ($has_re||$new['IN-REPLY-TO']) {
-            $sbj_pre = 'RE:';
+    		if ($has_re||$new['IN-REPLY-TO']) {
+        	    $sbj_pre = 'RE:';
 		}
         
 		/* strip out 're:', 'fw:' etc */
@@ -1364,22 +1409,22 @@
 		} else {
 		    $sbj = $new['SUBJECT'];
 		}
-        $new['SUBJECT'] = $sbj_pre.$sbj;
+    		$new['SUBJECT'] = $sbj_pre.$sbj;
 		
 		
 		/* if subject not a known thread-root, add to list */
 		if ($debug) {
 		    echo $id . ' ' . $new['SUBJECT'] . "\t" . $new['MESSAGE-ID'] . "\n";
 		}
-        $root_id = $roots[$sbj];
+    		$root_id = $roots[$sbj];
 		
 		if ($root_id && ($has_re || !$root_in_root[$root_id])) {
 			if ($debug) {
 			    echo "\tfound root: $root_id\n";
 			}
-            $sub_mids[$new['MESSAGE-ID']] = $root_id;
+        		$sub_mids[$new['MESSAGE-ID']] = $root_id;
 			$result[$root_id][]           = $id;
-		}else if (!isset($roots[$sbj]) || (!$has_re && $root_in_root[$root_id])) {
+		} else if (!isset($roots[$sbj]) || (!$has_re && $root_in_root[$root_id])) {
 			/* try to use In-Reply-To header to find root 
 				unless subject contains 'Re:' */
 			if ($has_re&&$new['IN-REPLY-TO']) {
@@ -1394,7 +1439,7 @@
 					if ($debug) {
 					    echo "\tfound parent: ".$new['SUBJECT']."\n";
 					}
-                    $result[$temp][]              = $id;
+                			$result[$temp][]              = $id;
 					$sub_mids[$new['MESSAGE-ID']] = $temp;
 					$sbj                          = '';
 				} else {
@@ -1408,16 +1453,15 @@
 				if ($debug) {
 				    echo "\t added to root\n";
 				}
-                $roots[$sbj]                  = $id;
+            			$roots[$sbj]                  = $id;
 				$root_in_root[$id]            = !$has_re;
 				$sub_mids[$new['MESSAGE-ID']] = $id;
 				$result[$id]                  = array($id);
 			}
 			if ($debug) {
 			    echo $new['MESSAGE-ID'] . "\t" . $sbj . "\n";
-            }
+        		}
 		}
-			
 	}
 	
 	//now that we've gone through all the messages,
@@ -1428,7 +1472,7 @@
 			if (!$root_id || $root_id==$id) {
 			    continue;
 			}
-            $result[$root_id] = array_merge($result[$root_id],$result[$id]);
+        		$result[$root_id] = array_merge($result[$root_id],$result[$id]);
 			unset($result[$id]);
 		}
 	}
@@ -1440,15 +1484,14 @@
 	if ($debug) {
 	    print_r($roots);
 	}
-    //print_r($result);
+
 	return $result;
 }
-
 
 function iil_SortThreads(&$tree, $index, $sort_order = 'ASC') {
 	if (!is_array($tree) || !is_array($index)) {
 	    return false;
-    }
+	}
     
 	//create an id to position lookup table
 	$i = 0;
@@ -1485,7 +1528,6 @@
 		}
 	}
 	
-	
 	//sort by key, this basically sorts all threads
 	ksort($itree);
 	$i   = 0;
@@ -1495,7 +1537,6 @@
 		$i++;
 	}
 	
-	//return
 	return $out;
 }
 
@@ -1563,9 +1604,9 @@
 	$request .= " FETCH $message_set (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)])\r\n";
+	$request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY)])";
 
-	if (!fputs($fp, $request)) {
+	if (!iil_PutLine($fp, $request)) {
 		return false;
 	}
 	do {
@@ -1637,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;
@@ -1696,12 +1737,12 @@
 	*/
 	$command_key = 'fh' . ($c++);
 	$request     = $command_key . $prefix;
-	$request    .= " FETCH $message_set (UID RFC822.SIZE FLAGS INTERNALDATE)\r\n";
+	$request    .= " FETCH $message_set (UID RFC822.SIZE FLAGS INTERNALDATE)";
 	
-	if (!fputs($fp, $request)) {
+	if (!iil_PutLine($fp, $request)) {
 	    return false;
 	}
-    do {
+	do {
 		$line = chop(iil_ReadLine($fp, 200));
 		//$a = explode(' ', $line);
 		//if (($line[0]=="*") && ($a[2]=="FETCH")) {
@@ -1737,11 +1778,6 @@
 					// process flags
 					$flags_str = eregi_replace('[\\\"]', '', $flags_str);
 					$flags_a   = explode(' ', $flags_str);
-
-                    /*
-                    trigger_error("<!-- ID: $id FLAGS: ".implode(",", $flags_a)." //-->\n",
-                        E_USER_WARNING);
-                    */
 					
 					if (is_array($flags_a)) {
 						reset($flags_a);
@@ -1754,9 +1790,15 @@
 							    $result[$id]->recent = true;
 							} else if (strcasecmp($val, 'Answered') == 0) {
 							    $result[$id]->answered = true;
-							} else if (strcasecmp($val, "\$MDNSent") == 0) {
+							} 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;
 					}
@@ -1812,18 +1854,17 @@
 	return false;
 }
 
-
 function iil_SortHeaders($a, $field, $flag) {
 	if (empty($field)) {
 	    $field = 'uid';
-    }
+	}
 	$field = strtolower($field);
 	if ($field == 'date' || $field == 'internaldate') {
 	    $field = 'timestamp';
-    }
+	}
 	if (empty($flag)) {
 	    $flag = 'ASC';
-    }
+	}
     
 	$flag     = strtoupper($flag);
 	$stripArr = ($field=='subject') ? array('Re: ','Fwd: ','Fw: ','"') : array('"');
@@ -1846,12 +1887,12 @@
 				$data = @strtotime($val->date);
 				if ($data == false) {
 					$data = $val->timestamp;
-                }
+            			}
 			} else {
 				$data = $val->$field;
 				if (is_string($data)) {
 					$data=strtoupper(str_replace($stripArr, '', $data));
-                }
+            			}
 			}
 			$index[$key]=$data;
 		}
@@ -1859,9 +1900,9 @@
 		// sort index
 		$i = 0;
 		if ($flag == 'ASC') {
-		    asort($index);
-        } else {
-            arsort($index);
+			asort($index);
+    		} else {
+        		arsort($index);
 		}
         
 		// form new array based on index 
@@ -1877,15 +1918,15 @@
 }
 
 function iil_C_Expunge(&$conn, $mailbox) {
-	$fp = $conn->fp;
+
 	if (iil_C_Select($conn, $mailbox)) {
 		$c = 0;
-		fputs($fp, "exp1 EXPUNGE\r\n");
+		iil_PutLine($conn->fp, "exp1 EXPUNGE");
 		do {
-			$line=chop(iil_ReadLine($fp, 100));
+			$line=chop(iil_ReadLine($conn->fp, 100));
 			if ($line[0] == '*') {
-                $c++;
-            }
+            			$c++;
+        		}
 		} while (!iil_StartsWith($line, 'exp1'));
 		
 		if (iil_ParseResult($line) == 0) {
@@ -1905,26 +1946,19 @@
 	}
     
 	$fp    = $conn->fp;
-	$flags = array(
-        'SEEN'     => '\\Seen',
-        'DELETED'  => '\\Deleted',
-        'RECENT'   => '\\Recent',
-        'ANSWERED' => '\\Answered',
-        'DRAFT'    => '\\Draft',
-        'FLAGGED'  => '\\Flagged',
-        'MDNSENT'  => "\$MDNSent");
+	$flags = $GLOBALS['IMAP_FLAGS'];
         
 	$flag = strtoupper($flag);
 	$flag = $flags[$flag];
     
 	if (iil_C_Select($conn, $mailbox)) {
 		$c = 0;
-		fputs($fp, "flg STORE $messages " . $mod . "FLAGS (" . $flag . ")\r\n");
+		iil_PutLine($fp, "flg STORE $messages " . $mod . "FLAGS (" . $flag . ")");
 		do {
 			$line=chop(iil_ReadLine($fp, 100));
 			if ($line[0] == '*') {
 			    $c++;
-            }
+        		}
 		} while (!iil_StartsWith($line, 'flg'));
 
 		if (iil_ParseResult($line) == 0) {
@@ -1958,18 +1992,17 @@
 	return iil_C_ModFlag($conn, $mailbox, $messages, 'SEEN', '-');
 }
 
-
 function iil_C_Copy(&$conn, $messages, $from, $to) {
 	$fp = $conn->fp;
 
 	if (empty($from) || empty($to)) {
 	    return -1;
-    }
+	}
     
 	if (iil_C_Select($conn, $from)) {
 		$c=0;
 		
-		fputs($fp, "cpy1 COPY $messages \"".iil_Escape($to)."\"\r\n");
+		iil_PutLine($fp, "cpy1 COPY $messages \"".iil_Escape($to)."\"");
 		$line=iil_ReadReply($fp);
 		return iil_ParseResult($line);
 	} else {
@@ -1979,7 +2012,7 @@
 
 function iil_FormatSearchDate($month, $day, $year) {
 	$month  = (int) $month;
-    $months = $GLOBALS['IMAP_MONTHS'];
+	$months = $GLOBALS['IMAP_MONTHS'];
 	return $day . '-' . $months[$month] . '-' . $year;
 }
 
@@ -1989,10 +2022,10 @@
 		$str = implode(',', $index);
 		if (empty($str)) {
 		    return false;
-        }
+    		}
 		return count($index);
 	}
-    return false;
+	return false;
 }
 
 function iil_C_UID2ID(&$conn, $folder, $uid) {
@@ -2002,7 +2035,7 @@
 			$count = count($id_a);
 			if ($count > 1) {
 			    return false;
-            }
+        		}
 			return $id_a[0];
 		}
 	}
@@ -2013,11 +2046,11 @@
 	$fp = $conn->fp;
 	if ($id == 0) {
 	    return 	-1;
-    }
-    $result = -1;
+	}
+	$result = -1;
 	if (iil_C_Select($conn, $folder)) {
 		$key = 'FUID';
-		if (fputs($fp, "$key FETCH $id (UID)\r\n")) {
+		if (iil_PutLine($fp, "$key FETCH $id (UID)")) {
 			do {
 				$line=chop(iil_ReadLine($fp, 1024));
 				if (eregi("^\* $id FETCH \(UID (.*)\)", $line, $r)) {
@@ -2034,8 +2067,8 @@
 	if (iil_C_Select($conn, $folder)) {
 		$c = 0;
 		
-		$query = 'srch1 SEARCH ' . chop($criteria) . "\r\n";
-		fputs($fp, $query);
+		$query = 'srch1 SEARCH ' . chop($criteria);
+		iil_PutLine($fp, $query);
 		do {
 			$line=trim(iil_ReadLine($fp, 10000));
 			if (eregi("^\* SEARCH", $line)) {
@@ -2049,8 +2082,7 @@
 		    return $messages;
 		}
 		$conn->error = 'iil_C_Search: ' . $line . "\n";
-		return false;
-		
+		return false;	
 	}
 	$conn->error = "iil_C_Search: Couldn't select \"$folder\"\n";
 	return false;
@@ -2088,9 +2120,9 @@
 	$delimiter = false;
 	
 	//try (LIST "" ""), should return delimiter (RFC2060 Sec 6.3.8)
-	if (!fputs($fp, 'ghd LIST "" ""' . "\r\n")) {
+	if (!iil_PutLine($fp, 'ghd LIST "" ""')) {
 	    return false;
-    }
+	}
     
 	do {
 		$line=iil_ReadLine($fp, 500);
@@ -2099,7 +2131,7 @@
 			$a=iil_ExplodeQuotedString(' ', $line);
 			if ($a[0] == '*') {
 			    $delimiter = str_replace('"', '', $a[count($a)-2]);
-            }
+        		}
 		}
 	} while (!iil_StartsWith($line, 'ghd'));
 
@@ -2109,7 +2141,7 @@
     
 	//if that fails, try namespace extension
 	//try to fetch namespace data
-	fputs($conn->fp, "ns1 NAMESPACE\r\n");
+	iil_PutLine($conn->fp, "ns1 NAMESPACE");
 	do {
 		$line = iil_ReadLine($conn->fp, 1024);
 		if (iil_StartsWith($line, '* NAMESPACE')) {
@@ -2132,7 +2164,7 @@
 	$first_userspace = $user_space_data[0];
 	if (!is_array($first_userspace)) {
 	    return false;
-    }
+	}
     
 	//extract delimiter
 	$delimiter = $first_userspace[1];	
@@ -2156,7 +2188,7 @@
 	}
     
 	// send command
-	if (!fputs($fp, "lmb LIST \"".$ref."\" \"".iil_Escape($mailbox)."\"\r\n")) {
+	if (!iil_PutLine($fp, "lmb LIST \"".$ref."\" \"".iil_Escape($mailbox)."\"")) {
 	    return false;
 	}
     
@@ -2169,41 +2201,40 @@
 		$a = explode(' ', $line);
 		if (($line[0] == '*') && ($a[1] == 'LIST')) {
 			$line = rtrim($line);
-            // split one line
+        		// split one line
 			$a = iil_ExplodeQuotedString(' ', $line);
-            // last string is folder name
+        		// last string is folder name
 			$folder = trim($a[count($a)-1], '"');
             
-            if (empty($ignore) || (!empty($ignore)
-                && !eregi($ignore, $folder))) {
-                $folders[$i] = $folder;
-            }
+        		if (empty($ignore) || (!empty($ignore)
+            			&& !eregi($ignore, $folder))) {
+            			$folders[$i] = $folder;
+        		}
             
-            // second from last is delimiter
-            $delim = trim($a[count($a)-2], '"');
-            // is it a container?
-            $i++;
+		        // second from last is delimiter
+        		$delim = trim($a[count($a)-2], '"');
+        		// is it a container?
+        		$i++;
 		}
 	} while (!iil_StartsWith($line, 'lmb'));
 
 	if (is_array($folders)) {
     	    if (!empty($ref)) {
-            // if rootdir was specified, make sure it's the first element
-            // some IMAP servers (i.e. Courier) won't return it
-            if ($ref[strlen($ref)-1]==$delim)
+        	// if rootdir was specified, make sure it's the first element
+        	// some IMAP servers (i.e. Courier) won't return it
+        	if ($ref[strlen($ref)-1]==$delim)
 		    $ref = substr($ref, 0, strlen($ref)-1);
-    	    if ($folders[0]!=$ref)
+    		if ($folders[0]!=$ref)
 		    array_unshift($folders, $ref);
     	    }
     	    return $folders;
-	}else if (iil_ParseResult($line) == 0) {
+	} else if (iil_ParseResult($line) == 0) {
 		return array('INBOX');
 	} else {
 		$conn->error = $line;
 		return false;
 	}
 }
-
 
 function iil_C_ListSubscribed(&$conn, $ref, $mailbox) {
 	global $IGNORE_FOLDERS;
@@ -2219,15 +2250,15 @@
 	}
 	$folders = array();
 
-    // send command
-	if (!fputs($fp, 'lsb LSUB "' . $ref . '" "' . iil_Escape($mailbox).'"' . "\r\n")) {
+	// send command
+	if (!iil_PutLine($fp, 'lsb LSUB "' . $ref . '" "' . iil_Escape($mailbox).'"')) {
 		$conn->error = "Couldn't send LSUB command\n";
 		return false;
 	}
 	
 	$i = 0;
 	
-    // get folder list
+	// get folder list
 	do {
 		$line = iil_ReadLine($fp, 500);
 		$line = iil_MultLine($fp, $line);
@@ -2236,79 +2267,76 @@
 		if (($line[0] == '*') && ($a[1] == 'LSUB' || $a[1] == 'LIST')) {
 			$line = rtrim($line);
             
-            // split one line
+        		// 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], '"');
+        		// last string is folder name
+        		//$folder = UTF7DecodeString(str_replace('"', '', $a[count($a)-1]));
+        		$folder = trim($a[count($a)-1], '"');
             
 			if ((!in_array($folder, $folders)) && (empty($ignore)
-                || (!empty($ignore) && !eregi($ignore, $folder)))) {
+            			|| (!empty($ignore) && !eregi($ignore, $folder)))) {
 			    $folders[$i] = $folder;
-            }
+        		}
             
-            // second from last is delimiter
-            $delim = trim($a[count($a)-2], '"');
+        		// second from last is delimiter
+        		$delim = trim($a[count($a)-2], '"');
             
-            // is it a container?
-            $i++;
+        		// is it a container?
+        		$i++;
 		}
 	} while (!iil_StartsWith($line, 'lsb'));
 
 	if (is_array($folders)) {
-        if (!empty($ref)) {
-            // if rootdir was specified, make sure it's the first element
-            // some IMAP servers (i.e. Courier) won't return it
-            if ($ref[strlen($ref)-1]==$delim) {
-                $ref = substr($ref, 0, strlen($ref)-1);
-            }
-            if ($folders[0]!=$ref) {
-                array_unshift($folders, $ref);
-            }
-        }
-        return $folders;
+    	    if (!empty($ref)) {
+        	// if rootdir was specified, make sure it's the first element
+        	// some IMAP servers (i.e. Courier) won't return it
+        	if ($ref[strlen($ref)-1]==$delim) {
+            	    $ref = substr($ref, 0, strlen($ref)-1);
+        	}
+        	if ($folders[0]!=$ref) {
+            	    array_unshift($folders, $ref);
+        	}
+    	    }
+    	    return $folders;
 	}
 	$conn->error = $line;
 	return false;
 }
 
-
 function iil_C_Subscribe(&$conn, $folder) {
 	$fp = $conn->fp;
 
-	$query = 'sub1 SUBSCRIBE "' . iil_Escape($folder). '"' . "\r\n";
-	fputs($fp, $query);
+	$query = 'sub1 SUBSCRIBE "' . iil_Escape($folder). '"';
+	iil_PutLine($fp, $query);
 
 	$line = trim(iil_ReadLine($fp, 10000));
 	return iil_ParseResult($line);
 }
-
 
 function iil_C_UnSubscribe(&$conn, $folder) {
 	$fp = $conn->fp;
 
-	$query = 'usub1 UNSUBSCRIBE "' . iil_Escape($folder) . '"' . "\r\n";
-	fputs($fp, $query);
+	$query = 'usub1 UNSUBSCRIBE "' . iil_Escape($folder) . '"';
+	iil_PutLine($fp, $query);
     
 	$line = trim(iil_ReadLine($fp, 10000));
 	return iil_ParseResult($line);
 }
-
 
 function iil_C_FetchPartHeader(&$conn, $mailbox, $id, $part) {
 	$fp     = $conn->fp;
 	$result = false;
 	if (($part == 0) || (empty($part))) {
 	    $part = 'HEADER';
-    } else {
-        $part .= '.MIME';
+	} else {
+    	    $part .= '.MIME';
 	}
     
 	if (iil_C_Select($conn, $mailbox)) {
 		$key     = 'fh' . ($c++);
-		$request = $key . " FETCH $id (BODY.PEEK[$part])\r\n";
-		if (!fputs($fp, $request)) return false;
+		$request = $key . " FETCH $id (BODY.PEEK[$part])";
+		if (!iil_PutLine($fp, $request)) return false;
 		do {
 			$line = chop(iil_ReadLine($fp, 200));
 			$a    = explode(' ', $line);
@@ -2326,114 +2354,138 @@
 	return $result;
 }
 
-
-function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part, $mode) {
-    /* modes:
-        1: return string
+function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part, $mode, $file=NULL) {
+	/* modes:
+        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;
+    		$reply_key = '* ' . $id;
         
-        // format request
+    		// format request
 		$key     = 'ftch' . ($c++) . ' ';
-		$request = $key . "FETCH $id (BODY.PEEK[$part])\r\n";
-        // send request
-		if (!fputs($fp, $request)) {
+		$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');
-        $len = strlen($line);
-        if ($line[$len-1] == ')') {
-            //one line response, get everything between first and last quotes
-	    if (substr($line, -4, 3) == 'NIL') {
-		// NIL response
-		$result = '';
-	    } else {
-	        $from = strpos($line, '"') + 1;
-        	$to   = strrpos($line, '"');
-        	$len  = $to - $from;
-		$result = substr($line, $from, $len);
-	    }
+    		// receive reply line
+    		do {
+        		$line = chop(iil_ReadLine($fp, 1000));
+        		$a    = explode(' ', $line);
+    		} while ($a[2] != 'FETCH');
+    		$len = strlen($line);
+    
+    		if ($line[$len-1] == ')') {
+        		// one line response, get everything between first and last quotes
+			if (substr($line, -4, 3) == 'NIL') {
+				// NIL response
+				$result = '';
+			} else {
+			        $from = strpos($line, '"') + 1;
+        			$to   = strrpos($line, '"');
+		        	$len  = $to - $from;
+				$result = substr($line, $from, $len);
+			}
 	    
-            if ($mode == 2) {
-                echo $result;
-            } else if ($mode == 3) {
-                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;
-            $to       = strrpos($line, '}');
-            $len      = $to - $from;
-            $sizeStr  = substr($line, $from, $len);
-            $bytes    = (int)$sizeStr;
-            $received = 0;
-            while ($received < $bytes) {
-                $remaining = $bytes - $received;
-                $line      = iil_ReadLine($fp, 1024);
-                $len       = strlen($line);
+	                if ($mode == 2) {
+        		        echo $result;
+	                } else if ($mode == 3) {
+				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;
+	                $to       = strrpos($line, '}');
+        		$len      = $to - $from;
+	                $sizeStr  = substr($line, $from, $len);
+        		$bytes    = (int)$sizeStr;
+
+        		while ($bytes > 0) {
+    		                $line      = iil_ReadLine($fp, 1024);
+            			$len       = strlen($line);
                 
-                if ($len > $remaining) {
-                    $line = substr($line, 0, $remaining);
-                }
-                $received += strlen($line);
-                if ($mode == 1) {
-                    $result .= rtrim($line, "\t\r\n\0\x0B") . "\n";
-                } else if ($mode == 2) {
-                    echo rtrim($line, "\t\r\n\0\x0B") . "\n"; flush();
-                } else if ($mode == 3) {
-                    echo base64_decode($line); flush();
-                }
-            }
-        }
-        // read in anything up until 'til last line
+		                if ($len > $bytes) {
+            			        $line = substr($line, 0, $bytes);
+		                }
+            			$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) {
+					if ($file)
+						fwrite($file, base64_decode($line));
+            				else
+						echo base64_decode($line);
+				}
+        		}
+    		}
+	        // read in anything up until last line
 		do {
-            $line = iil_ReadLine($fp, 1024);
+        		$line = iil_ReadLine($fp, 1024);
 		} while (!iil_StartsWith($line, $key));
         
-        if ($result) {
-	    $result = rtrim($result, "\t\r\n\0\x0B");
-            return $result; // substr($result, 0, strlen($result)-1);
-        }
-        return false;
+		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);
+    		}
+    		
+		return false;
 	} else {
 		echo 'Select failed.';
 	}
     
-    if ($mode==1) {
-        return $result;
-    }
-    return $received;
+	if ($mode==1) {
+		if ($file) {
+			fwrite($file, $result);
+			return true;
+		}
+    		return $result;
+	}
+	
+	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) {
-    iil_C_HandlePartBody($conn, $mailbox, $id, $part, 2);
+	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, 3);
 }
 
 function iil_C_CreateFolder(&$conn, $folder) {
 	$fp = $conn->fp;
-	if (fputs($fp, 'c CREATE "' . iil_Escape($folder) . '"' . "\r\n")) {
+	if (iil_PutLine($fp, 'c CREATE "' . iil_Escape($folder) . '"')) {
 		do {
 			$line=iil_ReadLine($fp, 300);
 		} while ($line[0] != 'c');
@@ -2445,31 +2497,31 @@
 
 function iil_C_RenameFolder(&$conn, $from, $to) {
 	$fp = $conn->fp;
-	if (fputs($fp, 'r RENAME "' . iil_Escape($from) . '" "' . iil_Escape($to) . '"' . "\r\n")) {
+	if (iil_PutLine($fp, 'r RENAME "' . iil_Escape($from) . '" "' . iil_Escape($to) . '"')) {
 		do {
 			$line = iil_ReadLine($fp, 300);
 		} while ($line[0] != 'r');
 		return (iil_ParseResult($line) == 0);
 	}
-    return false;
+	return false;
 }
 
 function iil_C_DeleteFolder(&$conn, $folder) {
 	$fp = $conn->fp;
-	if (fputs($fp, 'd DELETE "' . iil_Escape($folder). '"' . "\r\n")) {
+	if (iil_PutLine($fp, 'd DELETE "' . iil_Escape($folder). '"')) {
 		do {
 			$line=iil_ReadLine($fp, 300);
 		} while ($line[0] != 'd');
 		return (iil_ParseResult($line) == 0);
 	}
-    $conn->error = "Couldn't send command\n";
+	$conn->error = "Couldn't send command\n";
 	return false;
 }
 
 function iil_C_Append(&$conn, $folder, &$message) {
 	if (!$folder) {
-        return false;
-    }
+    		return false;
+	}
 	$fp = $conn->fp;
 
 	$message = str_replace("\r", '', $message);
@@ -2477,11 +2529,12 @@
 
 	$len = strlen($message);
 	if (!$len) {
-        return false;
+    		return false;
 	}
-	$request = 'A APPEND "' . iil_Escape($folder) .'" (\\Seen) {' . $len . "}\r\n";
+
+	$request = 'A APPEND "' . iil_Escape($folder) .'" (\\Seen) {' . $len . '}';
     
-	if (fputs($fp, $request)) {
+	if (iil_PutLine($fp, $request)) {
 		$line=iil_ReadLine($fp, 100);		
 		$sent = fwrite($fp, $message."\r\n");
 		do {
@@ -2491,14 +2544,13 @@
 		$result = (iil_ParseResult($line) == 0);
 		if (!$result) {
 		    $conn->error .= $line . "\n";
-        }
+    		}
 		return $result;
-	
 	}
-	$conn->error .= "Couldn't send command \"$request\"\n";
-    return false;
-}
 
+	$conn->error .= "Couldn't send command \"$request\"\n";
+	return false;
+}
 
 function iil_C_AppendFromFile(&$conn, $folder, $path) {
 	if (!$folder) {
@@ -2508,8 +2560,8 @@
 	//open message file
 	$in_fp = false;				
 	if (file_exists(realpath($path))) {
-	    $in_fp = fopen($path, 'r');
-    }
+		$in_fp = fopen($path, 'r');
+	}
 	if (!$in_fp) { 
 		$conn->error .= "Couldn't open $path for reading\n";
 		return false;
@@ -2518,24 +2570,24 @@
 	$fp  = $conn->fp;
 	$len = filesize($path);
 	if (!$len) {
-	    return false;
+		return false;
 	}
     
 	//send APPEND command
-	$request    = 'A APPEND "' . iil_Escape($folder) . '" (\\Seen) {' . $len . "}\r\n";
+	$request    = 'A APPEND "' . iil_Escape($folder) . '" (\\Seen) {' . $len . '}';
 	$bytes_sent = 0;
-	if (fputs($fp, $request)) {
+	if (iil_PutLine($fp, $request)) {
 		$line = iil_ReadLine($fp, 100);
 				
 		//send file
 		while (!feof($in_fp)) {
 			$buffer      = fgets($in_fp, 4096);
 			$bytes_sent += strlen($buffer);
-			fputs($fp, $buffer);
+			iil_PutLine($fp, $buffer, false);
 		}
 		fclose($in_fp);
 
-		fputs($fp, "\r\n");
+		iil_PutLine($fp, '');
 
 		//read response
 		do {
@@ -2546,13 +2598,13 @@
 		if (!$result) {
 		    $conn->error .= $line . "\n";
 		}
-        return $result;
-	
+        
+		return $result;
 	}
+	
 	$conn->error .= "Couldn't send command \"$request\"\n";
 	return false;
 }
-
 
 function iil_C_FetchStructureString(&$conn, $folder, $id) {
 	$fp     = $conn->fp;
@@ -2560,15 +2612,17 @@
 	
 	if (iil_C_Select($conn, $folder)) {
 		$key = 'F1247';
-        
-		if (fputs($fp, "$key FETCH $id (BODYSTRUCTURE)\r\n")) {
+
+		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, ')')-1)));
+			$result = trim(substr($result, strpos($result, 'BODYSTRUCTURE')+13, -(strlen($result)-strrpos($result, $key)+1)));
 		}
 	}
 	return $result;
@@ -2593,12 +2647,12 @@
 	$quota_line = '';
 	
 	//get line containing quota info
-	if (fputs($fp, 'QUOT1 GETQUOTAROOT "INBOX"' . "\r\n")) {
+	if (iil_PutLine($fp, 'QUOT1 GETQUOTAROOT "INBOX"')) {
 		do {
 			$line=chop(iil_ReadLine($fp, 5000));
 			if (iil_StartsWith($line, '* QUOTA ')) {
-			    $quota_line = $line;
-            }
+				$quota_line = $line;
+        		}
 		} while (!iil_StartsWith($line, 'QUOT1'));
 	}
 	
@@ -2608,25 +2662,20 @@
 		$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'];
 		}
 	}
 	return $result;
 }
 
-
 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:' . $num_in_trash);
+	}
 	return (iil_C_Expunge($conn, $folder) >= 0);
 }
 

--
Gitblit v1.9.1