Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F9784233
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
70 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/CHANGELOG b/CHANGELOG
index 5cb09012e..51f9b8efa 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,312 +1,314 @@
CHANGELOG RoundCube Webmail
---------------------------
2006/07/19 (thomasb)
----------
- Correct entity encoding of link urls (HTML validity)
-- Moved back button in compose step (Ticket #)
+- Improved usability in compose step (Ticket #1483807)
- Added absolute URLs to several buttons (for "open in new window")
+- Applied patch #1328032
+- Fixed Bug/Patch #1443200
2006/07/18 (thomasb)
----------
- Fixed password with spaces issue (Bug #1364122)
- Replaced _auth hash with second cookie (Ticket #1483811)
- Don't use get_input_value() for passwords (Bug #1468895)
- Made password encryption key configurable
- Minor bugfixes with charset encoding
- Added <label> tags to forms (Ticket #1483810)
2006/07/07 (thomasb)
----------
- Fixed INSTALL_PATH bug #1425663
2006/07/03 (richs)
----------
- Fixed compatibility with in-body email addresses containing "+" (Bug #1483836)
- Updated French localizations (Ticket #1483862)
- Incoming messages can now be moved to Drafts, edited, saved, then moved back (Feature #1436191)
- Added Firefox workaround when clicking whitespace to drag messages (Bug #1483857)
- Corrected Dutch and Italian localizations (Ticket #1483851 and #1483848)
- Enabled 'Empty' (purge) command for Junk mailbox (defined in main.inc.php)
2006/06/30 (richs)
----------
- Fixed empty INBOX compatibility bug (Patch #1443200)
- Temporarily fixed French "compact" localization (Patch #1483862)
- Fixed "Select All" not working with Delete interface button (Bug #1332434)
- Fixed messsage list column compatibility with Konqueror (Bug #1395711)
- Fixed "unread count" in window title when count changed (Bug #1483812)
- Fixed DB error when deleting from message table (Patch #1483835)
2006/06/29 (richs)
----------
- Added ability to remove attachments (Feature #1436721)
- Default folders are now auto-created on first login (Feature #1471594)
- Fixed compatibility with folder apostrophes (e.g.: Joe's Folder) (Bug #1429458)
- Corrected Italian localizations
- Tweaked rename-folder form to clear after a rename
2006/06/26 (richs)
----------
- Added button to immediately check for new messages
- New message checking now displays status "Checking for new messages..."
- New message checking now looks for unread messages in all mailboxes (Feature #1326401)
- Task buttons now respond to clicks by darkening (as in other applications)
- Fixed "Sender" column changing to "Recipient" for "Sent" and "Drafts" message lists
- Added ability to sort messages by "Size"
- Added ability to rename folders (Feature #1326396)
- Added 'protect_default_folders' option to main.inc.php to prevent renames/deletes/unsubscribes of default folders
- Corrected 5 typos of "INSTLL" to "INSTALL" in program/include/main.inc
2006/06/25
----------
- Changed behavior to include host-specific configuration (Bug #1483849)
- Assume ISO-8859-1 encoding of mail messages by default (Patch #1483839)
- Fixed spell checker to work with the new URL at google.com
- Some memory and security optimizations sendmail.inc
- Updated UGRADING description
2006/06/19
----------
- Added Drafts support (Feature #1326839) (richs)
2006/06/02
----------
- Updated Estonian localization and moved from ee to et
- Added Bulgarian localization
2006/05/25
----------
- Finalized GoogieSpell integration
2006/05/18
----------
- Added Arabic and Armenian localizations
- Updated Russian localization
- Removed MDB2 classes from repository. Install them seperately if used.
- Updated MDB2 wrapper class contributed by Lukas Kahwe Smith
- Allow & in e-mail addresses
2006/05/05
----------
- Fixed typos in function rcube_button() (Bugs #1473198 and #1473201)
- Check for zlib.output_compression before using ob_gzhandler (Bug #1471069)
- Casting date parts in iil_StrToTime() to avoid warnings (Bug #1482140)
- Corrected INSTALL description (Bug #1476106)
- Added charset to javascript HTTP headers
- Fixed Opera bug with CC and BCC fields (Bug #1474576)
- Changed login page title regarding product name (Bug #1476413)
- Pimped search function
- Applied attachment viewing/forwarding patches by Andrew Fladmark
- Applied prev/next patch by Leonard Bouchet
- Applied patches by Mark Bucciarelli
- Applied patch for requesting receipts by Salvatore Ansani
- Integrated GoogieSpell as suggested by phil (styling is not perfect yet, localization is missing)
2006/04/13
----------
- Added Slovenian localization
- Updated Portuguese localization
- Fixed parent.location problem for compose-links
- Added sort order saving patch by Jacob Brunson
- Added gzip compression support
2006/04/02
----------
- Added Lithuanian localization
- Improved search function
- Added version string as template object
- Load host-specific configuration file (see config/main.inc.php)
- New config parameter adding domain to user names for login
- Strip tags on _auth, _action, _task parameters
- Corrected labels for next/previous page buttons in address book
2006/03/23
----------
- Auto-detect mail header delimiters
- Regard daylight savings
- Localized quota display
- Started implementing search function
2006/03/20
----------
- Avoid error message when saving an unchanged identity (Bug #1429510)
- Fixed hard-coded cols selection for sent folder (Bug #1354586)
- Enable some HTML links for use with "open in new window" or "save target"
- Check meta-key instead of ctrl on Macs
- Ignore double clicks when holding down a modifier key
- Fixed reloading of the login page
- Fixed typo in compose template (Bug #1446852)
- Added compose button to message read step (Request #1433288)
- New config parameter for persistent database connections (Bug #1431817)
2006/03/14
----------
- Don't remove internal HTML tags in plaintext messages
- Improved error handling in DB connection failure
2006/02/22
----------
- Updated localizations
- Fixed bug #1435989
2006/02/19
----------
- Updated localizations
- Applied patch of Anders Karlsson
- Applied patch of Jacob Brunson
- Applied patch for virtuser_query by Robin Elfrink
- Added support for References header (patch by Auke)
- Added support for mbstring module by Tadashi Jokagi
- Added function for automatic remove of slashes on GET and POST vars
if magic_quotes is enabled
2006/02/05
----------
- Added Slovak, Hungarian, Bosnian and Croation translation
- Fixed bug when inserting signatures with !?&
- Chopping message headers before inserting into the message cache table
(to avoid bugs in Postgres)
- Allow one-char domains in e-mail addresses
- Make product name in page title configurable
- Make username available as skin object
- Added session_write_close() in rcube_db class destructor to avoid problems
in PHP 5.0.5
- Use move_uploaded_file() instead of copy() for a more secure handling of
uploaded attachments
- Additional config parameter to show/hide deleted messages
- Added periodic request for checking new mails (Request #1307821)
- Added EXPUNGE command
- Optimized loading time for mail interface
- Changed to full UTF-8 support
- Additional timezones (Patch #1389912)
- Added LDAP public search (experimental)
- Applied patch for correct ctrl/shift behavior for message selection (Bug #1326364)
- Casting to strings when adding empty headers to message cache (Bug #1406026)
- Skip sender-address as recipient when Reply-to-all
- Fixes in utf8-class
- Added patch for Quota display by Aury Fink Filho <nuny@aury.com.br>
- Added garbage collector for message cache
- Added patches for BCC headers
2005/12/16
----------
- Added Turkish and Simplified Chinese translation
- Use virtusertable to resolve e-mail addresses at login
- Configurable mail_domain used to compose correct e-mail addresses
on first login
2005/12/03
----------
- Added Finnish, Romanian, Polish, Czech, British, Norwegian, Greek, Russian,
Estonian and Chinese translation
- Get IMAP server capabilities in array
- Check for NAMESPACE capability before sending command
- Set default user language from config 'locale_string'
- Added sorting patch for message list
- Make default sort col/order configurable
- Fixed XSS in address book and identities
- Added more XSS protection (Bug #1308236)
- Added tab indexes for compose form
- Added 'changed' col to contacts table
- Support for 160-bit session hashes
- Added input check for contacts and identities (Patch #1346523)
- Added messages/warning to compose step (Patch #1323895)
- Added favicon to the default skin
- Fixed Bug #1334337 as far as possible
- Added Reply-To-All functionality (Request #1326395, Patch #1349777)
- Redesign of client side AJAX code (enable multi threading)
- Added keep-alive signal every minute
- Make logs dir configurable
- Added support for SMTPS
- Decode attachment file names
- Make delimiter for message headers configurable
- Add generic footer to sent messages
- Choose the rigt identity when replying
- Remove signature when replying (Request #1333167)
- Signatures for each identity
- Select charset when composing message
- Complete re-design of the caching mechanism
2005/08/11
----------
- Write list header to client even if list is empty
- Add functions "select all", "select none" to message list
- Improved filter for HTML messages to remove potentially malicious tags
(script, iframe, object) and event handlers.
- Buttons for next/previous message in view mode
- Add new created contact to list and show confirmation status
- Added folder management (subscribe/create/delete)
- Log message sending (SMTP log)
- Grant access for Camino browser
- Added German translation
2005/10/20
----------
- Added Swedish, Latvian, Portuguese and Catalan translation
- Make SMTP auth method configurable
- Make mailboxlist scrollable (Bug #1326372)
- Fixed SSL support
- Improved support for Courier IMAP (root folder and delimiter issues)
- Moved taskbar from bottom to top
- Added 'session_lifetime' parameter
- Fixed wrong unread count when deleting message (Bug #1332434)
- Srip tags when creating a new folder (Bug #1332084)
- Translate HTML tags in message headers (Bug #1330134)
- Correction in German translation (Bug #1329434)
- Display folder names with special chars correctly (Bug #1330157)
2005/10/07
----------
- Added French, Italian, Spanish, Danish, Dutch translation
- Clarified license (Bug #1305966)
- Fixed PHP warnings (Bug #1299403)
- Fixed english translation (Bug #1295406)
- Fixed bug #1290833: Last character of email not seen
- Fixed bug #1292199 when creating new user
- Allow more browsers (Bug #1285101)
- Added setting for showing pretty dates
- Added support for SQLite database
- Make use of message caching configurable
- Also add attachments when forwarding a message
- Long folder names will not flow over message list (Bug #1267232)
- Show nested mailboxes hieracically
- Enable IMAPS by host
2005/08/20
----------
- Improved cacheing of mailbox messagecount
- Fixed javascript bug when creating a new message folder
- Fixed javascript bugs #1260990 and #1260992: folder selection
- Make Trash folder configurable
- Auto create folders Inbox, Sent and Trash (if configured)
- Support for IMAP root folder
- Added support fot text/enriched messages
- Make list of special mailboxes configurable
diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index 70abdc40e..5251f8414 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -1,2110 +1,2111 @@
<?php
/////////////////////////////////////////////////////////
//
// Iloha IMAP Library (IIL)
//
// (C)Copyright 2002 Ryo Chijiiwa <Ryo@IlohaMail.org>
//
// This file is part of IlohaMail. IlohaMail is free software released
// under the GPL license. See enclosed file COPYING for details, or
// see http://www.fsf.org/copyleft/gpl.html
//
/////////////////////////////////////////////////////////
/********************************************************
FILE: include/imap.inc
PURPOSE:
Provide alternative IMAP library that doesn't rely on the standard
C-Client based version. This allows IlohaMail to function regardless
of whether or not the PHP build it's running on has IMAP functionality
built-in.
USEAGE:
Function containing "_C_" in name require connection handler to be
passed as one of the parameters. To obtain connection handler, use
iil_Connect()
VERSION:
IlohaMail-0.9-20050415
CHANGES:
File altered by Thomas Bruederli <roundcube@gmail.com>
to fit enhanced equirements by the RoundCube Webmail:
- Added list of server capabilites and check these before invoking commands
- Added junk flag to iilBasicHeader
- Enhanced error reporting on fsockopen()
- Additional parameter for SORT command
- Removed Call-time pass-by-reference because deprecated
- Parse charset from content-type in iil_C_FetchHeaders()
- Enhanced heaer sorting
- Pass message as reference in iil_C_Append (to save memory)
- Added BCC and REFERENCE to the list of headers to fetch in iil_C_FetchHeaders()
- Leave messageID unchanged in iil_C_FetchHeaders()
- Avoid stripslahes in iil_Connect()
- Added patch to iil_SortHeaders() by Richard Green
- Removed <br> from error messages (better for logging)
- Added patch to iil_C_Sort() enabling UID SORT commands
- Added function iil_C_ID2UID()
- Casting date parts in iil_StrToTime() to avoid mktime() warnings
+ - Also acceppt LIST responses in iil_C_ListSubscribed()
- Removed some debuggers (echo ...)
********************************************************/
// changed path to work within roundcube webmail
include_once("lib/icl_commons.inc");
if (!$IMAP_USE_HEADER_DATE) $IMAP_USE_INTERNAL_DATE = true;
$IMAP_MONTHS=array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12);
$IMAP_SERVER_TZ = date('Z');
$iil_error;
$iil_errornum;
$iil_selected;
class iilConnection{
var $fp;
var $error;
var $errorNum;
var $selected;
var $message;
var $host;
var $cache;
var $uid_cache;
var $do_cache;
var $exists;
var $recent;
var $rootdir;
var $delimiter;
var $capability = array();
}
class iilBasicHeader{
var $id;
var $uid;
var $subject;
var $from;
var $to;
var $cc;
var $replyto;
var $in_reply_to;
var $date;
var $messageID;
var $size;
var $encoding;
var $ctype;
var $flags;
var $timestamp;
var $f;
var $seen;
var $deleted;
var $recent;
var $answered;
var $junk;
var $internaldate;
var $is_reply;
}
class iilThreadHeader{
var $id;
var $sbj;
var $irt;
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;
}
function iil_ReadLine($fp, $size){
$line="";
if ($fp){
do{
$buffer = fgets($fp, 2048);
$line.=$buffer;
}while($buffer[strlen($buffer)-1]!="\n");
}
return $line;
}
function iil_MultLine($fp, $line){
$line = chop($line);
if (ereg('\{[0-9]+\}$', $line)){
$out = "";
preg_match_all('/(.*)\{([0-9]+)\}$/', $line, $a);
$bytes = $a[2][0];
while(strlen($out)<$bytes){
$out.=chop(iil_ReadLine($fp, 1024));
}
$line = $a[1][0]."\"$out\"";
}
return $line;
}
function iil_ReadBytes($fp, $bytes){
$data = "";
$len = 0;
do{
$data.=fread($fp, $bytes-$len);
$len = strlen($data);
}while($len<$bytes);
return $data;
}
function iil_ReadReply($fp){
do{
$line = chop(trim(iil_ReadLine($fp, 1024)));
}while($line[0]=="*");
return $line;
}
function iil_ParseResult($string){
$a=explode(" ", $string);
if (count($a) > 2){
if (strcasecmp($a[1], "OK")==0) return 0;
else if (strcasecmp($a[1], "NO")==0) return -1;
else if (strcasecmp($a[1], "BAD")==0) return -2;
}else return -3;
}
// check if $string starts with $match
function iil_StartsWith($string, $match){
$len = strlen($match);
if ($len==0) return false;
if (strncmp($string, $match, $len)==0) return true;
else return false;
}
function iil_StartsWithI($string, $match){
$len = strlen($match);
if ($len==0) return false;
if (strncasecmp($string, $match, $len)==0) return true;
else return false;
}
function iil_C_Authenticate(&$conn, $user, $pass, $encChallenge){
// initialize ipad, opad
for ($i=0;$i<64;$i++){
$ipad.=chr(0x36);
$opad.=chr(0x5C);
}
// pad $pass so it's 64 bytes
$padLen = 64 - strlen($pass);
for ($i=0;$i<$padLen;$i++) $pass .= chr(0);
// generate hash
$hash = md5(iil_xor($pass,$opad).pack("H*",md5(iil_xor($pass, $ipad).base64_decode($encChallenge))));
// generate reply
$reply = base64_encode($user." ".$hash);
// send result, get reply
fputs($conn->fp, $reply."\r\n");
$line = iil_ReadLine($conn->fp, 1024);
// process result
if (iil_ParseResult($line)==0){
$conn->error .= "";
$conn->errorNum = 0;
return $conn->fp;
}else{
$conn->error .= 'Authentication for '.$user.' failed (AUTH): "'.htmlspecialchars($line)."\"";
$conn->errorNum = -2;
return false;
}
}
function iil_C_Login(&$conn, $user, $password){
fputs($conn->fp, "a001 LOGIN $user \"$password\"\r\n");
do{
$line = iil_ReadReply($conn->fp);
}while(!iil_StartsWith($line, "a001 "));
$a=explode(" ", $line);
if (strcmp($a[1],"OK")==0){
$result=$conn->fp;
$conn->error.="";
$conn->errorNum = 0;
}else{
$result=false;
fclose($conn->fp);
$conn->error .= 'Authentication for '.$user.' failed (LOGIN): "'.htmlspecialchars($line)."\"";
$conn->errorNum = -2;
}
return $result;
}
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;
for($i;$i<$len;$i++){
$c = (string)$str[$i];
if ($c=='(' && !$in_quotes){
$i++;
$data[$elem] = iil_ParseNamespace2($str, $i, $len, $l++);
$elem++;
}else if ($c==')' && !$in_quotes) return $data;
else if ($c=="\\"){
$i++;
if ($in_quotes) $data[$elem].=$c.$str[$i];
}else if ($c=='"'){
$in_quotes = !$in_quotes;
if (!$in_quotes) $elem++;
}else if ($in_quotes){
$data[$elem].=$c;
}
}
return $data;
}
function iil_C_NameSpace(&$conn){
global $my_prefs;
if (!in_array('NAMESPACE', $conn->capability))
return false;
if ($my_prefs["rootdir"]) return true;
fputs($conn->fp, "ns1 NAMESPACE\r\n");
do{
$line = iil_ReadLine($conn->fp, 1024);
if (iil_StartsWith($line, "* NAMESPACE")){
$i = 0;
$data = iil_ParseNamespace2(substr($line,11), $i, 0, 0);
}
}while(!iil_StartsWith($line, "ns1"));
if (!is_array($data)) return false;
$user_space_data = $data[0];
if (!is_array($user_space_data)) return false;
$first_userspace = $user_space_data[0];
if (count($first_userspace)!=2) return false;
$conn->rootdir = $first_userspace[0];
$conn->delimiter = $first_userspace[1];
$my_prefs["rootdir"] = substr($conn->rootdir, 0, -1);
return true;
}
function iil_Connect($host, $user, $password){
global $iil_error, $iil_errornum;
global $ICL_SSL, $ICL_PORT;
global $IMAP_NO_CACHE;
global $my_prefs, $IMAP_USE_INTERNAL_DATE;
$iil_error = "";
$iil_errornum = 0;
//strip slashes
// $user = stripslashes($user);
// $password = stripslashes($password);
//set auth method
$auth_method = "plain";
if (func_num_args() >= 4){
$auth_array = func_get_arg(3);
if (is_array($auth_array)) $auth_method = $auth_array["imap"];
if (empty($auth_method)) $auth_method = "plain";
}
$message = "INITIAL: $auth_method\n";
$result = false;
//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;
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";
if (empty($user)) $iil_error .= "Invalid user\n";
if (empty($password)) $iil_error .= "Invalid password\n";
if (!empty($iil_error)) return false;
if (!$ICL_PORT) $ICL_PORT = 143;
//check for SSL
if ($ICL_SSL){
$host = "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";
$iil_errornum = -1;
return false;
}
$iil_error.="Socket connection established\r\n";
$line=iil_ReadLine($conn->fp, 300);
if (strcasecmp($auth_method, "check")==0){
//check for supported auth methods
//default to plain text auth
$auth_method = "plain";
//check for CRAM-MD5
fputs($conn->fp, "cp01 CAPABILITY\r\n");
do{
$line = trim(chop(iil_ReadLine($conn->fp, 100)));
$conn->message.="$line\n";
$a = explode(" ", $line);
if ($line[0]=="*"){
while ( list($k, $w) = each($a) ){
if ($w!='*' && $w!='CAPABILITY')
$conn->capability[] = $w;
if ((strcasecmp($w, "AUTH=CRAM_MD5")==0)||
(strcasecmp($w, "AUTH=CRAM-MD5")==0)){
$auth_method = "auth";
}
}
}
}while($a[0]!="cp01");
}
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");
$line = trim(chop(iil_ReadLine($conn->fp, 1024)));
$conn->message.="$line\n";
if ($line[0]=="+"){
$conn->message.='Got challenge: '.htmlspecialchars($line)."\n";
//got a challenge string, try CRAM-5
$result = iil_C_Authenticate($conn, $user, $password, substr($line,2));
$conn->message.= "Tried CRAM-MD5: $result \n";
}else{
$conn->message.='No challenge ('.htmlspecialchars($line)."), try plain\n";
$auth = "plain";
}
}
if ((!$result)||(strcasecmp($auth, "plain")==0)){
//do plain text auth
$result = iil_C_Login($conn, $user, $password);
$conn->message.="Tried PLAIN: $result \n";
}
$conn->message .= $auth;
if ($result){
iil_C_Namespace($conn);
return $conn;
}else{
$iil_error = $conn->error;
$iil_errornum = $conn->errorNum;
return false;
}
}
function iil_Close(&$conn){
iil_C_WriteCache($conn);
if (@fputs($conn->fp, "I LOGOUT\r\n")){
fgets($conn->fp, 1024);
fclose($conn->fp);
$conn->fp = false;
}
}
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]);
$string=implode("\"", $quotes);
$result=explode($delimiter, $string);
while ( list($key, $val) = each($result) )
$result[$key] = str_replace("_!@!_", $delimiter, $result[$key]);
return $result;
}
function iil_CheckForRecent($host, $user, $password, $mailbox){
if (empty($mailbox)) $mailbox="INBOX";
$conn=iil_Connect($host, $user, $password, "plain");
$fp = $conn->fp;
if ($fp){
fputs($fp, "a002 EXAMINE \"$mailbox\"\r\n");
do{
$line=chop(iil_ReadLine($fp, 300));
$a=explode(" ", $line);
if (($a[0]=="*") && (strcasecmp($a[2], "RECENT")==0)) $result=(int)$a[1];
}while (!iil_StartsWith($a[0],"a002"));
fputs($fp, "a003 LOGOUT\r\n");
fclose($fp);
}else $result=-2;
return $result;
}
function iil_C_Select(&$conn, $mailbox){
$fp = $conn->fp;
if (empty($mailbox)) return false;
if (strcmp($conn->selected, $mailbox)==0) return true;
iil_C_LoadCache($conn, $mailbox);
if (fputs($fp, "sel1 SELECT \"$mailbox\"\r\n")){
do{
$line=chop(iil_ReadLine($fp, 300));
$a=explode(" ", $line);
if (count($a) == 3){
if (strcasecmp($a[2], "EXISTS")==0) $conn->exists=(int)$a[1];
if (strcasecmp($a[2], "RECENT")==0) $conn->recent=(int)$a[1];
}
}while (!iil_StartsWith($line, "sel1"));
$a=explode(" ", $line);
if (strcasecmp($a[1],"OK")==0){
$conn->selected = $mailbox;
return true;
}else return false;
}else{
return false;
}
}
function iil_C_CheckForRecent(&$conn, $mailbox){
if (empty($mailbox)) $mailbox="INBOX";
iil_C_Select($conn, $mailbox);
if ($conn->selected==$mailbox) return $conn->recent;
else 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;
else return false;
}
function iil_SplitHeaderLine($string){
$pos=strpos($string, ":");
if ($pos>0){
$res[0]=substr($string, 0, $pos);
$res[1]=trim(substr($string, $pos+1));
return $res;
}else{
return $string;
}
}
function iil_StrToTime($str){
global $IMAP_MONTHS,$IMAP_SERVER_TZ;
if ($str) $time1 = strtotime($str);
if ($time1 && $time1!=-1) return $time1-$IMAP_SERVER_TZ;
//echo '<!--'.$str.'//-->';
//replace double spaces with single space
$str = trim($str);
$str = str_replace(" ", " ", $str);
//strip off day of week
$pos=strpos($str, " ");
if (!is_numeric(substr($str, 0, $pos))) $str = substr($str, $pos+1);
//explode, take good parts
$a=explode(" ",$str);
//$month_a=array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12);
$month_str=$a[1];
$month=$IMAP_MONTHS[$month_str];
$day=(int)$a[0];
$year=(int)$a[2];
$time=$a[3];
$tz_str = $a[4];
$tz = substr($tz_str, 0, 3);
$ta = explode(":",$time);
$hour=(int)$ta[0]-(int)$tz;
$minute=(int)$ta[1];
$second=(int)$ta[2];
//make UNIX timestamp
$time2 = mktime($hour, $minute, $second, $month, $day, $year);
//echo '<!--'.$time1.' '.$time2.' //-->'."\n";
return $time2;
}
function iil_C_Sort(&$conn, $mailbox, $field, $add='', $is_uid=FALSE, $encoding='US-ASCII'){
/* Do "SELECT" command */
if (!iil_C_Select($conn, $mailbox)) return false;
$field = strtoupper($field);
if ($field=='INTERNALDATE') $field='ARRIVAL';
$fields = array('ARRIVAL'=>1,'CC'=>1,'DATE'=>1,'FROM'=>1,'SIZE'=>1,'SUBJECT'=>1,'TO'=>1);
if (!$fields[$field])
return false;
$is_uid = $is_uid ? 'UID ' : '';
if (!empty($add))
$add = " $add";
$fp = $conn->fp;
$command = 's '. $is_uid .'SORT ('.$field.') '.$encoding.' ALL'."$add\r\n";
$line = $data = '';
if (!fputs($fp, $command)) return false;
do{
$line = chop(iil_ReadLine($fp, 1024));
if (iil_StartsWith($line, '* SORT')) $data.=($data?' ':'').substr($line,7);
}while($line[0]!='s');
if (empty($data)){
$conn->error = $line;
return false;
}
$out = explode(' ',$data);
return $out;
}
function iil_C_FetchHeaderIndex(&$conn, $mailbox, $message_set, $index_field, $normalize=true){
global $IMAP_USE_INTERNAL_DATE;
$c=0;
$result=array();
$fp = $conn->fp;
if (empty($index_field)) $index_field="DATE";
$index_field = strtoupper($index_field);
if ((empty($message_set)) || ($message_set == "1:0")) return array();
//$fields_a["DATE"] = ($IMAP_USE_INTERNAL_DATE?6:1);
$fields_a['DATE'] = 1;
$fields_a['INTERNALDATE'] = 6;
$fields_a['FROM'] = 1;
$fields_a['REPLY-TO'] = 1;
$fields_a['SENDER'] = 1;
$fields_a['TO'] = 1;
$fields_a['SUBJECT'] = 1;
$fields_a['UID'] = 2;
$fields_a['SIZE'] = 2;
$fields_a['SEEN'] = 3;
$fields_a['RECENT'] = 4;
$fields_a['DELETED'] = 5;
$mode=$fields_a[$index_field];
if (!($mode > 0)) return false;
/* 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)) return false;
do{
$line=chop(iil_ReadLine($fp, 200));
$a=explode(" ", $line);
if (($line[0]=="*") && ($a[2]=="FETCH") && ($line[strlen($line)-1]!=")")){
$id=$a[1];
$str=$line=chop(iil_ReadLine($fp, 300));
while($line[0]!=")"){ //caution, this line works only in this particular case
$line=chop(iil_ReadLine($fp, 300));
if ($line[0]!=")"){
if (ord($line[0]) <= 32){ //continuation from previous header line
$str.=" ".trim($line);
}
if ((ord($line[0]) > 32) || (strlen($line[0]) == 0)){
list($field, $string) = iil_SplitHeaderLine($str);
if (strcasecmp($field, "date")==0){
$result[$id]=iil_StrToTime($string);
}else{
$result[$id] = str_replace("\"", "", $string);
if ($normalize) $result[$id]=strtoupper($result[$id]);
}
$str=$line;
}
}
}
}
/*
$end_pos = strlen($line)-1;
if (($line[0]=="*") && ($a[2]=="FETCH") && ($line[$end_pos]=="}")){
$id = $a[1];
$pos = strrpos($line, "{")+1;
$bytes = (int)substr($line, $pos, $end_pos-$pos);
$received = 0;
do{
$line = iil_ReadLine($fp, 0);
$received+=strlen($line);
$line = chop($line);
if ($received>$bytes) break;
else if (!$line) continue;
list($field,$string)=explode(": ", $line);
if (strcasecmp($field, "date")==0)
$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
}
*/
}while(!iil_StartsWith($line, $key));
}else if ($mode==6){
$key="fhi".($c++);
$request = $key." FETCH $message_set (INTERNALDATE)\r\n";
if (!fputs($fp, $request)) return false;
do{
$line=chop(iil_ReadLine($fp, 200));
if ($line[0]=="*"){
//original: "* 10 FETCH (INTERNALDATE "31-Jul-2002 09:18:02 -0500")"
$paren_pos = strpos($line, "(");
$foo = substr($line, 0, $paren_pos);
$a = explode(" ", $foo);
$id = $a[1];
$open_pos = strpos($line, "\"") + 1;
$close_pos = strrpos($line, "\"");
if ($open_pos && $close_pos){
$len = $close_pos - $open_pos;
$time_str = substr($line, $open_pos, $len);
$result[$id] = strtotime($time_str);
}
}else{
$a = explode(" ", $line);
}
}while(!iil_StartsWith($a[0], $key));
}else{
if ($mode >= 3) $field_name="FLAGS";
else if ($index_field=="SIZE") $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";
if (!fputs($fp, $request)) return false;
do{
$line=chop(iil_ReadLine($fp, 200));
$a = explode(" ", $line);
if (($line[0]=="*") && ($a[2]=="FETCH")){
$line=str_replace("(", "", $line);
$line=str_replace(")", "", $line);
$a=explode(" ", $line);
$id=$a[1];
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
/* Caution, bad assumptions, next several lines */
if ($mode==2) $result[$id]=$a[4];
else{
$haystack=strtoupper($line);
$result[$id]=(strpos($haystack, $index_field) > 0 ? "F" : "N");
}
}
}while(!iil_StartsWith($line, $key));
}
//check number of elements...
list($start_mid,$end_mid)=explode(':',$message_set);
if (is_numeric($start_mid) && is_numeric($end_mid)){
//count how many we should have
$should_have = $end_mid - $start_mid +1;
//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] = '';
}
}
return $result;
}
function iil_CompressMessageSet($message_set){
//given a comma delimited list of independent mid's,
//compresses by grouping sequences together
//if less than 255 bytes long, let's not bother
if (strlen($message_set)<255) return $message_set;
//see if it's already been compress
if (strpos($message_set,':')!==false) return $message_set;
//separate, then sort
$ids = explode(',',$message_set);
sort($ids);
$result = array();
$start = $prev = $ids[0];
foreach($ids as $id){
$incr = $id - $prev;
if ($incr>1){ //found a gap
if ($start==$prev) $result[] = $prev; //push single id
else $result[] = $start.':'.$prev; //push sequence as start_id:end_id
$start = $id; //start of new sequence
}
$prev = $id;
}
//handle the last sequence/id
if ($start==$prev) $result[] = $prev;
else $result[] = $start.':'.$prev;
//return as comma separated string
return implode(',',$result);
}
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));
}
function iil_C_UIDToMID(&$conn, $mailbox, $uid){
$result = iil_C_UIDsToMIDs($conn, $mailbox, array($uid));
if (count($result)==1) return $result[0];
else return false;
}
function iil_C_FetchUIDs(&$conn,$mailbox){
global $clock;
$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
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'];
}
function iil_SortThreadHeaders($headers, $index_a, $uids){
asort($index_a);
$result = array();
foreach($index_a as $mid=>$foobar){
$uid = $uids[$mid];
$result[$uid] = $headers[$uid];
}
return $result;
}
function iil_C_FetchThreadHeaders(&$conn, $mailbox, $message_set){
global $clock;
global $index_a;
if (empty($message_set)) return false;
$result = array();
$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){
/* FETCH date,from,subject headers */
$key="fh";
$fp = $conn->fp;
$request=$key." FETCH $message_set (BODY.PEEK[HEADER.FIELDS (SUBJECT MESSAGE-ID IN-REPLY-TO)])\r\n";
$mid_to_id = array();
if (!fputs($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();
$new_thhd = new iilThreadHeader;
$new_thhd->id = $a[1];
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:'))){
$pos = strpos($line, ":");
$field_name = substr($line, 0, $pos);
$field_val = substr($line, $pos+1);
$new[strtoupper($field_name)] = trim($field_val);
}else if (ereg('^[[:space:]]', $line)){
$new[strtoupper($field_name)].= trim($line);
}
}while($line[0]!=')');
$new_thhd->sbj = $new['SUBJECT'];
$new_thhd->mid = substr($new['MESSAGE-ID'], 1, -1);
$new_thhd->irt = substr($new['IN-REPLY-TO'], 1, -1);
$result[$uids[$new_thhd->id]] = $new_thhd;
}
}while(!iil_StartsWith($line, "fh"));
}
/* 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";
//print_r($result);
return $result;
}
function iil_C_BuildThreads2(&$conn, $mailbox, $message_set, &$clock){
global $index_a;
if (empty($message_set)) return false;
$result=array();
$roots=array();
$root_mids = array();
$sub_mids = array();
$strays = array();
$messages = array();
$fp = $conn->fp;
$debug = false;
$sbj_filter_pat = '[a-zA-Z]{2,3}(\[[0-9]*\])?:([[:space:]]*)';
/* Do "SELECT" command */
if (!iil_C_Select($conn, $mailbox)) return false;
/* FETCH date,from,subject headers */
$mid_to_id = array();
$messages = array();
$headers = iil_C_FetchThreadHeaders($conn, $mailbox, $message_set);
if ($clock) $clock->register('fetched headers');
if ($debug) print_r($headers);
/* go through header records */
foreach($headers as $header){
//$id = $header['i'];
//$new = array('id'=>$id, 'MESSAGE-ID'=>$header['m'],
// '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);
/* add to message-id -> mid lookup table */
$mid_to_id[$new['MESSAGE-ID']] = $id;
/* if no subject, use message-id */
if (empty($new['SUBJECT'])) $new['SUBJECT'] = $new['MESSAGE-ID'];
/* if subject contains 'RE:' or has in-reply-to header, it's a reply */
$sbj_pre ='';
$has_re = false;
if (eregi($sbj_filter_pat, $new['SUBJECT'])) $has_re = true;
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']);
else $sbj = $new['SUBJECT'];
$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];
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;
$result[$root_id][] = $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']){
if ($debug) echo "\tlooking: ".$new['IN-REPLY-TO']."\n";
//reply to known message?
$temp = $sub_mids[$new['IN-REPLY-TO']];
if ($temp){
//found it, root:=parent's root
if ($debug) echo "\tfound parent: ".$new['SUBJECT']."\n";
$result[$temp][] = $id;
$sub_mids[$new['MESSAGE-ID']] = $temp;
$sbj = '';
}else{
//if we can't find referenced parent, it's a "stray"
$strays[$id] = $new['IN-REPLY-TO'];
}
}
//add subject as root
if ($sbj){
if ($debug) echo "\t added to root\n";
$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,
//go back and try and link up the stray threads
if (count($strays)>0){
foreach($strays as $id=>$irt){
$root_id = $sub_mids[$irt];
if (!$root_id || $root_id==$id) continue;
$result[$root_id] = array_merge($result[$root_id],$result[$id]);
unset($result[$id]);
}
}
if ($clock) $clock->register('data prepped');
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;
foreach($index as $id=>$val){
$i++;
$index[$id] = $i;
}
$max = $i+1;
//for each tree, set array key to position
$itree = array();
foreach($tree as $id=>$node){
if (count($tree[$id])<=1){
//for "threads" with only one message, key is position of that message
$n = $index[$id];
$itree[$n] = array($n=>$id);
}else{
//for "threads" with multiple messages,
$min = $max;
$new_a = array();
foreach($tree[$id] as $mid){
$new_a[$index[$mid]] = $mid; //create new sub-array mapping position to id
$pos = $index[$mid];
if ($pos&&$pos<$min) $min = $index[$mid]; //find smallest position
}
$n = $min; //smallest position of child is thread position
//assign smallest position to root level key
//set children array to one created above
ksort($new_a);
$itree[$n] = $new_a;
}
}
//sort by key, this basically sorts all threads
ksort($itree);
$i=0;
$out=array();
foreach($itree as $k=>$node){
$out[$i] = $itree[$k];
$i++;
}
//return
return $out;
}
function iil_IndexThreads(&$tree){
/* creates array mapping mid to thread id */
if (!is_array($tree)) return false;
$t_index = array();
foreach($tree as $pos=>$kids){
foreach($kids as $kid) $t_index[$kid] = $pos;
}
return $t_index;
}
function iil_C_FetchHeaders(&$conn, $mailbox, $message_set){
global $IMAP_USE_INTERNAL_DATE;
$c=0;
$result=array();
$fp = $conn->fp;
if (empty($message_set)) return array();
/* Do "SELECT" command */
if (!iil_C_Select($conn, $mailbox)){
$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;
}
}
/* FETCH date,from,subject headers */
$key="fh".($c++);
$request=$key." FETCH $message_set (BODY.PEEK[HEADER.FIELDS (DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC CONTENT-TRANSFER-ENCODING CONTENT-TYPE MESSAGE-ID REFERENCE)])\r\n";
if (!fputs($fp, $request)) return false;
do{
$line=chop(iil_ReadLine($fp, 200));
$a=explode(" ", $line);
if (($line[0]=="*") && ($a[2]=="FETCH")){
$id=$a[1];
$result[$id]=new iilBasicHeader;
$result[$id]->id = $id;
$result[$id]->subject = "";
/*
Start parsing headers. The problem is, some header "lines" take up multiple lines.
So, we'll read ahead, and if the one we're reading now is a valid header, we'll
process the previous line. Otherwise, we'll keep adding the strings until we come
to the next valid header line.
*/
$i = 0;
$lines = array();
do{
$line = chop(iil_ReadLine($fp, 300),"\r\n");
if (ord($line[0])<=32) $lines[$i].=(empty($lines[$i])?"":"\n").trim(chop($line));
else{
$i++;
$lines[$i] = trim(chop($line));
}
}while($line[0]!=")" && strncmp($line, $key, strlen($key))); // patch from "Maksim Rubis" <siburny@hotmail.com>
if(strncmp($line, $key, strlen($key)))
{
//process header, fill iilBasicHeader obj.
// initialize
if (is_array($headers)){
reset($headers);
while ( list($k, $bar) = each($headers) ) $headers[$k] = "";
}
// create array with header field:data
$headers = array();
while ( list($lines_key, $str) = each($lines) ){
list($field, $string) = iil_SplitHeaderLine($str);
$field = strtolower($field);
$headers[$field] = $string;
}
$result[$id]->date = $headers["date"];
$result[$id]->timestamp = iil_StrToTime($headers["date"]);
$result[$id]->from = $headers["from"];
$result[$id]->to = str_replace("\n", " ", $headers["to"]);
$result[$id]->subject = str_replace("\n", "", $headers["subject"]);
$result[$id]->replyto = str_replace("\n", " ", $headers["reply-to"]);
$result[$id]->cc = str_replace("\n", " ", $headers["cc"]);
$result[$id]->bcc = str_replace("\n", " ", $headers["bcc"]);
$result[$id]->encoding = str_replace("\n", " ", $headers["content-transfer-encoding"]);
$result[$id]->ctype = str_replace("\n", " ", $headers["content-type"]);
$result[$id]->in_reply_to = ereg_replace("[\n<>]",'', $headers['in-reply-to']);
$result[$id]->reference = $headers["reference"];
list($result[$id]->ctype, $ctype_add) = explode(";", $headers["content-type"]);
if (preg_match('/charset="?([a-z0-9\-]+)"?/i', $ctype_add, $regs))
$result[$id]->charset = $regs[1];
$messageID = $headers["message-id"];
if (!$messageID) "mid:".$id;
$result[$id]->messageID = $messageID;
}
else {
$a=explode(" ", $line);
}
}
}while(strcmp($a[0], $key)!=0);
/*
FETCH uid, size, flags
Sample reply line: "* 3 FETCH (UID 2417 RFC822.SIZE 2730 FLAGS (\Seen \Deleted))"
*/
$command_key="fh".($c++);
$request= $command_key." FETCH $message_set (UID RFC822.SIZE FLAGS INTERNALDATE)\r\n";
if (!fputs($fp, $request)) return false;
do{
$line=chop(iil_ReadLine($fp, 200));
//$a = explode(" ", $line);
//if (($line[0]=="*") && ($a[2]=="FETCH")){
if ($line[0]=="*"){
//echo "<!-- $line //-->\n";
//get outter most parens
$open_pos = strpos($line, "(") + 1;
$close_pos = strrpos($line, ")");
if ($open_pos && $close_pos){
//extract ID from pre-paren
$pre_str = substr($line, 0, $open_pos);
$pre_a = explode(" ", $line);
$id = $pre_a[1];
//get data
$len = $close_pos - $open_pos;
$str = substr($line, $open_pos, $len);
//swap parents with quotes, then explode
$str = eregi_replace("[()]", "\"", $str);
$a = iil_ExplodeQuotedString(" ", $str);
//did we get the right number of replies?
$parts_count = count($a);
if ($parts_count>=8){
for ($i=0;$i<$parts_count;$i=$i+2){
if (strcasecmp($a[$i],"UID")==0) $result[$id]->uid=$a[$i+1];
else if (strcasecmp($a[$i],"RFC822.SIZE")==0) $result[$id]->size=$a[$i+1];
else if (strcasecmp($a[$i],"INTERNALDATE")==0) $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);
//echo "<!-- ID: $id FLAGS: ".implode(",", $flags_a)." //-->\n";
$result[$id]->seen = false;
$result[$id]->recent = false;
$result[$id]->deleted = false;
$result[$id]->answered = false;
if (is_array($flags_a)){
reset($flags_a);
while (list($key,$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;
}
$result[$id]->flags=$flags_str;
}
// if time is gmt...
$time_str = str_replace('GMT','+0000',$time_str);
//get timezone
$time_str = substr($time_str, 0, -1);
$time_zone_str = substr($time_str, -5); //extract timezone
$time_str = substr($time_str, 1, -6); //remove quotes
$time_zone = (float)substr($time_zone_str, 1, 2); //get first two digits
if ($time_zone_str[3]!='0') $time_zone += 0.5; //handle half hour offset
if ($time_zone_str[0]=="-") $time_zone = $time_zone * -1.0; //minus?
$result[$id]->internaldate = $time_str;
if ($IMAP_USE_INTERNAL_DATE){
//calculate timestamp
$timestamp = strtotime($time_str); //return's server's time
$na_timestamp = $timestamp;
$timestamp -= $time_zone * 3600; //compensate for tz, get GMT
$result[$id]->timestamp = $timestamp;
}
if ($conn->do_cache){
$uid = $result[$id]->uid;
$conn->cache[$mailbox][$uid] = $result[$id];
$conn->cache_dirty[$mailbox] = true;
}
//echo "<!-- ID: $id : $time_str -- local: $na_timestamp (".date("F j, Y, g:i a", $na_timestamp).") tz: $time_zone -- GMT: ".$timestamp." (".date("F j, Y, g:i a", $timestamp).") //-->\n";
}else{
//echo "<!-- ERROR: $id : $str //-->\n";
}
}
}
}while(strpos($line, $command_key)===false);
return $result;
}
function iil_C_FetchHeader(&$conn, $mailbox, $id){
$fp = $conn->fp;
$a=iil_C_FetchHeaders($conn, $mailbox, $id);
if (is_array($a)) return $a[$id];
else 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("\"");
$c=count($a);
if ($c>0){
/*
Strategy:
First, we'll create an "index" array.
Then, we'll use sort() on that array,
and use that to sort the main array.
*/
// create "index" array
$index=array();
reset($a);
while (list($key, $val)=each($a)){
if ($field=="timestamp"){
$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;
}
// sort index
$i=0;
if ($flag=="ASC") asort($index);
else arsort($index);
// form new array based on index
$result=array();
reset($index);
while (list($key, $val)=each($index)){
$result[$key]=$a[$key];
$i++;
}
}
return $result;
}
function iil_C_Expunge(&$conn, $mailbox){
$fp = $conn->fp;
if (iil_C_Select($conn, $mailbox)){
$c=0;
fputs($fp, "exp1 EXPUNGE\r\n");
do{
$line=chop(iil_ReadLine($fp, 100));
if ($line[0]=="*") $c++;
}while (!iil_StartsWith($line, "exp1"));
if (iil_ParseResult($line) == 0){
$conn->selected = ""; //state has changed, need to reselect
//$conn->exists-=$c;
return $c;
}else{
$conn->error = $line;
return -1;
}
}
return -1;
}
function iil_C_ModFlag(&$conn, $mailbox, $messages, $flag, $mod){
if ($mod!="+" && $mod!="-") return -1;
$fp = $conn->fp;
$flags=array(
"SEEN"=>"\\Seen",
"DELETED"=>"\\Deleted",
"RECENT"=>"\\Recent",
"ANSWERED"=>"\\Answered",
"DRAFT"=>"\\Draft",
"FLAGGED"=>"\\Flagged"
);
$flag=strtoupper($flag);
$flag=$flags[$flag];
if (iil_C_Select($conn, $mailbox)){
$c=0;
fputs($fp, "flg STORE $messages ".$mod."FLAGS (".$flag.")\r\n");
do{
$line=chop(iil_ReadLine($fp, 100));
if ($line[0]=="*") $c++;
}while (!iil_StartsWith($line, "flg"));
if (iil_ParseResult($line) == 0){
iil_C_ExpireCachedItems($conn, $mailbox, $messages);
return $c;
}else{
$conn->error = $line;
return -1;
}
}else{
$conn->error = "Select failed";
return -1;
}
}
function iil_C_Flag(&$conn, $mailbox, $messages, $flag){
return iil_C_ModFlag($conn, $mailbox, $messages, $flag, "+");
}
function iil_C_Unflag(&$conn, $mailbox, $messages, $flag){
return iil_C_ModFlag($conn, $mailbox, $messages, $flag, "-");
}
function iil_C_Delete(&$conn, $mailbox, $messages){
return iil_C_ModFlag($conn, $mailbox, $messages, "DELETED", "+");
}
function iil_C_Undelete(&$conn, $mailbox, $messages){
return iil_C_ModFlag($conn, $mailbox, $messages, "DELETED", "-");
}
function iil_C_Unseen(&$conn, $mailbox, $messages){
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 \"$to\"\r\n");
$line=iil_ReadReply($fp);
return iil_ParseResult($line);
}else{
return -1;
}
}
function iil_FormatSearchDate($month, $day, $year){
$month = (int)$month;
$months=array(
1=>"Jan", 2=>"Feb", 3=>"Mar", 4=>"Apr",
5=>"May", 6=>"Jun", 7=>"Jul", 8=>"Aug",
9=>"Sep", 10=>"Oct", 11=>"Nov", 12=>"Dec"
);
return $day."-".$months[$month]."-".$year;
}
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;
else return count($index);
}else return false;
}
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;
else return $id_a[0];
}
}
return false;
}
function iil_C_ID2UID(&$conn, $folder, $id){
$fp = $conn->fp;
$result=-1;
if ($id > 0) {
if (iil_C_Select($conn, $folder)){
$key = "FUID";
if (fputs($fp, "$key FETCH $id (UID)\r\n")){
do{
$line=chop(iil_ReadLine($fp, 1024));
if (eregi("^\* $id FETCH \(UID (.*)\)", $line, $r)){
$result = $r[1];
}
} while (!preg_match("/^$key/", $line));
}
}
}
return $result;
}
function iil_C_Search(&$conn, $folder, $criteria){
$fp = $conn->fp;
if (iil_C_Select($conn, $folder)){
$c=0;
$query = "srch1 SEARCH ".chop($criteria)."\r\n";
fputs($fp, $query);
do{
$line=trim(chop(iil_ReadLine($fp, 10000)));
if (eregi("^\* SEARCH", $line)){
$str = trim(substr($line, 8));
$messages = explode(" ", $str);
}
}while(!iil_StartsWith($line, "srch1"));
$result_code=iil_ParseResult($line);
if ($result_code==0) return $messages;
else{
$conn->error = "iil_C_Search: ".$line."\n";
return false;
}
}else{
$conn->error = "iil_C_Search: Couldn't select \"$folder\"\n";
return false;
}
}
function iil_C_Move(&$conn, $messages, $from, $to){
$fp = $conn->fp;
if (!$from || !$to) return -1;
$r=iil_C_Copy($conn, $messages, $from,$to);
if ($r==0){
return iil_C_Delete($conn, $from, $messages);
}else{
return $r;
}
}
function iil_C_GetHierarchyDelimiter(&$conn){
if ($conn->delimiter) return $conn->delimiter;
$fp = $conn->fp;
$delimiter = false;
//try (LIST "" ""), should return delimiter (RFC2060 Sec 6.3.8)
if (!fputs($fp, "ghd LIST \"\" \"\"\r\n")) return false;
do{
$line=iil_ReadLine($fp, 500);
if ($line[0]=="*"){
$line = rtrim($line);
$a=iil_ExplodeQuotedString(" ", $line);
if ($a[0]=="*") $delimiter = str_replace("\"", "", $a[count($a)-2]);
}
}while (!iil_StartsWith($line, "ghd"));
if (strlen($delimiter)>0) return $delimiter;
//if that fails, try namespace extension
//try to fetch namespace data
fputs($conn->fp, "ns1 NAMESPACE\r\n");
do{
$line = iil_ReadLine($conn->fp, 1024);
if (iil_StartsWith($line, "* NAMESPACE")){
$i = 0;
$data = iil_ParseNamespace2(substr($line,11), $i, 0, 0);
}
}while(!iil_StartsWith($line, "ns1"));
if (!is_array($data)) return false;
//extract user space data (opposed to global/shared space)
$user_space_data = $data[0];
if (!is_array($user_space_data)) return false;
//get first element
$first_userspace = $user_space_data[0];
if (!is_array($first_userspace)) return false;
//extract delimiter
$delimiter = $first_userspace[1];
return $delimiter;
}
function iil_C_ListMailboxes(&$conn, $ref, $mailbox){
global $IGNORE_FOLDERS;
$ignore = $IGNORE_FOLDERS[strtolower($conn->host)];
$fp = $conn->fp;
if (empty($mailbox)) $mailbox="*";
if (empty($ref) && $conn->rootdir) $ref = $conn->rootdir;
// send command
if (!fputs($fp, "lmb LIST \"".$ref."\" \"$mailbox\"\r\n")) return false;
$i=0;
// get folder list
do{
$line=iil_ReadLine($fp, 500);
$line=iil_MultLine($fp, $line);
$a = explode(" ", $line);
if (($line[0]=="*") && ($a[1]=="LIST")){
$line = rtrim($line);
// split one line
$a=iil_ExplodeQuotedString(" ", $line);
// last string is folder name
$folder = str_replace("\"", "", $a[count($a)-1]);
if (empty($ignore) || (!empty($ignore) && !eregi($ignore, $folder))) $folders[$i] = $folder;
// second from last is delimiter
$delim = str_replace("\"", "", $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) $ref = substr($ref, 0, strlen($ref)-1);
if ($folders[0]!=$ref) array_unshift($folders, $ref);
}
return $folders;
}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;
$ignore = $IGNORE_FOLDERS[strtolower($conn->host)];
$fp = $conn->fp;
if (empty($mailbox)) $mailbox = "*";
if (empty($ref) && $conn->rootdir) $ref = $conn->rootdir;
$folders = array();
// send command
if (!fputs($fp, "lsb LSUB \"".$ref."\" \"".$mailbox."\"\r\n")){
$conn->error = "Couldn't send LSUB command\n";
return false;
}
$i=0;
// get folder list
do{
$line=iil_ReadLine($fp, 500);
$line=iil_MultLine($fp, $line);
$a = explode(" ", $line);
if (($line[0]=="*") && ($a[1]=="LSUB" || $a[1]=="LIST")){
$line = rtrim($line);
// split one line
$a=iil_ExplodeQuotedString(" ", $line);
// last string is folder name
//$folder = UTF7DecodeString(str_replace("\"", "", $a[count($a)-1]));
$folder = str_replace("\"", "", $a[count($a)-1]);
if ((!in_array($folder, $folders)) && (empty($ignore) || (!empty($ignore) && !eregi($ignore, $folder)))) $folders[$i] = $folder;
// second from last is delimiter
$delim = str_replace("\"", "", $a[count($a)-2]);
// 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;
}else{
$conn->error = $line;
return false;
}
}
function iil_C_Subscribe(&$conn, $folder){
$fp = $conn->fp;
$query = "sub1 SUBSCRIBE \"".$folder."\"\r\n";
fputs($fp, $query);
$line=trim(chop(iil_ReadLine($fp, 10000)));
return iil_ParseResult($line);
}
function iil_C_UnSubscribe(&$conn, $folder){
$fp = $conn->fp;
$query = "usub1 UNSUBSCRIBE \"".$folder."\"\r\n";
fputs($fp, $query);
$line=trim(chop(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";
if (iil_C_Select($conn, $mailbox)){
$key="fh".($c++);
$request=$key." FETCH $id (BODY.PEEK[$part])\r\n";
if (!fputs($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=iil_ReadLine($fp, 300);
while(chop($line)!=")"){
$result.=$line;
$line=iil_ReadLine($fp, 300);
}
}
}while(strcmp($a[0], $key)!=0);
}
return $result;
}
function iil_C_HandlePartBody(&$conn, $mailbox, $id, $part, $mode){
/* modes:
1: return string
2: print
3: base64 and print
*/
$fp = $conn->fp;
$result=false;
if (($part==0)||(empty($part))) $part="TEXT";
if (iil_C_Select($conn, $mailbox)){
$reply_key="* ".$id;
// format request
$key="ftch".($c++)." ";
$request=$key."FETCH $id (BODY.PEEK[$part])\r\n";
// send request
if (!fputs($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
$from = strpos($line, "\"") + 1;
$to = strrpos($line, "\"");
$len = $to - $from;
if ($mode==1) $result = substr($line, $from, $len);
else if ($mode==2) echo substr($line, $from, $len);
else if ($mode==3) echo base64_decode(substr($line, $from, $len));
}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 ($len > $remaining) substr($line, 0, $remaining);
$received += strlen($line);
if ($mode==1) $result .= chop($line)."\n";
else if ($mode==2){ echo chop($line)."\n"; flush(); }
else if ($mode==3){ echo base64_decode($line); flush(); }
}
}
// read in anything up until 'til last line
do{
$line = iil_ReadLine($fp, 1024);
}while(!iil_StartsWith($line, $key));
if ($result){
$result = chop($result);
return $result; // substr($result, 0, strlen($result)-1);
}else return false;
}else{
echo "Select failed.";
}
if ($mode==1) return $result;
else return $received;
}
function iil_C_FetchPartBody(&$conn, $mailbox, $id, $part){
return iil_C_HandlePartBody($conn, $mailbox, $id, $part, 1);
}
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);
}
function iil_C_CreateFolder(&$conn, $folder){
$fp = $conn->fp;
if (fputs($fp, "c CREATE \"".$folder."\"\r\n")){
do{
$line=iil_ReadLine($fp, 300);
}while($line[0]!="c");
$conn->error = $line;
return (iil_ParseResult($line)==0);
}else{
return false;
}
}
function iil_C_RenameFolder(&$conn, $from, $to){
$fp = $conn->fp;
if (fputs($fp, "r RENAME \"".$from."\" \"".$to."\"\r\n")){
do{
$line=iil_ReadLine($fp, 300);
}while($line[0]!="r");
return (iil_ParseResult($line)==0);
}else{
return false;
}
}
function iil_C_DeleteFolder(&$conn, $folder){
$fp = $conn->fp;
if (fputs($fp, "d DELETE \"".$folder."\"\r\n")){
do{
$line=iil_ReadLine($fp, 300);
}while($line[0]!="d");
return (iil_ParseResult($line)==0);
}else{
$conn->error = "Couldn't send command\n";
return false;
}
}
function iil_C_Append(&$conn, $folder, &$message){
if (!$folder) return false;
$fp = $conn->fp;
$message = str_replace("\r", "", $message);
$message = str_replace("\n", "\r\n", $message);
$len = strlen($message);
if (!$len) return false;
$request="A APPEND \"".$folder."\" (\\Seen) {".$len."}\r\n";
if (fputs($fp, $request)){
$line=iil_ReadLine($fp, 100);
$sent = fwrite($fp, $message."\r\n");
flush();
do{
$line=iil_ReadLine($fp, 1000);
}while($line[0]!="A");
$result = (iil_ParseResult($line)==0);
if (!$result) $conn->error .= $line."\n";
return $result;
}else{
$conn->error .= "Couldn't send command \"$request\"\n";
return false;
}
}
function iil_C_AppendFromFile(&$conn, $folder, $path){
if (!$folder) return false;
//open message file
$in_fp = false;
if (file_exists(realpath($path))) $in_fp = fopen($path, "r");
if (!$in_fp){
$conn->error .= "Couldn't open $path for reading\n";
return false;
}
$fp = $conn->fp;
$len = filesize($path);
if (!$len) return false;
//send APPEND command
$request="A APPEND \"".$folder."\" (\\Seen) {".$len."}\r\n";
$bytes_sent = 0;
if (fputs($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);
}
fclose($in_fp);
fputs($fp, "\r\n");
//read response
do{
$line=iil_ReadLine($fp, 1000);
}while($line[0]!="A");
$result = (iil_ParseResult($line)==0);
if (!$result) $conn->error .= $line."\n";
return $result;
}else{
$conn->error .= "Couldn't send command \"$request\"\n";
return false;
}
}
function iil_C_FetchStructureString(&$conn, $folder, $id){
$fp = $conn->fp;
$result=false;
if (iil_C_Select($conn, $folder)){
$key = "F1247";
if (fputs($fp, "$key FETCH $id (BODYSTRUCTURE)\r\n")){
do{
$line=chop(iil_ReadLine($fp, 5000));
if ($line[0]=="*"){
if (ereg("\}$", $line)){
preg_match('/(.+)\{([0-9]+)\}/', $line, $match);
$result = $match[1];
do{
$line = chop(iil_ReadLine($fp, 100));
if (!preg_match("/^$key/", $line)) $result .= $line;
else $done = true;
}while(!$done);
}else{
$result = $line;
}
list($pre, $post) = explode("BODYSTRUCTURE ", $result);
$result = substr($post, 0, strlen($post)-1); //truncate last ')' and return
}
}while (!preg_match("/^$key/",$line));
}
}
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){
/*
b GETQUOTAROOT "INBOX"
* QUOTAROOT INBOX user/rchijiiwa1
* QUOTA user/rchijiiwa1 (STORAGE 654 9765)
b OK Completed
*/
$fp = $conn->fp;
$result=false;
$quota_line = "";
//get line containing quota info
if (fputs($fp, "QUOT1 GETQUOTAROOT \"INBOX\"\r\n")){
do{
$line=chop(iil_ReadLine($fp, 5000));
if (iil_StartsWith($line, "* QUOTA ")) $quota_line = $line;
}while(!iil_StartsWith($line, "QUOT1"));
}
//return false if not found, parse if found
if (!empty($quota_line)){
$quota_line = eregi_replace("[()]", "", $quota_line);
$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["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);
return (iil_C_Expunge($conn, $folder) >= 0);
}
?>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Aug 17, 11:12 AM (17 m, 43 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1261303
Default Alt Text
(70 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment