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