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