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