9cfd1c74fb2037ad38c36b84e2d14672bf4bd8bc
[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, $addr_ar = array(), $group = '', $host='', $limit=0) {
590 $pos = 0;
591 $j = strlen($address);
592 $personal = '';
593 $addr = '';
594 $comment = '';
595 if ($max && $max == count($addr_ar)) {
596 return $addr_ar;
597 }
598 while ($pos < $j) {
599 if ($max && $max == count($addr_ar)) {
600 return $addr_ar;
601 }
602 $char = $address{$pos};
603 switch ($char) {
604 case '=':
605 /* check if it is an encoded string */
606 if (preg_match('/^(=\?([^?]*)\?(Q|B)\?([^?]*)\?=)(.*)/Ui',substr($address,$pos),$reg)) {
607 /* add stringpart before the encoded string to the personal var */
608 if (!$personal) {
609 $personal = substr($address,0,$pos);
610 }
611 $personal .= $reg[1];
612 $pos += strlen($reg[1]);
613 } else {
614 ++$pos;
615 }
616 break;
617 case '"': /* get the personal name */
618 ++$pos;
619 if ($address{$pos} == '"') {
620 ++$pos;
621 } else {
622 $personal_start = $personal_end = $pos;
623 while ($pos < $j) {
624 $personal_end = strpos($address,'"',$pos);
625 if (($personal_end-2)>0 && (substr($address,$personal_end-2,2) === '\\"' ||
626 substr($address,$personal_end-2,2) === '\\\\')) {
627 $pos = $personal_end+1;
628 } else {
629 $personal = substr($address,$personal_start,$personal_end-$personal_start);
630 break;
631 }
632 }
633 if ($personal_end) { /* prohibit endless loops due to very wrong addresses */
634 $pos = $personal_end+1;
635 } else {
636 $pos = $j;
637 }
638 }
639 break;
640 case '<': /* get email address */
641 $addr_start = $pos;
642 $addr_end = strpos($address,'>',$addr_start);
643 if($addr_end === FALSE) {
644 // in case the address doesn't end, prevent loop
645 $pos++;
646 } else {
647 $addr = substr($address,$addr_start+1,$addr_end-$addr_start-1);
648 $pos = $addr_end+1;
649 }
650 break;
651 case '(': /* rip off comments */
652 $addr_start = $pos;
653 $pos = strpos($address,')');
654 if ($pos !== false) {
655 $comment = substr($address, $addr_start+1,($pos-$addr_start-1));
656 $address_start = substr($address, 0, $addr_start);
657 $address_end = substr($address, $pos + 1);
658 $address = $address_start . $address_end;
659 }
660 $j = strlen($address);
661 $pos = $addr_start + 1;
662 break;
663 case ';': /* we reached a non rfc2822 compliant delimiter */
664 if ($group) {
665 $address = substr($address, 0, $pos - 1);
666 ++$pos;
667 break;
668 }
669 case ',': /* we reached a delimiter */
670 if ($addr == '') {
671 $addr = substr($address, 0, $pos);
672 } else if ($personal == '') {
673 $personal = trim(substr($address, 0, $addr_start));
674 }
675 if (!$personal && $comment) $personal = $comment;
676 if ($personal) $personal = decodeHeader($personal);
677 $addr_ar[] = array($addr,$personal);
678 $address = trim(substr($address, $pos+1));
679 $j = strlen($address);
680 $pos = 0;
681 $personal = '';
682 $addr = '';
683 break;
684 case ':': /* process the group addresses */
685 /* group marker */
686 $group = substr($address, 0, $pos);
687 $address = substr($address, $pos+1);
688 $result = parseAddress($address, $max, $addr_ar, $group);
689 $addr_ar = $result[0];
690 $pos = $result[1];
691 $address = substr($address, $pos++);
692 $j = strlen($address);
693 $group = '';
694 break;
695 default:
696 ++$pos;
697 break;
698 }
699 }
700 if ($addr == '') {
701 $addr = substr($address, 0, $pos);
702 } else if ($personal == '') {
703 $personal = trim(substr($address, 0, $addr_start));
704 }
705 if (!$personal && $comment) $personal = $comment;
706 $email = $addr;
707 if ($group && $addr == '') { /* no addresses found in group */
708 $personal = $group;
709 $addr_ar[] = array('',$personal);
710 return (array($addr_ar,$pos+1 ));
711 } elseif ($group) {
712 $addr_ar[] = array($addr,$personal);
713 return (array($addr_ar,$pos+1 ));
714 } else {
715 if ($personal || $addr) {
716 $addr_ar[] = array($addr, $personal);
717 }
718 }
719 return ($addr_ar);
720 }
721
722 /*
723 * Returns the number of unseen messages in this folder
724 */
725 function sqimap_unseen_messages ($imap_stream, $mailbox) {
726 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (UNSEEN)", false, $result, $message);
727 $i = 0;
728 $regs = array(false, false);
729 while (isset($read_ary[$i])) {
730 if (ereg("UNSEEN ([0-9]+)", $read_ary[$i], $regs)) {
731 break;
732 }
733 $i++;
734 }
735 return $regs[1];
736 }
737
738 /*
739 * Returns the number of unseen/total messages in this folder
740 */
741 function sqimap_status_messages ($imap_stream, $mailbox) {
742 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (MESSAGES UNSEEN RECENT)", false, $result, $message);
743 $i = 0;
744 $messages = $unseen = $recent = false;
745 $regs = array(false,false);
746 while (isset($read_ary[$i])) {
747 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
748 $unseen = $regs[1];
749 }
750 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
751 $messages = $regs[1];
752 }
753 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
754 $recent = $regs[1];
755 }
756 $i++;
757 }
758 return array('MESSAGES' => $messages, 'UNSEEN'=>$unseen, 'RECENT' => $recent);
759 }
760
761
762 /*
763 * Saves a message to a given folder -- used for saving sent messages
764 */
765 function sqimap_append ($imap_stream, $sent_folder, $length) {
766 fputs ($imap_stream, sqimap_session_id() . " APPEND \"$sent_folder\" (\\Seen) \{$length}\r\n");
767 $tmp = fgets ($imap_stream, 1024);
768 }
769
770 function sqimap_append_done ($imap_stream, $folder='') {
771 global $squirrelmail_language, $color;
772 fputs ($imap_stream, "\r\n");
773 $tmp = fgets ($imap_stream, 1024);
774 if (preg_match("/(.*)(BAD|NO)(.*)$/", $tmp, $regs)) {
775 set_up_language($squirrelmail_language);
776 require_once(SM_PATH . 'functions/display_messages.php');
777 $reason = $regs[3];
778 if ($regs[2] == 'NO') {
779 $string = "<b><font color=$color[2]>\n" .
780 _("ERROR : Could not append message to") ." $folder." .
781 "</b><br>\n" .
782 _("Server responded: ") .
783 $reason . "<br>\n";
784 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
785 $string .= _("Solution: ") .
786 _("Remove unneccessary messages from your folder and start with your Trash folder.")
787 ."<br>\n";
788 }
789 $string .= "</font>\n";
790 error_box($string,$color);
791 } else {
792 $string = "<b><font color=$color[2]>\n" .
793 _("ERROR : Bad or malformed request.") .
794 "</b><br>\n" .
795 _("Server responded: ") .
796 $tmp . "</font><br>\n";
797 error_box($string,$color);
798 exit;
799 }
800 }
801 }
802
803 function sqimap_get_user_server ($imap_server, $username) {
804 if (substr($imap_server, 0, 4) != "map:") {
805 return $imap_server;
806 }
807 $function = substr($imap_server, 4);
808 return $function($username);
809 }
810
811 /* This is an example that gets imapservers from yellowpages (NIS).
812 * you can simple put map:map_yp_alias in your $imap_server_address
813 * in config.php use your own function instead map_yp_alias to map your
814 * LDAP whatever way to find the users imapserver. */
815
816 function map_yp_alias($username) {
817 $yp = `ypmatch $username aliases`;
818 return chop(substr($yp, strlen($username)+1));
819 }
820
821 ?>