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