Rewritten addressparser
[squirrelmail.git] / functions / imap_general.php
CommitLineData
59177427 1<?php
bccadd02 2
35586184 3/**
a6fd80f5 4 * imap_general.php
35586184 5 *
76911253 6 * Copyright (c) 1999-2003 The SquirrelMail Project Team
15e6162e 7 * Licensed under the GNU GPL. For full terms see the file COPYING.
35586184 8 *
15e6162e 9 * This implements all functions that do general imap functions.
35586184 10 *
15e6162e 11 * $Id$
35586184 12 */
13
b68edc75 14require_once(SM_PATH . 'functions/page_header.php');
47a29326 15require_once(SM_PATH . 'functions/auth.php');
16
35586184 17
41600f7d 18global $sqimap_session_id;
19$sqimap_session_id = 1;
71257f8b 20
3411d4ec 21/* Sets an unique session id in order to avoid simultanous sessions crash. */
487daa81 22function sqimap_session_id($unique_id = false) {
41600f7d 23 global $data_dir, $username, $sqimap_session_id;
487daa81 24 if (!$unique_id) {
098ea084 25 return( sprintf("A%03d", $sqimap_session_id++) );
487daa81 26 } else {
098ea084 27 return( sprintf("A%03d", $sqimap_session_id++) . ' UID' );
487daa81 28 }
9c737111 29}
30
3411d4ec 31/*
32 * Both send a command and accept the result from the command.
33 * This is to allow proper session number handling.
34 */
487daa81 35function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
c5809184 36 if ($imap_stream) {
098ea084 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;
c5809184 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);
098ea084 49 return false;
c5809184 50 }
51
1c72b151 52}
53
487daa81 54function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
c5809184 55 if ($imap_stream) {
56 $sid = sqimap_session_id($unique_id);
098ea084 57 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
58 $read = sqimap_read_data ($imap_stream, $sid, $handle_errors, $response, $message, $query);
59 return $read;
c5809184 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);
098ea084 68 return false;
c5809184 69 }
70
42a07ac1 71}
72
9c737111 73
b8c285ab 74/*
75 * custom fgets function. gets a line from IMAP
76 * no matter how big it may be
77 */
78
79function sqimap_fgets($imap_stream) {
80 $read = '';
81 $buffer = 4096;
82 $results = '';
c41daf03 83 $offset = 0;
84 while (strpos($results, "\r\n", $offset) === false) {
b8c285ab 85 if (!($read = fgets($imap_stream, $buffer))) {
c0b23345 86 /* this happens in case of an error */
87 /* reset $results because it's useless */
88 $results = false;
b8c285ab 89 break;
90 }
c41daf03 91 if ( $results != '' ) {
92 $offset = strlen($results) - 1;
93 }
b8c285ab 94 $results .= $read;
95 }
96 return $results;
97}
98
bee165ef 99/*
3411d4ec 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
bee165ef 103 */
b8c285ab 104
bea3eb1e 105function sqimap_read_data_list ($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '') {
9c737111 106 global $color, $squirrelmail_language;
9c737111 107 $read = '';
bea3eb1e 108 $tag_uid_a = explode(' ',trim($tag_uid));
109 $tag = $tag_uid_a[0];
b8c285ab 110 $resultlist = array();
111 $data = array();
112 $read = sqimap_fgets($imap_stream);
ba8f367a 113 $i = 0;
bea3eb1e 114 while ($read) {
115 $char = $read{0};
116 switch ($char)
117 {
15bc7f66 118 case '+':
119 default:
120 $read = sqimap_fgets($imap_stream);
121 break;
122
123 case $tag{0}:
124 {
bea3eb1e 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 {
15bc7f66 136 case 'OK':
137 case 'BAD':
138 case 'NO':
139 case 'BYE':
140 case 'PREAUTH':
bea3eb1e 141 $response = $arg;
142 $message = trim(substr($read,$i+strlen($arg)));
c0b23345 143 break 3; /* switch switch while */
15bc7f66 144 default:
bea3eb1e 145 /* this shouldn't happen */
146 $response = $arg;
147 $message = trim(substr($read,$i+strlen($arg)));
c0b23345 148 break 3; /* switch switch while */
bea3eb1e 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 }
15bc7f66 156 } // end case $tag{0}
157
158 case '*':
159 {
bea3eb1e 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);
c0b23345 175 if ($sLiteral === false) { /* error */
176 break 4; /* while while switch while */
177 }
bea3eb1e 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 */
c0b23345 190 $read = sqimap_fgets($imap_stream);
191 if ($read === false) { /* error */
192 break 4; /* while while switch while */
193 }
194 $fetch_data[] = $read;
bea3eb1e 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);
c0b23345 201 if ($read === false) { /* error */
202 break 4; /* while while switch while */
203 }
bea3eb1e 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} !== '*' &&
106d4087 210 substr($read,0,strlen($tag)) !== $tag);
211 $resultlist[] = $fetch_data;
bea3eb1e 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;
c0b23345 221 $sLiteral = fread($imap_stream,$iLit);
222 if ($sLiteral === false) { /* error */
223 $read = false;
224 break 3; /* while switch while */
225 }
226 $data[] = $sLiteral;
bea3eb1e 227 $fetch_data[] = sqimap_fgets($imap_stream);
228 } else {
229 $data[] = $read;
230 }
231 $read = sqimap_fgets($imap_stream);
106d4087 232 if ($read === false) {
233 break 3; /* while switch while */
234 } else if ($read{0} == '*') {
235 break;
236 }
bea3eb1e 237 $s = substr($read,-3);
238 } while ($s === "}\r\n");
239 break 1;
240 }
241 break;
15bc7f66 242 } // end case '*'
243 } // end switch
c0b23345 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;
b8c285ab 258 }
c0b23345 259
15bc7f66 260 /* Set $resultlist array */
b8c285ab 261 if (!empty($data)) {
9c737111 262 $resultlist[] = $data;
263 }
b8c285ab 264 elseif (empty($resultlist)) {
265 $resultlist[] = array();
266 }
15bc7f66 267
268 /* Return result or handle errors */
bee165ef 269 if ($handle_errors == false) {
270 return( $resultlist );
dd381002 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) */
9c737111 279 if (strstr($message, 'command resulted in') === false) {
441f2d33 280 set_up_language($squirrelmail_language);
098ea084 281 require_once(SM_PATH . 'functions/display_messages.php');
282 $string = "<b><font color=$color[2]>\n" .
b8c285ab 283 _("ERROR : Could not complete request.") .
284 "</b><br>\n" .
9b761dbd 285 _("Query:") . ' ' .
286 htmlspecialchars($query) . '<br>' .
b8c285ab 287 _("Reason Given: ") .
9b761dbd 288 htmlspecialchars($message) . "</font><br>\n";
098ea084 289 error_box($string,$color);
dd381002 290 echo '</body></html>';
052e0c26 291 exit;
9c737111 292 }
dd381002 293 break;
294 case 'BAD':
9c737111 295 set_up_language($squirrelmail_language);
098ea084 296 require_once(SM_PATH . 'functions/display_messages.php');
bef6629c 297 $string = "<b><font color=$color[2]>\n" .
b8c285ab 298 _("ERROR : Bad or malformed request.") .
299 "</b><br>\n" .
9b761dbd 300 _("Query:") . ' '.
301 htmlspecialchars($query) . '<br>' .
b8c285ab 302 _("Server responded: ") .
9b761dbd 303 htmlspecialchars($message) . "</font><br>\n";
dd381002 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>';
9c737111 319 exit;
dd381002 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;
9c737111 335 }
9c737111 336}
337
bea3eb1e 338function 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);
863936bb 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
ba8f367a 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// }
863936bb 354 if (isset($result)) {
355 return $result;
56afb33f 356 }
56afb33f 357 else {
863936bb 358 return $res[0];
56afb33f 359 }
360
9c737111 361}
362
3411d4ec 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 */
9c737111 367function sqimap_login ($username, $password, $imap_server_address, $imap_port, $hide) {
47a29326 368 global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;
85fc999e 369
eb2f6102 370 if (!isset($onetimepad) || empty($onetimepad)) {
371 sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION );
372 }
bd9829d7 373 $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
098ea084 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 }
47a29326 380
3411d4ec 381 $imap_stream = fsockopen ( $imap_server_address, $imap_port, $error_number, $error_string, 15);
85fc999e 382
3411d4ec 383 /* Do some error correction */
9c737111 384 if (!$imap_stream) {
385 if (!$hide) {
441f2d33 386 set_up_language($squirrelmail_language, true);
098ea084 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) .
1f720b34 390 "$error_number : $error_string<br>\r\n";
098ea084 391 logout_error($string,$color);
9c737111 392 }
393 exit;
394 }
052e0c26 395
2f1f7a12 396 $server_info = fgets ($imap_stream, 1024);
397
398 /* Decrypt the password */
399 $password = OneTimePadDecrypt($password, $onetimepad);
400
098ea084 401 if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
fe0b18b3 402 // We're using some sort of authentication OTHER than plain or login
098ea084 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];
47a29326 433 } else {
098ea084 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.';
47a29326 438 }
fe0b18b3 439 } elseif ($imap_auth_mech == 'login') {
098ea084 440 // Original IMAP login code
fbb76d0e 441 $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
47a29326 442 $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
1e7fc1cb 443 } elseif ($imap_auth_mech == 'plain') {
098ea084 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 }
47a29326 451
098ea084 452 /* If the connection was not successful, lets see why */
9c737111 453 if ($response != 'OK') {
454 if (!$hide) {
74424a43 455 if ($response != 'NO') {
3411d4ec 456 /* "BAD" and anything else gets reported here. */
098ea084 457 $message = htmlspecialchars($message);
9c737111 458 set_up_language($squirrelmail_language, true);
098ea084 459 require_once(SM_PATH . 'functions/display_messages.php');
9c737111 460 if ($response == 'BAD') {
bea3eb1e 461 $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
9c737111 462 } else {
bea3eb1e 463 $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
9c737111 464 }
1e7fc1cb 465 if (isset($read) && is_array($read)) {
bea3eb1e 466 $string .= '<br>' . _("Read data:") . "<br>\n";
9c737111 467 foreach ($read as $line) {
1f720b34 468 $string .= htmlspecialchars($line) . "<br>\n";
9c737111 469 }
470 }
098ea084 471 error_box($string,$color);
9c737111 472 exit;
165e24a7 473 } else {
3411d4ec 474 /*
475 * If the user does not log in with the correct
1c72b151 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.
3411d4ec 480 *
481 * $squirrelmail_language is set by a cookie when
1c72b151 482 * the user selects language and logs out
bee165ef 483 */
9be8198d 484
9c737111 485 set_up_language($squirrelmail_language, true);
bd9c880b 486 include_once(SM_PATH . 'functions/display_messages.php' );
098ea084 487 sqsession_destroy();
bd9c880b 488 logout_error( _("Unknown user or password incorrect.") );
9c737111 489 exit;
052e0c26 490 }
9c737111 491 } else {
052e0c26 492 exit;
9c737111 493 }
494 }
9c737111 495 return $imap_stream;
496}
f1e6f580 497
3411d4ec 498/* Simply logs out the IMAP session */
9c737111 499function sqimap_logout ($imap_stream) {
8d936b0c 500 /* Logout is not valid until the server returns 'BYE'
501 * If we don't have an imap_ stream we're already logged out */
26a2cc8b 502 if(isset($imap_stream) && $imap_stream)
8d936b0c 503 sqimap_run_command($imap_stream, 'LOGOUT', false, $response, $message);
9c737111 504}
505
487daa81 506function sqimap_capability($imap_stream, $capability='') {
9c737111 507 global $sqimap_capabilities;
9c737111 508 if (!is_array($sqimap_capabilities)) {
1c72b151 509 $read = sqimap_run_command($imap_stream, 'CAPABILITY', true, $a, $b);
510
9c737111 511 $c = explode(' ', $read[0]);
512 for ($i=2; $i < count($c); $i++) {
513 $cap_list = explode('=', $c[$i]);
3411d4ec 514 if (isset($cap_list[1])) {
9c737111 515 $sqimap_capabilities[$cap_list[0]] = $cap_list[1];
3411d4ec 516 } else {
9c737111 517 $sqimap_capabilities[$cap_list[0]] = TRUE;
3411d4ec 518 }
f1e6f580 519 }
9c737111 520 }
487daa81 521 if ($capability) {
098ea084 522 if (isset($sqimap_capabilities[$capability])) {
523 return $sqimap_capabilities[$capability];
524 } else {
525 return false;
526 }
f1e6f580 527 }
487daa81 528 return $sqimap_capabilities;
9c737111 529}
530
3411d4ec 531/* Returns the delimeter between mailboxes: INBOX/Test, or INBOX.Test */
9c737111 532function sqimap_get_delimiter ($imap_stream = false) {
3411d4ec 533 global $sqimap_delimiter, $optional_delimiter;
85fc999e 534
9c737111 535 /* Use configured delimiter if set */
536 if((!empty($optional_delimiter)) && $optional_delimiter != 'detect') {
537 return $optional_delimiter;
538 }
85fc999e 539
9c737111 540 /* Do some caching here */
541 if (!$sqimap_delimiter) {
542 if (sqimap_capability($imap_stream, 'NAMESPACE')) {
3411d4ec 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 */
1c72b151 550 $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b);
f1e6f580 551 if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) {
9c737111 552 if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) {
f1e6f580 553 $pn = $data2[1];
9c737111 554 }
f1e6f580 555 $pna = explode(')(', $pn);
9c737111 556 while (list($k, $v) = each($pna)) {
862ff2d3 557 $lst = explode('"', $v);
558 if (isset($lst[3])) {
559 $pn[$lst[1]] = $lst[3];
560 } else {
74424a43 561 $pn[$lst[1]] = '';
862ff2d3 562 }
f1e6f580 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;
9c737111 574}
052e0c26 575
576
3411d4ec 577/* Gets the number of messages in the current mailbox. */
9c737111 578function sqimap_get_num_messages ($imap_stream, $mailbox) {
1f720b34 579 $read_ary = sqimap_run_command ($imap_stream, "EXAMINE \"$mailbox\"", false, $result, $message);
9c737111 580 for ($i = 0; $i < count($read_ary); $i++) {
85fc999e 581 if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
582 return $regs[1];
583 }
9c737111 584 }
1f720b34 585 return false; //"BUG! Couldn't get number of messages in $mailbox!";
9c737111 586}
587
cfe1a81e 588
91688e5f 589function 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
614 case '"':
615 $iEnd = strpos($address,$cChar,$i+1);
616 if (!$iEnd) {
617 $sToken = substr($address,$i);
618 $i = $iCnt;
619 } else {
620 $sToken = substr($address,$i,$iEnd - $i +1);
621 $i = $iEnd;
622 }
623 $sToken = str_replace($aReplace, $aSpecials,$sToken);
624 $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 $aTokens[] = $cChar;
642 break;
643 default:
644 $iEnd = strpos($address,' ',$i+1);
645 if ($iEnd) {
646 $sToken = trim(substr($address,$i,$iEnd - $i));
647 $i = $iEnd;
648 } else {
649 $sToken = trim(substr($address,$i));
650 $i = $iCnt;
651 }
652 if ($sToken) $aTokens[] = $sToken;
653 }
654 ++$i;
9c737111 655 }
91688e5f 656 $sPersonal = $sEmail = $sComment = $sGroup = '';
657 $aStack = $aComment = array();
658 foreach ($aTokens as $sToken) {
659 if ($max && $max == count($aAddress)) {
660 return $aAddress;
092d4f2c 661 }
91688e5f 662 $cChar = $sToken{0};
663 switch ($cChar)
664 {
665 case '=':
666 case '"':
667 case ' ':
668 $aStack[] = $sToken;
669 break;
670 case '(':
671 $aComment[] = $sToken;
672 break;
673 case ';':
674 if ($sGroup) {
675 $sEmail = trim(implode(' ',$aStack));
676 $aAddress[] = array($sGroup,$sEmail);
677 $aStack = $aComment = array();
678 $sGroup = '';
679 break;
bea3eb1e 680 }
91688e5f 681 case ',':
682 if (!$sEmail) {
683 while (count($aStack) && !$sEmail) {
684 $sEmail = array_pop($aStack);
685 }
686 }
687 if (count($aStack)) {
688 $sPersonal = implode(' ',$aStack);
689 if ($sPersonal && $sPersonal{0} == '"') {
690 $sPersonal = substr($sPersonal,1,-1);
691 }
692 } else {
693 $sPersonal = '';
694 }
695 if (count($aComment)) {
696 $sComment = implode(' ',$aComment);
697 $sPersonal .= $sComment;
698 }
699
700 $aAddress[] = array($sEmail,$sPersonal);
701 $sPersonal = $sComment = $sEmail = '';
702 $aStack = $aComment = array();
703 break;
704 case ':':
705 $sGroup = implode(' ',$aStack); break;
706 $aStack = array();
707 break;
708
709 case '<':
710 $sEmail = trim(substr($sToken,1,-1));
711 break;
712 case '>':
713 /* skip */
714 break;
715 default: $aStack[] = $sToken; break;
33565ec4 716 }
7e3de682 717 }
91688e5f 718 /* now do the action again for the last address */
719 if (!$sEmail) {
720 while (count($aStack) && !$sEmail) {
721 $sEmail = array_pop($aStack);
722 }
7e3de682 723 }
91688e5f 724 if (count($aStack)) {
725 $sPersonal = implode(' ',$aStack);
726 if ($sPersonal && $sPersonal{0} == '"') {
727 $sPersonal = substr($sPersonal,1,-1);
728 }
098ea084 729 } else {
91688e5f 730 $sPersonal = '';
9c737111 731 }
91688e5f 732 if (count($aComment)) {
733 $sComment = implode(' ',$aComment);
734 $sPersonal .= $sComment;
735 }
736 $aAddress[] = array($sEmail,$sPersonal);
737 return $aAddress;
738}
739
740
85fc999e 741
9c737111 742/*
3411d4ec 743 * Returns the number of unseen messages in this folder
744 */
9c737111 745function sqimap_unseen_messages ($imap_stream, $mailbox) {
1f720b34 746 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (UNSEEN)", false, $result, $message);
ea7ff111 747 $i = 0;
1f720b34 748 $regs = array(false, false);
ea7ff111 749 while (isset($read_ary[$i])) {
750 if (ereg("UNSEEN ([0-9]+)", $read_ary[$i], $regs)) {
751 break;
752 }
753 $i++;
754 }
9c737111 755 return $regs[1];
756}
757
1f720b34 758/*
759 * Returns the number of unseen/total messages in this folder
760 */
761function sqimap_status_messages ($imap_stream, $mailbox) {
b8ec18ef 762 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (MESSAGES UNSEEN RECENT)", false, $result, $message);
1f720b34 763 $i = 0;
b8ec18ef 764 $messages = $unseen = $recent = false;
1f720b34 765 $regs = array(false,false);
766 while (isset($read_ary[$i])) {
767 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 768 $unseen = $regs[1];
769 }
1f720b34 770 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 771 $messages = $regs[1];
772 }
b8ec18ef 773 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 774 $recent = $regs[1];
775 }
1f720b34 776 $i++;
777 }
b8ec18ef 778 return array('MESSAGES' => $messages, 'UNSEEN'=>$unseen, 'RECENT' => $recent);
1f720b34 779}
780
9c737111 781
782/*
3411d4ec 783 * Saves a message to a given folder -- used for saving sent messages
784 */
9c737111 785function sqimap_append ($imap_stream, $sent_folder, $length) {
786 fputs ($imap_stream, sqimap_session_id() . " APPEND \"$sent_folder\" (\\Seen) \{$length}\r\n");
85fc999e 787 $tmp = fgets ($imap_stream, 1024);
9c737111 788}
789
8813fb15 790function sqimap_append_done ($imap_stream, $folder='') {
1f720b34 791 global $squirrelmail_language, $color;
9c737111 792 fputs ($imap_stream, "\r\n");
793 $tmp = fgets ($imap_stream, 1024);
69146537 794 if (preg_match("/(.*)(BAD|NO)(.*)$/", $tmp, $regs)) {
795 set_up_language($squirrelmail_language);
1f720b34 796 require_once(SM_PATH . 'functions/display_messages.php');
098ea084 797 $reason = $regs[3];
798 if ($regs[2] == 'NO') {
799 $string = "<b><font color=$color[2]>\n" .
800 _("ERROR : Could not append message to") ." $folder." .
801 "</b><br>\n" .
802 _("Server responded: ") .
803 $reason . "<br>\n";
804 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
805 $string .= _("Solution: ") .
806 _("Remove unneccessary messages from your folder and start with your Trash folder.")
807 ."<br>\n";
808 }
809 $string .= "</font>\n";
810 error_box($string,$color);
811 } else {
8813fb15 812 $string = "<b><font color=$color[2]>\n" .
098ea084 813 _("ERROR : Bad or malformed request.") .
814 "</b><br>\n" .
815 _("Server responded: ") .
816 $tmp . "</font><br>\n";
817 error_box($string,$color);
8813fb15 818 exit;
098ea084 819 }
69146537 820 }
9c737111 821}
85fc999e 822
bd9829d7 823function sqimap_get_user_server ($imap_server, $username) {
bd9829d7 824 if (substr($imap_server, 0, 4) != "map:") {
825 return $imap_server;
826 }
bd9829d7 827 $function = substr($imap_server, 4);
828 return $function($username);
829}
830
831/* This is an example that gets imapservers from yellowpages (NIS).
832 * you can simple put map:map_yp_alias in your $imap_server_address
833 * in config.php use your own function instead map_yp_alias to map your
834 * LDAP whatever way to find the users imapserver. */
835
836function map_yp_alias($username) {
837 $yp = `ypmatch $username aliases`;
838 return chop(substr($yp, strlen($username)+1));
839}
840
15e6162e 841?>