adding param and since tags to some functions
[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 }
9c737111 821 return $imap_stream;
822}
f1e6f580 823
48af4b64 824/**
825 * Simply logs out the IMAP session
826 * @param stream imap_stream the IMAP connection to log out.
827 * @return void
828 */
9c737111 829function sqimap_logout ($imap_stream) {
8d936b0c 830 /* Logout is not valid until the server returns 'BYE'
831 * If we don't have an imap_ stream we're already logged out */
26a2cc8b 832 if(isset($imap_stream) && $imap_stream)
8d936b0c 833 sqimap_run_command($imap_stream, 'LOGOUT', false, $response, $message);
9c737111 834}
835
48af4b64 836/**
837 * Retreive the CAPABILITY string from the IMAP server.
838 * If capability is set, returns only that specific capability,
839 * else returns array of all capabilities.
0022f6db 840 * @param $imap_stream
841 * @param string $capability (optional since 1.3.0)
842 * @return mixed (string if $capability is set and found,
843 * false, if $capability is set and not found,
844 * array if $capability not set)
48af4b64 845 */
487daa81 846function sqimap_capability($imap_stream, $capability='') {
9c737111 847 global $sqimap_capabilities;
9c737111 848 if (!is_array($sqimap_capabilities)) {
1c72b151 849 $read = sqimap_run_command($imap_stream, 'CAPABILITY', true, $a, $b);
850
9c737111 851 $c = explode(' ', $read[0]);
852 for ($i=2; $i < count($c); $i++) {
853 $cap_list = explode('=', $c[$i]);
3411d4ec 854 if (isset($cap_list[1])) {
ecc92309 855 // FIX ME. capabilities can occure multiple times.
856 // THREAD=REFERENCES THREAD=ORDEREDSUBJECT
9c737111 857 $sqimap_capabilities[$cap_list[0]] = $cap_list[1];
3411d4ec 858 } else {
9c737111 859 $sqimap_capabilities[$cap_list[0]] = TRUE;
3411d4ec 860 }
f1e6f580 861 }
9c737111 862 }
487daa81 863 if ($capability) {
098ea084 864 if (isset($sqimap_capabilities[$capability])) {
865 return $sqimap_capabilities[$capability];
866 } else {
867 return false;
868 }
f1e6f580 869 }
487daa81 870 return $sqimap_capabilities;
9c737111 871}
872
48af4b64 873/**
874 * Returns the delimeter between mailboxes: INBOX/Test, or INBOX.Test
0022f6db 875 * @param stream $imap_stream
876 * @return string
48af4b64 877 */
9c737111 878function sqimap_get_delimiter ($imap_stream = false) {
3411d4ec 879 global $sqimap_delimiter, $optional_delimiter;
85fc999e 880
9c737111 881 /* Use configured delimiter if set */
882 if((!empty($optional_delimiter)) && $optional_delimiter != 'detect') {
883 return $optional_delimiter;
884 }
85fc999e 885
9c737111 886 /* Do some caching here */
887 if (!$sqimap_delimiter) {
888 if (sqimap_capability($imap_stream, 'NAMESPACE')) {
3411d4ec 889 /*
890 * According to something that I can't find, this is supposed to work on all systems
891 * OS: This won't work in Courier IMAP.
892 * OS: According to rfc2342 response from NAMESPACE command is:
893 * OS: * NAMESPACE (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES)
894 * OS: We want to lookup all personal NAMESPACES...
895 */
1c72b151 896 $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b);
f1e6f580 897 if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) {
9c737111 898 if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) {
f1e6f580 899 $pn = $data2[1];
9c737111 900 }
f1e6f580 901 $pna = explode(')(', $pn);
9c737111 902 while (list($k, $v) = each($pna)) {
862ff2d3 903 $lst = explode('"', $v);
904 if (isset($lst[3])) {
905 $pn[$lst[1]] = $lst[3];
906 } else {
74424a43 907 $pn[$lst[1]] = '';
862ff2d3 908 }
f1e6f580 909 }
910 }
911 $sqimap_delimiter = $pn[0];
912 } else {
913 fputs ($imap_stream, ". LIST \"INBOX\" \"\"\r\n");
914 $read = sqimap_read_data($imap_stream, '.', true, $a, $b);
91e0dccc 915 $read = $read['.'][0]; //sqimap_read_data() now returns a tag array of response array
f1e6f580 916 $quote_position = strpos ($read[0], '"');
917 $sqimap_delimiter = substr ($read[0], $quote_position+1, 1);
918 }
919 }
920 return $sqimap_delimiter;
9c737111 921}
052e0c26 922
48af4b64 923/**
924 * This encodes a mailbox name for use in IMAP commands.
925 * @param string what the mailbox to encode
926 * @return string the encoded mailbox string
0022f6db 927 * @since 1.5.0
48af4b64 928 */
b2306cbe 929function sqimap_encode_mailbox_name($what)
930{
91e0dccc 931 if (ereg("[\"\\\r\n]", $what))
932 return '{' . strlen($what) . "}\r\n" . $what; /* 4.3 literal form */
933 return '"' . $what . '"'; /* 4.3 quoted string form */
b2306cbe 934}
935
48af4b64 936/**
937 * Gets the number of messages in the current mailbox.
1e0a2f0e 938 *
939 * OBSOLETE use sqimap_status_messages instead.
48af4b64 940 */
9c737111 941function sqimap_get_num_messages ($imap_stream, $mailbox) {
b2306cbe 942 $read_ary = sqimap_run_command ($imap_stream, 'EXAMINE ' . sqimap_encode_mailbox_name($mailbox), false, $result, $message);
9c737111 943 for ($i = 0; $i < count($read_ary); $i++) {
85fc999e 944 if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
945 return $regs[1];
946 }
9c737111 947 }
1f720b34 948 return false; //"BUG! Couldn't get number of messages in $mailbox!";
9c737111 949}
1e0a2f0e 950include_once(SM_PATH . 'functions/rfc822address.php');
9c737111 951
1e0a2f0e 952/**
953 * OBSOLETE FUNCTION should be removed after mailbox_display,
954 * printMessage function is adapted
955 */
91688e5f 956function parseAddress($address, $max=0) {
1e0a2f0e 957 $aAddress = parseRFC822Address($address,array('limit'=> $max));
958 /*
959 * Because the expected format of the array element is changed we adapt it now.
960 * This also implies that this function is obsolete and should be removed after the
961 * rest of the source is adapted. See Rfc822Address.php for the new function.
962 */
963 array_walk($aAddress, '_adaptAddress');
964 return $aAddress;
965}
91688e5f 966
1e0a2f0e 967/**
968 * OBSOLETE FUNCTION should be removed after mailbox_display,
969 * printMessage function is adapted
970 */
971function _adaptAddress(&$aAddr,$k) {
972 $sPersonal = (isset($aAddr[SQM_ADDR_PERSONAL]) && $aAddr[SQM_ADDR_PERSONAL]) ?
973 $aAddr[SQM_ADDR_PERSONAL] : '';
974 $sEmail = ($aAddr[SQM_ADDR_HOST]) ?
3cd52f38 975 $aAddr[SQM_ADDR_MAILBOX] . '@'.$aAddr[SQM_ADDR_HOST] :
976 $aAddr[SQM_ADDR_MAILBOX];
1e0a2f0e 977 $aAddr = array($sEmail,$sPersonal);
978}
91688e5f 979
48af4b64 980/**
981 * Returns the number of unseen messages in this folder.
26e90c74 982 * obsoleted by sqimap_status_messages !
3411d4ec 983 */
9c737111 984function sqimap_unseen_messages ($imap_stream, $mailbox) {
26e90c74 985 $aStatus = sqimap_status_messages($imap_stream,$mailbox,array('UNSEEN'));
986 return $aStatus['UNSEEN'];
9c737111 987}
988
48af4b64 989/**
26e90c74 990 * Returns the status items of a mailbox.
991 * Default it returns MESSAGES,UNSEEN and RECENT
992 * Supported status items are MESSAGES, UNSEEN, RECENT, UIDNEXT and UIDVALIDITY
1f720b34 993 */
1e0a2f0e 994function sqimap_status_messages ($imap_stream, $mailbox,
26e90c74 995 $aStatusItems = array('MESSAGES','UNSEEN','RECENT')) {
996
3fedd15b 997 $aStatusItems = implode(' ',$aStatusItems);
26e90c74 998 $read_ary = sqimap_run_command ($imap_stream, 'STATUS ' . sqimap_encode_mailbox_name($mailbox) .
999 " ($aStatusItems)", false, $result, $message);
1f720b34 1000 $i = 0;
26e90c74 1001 $messages = $unseen = $recent = $uidnext = $uidvalidity = false;
1f720b34 1002 $regs = array(false,false);
1003 while (isset($read_ary[$i])) {
1004 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 1005 $unseen = $regs[1];
1006 }
1f720b34 1007 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 1008 $messages = $regs[1];
1009 }
b8ec18ef 1010 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 1011 $recent = $regs[1];
1e0a2f0e 1012 }
26e90c74 1013 if (preg_match('/UIDNEXT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
1014 $uidnext = $regs[1];
1e0a2f0e 1015 }
26e90c74 1016 if (preg_match('/UIDVALIDITY\s+([0-9]+)/i', $read_ary[$i], $regs)) {
1017 $uidvalidity = $regs[1];
1e0a2f0e 1018 }
1f720b34 1019 $i++;
1020 }
1e0a2f0e 1021 return array('MESSAGES' => $messages,
1022 'UNSEEN'=>$unseen,
26e90c74 1023 'RECENT' => $recent,
1024 'UIDNEXT' => $uidnext,
1025 'UIDVALIDITY' => $uidvalidity);
1f720b34 1026}
1027
9c737111 1028
48af4b64 1029/**
1030 * Saves a message to a given folder -- used for saving sent messages
3411d4ec 1031 */
9c737111 1032function sqimap_append ($imap_stream, $sent_folder, $length) {
b2306cbe 1033 fputs ($imap_stream, sqimap_session_id() . ' APPEND ' . sqimap_encode_mailbox_name($sent_folder) . " (\\Seen) \{$length}\r\n");
85fc999e 1034 $tmp = fgets ($imap_stream, 1024);
7ec3a6b9 1035 sqimap_append_checkresponse($tmp, $sent_folder);
9c737111 1036}
1037
8813fb15 1038function sqimap_append_done ($imap_stream, $folder='') {
9c737111 1039 fputs ($imap_stream, "\r\n");
1040 $tmp = fgets ($imap_stream, 1024);
7ec3a6b9 1041 sqimap_append_checkresponse($tmp, $folder);
1042}
1043
1044function sqimap_append_checkresponse($response, $folder) {
1045
1046 if (preg_match("/(.*)(BAD|NO)(.*)$/", $response, $regs)) {
1047 global $squirrelmail_language, $color;
69146537 1048 set_up_language($squirrelmail_language);
1f720b34 1049 require_once(SM_PATH . 'functions/display_messages.php');
7ec3a6b9 1050
098ea084 1051 $reason = $regs[3];
1052 if ($regs[2] == 'NO') {
6fd95361 1053 $string = "<b><font color=\"$color[2]\">\n" .
098ea084 1054 _("ERROR : Could not append message to") ." $folder." .
6fd95361 1055 "</b><br />\n" .
098ea084 1056 _("Server responded: ") .
6fd95361 1057 $reason . "<br />\n";
098ea084 1058 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
1e0a2f0e 1059 $string .= _("Solution: ") .
1060 _("Remove unneccessary messages from your folder and start with your Trash folder.")
6fd95361 1061 ."<br />\n";
098ea084 1062 }
1063 $string .= "</font>\n";
1064 error_box($string,$color);
1065 } else {
6fd95361 1066 $string = "<b><font color=\"$color[2]\">\n" .
098ea084 1067 _("ERROR : Bad or malformed request.") .
6fd95361 1068 "</b><br />\n" .
098ea084 1069 _("Server responded: ") .
7ec3a6b9 1070 $reason . "</font><br />\n";
098ea084 1071 error_box($string,$color);
8813fb15 1072 exit;
098ea084 1073 }
69146537 1074 }
9c737111 1075}
85fc999e 1076
bd9829d7 1077function sqimap_get_user_server ($imap_server, $username) {
bd9829d7 1078 if (substr($imap_server, 0, 4) != "map:") {
1079 return $imap_server;
1080 }
bd9829d7 1081 $function = substr($imap_server, 4);
1082 return $function($username);
1083}
1084
48af4b64 1085/**
1086 * This is an example that gets imapservers from yellowpages (NIS).
1e0a2f0e 1087 * you can simple put map:map_yp_alias in your $imap_server_address
bd9829d7 1088 * in config.php use your own function instead map_yp_alias to map your
48af4b64 1089 * LDAP whatever way to find the users imapserver.
1090 */
bd9829d7 1091function map_yp_alias($username) {
1092 $yp = `ypmatch $username aliases`;
1093 return chop(substr($yp, strlen($username)+1));
1e0a2f0e 1094}
bd9829d7 1095
7ec3a6b9 1096?>