because we remove the quotes an empty string could be left => check if the
[squirrelmail.git] / functions / imap_general.php
1 <?php
2
3 /**
4 * imap_general.php
5 *
6 * Copyright (c) 1999-2003 The SquirrelMail Project Team
7 * Licensed under the GNU GPL. For full terms see the file COPYING.
8 *
9 * This implements all functions that do general imap functions.
10 *
11 * $Id$
12 */
13
14 require_once(SM_PATH . 'functions/page_header.php');
15 require_once(SM_PATH . 'functions/auth.php');
16
17
18 global $sqimap_session_id;
19 $sqimap_session_id = 1;
20
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;
24 if (!$unique_id) {
25 return( sprintf("A%03d", $sqimap_session_id++) );
26 } else {
27 return( sprintf("A%03d", $sqimap_session_id++) . ' UID' );
28 }
29 }
30
31 /*
32 * Both send a command and accept the result from the command.
33 * This is to allow proper session number handling.
34 */
35 function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
36 if ($imap_stream) {
37 $sid = sqimap_session_id($unique_id);
38 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
39 $read = sqimap_read_data_list ($imap_stream, $sid, $handle_errors, $response, $message, $query );
40 return $read;
41 } else {
42 global $squirrelmail_language, $color;
43 set_up_language($squirrelmail_language);
44 require_once(SM_PATH . 'functions/display_messages.php');
45 $string = "<b><font color=$color[2]>\n" .
46 _("ERROR : No available imapstream.") .
47 "</b></font>\n";
48 error_box($string,$color);
49 return false;
50 }
51
52 }
53
54 function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
55 if ($imap_stream) {
56 $sid = sqimap_session_id($unique_id);
57 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
58 $read = sqimap_read_data ($imap_stream, $sid, $handle_errors, $response, $message, $query);
59 return $read;
60 } else {
61 global $squirrelmail_language, $color;
62 set_up_language($squirrelmail_language);
63 require_once(SM_PATH . 'functions/display_messages.php');
64 $string = "<b><font color=$color[2]>\n" .
65 _("ERROR : No available imapstream.") .
66 "</b></font>\n";
67 error_box($string,$color);
68 return false;
69 }
70
71 }
72
73
74 /*
75 * custom fgets function. gets a line from IMAP
76 * no matter how big it may be
77 */
78
79 function sqimap_fgets($imap_stream) {
80 $read = '';
81 $buffer = 4096;
82 $results = '';
83 $offset = 0;
84 while (strpos($results, "\r\n", $offset) === false) {
85 if (!($read = fgets($imap_stream, $buffer))) {
86 /* this happens in case of an error */
87 /* reset $results because it's useless */
88 $results = false;
89 break;
90 }
91 if ( $results != '' ) {
92 $offset = strlen($results) - 1;
93 }
94 $results .= $read;
95 }
96 return $results;
97 }
98
99 /*
100 * Reads the output from the IMAP stream. If handle_errors is set to true,
101 * this will also handle all errors that are received. If it is not set,
102 * the errors will be sent back through $response and $message
103 */
104
105 function sqimap_read_data_list ($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '') {
106 global $color, $squirrelmail_language;
107 $read = '';
108 $tag_uid_a = explode(' ',trim($tag_uid));
109 $tag = $tag_uid_a[0];
110 $resultlist = array();
111 $data = array();
112 $read = sqimap_fgets($imap_stream);
113 $i = 0;
114 while ($read) {
115 $char = $read{0};
116 switch ($char)
117 {
118 case '+':
119 default:
120 $read = sqimap_fgets($imap_stream);
121 break;
122
123 case $tag{0}:
124 {
125 /* get the command */
126 $arg = '';
127 $i = strlen($tag)+1;
128 $s = substr($read,$i);
129 if (($j = strpos($s,' ')) || ($j = strpos($s,"\n"))) {
130 $arg = substr($s,0,$j);
131 }
132 $found_tag = substr($read,0,$i-1);
133 if ($arg && $found_tag==$tag) {
134 switch ($arg)
135 {
136 case 'OK':
137 case 'BAD':
138 case 'NO':
139 case 'BYE':
140 case 'PREAUTH':
141 $response = $arg;
142 $message = trim(substr($read,$i+strlen($arg)));
143 break 3; /* switch switch while */
144 default:
145 /* this shouldn't happen */
146 $response = $arg;
147 $message = trim(substr($read,$i+strlen($arg)));
148 break 3; /* switch switch while */
149 }
150 } elseif($found_tag !== $tag) {
151 /* reset data array because we do not need this reponse */
152 $data = array();
153 $read = sqimap_fgets($imap_stream);
154 break;
155 }
156 } // end case $tag{0}
157
158 case '*':
159 {
160 if (preg_match('/^\*\s\d+\sFETCH/',$read)) {
161 /* check for literal */
162 $s = substr($read,-3);
163 $fetch_data = array();
164 do { /* outer loop, continue until next untagged fetch
165 or tagged reponse */
166 do { /* innerloop for fetching literals. with this loop
167 we prohibid that literal responses appear in the
168 outer loop so we can trust the untagged and
169 tagged info provided by $read */
170 if ($s === "}\r\n") {
171 $j = strrpos($read,'{');
172 $iLit = substr($read,$j+1,-3);
173 $fetch_data[] = $read;
174 $sLiteral = fread($imap_stream,$iLit);
175 if ($sLiteral === false) { /* error */
176 break 4; /* while while switch while */
177 }
178 /* backwards compattibility */
179 $aLiteral = explode("\n", $sLiteral);
180 /* release not neaded data */
181 unset($sLiteral);
182 foreach ($aLiteral as $line) {
183 $fetch_data[] = $line ."\n";
184 }
185 /* release not neaded data */
186 unset($aLiteral);
187 /* next fgets belongs to this fetch because
188 we just got the exact literalsize and there
189 must follow data to complete the response */
190 $read = sqimap_fgets($imap_stream);
191 if ($read === false) { /* error */
192 break 4; /* while while switch while */
193 }
194 $fetch_data[] = $read;
195 } else {
196 $fetch_data[] = $read;
197 }
198 /* retrieve next line and check in the while
199 statements if it belongs to this fetch response */
200 $read = sqimap_fgets($imap_stream);
201 if ($read === false) { /* error */
202 break 4; /* while while switch while */
203 }
204 /* check for next untagged reponse and break */
205 if ($read{0} == '*') break 2;
206 $s = substr($read,-3);
207 } while ($s === "}\r\n");
208 $s = substr($read,-3);
209 } while ($read{0} !== '*' &&
210 substr($read,0,strlen($tag)) !== $tag);
211 $resultlist[] = $fetch_data;
212 /* release not neaded data */
213 unset ($fetch_data);
214 } else {
215 $s = substr($read,-3);
216 do {
217 if ($s === "}\r\n") {
218 $j = strrpos($read,'{');
219 $iLit = substr($read,$j+1,-3);
220 $data[] = $read;
221 $sLiteral = fread($imap_stream,$iLit);
222 if ($sLiteral === false) { /* error */
223 $read = false;
224 break 3; /* while switch while */
225 }
226 $data[] = $sLiteral;
227 $fetch_data[] = sqimap_fgets($imap_stream);
228 } else {
229 $data[] = $read;
230 }
231 $read = sqimap_fgets($imap_stream);
232 if ($read === false) {
233 break 3; /* while switch while */
234 } else if ($read{0} == '*') {
235 break;
236 }
237 $s = substr($read,-3);
238 } while ($s === "}\r\n");
239 break 1;
240 }
241 break;
242 } // end case '*'
243 } // end switch
244 } // end while
245
246 /* error processing in case $read is false */
247 if ($read === false) {
248 unset($data);
249 set_up_language($squirrelmail_language);
250 require_once(SM_PATH . 'functions/display_messages.php');
251 $string = "<b><font color=$color[2]>\n" .
252 _("ERROR : Connection dropped by imap-server.") .
253 "</b><br>\n" .
254 _("Query:") . ' '.
255 htmlspecialchars($query) . '<br>' . "</font><br>\n";
256 error_box($string,$color);
257 exit;
258 }
259
260 /* Set $resultlist array */
261 if (!empty($data)) {
262 $resultlist[] = $data;
263 }
264 elseif (empty($resultlist)) {
265 $resultlist[] = array();
266 }
267
268 /* Return result or handle errors */
269 if ($handle_errors == false) {
270 return( $resultlist );
271 }
272 switch ($response)
273 {
274 case 'OK':
275 return $resultlist;
276 break;
277 case 'NO':
278 /* ignore this error from M$ exchange, it is not fatal (aka bug) */
279 if (strstr($message, 'command resulted in') === false) {
280 set_up_language($squirrelmail_language);
281 require_once(SM_PATH . 'functions/display_messages.php');
282 $string = "<b><font color=$color[2]>\n" .
283 _("ERROR : Could not complete request.") .
284 "</b><br>\n" .
285 _("Query:") . ' ' .
286 htmlspecialchars($query) . '<br>' .
287 _("Reason Given: ") .
288 htmlspecialchars($message) . "</font><br>\n";
289 error_box($string,$color);
290 echo '</body></html>';
291 exit;
292 }
293 break;
294 case 'BAD':
295 set_up_language($squirrelmail_language);
296 require_once(SM_PATH . 'functions/display_messages.php');
297 $string = "<b><font color=$color[2]>\n" .
298 _("ERROR : Bad or malformed request.") .
299 "</b><br>\n" .
300 _("Query:") . ' '.
301 htmlspecialchars($query) . '<br>' .
302 _("Server responded: ") .
303 htmlspecialchars($message) . "</font><br>\n";
304 error_box($string,$color);
305 echo '</body></html>';
306 exit;
307 case 'BYE':
308 set_up_language($squirrelmail_language);
309 require_once(SM_PATH . 'functions/display_messages.php');
310 $string = "<b><font color=$color[2]>\n" .
311 _("ERROR : Imap server closed the connection.") .
312 "</b><br>\n" .
313 _("Query:") . ' '.
314 htmlspecialchars($query) . '<br>' .
315 _("Server responded: ") .
316 htmlspecialchars($message) . "</font><br>\n";
317 error_box($string,$color);
318 echo '</body></html>';
319 exit;
320 default:
321 set_up_language($squirrelmail_language);
322 require_once(SM_PATH . 'functions/display_messages.php');
323 $string = "<b><font color=$color[2]>\n" .
324 _("ERROR : Unknown imap response.") .
325 "</b><br>\n" .
326 _("Query:") . ' '.
327 htmlspecialchars($query) . '<br>' .
328 _("Server responded: ") .
329 htmlspecialchars($message) . "</font><br>\n";
330 error_box($string,$color);
331 /* the error is displayed but because we don't know the reponse we
332 return the result anyway */
333 return $resultlist;
334 break;
335 }
336 }
337
338 function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '') {
339 $res = sqimap_read_data_list($imap_stream, $tag_uid, $handle_errors, $response, $message, $query);
340
341 /* sqimap_read_data should be called for one response
342 but since it just calls sqimap_read_data_list which
343 handles multiple responses we need to check for that
344 and merge the $res array IF they are seperated and
345 IF it was a FETCH response. */
346
347 // if (isset($res[1]) && is_array($res[1]) && isset($res[1][0])
348 // && preg_match('/^\* \d+ FETCH/', $res[1][0])) {
349 // $result = array();
350 // foreach($res as $index=>$value) {
351 // $result = array_merge($result, $res["$index"]);
352 // }
353 // }
354 if (isset($result)) {
355 return $result;
356 }
357 else {
358 return $res[0];
359 }
360
361 }
362
363 /*
364 * Logs the user into the imap server. If $hide is set, no error messages
365 * will be displayed. This function returns the imap connection handle.
366 */
367 function sqimap_login ($username, $password, $imap_server_address, $imap_port, $hide) {
368 global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;
369
370 if (!isset($onetimepad) || empty($onetimepad)) {
371 sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION );
372 }
373 $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
374 $host=$imap_server_address;
375
376 if (($use_imap_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) {
377 /* Use TLS by prefixing "tls://" to the hostname */
378 $imap_server_address = 'tls://' . $imap_server_address;
379 }
380
381 $imap_stream = fsockopen ( $imap_server_address, $imap_port, $error_number, $error_string, 15);
382
383 /* Do some error correction */
384 if (!$imap_stream) {
385 if (!$hide) {
386 set_up_language($squirrelmail_language, true);
387 require_once(SM_PATH . 'functions/display_messages.php');
388 $string = sprintf (_("Error connecting to IMAP server: %s.") .
389 "<br>\r\n", $imap_server_address) .
390 "$error_number : $error_string<br>\r\n";
391 logout_error($string,$color);
392 }
393 exit;
394 }
395
396 $server_info = fgets ($imap_stream, 1024);
397
398 /* Decrypt the password */
399 $password = OneTimePadDecrypt($password, $onetimepad);
400
401 if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
402 // We're using some sort of authentication OTHER than plain or login
403 $tag=sqimap_session_id(false);
404 if ($imap_auth_mech == 'digest-md5') {
405 $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
406 } elseif ($imap_auth_mech == 'cram-md5') {
407 $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
408 }
409 fputs($imap_stream,$query);
410 $answer=sqimap_fgets($imap_stream);
411 // Trim the "+ " off the front
412 $response=explode(" ",$answer,3);
413 if ($response[0] == '+') {
414 // Got a challenge back
415 $challenge=$response[1];
416 if ($imap_auth_mech == 'digest-md5') {
417 $reply = digest_md5_response($username,$password,$challenge,'imap',$host);
418 } elseif ($imap_auth_mech == 'cram-md5') {
419 $reply = cram_md5_response($username,$password,$challenge);
420 }
421 fputs($imap_stream,$reply);
422 $read=sqimap_fgets($imap_stream);
423 if ($imap_auth_mech == 'digest-md5') {
424 // DIGEST-MD5 has an extra step..
425 if (substr($read,0,1) == '+') { // OK so far..
426 fputs($imap_stream,"\r\n");
427 $read=sqimap_fgets($imap_stream);
428 }
429 }
430 $results=explode(" ",$read,3);
431 $response=$results[1];
432 $message=$results[2];
433 } else {
434 // Fake the response, so the error trap at the bottom will work
435 $response="BAD";
436 $message='IMAP server does not appear to support the authentication method selected.';
437 $message .= ' Please contact your system administrator.';
438 }
439 } elseif ($imap_auth_mech == 'login') {
440 // Original IMAP login code
441 $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
442 $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
443 } elseif ($imap_auth_mech == 'plain') {
444 /* Replace this with SASL PLAIN if it ever gets implemented */
445 $response="BAD";
446 $message='SquirrelMail does not support SASL PLAIN yet. Rerun conf.pl and use login instead.';
447 } else {
448 $response="BAD";
449 $message="Internal SquirrelMail error - unknown IMAP authentication method chosen. Please contact the developers.";
450 }
451
452 /* If the connection was not successful, lets see why */
453 if ($response != 'OK') {
454 if (!$hide) {
455 if ($response != 'NO') {
456 /* "BAD" and anything else gets reported here. */
457 $message = htmlspecialchars($message);
458 set_up_language($squirrelmail_language, true);
459 require_once(SM_PATH . 'functions/display_messages.php');
460 if ($response == 'BAD') {
461 $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
462 } else {
463 $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
464 }
465 if (isset($read) && is_array($read)) {
466 $string .= '<br>' . _("Read data:") . "<br>\n";
467 foreach ($read as $line) {
468 $string .= htmlspecialchars($line) . "<br>\n";
469 }
470 }
471 error_box($string,$color);
472 exit;
473 } else {
474 /*
475 * If the user does not log in with the correct
476 * username and password it is not possible to get the
477 * correct locale from the user's preferences.
478 * Therefore, apply the same hack as on the login
479 * screen.
480 *
481 * $squirrelmail_language is set by a cookie when
482 * the user selects language and logs out
483 */
484
485 set_up_language($squirrelmail_language, true);
486 include_once(SM_PATH . 'functions/display_messages.php' );
487 sqsession_destroy();
488 logout_error( _("Unknown user or password incorrect.") );
489 exit;
490 }
491 } else {
492 exit;
493 }
494 }
495 return $imap_stream;
496 }
497
498 /* Simply logs out the IMAP session */
499 function sqimap_logout ($imap_stream) {
500 /* Logout is not valid until the server returns 'BYE'
501 * If we don't have an imap_ stream we're already logged out */
502 if(isset($imap_stream) && $imap_stream)
503 sqimap_run_command($imap_stream, 'LOGOUT', false, $response, $message);
504 }
505
506 function sqimap_capability($imap_stream, $capability='') {
507 global $sqimap_capabilities;
508 if (!is_array($sqimap_capabilities)) {
509 $read = sqimap_run_command($imap_stream, 'CAPABILITY', true, $a, $b);
510
511 $c = explode(' ', $read[0]);
512 for ($i=2; $i < count($c); $i++) {
513 $cap_list = explode('=', $c[$i]);
514 if (isset($cap_list[1])) {
515 $sqimap_capabilities[$cap_list[0]] = $cap_list[1];
516 } else {
517 $sqimap_capabilities[$cap_list[0]] = TRUE;
518 }
519 }
520 }
521 if ($capability) {
522 if (isset($sqimap_capabilities[$capability])) {
523 return $sqimap_capabilities[$capability];
524 } else {
525 return false;
526 }
527 }
528 return $sqimap_capabilities;
529 }
530
531 /* Returns the delimeter between mailboxes: INBOX/Test, or INBOX.Test */
532 function sqimap_get_delimiter ($imap_stream = false) {
533 global $sqimap_delimiter, $optional_delimiter;
534
535 /* Use configured delimiter if set */
536 if((!empty($optional_delimiter)) && $optional_delimiter != 'detect') {
537 return $optional_delimiter;
538 }
539
540 /* Do some caching here */
541 if (!$sqimap_delimiter) {
542 if (sqimap_capability($imap_stream, 'NAMESPACE')) {
543 /*
544 * According to something that I can't find, this is supposed to work on all systems
545 * OS: This won't work in Courier IMAP.
546 * OS: According to rfc2342 response from NAMESPACE command is:
547 * OS: * NAMESPACE (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES)
548 * OS: We want to lookup all personal NAMESPACES...
549 */
550 $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b);
551 if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) {
552 if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) {
553 $pn = $data2[1];
554 }
555 $pna = explode(')(', $pn);
556 while (list($k, $v) = each($pna)) {
557 $lst = explode('"', $v);
558 if (isset($lst[3])) {
559 $pn[$lst[1]] = $lst[3];
560 } else {
561 $pn[$lst[1]] = '';
562 }
563 }
564 }
565 $sqimap_delimiter = $pn[0];
566 } else {
567 fputs ($imap_stream, ". LIST \"INBOX\" \"\"\r\n");
568 $read = sqimap_read_data($imap_stream, '.', true, $a, $b);
569 $quote_position = strpos ($read[0], '"');
570 $sqimap_delimiter = substr ($read[0], $quote_position+1, 1);
571 }
572 }
573 return $sqimap_delimiter;
574 }
575
576
577 /* Gets the number of messages in the current mailbox. */
578 function sqimap_get_num_messages ($imap_stream, $mailbox) {
579 $read_ary = sqimap_run_command ($imap_stream, "EXAMINE \"$mailbox\"", false, $result, $message);
580 for ($i = 0; $i < count($read_ary); $i++) {
581 if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
582 return $regs[1];
583 }
584 }
585 return false; //"BUG! Couldn't get number of messages in $mailbox!";
586 }
587
588
589 function parseAddress($address, $max=0) {
590 $aTokens = array();
591 $aAddress = array();
592 $iCnt = strlen($address);
593 $aSpecials = array('(' ,'<' ,',' ,';' ,':');
594 $aReplace = array(' (',' <',' ,',' ;',' :');
595 $address = str_replace($aSpecials,$aReplace,$address);
596 $i = 0;
597 while ($i < $iCnt) {
598 $cChar = $address{$i};
599 switch($cChar)
600 {
601 case '<':
602 $iEnd = strpos($address,'>',$i+1);
603 if (!$iEnd) {
604 $sToken = substr($address,$i);
605 $i = $iCnt;
606 } else {
607 $sToken = substr($address,$i,$iEnd - $i +1);
608 $i = $iEnd;
609 }
610 $sToken = str_replace($aReplace, $aSpecials,$sToken);
611 $aTokens[] = $sToken;
612 break;
613 case '"':
614 $iEnd = strpos($address,$cChar,$i+1);
615 if (!$iEnd) {
616 $sToken = substr($address,$i);
617 $i = $iCnt;
618 } else {
619 // also remove the surrounding quotes
620 $sToken = substr($address,$i+1,$iEnd - $i -1);
621 $i = $iEnd;
622 }
623 $sToken = str_replace($aReplace, $aSpecials,$sToken);
624 if ($sToken) $aTokens[] = $sToken;
625 break;
626 case '(':
627 $iEnd = strpos($address,')',$i);
628 if (!$iEnd) {
629 $sToken = substr($address,$i);
630 $i = $iCnt;
631 } else {
632 $sToken = substr($address,$i,$iEnd - $i + 1);
633 $i = $iEnd;
634 }
635 $sToken = str_replace($aReplace, $aSpecials,$sToken);
636 $aTokens[] = $sToken;
637 break;
638 case ',':
639 case ';':
640 case ';':
641 case ' ':
642 $aTokens[] = $cChar;
643 break;
644 default:
645 $iEnd = strpos($address,' ',$i+1);
646 if ($iEnd) {
647 $sToken = trim(substr($address,$i,$iEnd - $i));
648 $i = $iEnd-1;
649 } else {
650 $sToken = trim(substr($address,$i));
651 $i = $iCnt;
652 }
653 if ($sToken) $aTokens[] = $sToken;
654 }
655 ++$i;
656 }
657 $sPersonal = $sEmail = $sComment = $sGroup = '';
658 $aStack = $aComment = array();
659 foreach ($aTokens as $sToken) {
660 if ($max && $max == count($aAddress)) {
661 return $aAddress;
662 }
663 $cChar = $sToken{0};
664 switch ($cChar)
665 {
666 case '=':
667 case '"':
668 case ' ':
669 $aStack[] = $sToken;
670 break;
671 case '(':
672 $aComment[] = substr($sToken,1,-1);
673 break;
674 case ';':
675 if ($sGroup) {
676 $sEmail = trim(implode(' ',$aStack));
677 $aAddress[] = array($sGroup,$sEmail);
678 $aStack = $aComment = array();
679 $sGroup = '';
680 break;
681 }
682 case ',':
683 if (!$sEmail) {
684 while (count($aStack) && !$sEmail) {
685 $sEmail = trim(array_pop($aStack));
686 }
687 }
688 if (count($aStack)) {
689 $sPersonal = trim(implode('',$aStack));
690 } else {
691 $sPersonal = '';
692 }
693 if (!$sPersonal && count($aComment)) {
694 $sComment = implode(' ',$aComment);
695 $sPersonal .= $sComment;
696 }
697 $aAddress[] = array($sEmail,$sPersonal);
698 $sPersonal = $sComment = $sEmail = '';
699 $aStack = $aComment = array();
700 break;
701 case ':':
702 $sGroup = implode(' ',$aStack); break;
703 $aStack = array();
704 break;
705 case '<':
706 $sEmail = trim(substr($sToken,1,-1));
707 break;
708 case '>':
709 /* skip */
710 break;
711 default: $aStack[] = $sToken; break;
712 }
713 }
714 /* now do the action again for the last address */
715 if (!$sEmail) {
716 while (count($aStack) && !$sEmail) {
717 $sEmail = trim(array_pop($aStack));
718 }
719 }
720 if (count($aStack)) {
721 $sPersonal = trim(implode('',$aStack));
722 } else {
723 $sPersonal = '';
724 }
725 if (!$sPersonal && count($aComment)) {
726 $sComment = implode(' ',$aComment);
727 $sPersonal .= $sComment;
728 }
729 $aAddress[] = array($sEmail,$sPersonal);
730 return $aAddress;
731 }
732
733
734
735 /*
736 * Returns the number of unseen messages in this folder
737 */
738 function sqimap_unseen_messages ($imap_stream, $mailbox) {
739 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (UNSEEN)", false, $result, $message);
740 $i = 0;
741 $regs = array(false, false);
742 while (isset($read_ary[$i])) {
743 if (ereg("UNSEEN ([0-9]+)", $read_ary[$i], $regs)) {
744 break;
745 }
746 $i++;
747 }
748 return $regs[1];
749 }
750
751 /*
752 * Returns the number of unseen/total messages in this folder
753 */
754 function sqimap_status_messages ($imap_stream, $mailbox) {
755 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (MESSAGES UNSEEN RECENT)", false, $result, $message);
756 $i = 0;
757 $messages = $unseen = $recent = false;
758 $regs = array(false,false);
759 while (isset($read_ary[$i])) {
760 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
761 $unseen = $regs[1];
762 }
763 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
764 $messages = $regs[1];
765 }
766 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
767 $recent = $regs[1];
768 }
769 $i++;
770 }
771 return array('MESSAGES' => $messages, 'UNSEEN'=>$unseen, 'RECENT' => $recent);
772 }
773
774
775 /*
776 * Saves a message to a given folder -- used for saving sent messages
777 */
778 function sqimap_append ($imap_stream, $sent_folder, $length) {
779 fputs ($imap_stream, sqimap_session_id() . " APPEND \"$sent_folder\" (\\Seen) \{$length}\r\n");
780 $tmp = fgets ($imap_stream, 1024);
781 }
782
783 function sqimap_append_done ($imap_stream, $folder='') {
784 global $squirrelmail_language, $color;
785 fputs ($imap_stream, "\r\n");
786 $tmp = fgets ($imap_stream, 1024);
787 if (preg_match("/(.*)(BAD|NO)(.*)$/", $tmp, $regs)) {
788 set_up_language($squirrelmail_language);
789 require_once(SM_PATH . 'functions/display_messages.php');
790 $reason = $regs[3];
791 if ($regs[2] == 'NO') {
792 $string = "<b><font color=$color[2]>\n" .
793 _("ERROR : Could not append message to") ." $folder." .
794 "</b><br>\n" .
795 _("Server responded: ") .
796 $reason . "<br>\n";
797 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
798 $string .= _("Solution: ") .
799 _("Remove unneccessary messages from your folder and start with your Trash folder.")
800 ."<br>\n";
801 }
802 $string .= "</font>\n";
803 error_box($string,$color);
804 } else {
805 $string = "<b><font color=$color[2]>\n" .
806 _("ERROR : Bad or malformed request.") .
807 "</b><br>\n" .
808 _("Server responded: ") .
809 $tmp . "</font><br>\n";
810 error_box($string,$color);
811 exit;
812 }
813 }
814 }
815
816 function sqimap_get_user_server ($imap_server, $username) {
817 if (substr($imap_server, 0, 4) != "map:") {
818 return $imap_server;
819 }
820 $function = substr($imap_server, 4);
821 return $function($username);
822 }
823
824 /* This is an example that gets imapservers from yellowpages (NIS).
825 * you can simple put map:map_yp_alias in your $imap_server_address
826 * in config.php use your own function instead map_yp_alias to map your
827 * LDAP whatever way to find the users imapserver. */
828
829 function map_yp_alias($username) {
830 $yp = `ypmatch $username aliases`;
831 return chop(substr($yp, strlen($username)+1));
832 }
833
834 ?>