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