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