6 * Copyright (c) 1999-2003 The SquirrelMail Project Team
7 * Licensed under the GNU GPL. For full terms see the file COPYING.
9 * This implements all functions that do general imap functions.
14 require_once(SM_PATH
. 'functions/page_header.php');
15 require_once(SM_PATH
. 'functions/auth.php');
18 global $sqimap_session_id;
19 $sqimap_session_id = 1;
21 /* Sets an unique session id in order to avoid simultanous sessions crash. */
22 function sqimap_session_id($unique_id = false) {
23 global $data_dir, $username, $sqimap_session_id;
25 return( sprintf("A%03d", $sqimap_session_id++
) );
27 return( sprintf("A%03d", $sqimap_session_id++
) . ' UID' );
32 * Both send a command and accept the result from the command.
33 * This is to allow proper session number handling.
35 function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
37 $sid = sqimap_session_id($unique_id);
38 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
39 $tag_uid_a = explode(' ',trim($sid));
41 $read = sqimap_read_data_list ($imap_stream, $tag, $handle_errors, $response, $message, $query );
42 /* get the response and the message */
43 $message = $message[$tag];
44 $response = $response[$tag];
47 global $squirrelmail_language, $color;
48 set_up_language($squirrelmail_language);
49 require_once(SM_PATH
. 'functions/display_messages.php');
50 $string = "<b><font color=$color[2]>\n" .
51 _("ERROR : No available imapstream.") .
53 error_box($string,$color);
58 function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response,
59 &$message, $unique_id = false,$filter=false,
60 $outputstream=false,$no_return=false) {
62 $sid = sqimap_session_id($unique_id);
63 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
64 $tag_uid_a = explode(' ',trim($sid));
67 $read = sqimap_read_data ($imap_stream, $tag, $handle_errors, $response,
68 $message, $query,$filter,$outputstream,$no_return);
69 /* retrieve the response and the message */
70 $response = $response[$tag];
71 $message = $message[$tag];
73 if (!empty($read[$tag])) {
74 return $read[$tag][0];
79 global $squirrelmail_language, $color;
80 set_up_language($squirrelmail_language);
81 require_once(SM_PATH
. 'functions/display_messages.php');
82 $string = "<b><font color=$color[2]>\n" .
83 _("ERROR : No available imapstream.") .
85 error_box($string,$color);
89 function sqimap_prepare_pipelined_query($new_query,&$tag,&$aQuery,$unique_id) {
90 $sid = sqimap_session_id($unique_id);
91 $tag_uid_a = explode(' ',trim($sid));
93 $query = $sid . ' '.$new_query."\n";
94 $aQuery[$tag] = $query;
97 function sqimap_run_pipelined_command ($imap_stream, $aQuery, $handle_errors,
98 &$aServerResponse, &$aServerMessage, $unique_id = false,
99 $filter=false,$outputstream=false,$no_return=false) {
101 foreach($aQuery as $tag => $query) {
102 fputs($imap_stream,$query);
103 $aResults[$tag] = false;
106 foreach($aQuery as $tag => $query) {
107 if (!$aResults[$tag]) {
108 $aReturnedResponse = sqimap_read_data_list ($imap_stream, $tag,
109 $handle_errors, $response, $message, $query,
110 $filter,$outputstream,$no_return);
111 foreach ($aReturnedResponse as $returned_tag => $aResponse) {
112 $aResults[$returned_tag] = $aResponse;
113 $aServerResponse[$returned_tag] = $response[$returned_tag];
114 $aServerMessage[$returned_tag] = $message[$returned_tag];
121 * custom fgets function. gets a line from IMAP
122 * no matter how big it may be
125 function sqimap_fgets($imap_stream) {
130 while (strpos($results, "\r\n", $offset) === false) {
131 if (!($read = fgets($imap_stream, $buffer))) {
132 /* this happens in case of an error */
133 /* reset $results because it's useless */
137 if ( $results != '' ) {
138 $offset = strlen($results) - 1;
145 function sqimap_fread($imap_stream,$iSize,$filter=false,
146 $outputstream=false, $no_return=false) {
147 if (!$filter ||
!$outputstream) {
148 $iBufferSize = $iSize;
150 $iBufferSize = 62400; // multiple of 78 in case of base64 decoding.
152 $iRet = $iSize - $iBufferSize;
155 $results = $sReadRem = '';
156 $bFinished = $bBufferSizeAdapted = $bBufferIsOk = false;
157 while (($iRetrieved < ($iSize - $iBufferSize))) {
158 $sRead = fread($imap_stream,$iBufferSize);
163 $iRetrieved +
= $iBufferSize;
165 // in case line-endings do not appear at position 78 we adapt the buffersize so we can base64 decode on the fly
166 if (!$bBufferSizeAdapted) {
167 $i = strpos($sRead,"\n");
170 $iFragments = floor($iBufferSize / $i);
171 $iNewBufferSize = $iFragments * $i;
172 $iRemainder = $iNewBufferSize +
$i - $iBufferSize;
173 if ($iNewBufferSize == $iBufferSize) {
176 $iNewBufferSize = $iBufferSize;
177 $bBufferSizeAdapted = true;
179 if (!$bBufferIsOk && ($iRemainder +
$iBufferSize) < $iSize) {
180 $sReadRem = fread($imap_stream,$iRemainder);
181 } else if (!$bBufferIsOk) {
182 $sReadRem = fread($imap_stream,$iSize - $iBufferSize);
185 if (!$sReadRem && $sReadRem !== '') {
189 $iBufferSize = $iNewBufferSize;
190 $bBufferSizeAdapted = true;
192 $sReadRem = fread($imap_stream,$iSize - $iBufferSize);
200 $iRetrieved +
= $iRemainder;
206 if (is_resource($outputstream)) {
207 fwrite($outputstream,$sRead);
208 } else if ($outputstream == 'php://stdout') {
217 if (!$results && !$bFinished) {
218 $sRead = fread($imap_stream,($iSize - ($iRetrieved)));
223 if (is_resource($outputstream)) {
224 fwrite($outputstream,$sRead);
225 } else if ($outputstream == 'php://stdout') { // FIXME
240 * Reads the output from the IMAP stream. If handle_errors is set to true,
241 * this will also handle all errors that are received. If it is not set,
242 * the errors will be sent back through $response and $message
245 function sqimap_read_data_list ($imap_stream, $tag, $handle_errors,
246 &$response, &$message, $query = '',
247 $filter = false, $outputstream = false, $no_return = false) {
248 global $color, $squirrelmail_language;
250 if (!is_array($message)) $message = array();
251 if (!is_array($response)) $response = array();
252 $resultlist = array();
254 $read = sqimap_fgets($imap_stream);
262 $read = sqimap_fgets($imap_stream);
267 /* get the command */
270 $s = substr($read,$i);
271 if (($j = strpos($s,' ')) ||
($j = strpos($s,"\n"))) {
272 $arg = substr($s,0,$j);
274 $found_tag = substr($read,0,$i-1);
275 if ($arg && $found_tag==$tag) {
283 $response[$found_tag] = $arg;
284 $message[$found_tag] = trim(substr($read,$i+
strlen($arg)));
286 $resultlist[] = $data;
288 $aResponse[$tag] = $resultlist;
289 break 3; /* switch switch while */
291 /* this shouldn't happen */
292 $response[$found_tag] = $arg;
293 $message[$found_tag] = trim(substr($read,$i+
strlen($arg)));
295 $resultlist[] = $data;
297 $aResponse[$found_tag] = $resultlist;
298 break 3; /* switch switch while */
300 } elseif($found_tag !== $tag) {
301 /* not the tag we are looking for, continue */
303 $resultlist[] = $data;
305 $aResponse[$found_tag] = $resultlist;
306 $resultlist = $data = array();
307 $read = sqimap_fgets($imap_stream);
308 if ($read === false) { /* error */
309 break 3; /* switch switch while */
313 } // end case $tag{0}
317 if (preg_match('/^\*\s\d+\sFETCH/',$read)) {
318 /* check for literal */
319 $s = substr($read,-3);
320 $fetch_data = array();
321 do { /* outer loop, continue until next untagged fetch
323 do { /* innerloop for fetching literals. with this loop
324 we prohibid that literal responses appear in the
325 outer loop so we can trust the untagged and
326 tagged info provided by $read */
327 if ($s === "}\r\n") {
328 $j = strrpos($read,'{');
329 $iLit = substr($read,$j+
1,-3);
330 $fetch_data[] = $read;
331 $sLiteral = sqimap_fread($imap_stream,$iLit,$filter,$outputstream,$no_return);
332 if ($sLiteral === false) { /* error */
333 break 4; /* while while switch while */
335 /* backwards compattibility */
336 $aLiteral = explode("\n", $sLiteral);
337 /* release not neaded data */
339 foreach ($aLiteral as $line) {
340 $fetch_data[] = $line ."\n";
342 /* release not neaded data */
344 /* next fgets belongs to this fetch because
345 we just got the exact literalsize and there
346 must follow data to complete the response */
347 $read = sqimap_fgets($imap_stream);
348 if ($read === false) { /* error */
349 break 4; /* while while switch while */
351 $fetch_data[] = $read;
353 $fetch_data[] = $read;
355 /* retrieve next line and check in the while
356 statements if it belongs to this fetch response */
357 $read = sqimap_fgets($imap_stream);
358 if ($read === false) { /* error */
359 break 4; /* while while switch while */
361 /* check for next untagged reponse and break */
362 if ($read{0} == '*') break 2;
363 $s = substr($read,-3);
364 } while ($s === "}\r\n");
365 $s = substr($read,-3);
366 } while ($read{0} !== '*' &&
367 substr($read,0,strlen($tag)) !== $tag);
368 $resultlist[] = $fetch_data;
369 /* release not neaded data */
372 $s = substr($read,-3);
374 if ($s === "}\r\n") {
375 $j = strrpos($read,'{');
376 $iLit = substr($read,$j+
1,-3);
378 $sLiteral = fread($imap_stream,$iLit);
379 if ($sLiteral === false) { /* error */
381 break 3; /* while switch while */
384 $fetch_data[] = sqimap_fgets($imap_stream);
388 $read = sqimap_fgets($imap_stream);
389 if ($read === false) {
390 break 3; /* while switch while */
391 } else if ($read{0} == '*') {
394 $s = substr($read,-3);
395 } while ($s === "}\r\n");
403 /* error processing in case $read is false */
404 if ($read === false) {
406 set_up_language($squirrelmail_language);
407 require_once(SM_PATH
. 'functions/display_messages.php');
408 $string = "<b><font color=$color[2]>\n" .
409 _("ERROR : Connection dropped by imap-server.") .
412 htmlspecialchars($query) . '<br>' . "</font><br>\n";
413 error_box($string,$color);
417 /* Set $resultlist array */
419 //$resultlist[] = $data;
421 elseif (empty($resultlist)) {
422 $resultlist[] = array();
425 /* Return result or handle errors */
426 if ($handle_errors == false) {
428 return( $resultlist );
430 switch ($response[$tag])
436 /* ignore this error from M$ exchange, it is not fatal (aka bug) */
437 if (strstr($message[$tag], 'command resulted in') === false) {
438 set_up_language($squirrelmail_language);
439 require_once(SM_PATH
. 'functions/display_messages.php');
440 $string = "<b><font color=$color[2]>\n" .
441 _("ERROR : Could not complete request.") .
444 htmlspecialchars($query) . '<br>' .
445 _("Reason Given: ") .
446 htmlspecialchars($message[$tag]) . "</font><br>\n";
447 error_box($string,$color);
448 echo '</body></html>';
453 set_up_language($squirrelmail_language);
454 require_once(SM_PATH
. 'functions/display_messages.php');
455 $string = "<b><font color=$color[2]>\n" .
456 _("ERROR : Bad or malformed request.") .
459 htmlspecialchars($query) . '<br>' .
460 _("Server responded: ") .
461 htmlspecialchars($message[$tag]) . "</font><br>\n";
462 error_box($string,$color);
463 echo '</body></html>';
466 set_up_language($squirrelmail_language);
467 require_once(SM_PATH
. 'functions/display_messages.php');
468 $string = "<b><font color=$color[2]>\n" .
469 _("ERROR : Imap server closed the connection.") .
472 htmlspecialchars($query) . '<br>' .
473 _("Server responded: ") .
474 htmlspecialchars($message[$tag]) . "</font><br>\n";
475 error_box($string,$color);
476 echo '</body></html>';
479 set_up_language($squirrelmail_language);
480 require_once(SM_PATH
. 'functions/display_messages.php');
481 $string = "<b><font color=$color[2]>\n" .
482 _("ERROR : Unknown imap response.") .
485 htmlspecialchars($query) . '<br>' .
486 _("Server responded: ") .
487 htmlspecialchars($message[$tag]) . "</font><br>\n";
488 error_box($string,$color);
489 /* the error is displayed but because we don't know the reponse we
490 return the result anyway */
496 function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors,
497 &$response, &$message, $query = '',
498 $filter=false,$outputstream=false,$no_return=false) {
500 $tag_uid_a = explode(' ',trim($tag_uid));
501 $tag = $tag_uid_a[0];
503 $res = sqimap_read_data_list($imap_stream, $tag, $handle_errors,
504 $response, $message, $query,$filter,$outputstream,$no_return);
505 /* sqimap_read_data should be called for one response
506 but since it just calls sqimap_read_data_list which
507 handles multiple responses we need to check for that
508 and merge the $res array IF they are seperated and
509 IF it was a FETCH response. */
511 // if (isset($res[1]) && is_array($res[1]) && isset($res[1][0])
512 // && preg_match('/^\* \d+ FETCH/', $res[1][0])) {
513 // $result = array();
514 // foreach($res as $index=>$value) {
515 // $result = array_merge($result, $res["$index"]);
518 if (isset($result)) {
519 return $result[$tag];
527 * Logs the user into the imap server. If $hide is set, no error messages
528 * will be displayed. This function returns the imap connection handle.
530 function sqimap_login ($username, $password, $imap_server_address, $imap_port, $hide) {
531 global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;
533 if (!isset($onetimepad) ||
empty($onetimepad)) {
534 sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION
);
536 $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
537 $host=$imap_server_address;
539 if (($use_imap_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) {
540 /* Use TLS by prefixing "tls://" to the hostname */
541 $imap_server_address = 'tls://' . $imap_server_address;
544 $imap_stream = fsockopen ( $imap_server_address, $imap_port, $error_number, $error_string, 15);
546 /* Do some error correction */
549 set_up_language($squirrelmail_language, true);
550 require_once(SM_PATH
. 'functions/display_messages.php');
551 $string = sprintf (_("Error connecting to IMAP server: %s.") .
552 "<br>\r\n", $imap_server_address) .
553 "$error_number : $error_string<br>\r\n";
554 logout_error($string,$color);
559 $server_info = fgets ($imap_stream, 1024);
561 /* Decrypt the password */
562 $password = OneTimePadDecrypt($password, $onetimepad);
564 if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
565 // We're using some sort of authentication OTHER than plain or login
566 $tag=sqimap_session_id(false);
567 if ($imap_auth_mech == 'digest-md5') {
568 $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
569 } elseif ($imap_auth_mech == 'cram-md5') {
570 $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
572 fputs($imap_stream,$query);
573 $answer=sqimap_fgets($imap_stream);
574 // Trim the "+ " off the front
575 $response=explode(" ",$answer,3);
576 if ($response[0] == '+') {
577 // Got a challenge back
578 $challenge=$response[1];
579 if ($imap_auth_mech == 'digest-md5') {
580 $reply = digest_md5_response($username,$password,$challenge,'imap',$host);
581 } elseif ($imap_auth_mech == 'cram-md5') {
582 $reply = cram_md5_response($username,$password,$challenge);
584 fputs($imap_stream,$reply);
585 $read=sqimap_fgets($imap_stream);
586 if ($imap_auth_mech == 'digest-md5') {
587 // DIGEST-MD5 has an extra step..
588 if (substr($read,0,1) == '+') { // OK so far..
589 fputs($imap_stream,"\r\n");
590 $read=sqimap_fgets($imap_stream);
593 $results=explode(" ",$read,3);
594 $response=$results[1];
595 $message=$results[2];
597 // Fake the response, so the error trap at the bottom will work
599 $message='IMAP server does not appear to support the authentication method selected.';
600 $message .= ' Please contact your system administrator.';
602 } elseif ($imap_auth_mech == 'login') {
603 // Original IMAP login code
604 $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
605 $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
606 } elseif ($imap_auth_mech == 'plain') {
607 /* Replace this with SASL PLAIN if it ever gets implemented */
609 $message='SquirrelMail does not support SASL PLAIN yet. Rerun conf.pl and use login instead.';
612 $message="Internal SquirrelMail error - unknown IMAP authentication method chosen. Please contact the developers.";
615 /* If the connection was not successful, lets see why */
616 if ($response != 'OK') {
618 if ($response != 'NO') {
619 /* "BAD" and anything else gets reported here. */
620 $message = htmlspecialchars($message);
621 set_up_language($squirrelmail_language, true);
622 require_once(SM_PATH
. 'functions/display_messages.php');
623 if ($response == 'BAD') {
624 $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
626 $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
628 if (isset($read) && is_array($read)) {
629 $string .= '<br>' . _("Read data:") . "<br>\n";
630 foreach ($read as $line) {
631 $string .= htmlspecialchars($line) . "<br>\n";
634 error_box($string,$color);
638 * If the user does not log in with the correct
639 * username and password it is not possible to get the
640 * correct locale from the user's preferences.
641 * Therefore, apply the same hack as on the login
644 * $squirrelmail_language is set by a cookie when
645 * the user selects language and logs out
648 set_up_language($squirrelmail_language, true);
649 include_once(SM_PATH
. 'functions/display_messages.php' );
651 logout_error( _("Unknown user or password incorrect.") );
661 /* Simply logs out the IMAP session */
662 function sqimap_logout ($imap_stream) {
663 /* Logout is not valid until the server returns 'BYE'
664 * If we don't have an imap_ stream we're already logged out */
665 if(isset($imap_stream) && $imap_stream)
666 sqimap_run_command($imap_stream, 'LOGOUT', false, $response, $message);
669 function sqimap_capability($imap_stream, $capability='') {
670 global $sqimap_capabilities;
671 if (!is_array($sqimap_capabilities)) {
672 $read = sqimap_run_command($imap_stream, 'CAPABILITY', true, $a, $b);
674 $c = explode(' ', $read[0]);
675 for ($i=2; $i < count($c); $i++
) {
676 $cap_list = explode('=', $c[$i]);
677 if (isset($cap_list[1])) {
678 $sqimap_capabilities[$cap_list[0]] = $cap_list[1];
680 $sqimap_capabilities[$cap_list[0]] = TRUE;
685 if (isset($sqimap_capabilities[$capability])) {
686 return $sqimap_capabilities[$capability];
691 return $sqimap_capabilities;
694 /* Returns the delimeter between mailboxes: INBOX/Test, or INBOX.Test */
695 function sqimap_get_delimiter ($imap_stream = false) {
696 global $sqimap_delimiter, $optional_delimiter;
698 /* Use configured delimiter if set */
699 if((!empty($optional_delimiter)) && $optional_delimiter != 'detect') {
700 return $optional_delimiter;
703 /* Do some caching here */
704 if (!$sqimap_delimiter) {
705 if (sqimap_capability($imap_stream, 'NAMESPACE')) {
707 * According to something that I can't find, this is supposed to work on all systems
708 * OS: This won't work in Courier IMAP.
709 * OS: According to rfc2342 response from NAMESPACE command is:
710 * OS: * NAMESPACE (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES)
711 * OS: We want to lookup all personal NAMESPACES...
713 $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b);
714 if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) {
715 if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) {
718 $pna = explode(')(', $pn);
719 while (list($k, $v) = each($pna)) {
720 $lst = explode('"', $v);
721 if (isset($lst[3])) {
722 $pn[$lst[1]] = $lst[3];
728 $sqimap_delimiter = $pn[0];
730 fputs ($imap_stream, ". LIST \"INBOX\" \"\"\r\n");
731 $read = sqimap_read_data($imap_stream, '.', true, $a, $b);
732 $quote_position = strpos ($read[0], '"');
733 $sqimap_delimiter = substr ($read[0], $quote_position+
1, 1);
736 return $sqimap_delimiter;
740 /* Gets the number of messages in the current mailbox. */
741 function sqimap_get_num_messages ($imap_stream, $mailbox) {
742 $read_ary = sqimap_run_command ($imap_stream, "EXAMINE \"$mailbox\"", false, $result, $message);
743 for ($i = 0; $i < count($read_ary); $i++
) {
744 if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
748 return false; //"BUG! Couldn't get number of messages in $mailbox!";
752 function parseAddress($address, $max=0) {
755 $iCnt = strlen($address);
756 $aSpecials = array('(' ,'<' ,',' ,';' ,':');
757 $aReplace = array(' (',' <',' ,',' ;',' :');
758 $address = str_replace($aSpecials,$aReplace,$address);
759 $i = $iAddrFound = $bGroup = 0;
761 $cChar = $address{$i};
765 $iEnd = strpos($address,'>',$i+
1);
767 $sToken = substr($address,$i);
770 $sToken = substr($address,$i,$iEnd - $i +
1);
773 $sToken = str_replace($aReplace, $aSpecials,$sToken);
774 $aTokens[] = $sToken;
777 $iEnd = strpos($address,$cChar,$i+
1);
779 // skip escaped quotes
780 $prev_char = $address{$iEnd-1};
781 while ($prev_char === '\\' && substr($address,$iEnd-2,2) !== '\\\\') {
782 $iEnd = strpos($address,$cChar,$iEnd+
1);
784 $prev_char = $address{$iEnd-1};
791 $sToken = substr($address,$i);
794 // also remove the surrounding quotes
795 $sToken = substr($address,$i+
1,$iEnd - $i -1);
798 $sToken = str_replace($aReplace, $aSpecials,$sToken);
799 if ($sToken) $aTokens[] = $sToken;
802 $iEnd = strpos($address,')',$i);
804 $sToken = substr($address,$i);
807 $sToken = substr($address,$i,$iEnd - $i +
1);
810 $sToken = str_replace($aReplace, $aSpecials,$sToken);
811 $aTokens[] = $sToken;
821 if ($max && $max == $iAddrFound) {
833 $iEnd = strpos($address,' ',$i+
1);
835 $sToken = trim(substr($address,$i,$iEnd - $i));
838 $sToken = trim(substr($address,$i));
841 if ($sToken) $aTokens[] = $sToken;
845 $sPersonal = $sEmail = $sComment = $sGroup = '';
846 $aStack = $aComment = array();
847 foreach ($aTokens as $sToken) {
848 if ($max && $max == count($aAddress)) {
860 $aComment[] = substr($sToken,1,-1);
864 $sEmail = trim(implode(' ',$aStack));
865 $aAddress[] = array($sGroup,$sEmail);
866 $aStack = $aComment = array();
872 while (count($aStack) && !$sEmail) {
873 $sEmail = trim(array_pop($aStack));
876 if (count($aStack)) {
877 $sPersonal = trim(implode('',$aStack));
881 if (!$sPersonal && count($aComment)) {
882 $sComment = implode(' ',$aComment);
883 $sPersonal .= $sComment;
885 $aAddress[] = array($sEmail,$sPersonal);
886 $sPersonal = $sComment = $sEmail = '';
887 $aStack = $aComment = array();
890 $sGroup = implode(' ',$aStack); break;
894 $sEmail = trim(substr($sToken,1,-1));
899 default: $aStack[] = $sToken; break;
902 /* now do the action again for the last address */
904 while (count($aStack) && !$sEmail) {
905 $sEmail = trim(array_pop($aStack));
908 if (count($aStack)) {
909 $sPersonal = trim(implode('',$aStack));
913 if (!$sPersonal && count($aComment)) {
914 $sComment = implode(' ',$aComment);
915 $sPersonal .= $sComment;
917 $aAddress[] = array($sEmail,$sPersonal);
924 * Returns the number of unseen messages in this folder
926 function sqimap_unseen_messages ($imap_stream, $mailbox) {
927 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (UNSEEN)", false, $result, $message);
929 $regs = array(false, false);
930 while (isset($read_ary[$i])) {
931 if (ereg("UNSEEN ([0-9]+)", $read_ary[$i], $regs)) {
940 * Returns the number of unseen/total messages in this folder
942 function sqimap_status_messages ($imap_stream, $mailbox) {
943 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (MESSAGES UNSEEN RECENT)", false, $result, $message);
945 $messages = $unseen = $recent = false;
946 $regs = array(false,false);
947 while (isset($read_ary[$i])) {
948 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
951 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
952 $messages = $regs[1];
954 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
959 return array('MESSAGES' => $messages, 'UNSEEN'=>$unseen, 'RECENT' => $recent);
964 * Saves a message to a given folder -- used for saving sent messages
966 function sqimap_append ($imap_stream, $sent_folder, $length) {
967 fputs ($imap_stream, sqimap_session_id() . " APPEND \"$sent_folder\" (\\Seen) \{$length}\r\n");
968 $tmp = fgets ($imap_stream, 1024);
971 function sqimap_append_done ($imap_stream, $folder='') {
972 global $squirrelmail_language, $color;
973 fputs ($imap_stream, "\r\n");
974 $tmp = fgets ($imap_stream, 1024);
975 if (preg_match("/(.*)(BAD|NO)(.*)$/", $tmp, $regs)) {
976 set_up_language($squirrelmail_language);
977 require_once(SM_PATH
. 'functions/display_messages.php');
979 if ($regs[2] == 'NO') {
980 $string = "<b><font color=$color[2]>\n" .
981 _("ERROR : Could not append message to") ." $folder." .
983 _("Server responded: ") .
985 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
986 $string .= _("Solution: ") .
987 _("Remove unneccessary messages from your folder and start with your Trash folder.")
990 $string .= "</font>\n";
991 error_box($string,$color);
993 $string = "<b><font color=$color[2]>\n" .
994 _("ERROR : Bad or malformed request.") .
996 _("Server responded: ") .
997 $tmp . "</font><br>\n";
998 error_box($string,$color);
1004 function sqimap_get_user_server ($imap_server, $username) {
1005 if (substr($imap_server, 0, 4) != "map:") {
1006 return $imap_server;
1008 $function = substr($imap_server, 4);
1009 return $function($username);
1012 /* This is an example that gets imapservers from yellowpages (NIS).
1013 * you can simple put map:map_yp_alias in your $imap_server_address
1014 * in config.php use your own function instead map_yp_alias to map your
1015 * LDAP whatever way to find the users imapserver. */
1017 function map_yp_alias($username) {
1018 $yp = `ypmatch
$username aliases`
;
1019 return chop(substr($yp, strlen($username)+
1));