Partial support for IMAP LOgin Referrals: tell the user what's going on
[squirrelmail.git] / functions / imap_general.php
CommitLineData
59177427 1<?php
bccadd02 2
35586184 3/**
a6fd80f5 4 * imap_general.php
35586184 5 *
6c84ba1e 6 * Copyright (c) 1999-2005 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 *
eb19bc67 11 * @version $Id$
d6c32258 12 * @package squirrelmail
eb19bc67 13 * @subpackage imap
35586184 14 */
15
d6c32258 16/** Includes.. */
b68edc75 17require_once(SM_PATH . 'functions/page_header.php');
47a29326 18require_once(SM_PATH . 'functions/auth.php');
19
35586184 20
48af4b64 21/**
22 * Generates a new session ID by incrementing the last one used;
23 * this ensures that each command has a unique ID.
b35a5862 24 * @param bool $unique_id (since 1.3.0) controls use of unique
25 * identifiers/message sequence numbers in IMAP commands. See IMAP
26 * rfc 'UID command' chapter.
48af4b64 27 * @return string IMAP session id of the form 'A000'.
b35a5862 28 * @since 1.2.0
48af4b64 29 */
2aca19a1 30function sqimap_session_id($unique_id = FALSE) {
31 static $sqimap_session_id = 1;
32
487daa81 33 if (!$unique_id) {
098ea084 34 return( sprintf("A%03d", $sqimap_session_id++) );
487daa81 35 } else {
098ea084 36 return( sprintf("A%03d", $sqimap_session_id++) . ' UID' );
487daa81 37 }
9c737111 38}
39
48af4b64 40/**
3411d4ec 41 * Both send a command and accept the result from the command.
42 * This is to allow proper session number handling.
b35a5862 43 * @param resource $imap_stream imap connection resource
44 * @param string $query imap command
45 * @param boolean $handle_errors see sqimap_retrieve_imap_response()
46 * @param mixed $response
47 * @param mixed $message
48 * @param boolean $unique_id (since 1.3.0) controls use of unique
49 * identifiers/message sequence numbers in IMAP commands. See IMAP
50 * rfc 'UID command' chapter.
51 * @return mixed returns false on imap error. displays error message
52 * if imap stream is not available.
53 * @since 1.2.3
3411d4ec 54 */
487daa81 55function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
c5809184 56 if ($imap_stream) {
098ea084 57 $sid = sqimap_session_id($unique_id);
58 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
bc78cc6e 59 $tag_uid_a = explode(' ',trim($sid));
60 $tag = $tag_uid_a[0];
0dc05a81 61 $read = sqimap_retrieve_imap_response ($imap_stream, $tag, $handle_errors, $response, $message, $query );
bc78cc6e 62 /* get the response and the message */
63 $message = $message[$tag];
1e0a2f0e 64 $response = $response[$tag];
bc78cc6e 65 return $read[$tag];
c5809184 66 } else {
67 global $squirrelmail_language, $color;
68 set_up_language($squirrelmail_language);
69 require_once(SM_PATH . 'functions/display_messages.php');
6fd95361 70 $string = "<b><font color=\"$color[2]\">\n" .
c5809184 71 _("ERROR : No available imapstream.") .
72 "</b></font>\n";
73 error_box($string,$color);
098ea084 74 return false;
c5809184 75 }
1c72b151 76}
77
b35a5862 78/**
79 * @param resource $imap_stream imap connection resource
80 * @param string $query imap command
81 * @param boolean $handle_errors see sqimap_retrieve_imap_response()
82 * @param mixed $response
83 * @param mixed $message
84 * @param boolean $unique_id (since 1.3.0) controls use of unique
85 * identifiers/message sequence numbers in IMAP commands. See IMAP
86 * rfc 'UID command' chapter.
87 * @param mixed $filter (since 1.4.1 and 1.5.0)
88 * @param mixed $outputstream (since 1.4.1 and 1.5.0)
89 * @param mixed $no_return (since 1.4.1 and 1.5.0)
90 * @return mixed returns false on imap error. displays error message
91 * if imap stream is not available.
92 * @since 1.2.3
93 */
1e0a2f0e 94function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response,
7c7b74b3 95 &$message, $unique_id = false,$filter=false,
96 $outputstream=false,$no_return=false) {
c5809184 97 if ($imap_stream) {
98 $sid = sqimap_session_id($unique_id);
1e0a2f0e 99 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
bc78cc6e 100 $tag_uid_a = explode(' ',trim($sid));
101 $tag = $tag_uid_a[0];
1e0a2f0e 102
bc78cc6e 103 $read = sqimap_read_data ($imap_stream, $tag, $handle_errors, $response,
7c7b74b3 104 $message, $query,$filter,$outputstream,$no_return);
91e0dccc 105 if (empty($read)) { //Imap server dropped its connection
ec73f243 106 $response = '';
107 $message = '';
108 return false;
109 }
bc78cc6e 110 /* retrieve the response and the message */
111 $response = $response[$tag];
112 $message = $message[$tag];
1e0a2f0e 113
bc78cc6e 114 if (!empty($read[$tag])) {
115 return $read[$tag][0];
116 } else {
117 return $read[$tag];
118 }
c5809184 119 } else {
120 global $squirrelmail_language, $color;
121 set_up_language($squirrelmail_language);
122 require_once(SM_PATH . 'functions/display_messages.php');
6fd95361 123 $string = "<b><font color=\"$color[2]\">\n" .
c5809184 124 _("ERROR : No available imapstream.") .
125 "</b></font>\n";
126 error_box($string,$color);
098ea084 127 return false;
1e0a2f0e 128 }
bc78cc6e 129}
48af4b64 130
0022f6db 131/**
132 * @param mixed $new_query
133 * @param string $tag
134 * @param array $aQuery
135 * @param boolean $unique_id
136 * @since 1.5.0
137 */
bc78cc6e 138function sqimap_prepare_pipelined_query($new_query,&$tag,&$aQuery,$unique_id) {
139 $sid = sqimap_session_id($unique_id);
140 $tag_uid_a = explode(' ',trim($sid));
141 $tag = $tag_uid_a[0];
0b38d197 142 $query = $sid . ' '.$new_query."\r\n";
bc78cc6e 143 $aQuery[$tag] = $query;
42a07ac1 144}
145
0022f6db 146/**
147 * @param stream $imap_stream
148 * @param array $aQueryList
149 * @param boolean $handle_errors
150 * @param array $aServerResponse
151 * @param array $aServerMessage
152 * @param boolean $unique_id
153 * @param mixed $filter see sqimap_retrieve_imap_response()
154 * @param mixed $outputstream see sqimap_retrieve_imap_response()
155 * @param mixed $no_return see sqimap_retrieve_imap_response()
156 * @since 1.5.0
157 */
1e0a2f0e 158function sqimap_run_pipelined_command ($imap_stream, $aQueryList, $handle_errors,
bc78cc6e 159 &$aServerResponse, &$aServerMessage, $unique_id = false,
1e0a2f0e 160 $filter=false,$outputstream=false,$no_return=false) {
bc78cc6e 161 $aResponse = false;
5c300c60 162
1e0a2f0e 163 /*
52c8b585 164 Do not fire all calls at once to the imap-server but split the calls up
1e0a2f0e 165 in portions of $iChunkSize. If we do not do that I think we misbehave as
52c8b585 166 IMAP client or should handle BYE calls if the IMAP-server drops the
167 connection because the number of queries is to large. This isn't tested
168 but a wild guess how it could work in the field.
1e0a2f0e 169
170 After testing it on Exchange 2000 we discovered that a chunksize of 32
0b38d197 171 was quicker then when we raised it to 128.
52c8b585 172 */
173 $iQueryCount = count($aQueryList);
174 $iChunkSize = 32;
175 // array_chunk would also do the job but it's supported from php > 4.2
176 $aQueryChunks = array();
177 $iLoops = floor($iQueryCount / $iChunkSize);
178
5c300c60 179 if ($iLoops * $iChunkSize != $iQueryCount) ++$iLoops;
52c8b585 180
181 if (!function_exists('array_chunk')) { // arraychunk replacement
5c300c60 182 reset($aQueryList);
52c8b585 183 for($i=0;$i<$iLoops;++$i) {
5c300c60 184 for($j=0;$j<$iChunkSize;++$j) {
185 $key = key($aQueryList);
186 $aTmp[$key] = $aQueryList[$key];
187 if (next($aQueryList) === false) break;
188 }
189 $aQueryChunks[] = $aTmp;
1e0a2f0e 190 }
52c8b585 191 } else {
192 $aQueryChunks = array_chunk($aQueryList,$iChunkSize,true);
bc78cc6e 193 }
1e0a2f0e 194
52c8b585 195 for ($i=0;$i<$iLoops;++$i) {
196 $aQuery = $aQueryChunks[$i];
197 foreach($aQuery as $tag => $query) {
198 fputs($imap_stream,$query);
199 $aResults[$tag] = false;
200 }
52c8b585 201 foreach($aQuery as $tag => $query) {
5c300c60 202 if ($aResults[$tag] == false) {
1e0a2f0e 203 $aReturnedResponse = sqimap_retrieve_imap_response ($imap_stream, $tag,
bc78cc6e 204 $handle_errors, $response, $message, $query,
205 $filter,$outputstream,$no_return);
52c8b585 206 foreach ($aReturnedResponse as $returned_tag => $aResponse) {
5c300c60 207 if (!empty($aResponse)) {
52c8b585 208 $aResults[$returned_tag] = $aResponse[0];
5c300c60 209 } else {
210 $aResults[$returned_tag] = $aResponse;
211 }
52c8b585 212 $aServerResponse[$returned_tag] = $response[$returned_tag];
213 $aServerMessage[$returned_tag] = $message[$returned_tag];
214 }
bc78cc6e 215 }
216 }
217 }
b7277e4f 218 return $aResults;
bc78cc6e 219}
9c737111 220
1e0a2f0e 221/**
48af4b64 222 * Custom fgets function: gets a line from the IMAP-server,
223 * no matter how big it may be.
224 * @param stream imap_stream the stream to read from
225 * @return string a line
0022f6db 226 * @since 1.2.8
b8c285ab 227 */
b8c285ab 228function sqimap_fgets($imap_stream) {
229 $read = '';
230 $buffer = 4096;
231 $results = '';
c41daf03 232 $offset = 0;
233 while (strpos($results, "\r\n", $offset) === false) {
b8c285ab 234 if (!($read = fgets($imap_stream, $buffer))) {
329a7ca5 235 /* this happens in case of an error */
236 /* reset $results because it's useless */
237 $results = false;
b8c285ab 238 break;
239 }
c41daf03 240 if ( $results != '' ) {
241 $offset = strlen($results) - 1;
242 }
b8c285ab 243 $results .= $read;
244 }
245 return $results;
246}
247
0022f6db 248/**
249 * @param stream $imap_stream
250 * @param integer $iSize
251 * @param mixed $filter see sqimap_retrieve_imap_response()
252 * @param mixed $outputstream see sqimap_retrieve_imap_response()
253 * @param mixed $no_return see sqimap_retrieve_imap_response()
254 * @return string
255 * @since 1.4.1
256 */
7c7b74b3 257function sqimap_fread($imap_stream,$iSize,$filter=false,
258 $outputstream=false, $no_return=false) {
259 if (!$filter || !$outputstream) {
260 $iBufferSize = $iSize;
261 } else {
811318c5 262 // see php bug 24033. They changed fread behaviour %$^&$%
977a6085 263 $iBufferSize = 7800; // multiple of 78 in case of base64 decoding.
264 }
265 if ($iSize < $iBufferSize) {
266 $iBufferSize = $iSize;
7c7b74b3 267 }
7c0ec1d8 268
5eba0be2 269 $iRetrieved = 0;
977a6085 270 $results = '';
271 $sRead = $sReadRem = '';
1e0a2f0e 272 // NB: fread can also stop at end of a packet on sockets.
977a6085 273 while ($iRetrieved < $iSize) {
7c7b74b3 274 $sRead = fread($imap_stream,$iBufferSize);
977a6085 275 $iLength = strlen($sRead);
276 $iRetrieved += $iLength ;
277 $iRemaining = $iSize - $iRetrieved;
278 if ($iRemaining < $iBufferSize) {
279 $iBufferSize = $iRemaining;
280 }
13aabbcf 281 if ($sRead == '') {
7c7b74b3 282 $results = false;
283 break;
284 }
13aabbcf 285 if ($sReadRem != '') {
977a6085 286 $sRead = $sReadRem . $sRead;
287 $sReadRem = '';
288 }
7c0ec1d8 289
13aabbcf 290 if ($filter && $sRead != '') {
1e0a2f0e 291 // in case the filter is base64 decoding we return a remainder
7c0ec1d8 292 $sReadRem = $filter($sRead);
7c7b74b3 293 }
13aabbcf 294 if ($outputstream && $sRead != '') {
7c7b74b3 295 if (is_resource($outputstream)) {
296 fwrite($outputstream,$sRead);
297 } else if ($outputstream == 'php://stdout') {
298 echo $sRead;
299 }
300 }
301 if ($no_return) {
302 $sRead = '';
1e0a2f0e 303 } else {
977a6085 304 $results .= $sRead;
7c7b74b3 305 }
7c7b74b3 306 }
1e0a2f0e 307 return $results;
308}
977a6085 309
7c0ec1d8 310
48af4b64 311/**
312 * Obsolete function, inform plugins that use it
b35a5862 313 * @since 1.1.3
314 * @deprecated (since 1.5.0) use sqimap_run_command or sqimap_run_command_list instead
48af4b64 315 */
1e0a2f0e 316function sqimap_read_data_list($imap_stream, $tag, $handle_errors,
0dc05a81 317 &$response, &$message, $query = '') {
318 global $color, $squirrelmail_language;
319 set_up_language($squirrelmail_language);
320 require_once(SM_PATH . 'functions/display_messages.php');
6fd95361 321 $string = "<b><font color=\"$color[2]\">\n" .
0dc05a81 322 _("ERROR : Bad function call.") .
6fd95361 323 "</b><br />\n" .
0dc05a81 324 _("Reason:") . ' '.
6fd95361 325 'There is a plugin installed which make use of the <br />' .
326 'SquirrelMail internal function sqimap_read_data_list.<br />'.
327 'Please adapt the installed plugin and let it use<br />'.
328 'sqimap_run_command or sqimap_run_command_list instead<br /><br />'.
329 'The following query was issued:<br />'.
330 htmlspecialchars($query) . '<br />' . "</font><br />\n";
0dc05a81 331 error_box($string,$color);
1e0a2f0e 332 echo '</body></html>';
333 exit;
0dc05a81 334}
7c7b74b3 335
48af4b64 336/**
337 * Function to display an error related to an IMAP-query.
338 * @param string title the caption of the error box
339 * @param string query the query that went wrong
ec73f243 340 * @param string message_title optional message title
341 * @param string message optional error message
342 * @param string $link an optional link to try again
48af4b64 343 * @return void
0022f6db 344 * @since 1.5.0
48af4b64 345 */
ec73f243 346function sqimap_error_box($title, $query = '', $message_title = '', $message = '', $link = '')
4974c2a0 347{
348 global $color, $squirrelmail_language;
349
350 set_up_language($squirrelmail_language);
351 require_once(SM_PATH . 'functions/display_messages.php');
6fd95361 352 $string = "<font color=\"$color[2]\"><b>\n" . $title . "</b><br />\n";
bf15f116 353 $cmd = explode(' ',$query);
354 $cmd= strtolower($cmd[0]);
355
356 if ($query != '' && $cmd != 'login')
6fd95361 357 $string .= _("Query:") . ' ' . htmlspecialchars($query) . '<br />';
4974c2a0 358 if ($message_title != '')
359 $string .= $message_title;
360 if ($message != '')
361 $string .= htmlspecialchars($message);
6fd95361 362 $string .= "</font><br />\n";
ec73f243 363 if ($link != '')
364 $string .= $link;
4974c2a0 365 error_box($string,$color);
366}
367
48af4b64 368/**
3411d4ec 369 * Reads the output from the IMAP stream. If handle_errors is set to true,
370 * this will also handle all errors that are received. If it is not set,
48af4b64 371 * the errors will be sent back through $response and $message.
0022f6db 372 * @param stream $imap_stream
373 * @param mixed $tag
374 * @param boolean $handle_errors
375 * @param array $response
376 * @param array $message
377 * @param mixed $query
378 * @param mixed $filter
379 * @param mixed $outputstream
380 * @param mixed $no_return
381 * @since 1.5.0
bee165ef 382 */
1e0a2f0e 383function sqimap_retrieve_imap_response($imap_stream, $tag, $handle_errors,
7c7b74b3 384 &$response, &$message, $query = '',
385 $filter = false, $outputstream = false, $no_return = false) {
9c737111 386 global $color, $squirrelmail_language;
9c737111 387 $read = '';
bc78cc6e 388 if (!is_array($message)) $message = array();
389 if (!is_array($response)) $response = array();
ec73f243 390 $aResponse = '';
b8c285ab 391 $resultlist = array();
392 $data = array();
393 $read = sqimap_fgets($imap_stream);
8d8da447 394 $i = 0;
bea3eb1e 395 while ($read) {
396 $char = $read{0};
397 switch ($char)
398 {
15bc7f66 399 case '+':
400 default:
401 $read = sqimap_fgets($imap_stream);
402 break;
403
404 case $tag{0}:
405 {
bea3eb1e 406 /* get the command */
407 $arg = '';
408 $i = strlen($tag)+1;
409 $s = substr($read,$i);
410 if (($j = strpos($s,' ')) || ($j = strpos($s,"\n"))) {
411 $arg = substr($s,0,$j);
412 }
413 $found_tag = substr($read,0,$i-1);
5c300c60 414 if ($found_tag) {
bea3eb1e 415 switch ($arg)
416 {
15bc7f66 417 case 'OK':
418 case 'BAD':
419 case 'NO':
420 case 'BYE':
421 case 'PREAUTH':
bc78cc6e 422 $response[$found_tag] = $arg;
423 $message[$found_tag] = trim(substr($read,$i+strlen($arg)));
424 if (!empty($data)) {
425 $resultlist[] = $data;
426 }
5c300c60 427 $aResponse[$found_tag] = $resultlist;
428 $data = $resultlist = array();
429 if ($found_tag == $tag) {
430 break 3; /* switch switch while */
431 }
432 break;
1e0a2f0e 433 default:
bea3eb1e 434 /* this shouldn't happen */
bc78cc6e 435 $response[$found_tag] = $arg;
436 $message[$found_tag] = trim(substr($read,$i+strlen($arg)));
437 if (!empty($data)) {
438 $resultlist[] = $data;
439 }
440 $aResponse[$found_tag] = $resultlist;
5c300c60 441 $data = $resultlist = array();
442 if ($found_tag == $tag) {
443 break 3; /* switch switch while */
444 }
bc78cc6e 445 }
bea3eb1e 446 }
5c300c60 447 $read = sqimap_fgets($imap_stream);
448 if ($read === false) { /* error */
4920e1e0 449 break 2; /* switch while */
5c300c60 450 }
451 break;
15bc7f66 452 } // end case $tag{0}
453
454 case '*':
455 {
bea3eb1e 456 if (preg_match('/^\*\s\d+\sFETCH/',$read)) {
457 /* check for literal */
458 $s = substr($read,-3);
459 $fetch_data = array();
460 do { /* outer loop, continue until next untagged fetch
461 or tagged reponse */
462 do { /* innerloop for fetching literals. with this loop
463 we prohibid that literal responses appear in the
464 outer loop so we can trust the untagged and
465 tagged info provided by $read */
466 if ($s === "}\r\n") {
467 $j = strrpos($read,'{');
468 $iLit = substr($read,$j+1,-3);
469 $fetch_data[] = $read;
7c7b74b3 470 $sLiteral = sqimap_fread($imap_stream,$iLit,$filter,$outputstream,$no_return);
329a7ca5 471 if ($sLiteral === false) { /* error */
472 break 4; /* while while switch while */
473 }
bea3eb1e 474 /* backwards compattibility */
475 $aLiteral = explode("\n", $sLiteral);
476 /* release not neaded data */
477 unset($sLiteral);
478 foreach ($aLiteral as $line) {
479 $fetch_data[] = $line ."\n";
480 }
481 /* release not neaded data */
1e0a2f0e 482 unset($aLiteral);
bea3eb1e 483 /* next fgets belongs to this fetch because
484 we just got the exact literalsize and there
485 must follow data to complete the response */
329a7ca5 486 $read = sqimap_fgets($imap_stream);
487 if ($read === false) { /* error */
488 break 4; /* while while switch while */
489 }
c0b23345 490 $fetch_data[] = $read;
bea3eb1e 491 } else {
329a7ca5 492 $fetch_data[] = $read;
bea3eb1e 493 }
494 /* retrieve next line and check in the while
495 statements if it belongs to this fetch response */
496 $read = sqimap_fgets($imap_stream);
329a7ca5 497 if ($read === false) { /* error */
498 break 4; /* while while switch while */
499 }
bea3eb1e 500 /* check for next untagged reponse and break */
501 if ($read{0} == '*') break 2;
502 $s = substr($read,-3);
503 } while ($s === "}\r\n");
504 $s = substr($read,-3);
505 } while ($read{0} !== '*' &&
106d4087 506 substr($read,0,strlen($tag)) !== $tag);
329a7ca5 507 $resultlist[] = $fetch_data;
bea3eb1e 508 /* release not neaded data */
509 unset ($fetch_data);
510 } else {
511 $s = substr($read,-3);
512 do {
513 if ($s === "}\r\n") {
514 $j = strrpos($read,'{');
515 $iLit = substr($read,$j+1,-3);
516 $data[] = $read;
329a7ca5 517 $sLiteral = fread($imap_stream,$iLit);
c0b23345 518 if ($sLiteral === false) { /* error */
329a7ca5 519 $read = false;
520 break 3; /* while switch while */
521 }
c0b23345 522 $data[] = $sLiteral;
b7277e4f 523 $data[] = sqimap_fgets($imap_stream);
bea3eb1e 524 } else {
329a7ca5 525 $data[] = $read;
bea3eb1e 526 }
527 $read = sqimap_fgets($imap_stream);
329a7ca5 528 if ($read === false) {
529 break 3; /* while switch while */
530 } else if ($read{0} == '*') {
106d4087 531 break;
532 }
bea3eb1e 533 $s = substr($read,-3);
534 } while ($s === "}\r\n");
535 break 1;
1e0a2f0e 536 }
bea3eb1e 537 break;
15bc7f66 538 } // end case '*'
539 } // end switch
c0b23345 540 } // end while
1e0a2f0e 541
c0b23345 542 /* error processing in case $read is false */
d7542838 543 if ($read === false) {
d3d9ef2d 544 // try to retrieve an untagged bye respons from the results
545 $sResponse = array_pop($data);
d7542838 546 if ($sResponse !== NULL && strpos($sResponse,'* BYE') !== false) {
547 if (!$handle_errors) {
548 $query = '';
549 }
550 sqimap_error_box(_("ERROR : Imap server closed the connection."), $query, _("Server responded:"),$sResponse);
551 echo '</body></html>';
552 exit;
553 } else if ($handle_errors) {
1e0a2f0e 554 unset($data);
ec73f243 555 sqimap_error_box(_("ERROR : Connection dropped by imap-server."), $query);
556 exit;
557 }
b8c285ab 558 }
1e0a2f0e 559
15bc7f66 560 /* Set $resultlist array */
b8c285ab 561 if (!empty($data)) {
bc78cc6e 562 //$resultlist[] = $data;
9c737111 563 }
b8c285ab 564 elseif (empty($resultlist)) {
1e0a2f0e 565 $resultlist[] = array();
b8c285ab 566 }
15bc7f66 567
568 /* Return result or handle errors */
bee165ef 569 if ($handle_errors == false) {
bc78cc6e 570 return $aResponse;
dd381002 571 }
4974c2a0 572 switch ($response[$tag]) {
dd381002 573 case 'OK':
bc78cc6e 574 return $aResponse;
329a7ca5 575 break;
1e0a2f0e 576 case 'NO':
dd381002 577 /* ignore this error from M$ exchange, it is not fatal (aka bug) */
6b6c2e06 578 if (strstr($message[$tag], 'command resulted in') === false) {
4974c2a0 579 sqimap_error_box(_("ERROR : Could not complete request."), $query, _("Reason Given: "), $message[$tag]);
329a7ca5 580 echo '</body></html>';
052e0c26 581 exit;
9c737111 582 }
329a7ca5 583 break;
1e0a2f0e 584 case 'BAD':
4974c2a0 585 sqimap_error_box(_("ERROR : Bad or malformed request."), $query, _("Server responded: "), $message[$tag]);
1e0a2f0e 586 echo '</body></html>';
587 exit;
588 case 'BYE':
4974c2a0 589 sqimap_error_box(_("ERROR : Imap server closed the connection."), $query, _("Server responded: "), $message[$tag]);
1e0a2f0e 590 echo '</body></html>';
9c737111 591 exit;
1e0a2f0e 592 default:
4974c2a0 593 sqimap_error_box(_("ERROR : Unknown imap response."), $query, _("Server responded: "), $message[$tag]);
329a7ca5 594 /* the error is displayed but because we don't know the reponse we
595 return the result anyway */
1e0a2f0e 596 return $aResponse;
329a7ca5 597 break;
9c737111 598 }
9c737111 599}
600
0022f6db 601/**
602 * @param stream $imap_stream
603 * @param string $tag_uid
604 * @param boolean $handle_errors
605 * @param array $response
606 * @param array $message
607 * @param mixed $query (since 1.2.5)
608 * @param mixed $filter (since 1.4.1) see sqimap_retrieve_imap_response()
609 * @param mixed $outputstream (since 1.4.1) see sqimap_retrieve_imap_response()
610 * @param mixed $no_return (since 1.4.1) see sqimap_retrieve_imap_response()
611 */
1e0a2f0e 612function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors,
7c7b74b3 613 &$response, &$message, $query = '',
614 $filter=false,$outputstream=false,$no_return=false) {
bc78cc6e 615
616 $tag_uid_a = explode(' ',trim($tag_uid));
617 $tag = $tag_uid_a[0];
618
1e0a2f0e 619 $res = sqimap_retrieve_imap_response($imap_stream, $tag, $handle_errors,
620 $response, $message, $query,$filter,$outputstream,$no_return);
621 return $res;
9c737111 622}
623
48af4b64 624/**
b98732e8 625 * Connects to the IMAP server and returns a resource identifier for use with
626 * the other SquirrelMail IMAP functions. Does NOT login!
48af4b64 627 * @param string server hostname of IMAP server
628 * @param int port port number to connect to
629 * @param bool tls whether to use TLS when connecting.
630 * @return imap-stream resource identifier
0022f6db 631 * @since 1.5.0 (usable only in 1.5.1 or later)
b98732e8 632 */
633function sqimap_create_stream($server,$port,$tls=false) {
ce68b76b 634 global $squirrelmail_language;
b98732e8 635
57ffe0af 636 if ($tls == true) {
b98732e8 637 if ((check_php_version(4,3)) and (extension_loaded('openssl'))) {
638 /* Use TLS by prefixing "tls://" to the hostname */
57ffe0af 639 $server = 'tls://' . $server;
b98732e8 640 } else {
641 require_once(SM_PATH . 'functions/display_messages.php');
3b151851 642 logout_error( sprintf(_("Error connecting to IMAP server: %s."), $server).
643 '<br />'.
644 _("TLS is enabled, but this version of PHP does not support TLS sockets, or is missing the openssl extension.").
645 '<br /><br />'.
646 _("Please contact your system administrator and report this error.") );
b98732e8 647 }
648 }
649
82f403aa 650 $imap_stream = @fsockopen($server, $port, $error_number, $error_string, 15);
b98732e8 651
652 /* Do some error correction */
653 if (!$imap_stream) {
654 set_up_language($squirrelmail_language, true);
655 require_once(SM_PATH . 'functions/display_messages.php');
3b151851 656 logout_error( sprintf(_("Error connecting to IMAP server: %s."), $server).
657 "<br />\r\n$error_number : $error_string<br />\r\n" );
b98732e8 658 exit;
659 }
660 $server_info = fgets ($imap_stream, 1024);
661 return $imap_stream;
662}
663
48af4b64 664/**
3411d4ec 665 * Logs the user into the imap server. If $hide is set, no error messages
666 * will be displayed. This function returns the imap connection handle.
0022f6db 667 * @param string $username user name
668 * @param string $password encrypted password
669 * @param string $imap_server_address address of imap server
670 * @param integer $imap_port port of imap server
671 * @param boolean $hide controls display connection errors
672 * @return stream
3411d4ec 673 */
9c737111 674function sqimap_login ($username, $password, $imap_server_address, $imap_port, $hide) {
fe55c7c7 675 global $color, $squirrelmail_language, $onetimepad, $use_imap_tls,
676 $imap_auth_mech, $sqimap_capabilities;
85fc999e 677
eb2f6102 678 if (!isset($onetimepad) || empty($onetimepad)) {
679 sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION );
680 }
fe55c7c7 681 if (!isset($sqimap_capabilities)) {
682 sqgetglobalvar('sqimap_capabilities' , $capability , SQ_SESSION );
683 }
684
b98732e8 685 $host = $imap_server_address;
bd9829d7 686 $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
fe55c7c7 687
b98732e8 688 $imap_stream = sqimap_create_stream($imap_server_address,$imap_port,$use_imap_tls);
fe55c7c7 689
2f1f7a12 690 /* Decrypt the password */
691 $password = OneTimePadDecrypt($password, $onetimepad);
692
b98732e8 693 if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
3b151851 694 // We're using some sort of authentication OTHER than plain or login
b98732e8 695 $tag=sqimap_session_id(false);
696 if ($imap_auth_mech == 'digest-md5') {
098ea084 697 $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
b98732e8 698 } elseif ($imap_auth_mech == 'cram-md5') {
098ea084 699 $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
b98732e8 700 }
701 fputs($imap_stream,$query);
702 $answer=sqimap_fgets($imap_stream);
703 // Trim the "+ " off the front
704 $response=explode(" ",$answer,3);
705 if ($response[0] == '+') {
098ea084 706 // Got a challenge back
b98732e8 707 $challenge=$response[1];
708 if ($imap_auth_mech == 'digest-md5') {
709 $reply = digest_md5_response($username,$password,$challenge,'imap',$host);
710 } elseif ($imap_auth_mech == 'cram-md5') {
711 $reply = cram_md5_response($username,$password,$challenge);
712 }
713 fputs($imap_stream,$reply);
714 $read=sqimap_fgets($imap_stream);
715 if ($imap_auth_mech == 'digest-md5') {
3b151851 716 // DIGEST-MD5 has an extra step..
b98732e8 717 if (substr($read,0,1) == '+') { // OK so far..
098ea084 718 fputs($imap_stream,"\r\n");
719 $read=sqimap_fgets($imap_stream);
098ea084 720 }
b98732e8 721 }
722 $results=explode(" ",$read,3);
723 $response=$results[1];
724 $message=$results[2];
725 } else {
3b151851 726 // Fake the response, so the error trap at the bottom will work
b98732e8 727 $response="BAD";
728 $message='IMAP server does not appear to support the authentication method selected.';
729 $message .= ' Please contact your system administrator.';
730 }
fe0b18b3 731 } elseif ($imap_auth_mech == 'login') {
b98732e8 732 // Original IMAP login code
733 $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
734 $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
1e7fc1cb 735 } elseif ($imap_auth_mech == 'plain') {
fe55c7c7 736 /***
737 * SASL PLAIN
738 *
739 * RFC 2595 Chapter 6
740 *
741 * The mechanism consists of a single message from the client to the
742 * server. The client sends the authorization identity (identity to
743 * login as), followed by a US-ASCII NUL character, followed by the
744 * authentication identity (identity whose password will be used),
745 * followed by a US-ASCII NUL character, followed by the clear-text
746 * password. The client may leave the authorization identity empty to
747 * indicate that it is the same as the authentication identity.
748 *
749 **/
b98732e8 750 $tag=sqimap_session_id(false);
2bd6b461 751 $sasl = (isset($capability['SASL-IR']) && $capability['SASL-IR']) ? true : false;
b98732e8 752 $auth = base64_encode("$username\0$username\0$password");
fe55c7c7 753 if ($sasl) {
754 // IMAP Extension for SASL Initial Client Response
2bd6b461 755 // <draft-siemborski-imap-sasl-initial-response-01b.txt>
fe55c7c7 756 $query = $tag . " AUTHENTICATE PLAIN $auth\r\n";
757 fputs($imap_stream, $query);
b98732e8 758 $read = sqimap_fgets($imap_stream);
fe55c7c7 759 } else {
760 $query = $tag . " AUTHENTICATE PLAIN\r\n";
761 fputs($imap_stream, $query);
762 $read=sqimap_fgets($imap_stream);
763 if (substr($read,0,1) == '+') { // OK so far..
764 fputs($imap_stream, "$auth\r\n");
765 $read = sqimap_fgets($imap_stream);
766 }
098ea084 767 }
b98732e8 768 $results=explode(" ",$read,3);
769 $response=$results[1];
770 $message=$results[2];
771 } else {
772 $response="BAD";
773 $message="Internal SquirrelMail error - unknown IMAP authentication method chosen. Please contact the developers.";
774 }
fe55c7c7 775
b98732e8 776 /* If the connection was not successful, lets see why */
9c737111 777 if ($response != 'OK') {
778 if (!$hide) {
74424a43 779 if ($response != 'NO') {
3411d4ec 780 /* "BAD" and anything else gets reported here. */
098ea084 781 $message = htmlspecialchars($message);
9c737111 782 set_up_language($squirrelmail_language, true);
098ea084 783 require_once(SM_PATH . 'functions/display_messages.php');
9c737111 784 if ($response == 'BAD') {
6fd95361 785 $string = sprintf (_("Bad request: %s")."<br />\r\n", $message);
9c737111 786 } else {
6fd95361 787 $string = sprintf (_("Unknown error: %s") . "<br />\n", $message);
9c737111 788 }
1e7fc1cb 789 if (isset($read) && is_array($read)) {
6fd95361 790 $string .= '<br />' . _("Read data:") . "<br />\n";
9c737111 791 foreach ($read as $line) {
6fd95361 792 $string .= htmlspecialchars($line) . "<br />\n";
9c737111 793 }
794 }
098ea084 795 error_box($string,$color);
9c737111 796 exit;
165e24a7 797 } else {
3411d4ec 798 /*
799 * If the user does not log in with the correct
1c72b151 800 * username and password it is not possible to get the
801 * correct locale from the user's preferences.
802 * Therefore, apply the same hack as on the login
803 * screen.
3411d4ec 804 *
805 * $squirrelmail_language is set by a cookie when
1c72b151 806 * the user selects language and logs out
bee165ef 807 */
fe55c7c7 808
9c737111 809 set_up_language($squirrelmail_language, true);
bd9c880b 810 include_once(SM_PATH . 'functions/display_messages.php' );
098ea084 811 sqsession_destroy();
d5c472f1 812 /* terminate the session nicely */
813 sqimap_logout($imap_stream);
bd9c880b 814 logout_error( _("Unknown user or password incorrect.") );
9c737111 815 exit;
052e0c26 816 }
9c737111 817 } else {
052e0c26 818 exit;
9c737111 819 }
820 }
1d20443c 821
822 /* Special error case:
823 * Login referrals. The server returns:
824 * ? OK [REFERRAL <imap url>]
825 * Check RFC 2221 for details. Since we do not support login referrals yet
826 * we log the user out.
827 */
828 if ( strpos($message, "REFERRAL") ) {
829 sqimap_logout($imap_stream);
830 set_up_language($squirrelmail_language, true);
831 include_once(SM_PATH . 'functions/display_messages.php' );
832 sqsession_destroy();
833 logout_error( _("Your mailbox is not located on this server.<br>".
834 "Try a different server or consult your Administrator") );
835 exit;
836 }
837
9c737111 838 return $imap_stream;
839}
f1e6f580 840
48af4b64 841/**
842 * Simply logs out the IMAP session
843 * @param stream imap_stream the IMAP connection to log out.
844 * @return void
845 */
9c737111 846function sqimap_logout ($imap_stream) {
8d936b0c 847 /* Logout is not valid until the server returns 'BYE'
848 * If we don't have an imap_ stream we're already logged out */
26a2cc8b 849 if(isset($imap_stream) && $imap_stream)
8d936b0c 850 sqimap_run_command($imap_stream, 'LOGOUT', false, $response, $message);
9c737111 851}
852
48af4b64 853/**
854 * Retreive the CAPABILITY string from the IMAP server.
855 * If capability is set, returns only that specific capability,
856 * else returns array of all capabilities.
0022f6db 857 * @param $imap_stream
858 * @param string $capability (optional since 1.3.0)
859 * @return mixed (string if $capability is set and found,
860 * false, if $capability is set and not found,
861 * array if $capability not set)
48af4b64 862 */
487daa81 863function sqimap_capability($imap_stream, $capability='') {
9c737111 864 global $sqimap_capabilities;
9c737111 865 if (!is_array($sqimap_capabilities)) {
1c72b151 866 $read = sqimap_run_command($imap_stream, 'CAPABILITY', true, $a, $b);
867
9c737111 868 $c = explode(' ', $read[0]);
869 for ($i=2; $i < count($c); $i++) {
870 $cap_list = explode('=', $c[$i]);
3411d4ec 871 if (isset($cap_list[1])) {
ecc92309 872 // FIX ME. capabilities can occure multiple times.
873 // THREAD=REFERENCES THREAD=ORDEREDSUBJECT
9c737111 874 $sqimap_capabilities[$cap_list[0]] = $cap_list[1];
3411d4ec 875 } else {
9c737111 876 $sqimap_capabilities[$cap_list[0]] = TRUE;
3411d4ec 877 }
f1e6f580 878 }
9c737111 879 }
487daa81 880 if ($capability) {
098ea084 881 if (isset($sqimap_capabilities[$capability])) {
882 return $sqimap_capabilities[$capability];
883 } else {
884 return false;
885 }
f1e6f580 886 }
487daa81 887 return $sqimap_capabilities;
9c737111 888}
889
48af4b64 890/**
891 * Returns the delimeter between mailboxes: INBOX/Test, or INBOX.Test
0022f6db 892 * @param stream $imap_stream
893 * @return string
48af4b64 894 */
9c737111 895function sqimap_get_delimiter ($imap_stream = false) {
3411d4ec 896 global $sqimap_delimiter, $optional_delimiter;
85fc999e 897
9c737111 898 /* Use configured delimiter if set */
899 if((!empty($optional_delimiter)) && $optional_delimiter != 'detect') {
900 return $optional_delimiter;
901 }
85fc999e 902
9c737111 903 /* Do some caching here */
904 if (!$sqimap_delimiter) {
905 if (sqimap_capability($imap_stream, 'NAMESPACE')) {
3411d4ec 906 /*
907 * According to something that I can't find, this is supposed to work on all systems
908 * OS: This won't work in Courier IMAP.
909 * OS: According to rfc2342 response from NAMESPACE command is:
910 * OS: * NAMESPACE (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES)
911 * OS: We want to lookup all personal NAMESPACES...
912 */
1c72b151 913 $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b);
f1e6f580 914 if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) {
9c737111 915 if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) {
f1e6f580 916 $pn = $data2[1];
9c737111 917 }
f1e6f580 918 $pna = explode(')(', $pn);
9c737111 919 while (list($k, $v) = each($pna)) {
862ff2d3 920 $lst = explode('"', $v);
921 if (isset($lst[3])) {
922 $pn[$lst[1]] = $lst[3];
923 } else {
74424a43 924 $pn[$lst[1]] = '';
862ff2d3 925 }
f1e6f580 926 }
927 }
928 $sqimap_delimiter = $pn[0];
929 } else {
930 fputs ($imap_stream, ". LIST \"INBOX\" \"\"\r\n");
931 $read = sqimap_read_data($imap_stream, '.', true, $a, $b);
91e0dccc 932 $read = $read['.'][0]; //sqimap_read_data() now returns a tag array of response array
f1e6f580 933 $quote_position = strpos ($read[0], '"');
934 $sqimap_delimiter = substr ($read[0], $quote_position+1, 1);
935 }
936 }
937 return $sqimap_delimiter;
9c737111 938}
052e0c26 939
48af4b64 940/**
941 * This encodes a mailbox name for use in IMAP commands.
942 * @param string what the mailbox to encode
943 * @return string the encoded mailbox string
0022f6db 944 * @since 1.5.0
48af4b64 945 */
b2306cbe 946function sqimap_encode_mailbox_name($what)
947{
91e0dccc 948 if (ereg("[\"\\\r\n]", $what))
949 return '{' . strlen($what) . "}\r\n" . $what; /* 4.3 literal form */
950 return '"' . $what . '"'; /* 4.3 quoted string form */
b2306cbe 951}
952
48af4b64 953/**
954 * Gets the number of messages in the current mailbox.
1e0a2f0e 955 *
956 * OBSOLETE use sqimap_status_messages instead.
48af4b64 957 */
9c737111 958function sqimap_get_num_messages ($imap_stream, $mailbox) {
b2306cbe 959 $read_ary = sqimap_run_command ($imap_stream, 'EXAMINE ' . sqimap_encode_mailbox_name($mailbox), false, $result, $message);
9c737111 960 for ($i = 0; $i < count($read_ary); $i++) {
85fc999e 961 if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
962 return $regs[1];
963 }
9c737111 964 }
1f720b34 965 return false; //"BUG! Couldn't get number of messages in $mailbox!";
9c737111 966}
1e0a2f0e 967include_once(SM_PATH . 'functions/rfc822address.php');
9c737111 968
1e0a2f0e 969/**
970 * OBSOLETE FUNCTION should be removed after mailbox_display,
971 * printMessage function is adapted
972 */
91688e5f 973function parseAddress($address, $max=0) {
1e0a2f0e 974 $aAddress = parseRFC822Address($address,array('limit'=> $max));
975 /*
976 * Because the expected format of the array element is changed we adapt it now.
977 * This also implies that this function is obsolete and should be removed after the
978 * rest of the source is adapted. See Rfc822Address.php for the new function.
979 */
980 array_walk($aAddress, '_adaptAddress');
981 return $aAddress;
982}
91688e5f 983
1e0a2f0e 984/**
985 * OBSOLETE FUNCTION should be removed after mailbox_display,
986 * printMessage function is adapted
987 */
988function _adaptAddress(&$aAddr,$k) {
989 $sPersonal = (isset($aAddr[SQM_ADDR_PERSONAL]) && $aAddr[SQM_ADDR_PERSONAL]) ?
990 $aAddr[SQM_ADDR_PERSONAL] : '';
991 $sEmail = ($aAddr[SQM_ADDR_HOST]) ?
3cd52f38 992 $aAddr[SQM_ADDR_MAILBOX] . '@'.$aAddr[SQM_ADDR_HOST] :
993 $aAddr[SQM_ADDR_MAILBOX];
1e0a2f0e 994 $aAddr = array($sEmail,$sPersonal);
995}
91688e5f 996
48af4b64 997/**
998 * Returns the number of unseen messages in this folder.
26e90c74 999 * obsoleted by sqimap_status_messages !
3411d4ec 1000 */
9c737111 1001function sqimap_unseen_messages ($imap_stream, $mailbox) {
26e90c74 1002 $aStatus = sqimap_status_messages($imap_stream,$mailbox,array('UNSEEN'));
1003 return $aStatus['UNSEEN'];
9c737111 1004}
1005
48af4b64 1006/**
26e90c74 1007 * Returns the status items of a mailbox.
1008 * Default it returns MESSAGES,UNSEEN and RECENT
1009 * Supported status items are MESSAGES, UNSEEN, RECENT, UIDNEXT and UIDVALIDITY
1f720b34 1010 */
1e0a2f0e 1011function sqimap_status_messages ($imap_stream, $mailbox,
26e90c74 1012 $aStatusItems = array('MESSAGES','UNSEEN','RECENT')) {
1013
3fedd15b 1014 $aStatusItems = implode(' ',$aStatusItems);
26e90c74 1015 $read_ary = sqimap_run_command ($imap_stream, 'STATUS ' . sqimap_encode_mailbox_name($mailbox) .
1016 " ($aStatusItems)", false, $result, $message);
1f720b34 1017 $i = 0;
26e90c74 1018 $messages = $unseen = $recent = $uidnext = $uidvalidity = false;
1f720b34 1019 $regs = array(false,false);
1020 while (isset($read_ary[$i])) {
1021 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 1022 $unseen = $regs[1];
1023 }
1f720b34 1024 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 1025 $messages = $regs[1];
1026 }
b8ec18ef 1027 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 1028 $recent = $regs[1];
1e0a2f0e 1029 }
26e90c74 1030 if (preg_match('/UIDNEXT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
1031 $uidnext = $regs[1];
1e0a2f0e 1032 }
26e90c74 1033 if (preg_match('/UIDVALIDITY\s+([0-9]+)/i', $read_ary[$i], $regs)) {
1034 $uidvalidity = $regs[1];
1e0a2f0e 1035 }
1f720b34 1036 $i++;
1037 }
1e0a2f0e 1038 return array('MESSAGES' => $messages,
1039 'UNSEEN'=>$unseen,
26e90c74 1040 'RECENT' => $recent,
1041 'UIDNEXT' => $uidnext,
1042 'UIDVALIDITY' => $uidvalidity);
1f720b34 1043}
1044
9c737111 1045
48af4b64 1046/**
1047 * Saves a message to a given folder -- used for saving sent messages
3411d4ec 1048 */
9c737111 1049function sqimap_append ($imap_stream, $sent_folder, $length) {
b2306cbe 1050 fputs ($imap_stream, sqimap_session_id() . ' APPEND ' . sqimap_encode_mailbox_name($sent_folder) . " (\\Seen) \{$length}\r\n");
85fc999e 1051 $tmp = fgets ($imap_stream, 1024);
7ec3a6b9 1052 sqimap_append_checkresponse($tmp, $sent_folder);
9c737111 1053}
1054
8813fb15 1055function sqimap_append_done ($imap_stream, $folder='') {
9c737111 1056 fputs ($imap_stream, "\r\n");
1057 $tmp = fgets ($imap_stream, 1024);
7ec3a6b9 1058 sqimap_append_checkresponse($tmp, $folder);
1059}
1060
1061function sqimap_append_checkresponse($response, $folder) {
1062
1063 if (preg_match("/(.*)(BAD|NO)(.*)$/", $response, $regs)) {
1064 global $squirrelmail_language, $color;
69146537 1065 set_up_language($squirrelmail_language);
1f720b34 1066 require_once(SM_PATH . 'functions/display_messages.php');
7ec3a6b9 1067
098ea084 1068 $reason = $regs[3];
1069 if ($regs[2] == 'NO') {
6fd95361 1070 $string = "<b><font color=\"$color[2]\">\n" .
098ea084 1071 _("ERROR : Could not append message to") ." $folder." .
6fd95361 1072 "</b><br />\n" .
098ea084 1073 _("Server responded: ") .
6fd95361 1074 $reason . "<br />\n";
098ea084 1075 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
1e0a2f0e 1076 $string .= _("Solution: ") .
1077 _("Remove unneccessary messages from your folder and start with your Trash folder.")
6fd95361 1078 ."<br />\n";
098ea084 1079 }
1080 $string .= "</font>\n";
1081 error_box($string,$color);
1082 } else {
6fd95361 1083 $string = "<b><font color=\"$color[2]\">\n" .
098ea084 1084 _("ERROR : Bad or malformed request.") .
6fd95361 1085 "</b><br />\n" .
098ea084 1086 _("Server responded: ") .
7ec3a6b9 1087 $reason . "</font><br />\n";
098ea084 1088 error_box($string,$color);
8813fb15 1089 exit;
098ea084 1090 }
69146537 1091 }
9c737111 1092}
85fc999e 1093
bd9829d7 1094function sqimap_get_user_server ($imap_server, $username) {
bd9829d7 1095 if (substr($imap_server, 0, 4) != "map:") {
1096 return $imap_server;
1097 }
bd9829d7 1098 $function = substr($imap_server, 4);
1099 return $function($username);
1100}
1101
48af4b64 1102/**
1103 * This is an example that gets imapservers from yellowpages (NIS).
1e0a2f0e 1104 * you can simple put map:map_yp_alias in your $imap_server_address
bd9829d7 1105 * in config.php use your own function instead map_yp_alias to map your
48af4b64 1106 * LDAP whatever way to find the users imapserver.
1107 */
bd9829d7 1108function map_yp_alias($username) {
1109 $yp = `ypmatch $username aliases`;
1110 return chop(substr($yp, strlen($username)+1));
1e0a2f0e 1111}
bd9829d7 1112
7ec3a6b9 1113?>