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