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 | 257 +++++++++++++++++++++++++++++--------------------- 1 files changed, 149 insertions(+), 108 deletions(-) diff --git a/program/lib/imap.inc b/program/lib/imap.inc index 877e8a2..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,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; } /** @@ -279,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 = ''; @@ -297,12 +349,10 @@ } // 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 iil_PutLine($conn->fp, $reply); @@ -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) { @@ -544,9 +576,9 @@ //do CRAM-MD5 authentication 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"; @@ -556,7 +588,7 @@ $conn->message .= "Tried CRAM-MD5: $result \n"; } else { $conn->message .='No challenge ('.htmlspecialchars($line)."), try plain\n"; - $auth = 'plain'; + $auth = 'plain'; } } @@ -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; @@ -1743,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); @@ -1760,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; } @@ -1910,14 +1946,7 @@ } $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]; @@ -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,16 +2606,17 @@ 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)-2))); + $result = trim(substr($result, strpos($result, 'BODYSTRUCTURE')+13, -(strlen($result)-strrpos($result, $key)+1))); } } return $result; @@ -2611,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