extra check for filename/name to achieve we do not show text/plain
[squirrelmail.git] / functions / imap_general.php
CommitLineData
59177427 1<?php
bccadd02 2
35586184 3/**
a6fd80f5 4 * imap_general.php
35586184 5 *
76911253 6 * Copyright (c) 1999-2003 The SquirrelMail Project Team
15e6162e 7 * Licensed under the GNU GPL. For full terms see the file COPYING.
35586184 8 *
15e6162e 9 * This implements all functions that do general imap functions.
35586184 10 *
15e6162e 11 * $Id$
35586184 12 */
13
b68edc75 14require_once(SM_PATH . 'functions/page_header.php');
47a29326 15require_once(SM_PATH . 'functions/auth.php');
16
35586184 17
41600f7d 18global $sqimap_session_id;
19$sqimap_session_id = 1;
71257f8b 20
3411d4ec 21/* Sets an unique session id in order to avoid simultanous sessions crash. */
487daa81 22function sqimap_session_id($unique_id = false) {
41600f7d 23 global $data_dir, $username, $sqimap_session_id;
487daa81 24 if (!$unique_id) {
098ea084 25 return( sprintf("A%03d", $sqimap_session_id++) );
487daa81 26 } else {
098ea084 27 return( sprintf("A%03d", $sqimap_session_id++) . ' UID' );
487daa81 28 }
9c737111 29}
30
3411d4ec 31/*
32 * Both send a command and accept the result from the command.
33 * This is to allow proper session number handling.
34 */
487daa81 35function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
c5809184 36 if ($imap_stream) {
098ea084 37 $sid = sqimap_session_id($unique_id);
38 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
bc78cc6e 39 $tag_uid_a = explode(' ',trim($sid));
40 $tag = $tag_uid_a[0];
41 $read = sqimap_read_data_list ($imap_stream, $tag, $handle_errors, $response, $message, $query );
42 /* get the response and the message */
43 $message = $message[$tag];
44 $response = $response[$tag];
45 return $read[$tag];
c5809184 46 } else {
47 global $squirrelmail_language, $color;
48 set_up_language($squirrelmail_language);
49 require_once(SM_PATH . 'functions/display_messages.php');
50 $string = "<b><font color=$color[2]>\n" .
51 _("ERROR : No available imapstream.") .
52 "</b></font>\n";
53 error_box($string,$color);
098ea084 54 return false;
c5809184 55 }
1c72b151 56}
57
7c7b74b3 58function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response,
59 &$message, $unique_id = false,$filter=false,
60 $outputstream=false,$no_return=false) {
c5809184 61 if ($imap_stream) {
62 $sid = sqimap_session_id($unique_id);
bc78cc6e 63 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
64 $tag_uid_a = explode(' ',trim($sid));
65 $tag = $tag_uid_a[0];
66
67 $read = sqimap_read_data ($imap_stream, $tag, $handle_errors, $response,
7c7b74b3 68 $message, $query,$filter,$outputstream,$no_return);
bc78cc6e 69 /* retrieve the response and the message */
70 $response = $response[$tag];
71 $message = $message[$tag];
72 if (!empty($read[$tag])) {
73 return $read[$tag][0];
74 } else {
75 return $read[$tag];
76 }
c5809184 77 } else {
78 global $squirrelmail_language, $color;
79 set_up_language($squirrelmail_language);
80 require_once(SM_PATH . 'functions/display_messages.php');
81 $string = "<b><font color=$color[2]>\n" .
82 _("ERROR : No available imapstream.") .
83 "</b></font>\n";
84 error_box($string,$color);
098ea084 85 return false;
bc78cc6e 86 }
87}
88function sqimap_prepare_pipelined_query($new_query,&$tag,&$aQuery,$unique_id) {
89 $sid = sqimap_session_id($unique_id);
90 $tag_uid_a = explode(' ',trim($sid));
91 $tag = $tag_uid_a[0];
92 $query = $sid . ' '.$new_query."\n";
93 $aQuery[$tag] = $query;
42a07ac1 94}
95
bc78cc6e 96function sqimap_run_pipelined_command ($imap_stream, $aQuery, $handle_errors,
97 &$aServerResponse, &$aServerMessage, $unique_id = false,
98 $filter=false,$outputstream=false,$no_return=false) {
99 $aResponse = false;
100 foreach($aQuery as $tag => $query) {
101 fputs($imap_stream,$query);
102 $aResults[$tag] = false;
103 }
104
105 foreach($aQuery as $tag => $query) {
106 if (!$aResults[$tag]) {
107 $aReturnedResponse = sqimap_read_data_list ($imap_stream, $tag,
108 $handle_errors, $response, $message, $query,
109 $filter,$outputstream,$no_return);
110 foreach ($aReturnedResponse as $returned_tag => $aResponse) {
111 $aResults[$returned_tag] = $aResponse;
112 $aServerResponse[$returned_tag] = $response[$returned_tag];
113 $aServerMessage[$returned_tag] = $message[$returned_tag];
114 }
115 }
116 }
117}
9c737111 118
b8c285ab 119/*
120 * custom fgets function. gets a line from IMAP
121 * no matter how big it may be
122 */
123
124function sqimap_fgets($imap_stream) {
125 $read = '';
126 $buffer = 4096;
127 $results = '';
c41daf03 128 $offset = 0;
129 while (strpos($results, "\r\n", $offset) === false) {
b8c285ab 130 if (!($read = fgets($imap_stream, $buffer))) {
329a7ca5 131 /* this happens in case of an error */
132 /* reset $results because it's useless */
133 $results = false;
b8c285ab 134 break;
135 }
c41daf03 136 if ( $results != '' ) {
137 $offset = strlen($results) - 1;
138 }
b8c285ab 139 $results .= $read;
140 }
141 return $results;
142}
143
7c7b74b3 144function sqimap_fread($imap_stream,$iSize,$filter=false,
145 $outputstream=false, $no_return=false) {
146 if (!$filter || !$outputstream) {
147 $iBufferSize = $iSize;
148 } else {
bc78cc6e 149 $iBufferSize = 62400; // multiple of 78 in case of base64 decoding.
7c7b74b3 150 }
151 $iRet = $iSize - $iBufferSize;
5eba0be2 152 $iRetrieved = 0;
7c7b74b3 153 $i = 0;
bc78cc6e 154 $results = $sReadRem = '';
155 $bFinished = $bBufferSizeAdapted = $bBufferIsOk = false;
5eba0be2 156 while (($iRetrieved < ($iSize - $iBufferSize))) {
7c7b74b3 157 $sRead = fread($imap_stream,$iBufferSize);
bc78cc6e 158 if (!$sRead) {
7c7b74b3 159 $results = false;
160 break;
161 }
5eba0be2 162 $iRetrieved += $iBufferSize;
7c7b74b3 163 if ($filter) {
bc78cc6e 164 // in case line-endings do not appear at position 78 we adapt the buffersize so we can base64 decode on the fly
165 if (!$bBufferSizeAdapted) {
166 $i = strpos($sRead,"\n");
167 if ($i) {
168 ++$i;
169 $iFragments = floor($iBufferSize / $i);
170 $iNewBufferSize = $iFragments * $i;
171 $iRemainder = $iNewBufferSize + $i - $iBufferSize;
172 if ($iNewBufferSize == $iBufferSize) {
173 $bBufferIsOk = true;
174 $iRemainder = 0;
175 $iNewBufferSize = $iBufferSize;
176 $bBufferSizeAdapted = true;
177 }
178 if (!$bBufferIsOk && ($iRemainder + $iBufferSize) < $iSize) {
179 $sReadRem = fread($imap_stream,$iRemainder);
180 } else if (!$bBufferIsOk) {
181 $sReadRem = fread($imap_stream,$iSize - $iBufferSize);
182 $bFinished = true;
183 }
184 if (!$sReadRem && $sReadRem !== '') {
185 $results = false;
186 break;
187 }
188 $iBufferSize = $iNewBufferSize;
189 $bBufferSizeAdapted = true;
190 } else {
191 $sReadRem = fread($imap_stream,$iSize - $iBufferSize);
192 $bFinished = true;
193 if (!$sReadRem) {
194 $results = false;
195 break;
196 }
197 }
198 $sRead .= $sReadRem;
199 $iRetrieved += $iRemainder;
200 unset($sReadRem);
201 }
7c7b74b3 202 $filter($sRead);
203 }
204 if ($outputstream) {
205 if (is_resource($outputstream)) {
206 fwrite($outputstream,$sRead);
207 } else if ($outputstream == 'php://stdout') {
208 echo $sRead;
209 }
210 }
211 if ($no_return) {
212 $sRead = '';
213 }
214 $results .= $sRead;
215 }
bc78cc6e 216 if (!$results && !$bFinished) {
5eba0be2 217 $sRead = fread($imap_stream,($iSize - ($iRetrieved)));
7c7b74b3 218 if ($filter) {
219 $filter($sRead);
220 }
221 if ($outputstream) {
222 if (is_resource($outputstream)) {
223 fwrite($outputstream,$sRead);
224 } else if ($outputstream == 'php://stdout') { // FIXME
225 echo $sRead;
226 }
227 }
228 if ($no_return) {
229 $sRead = '';
230 }
231 $results .= $sRead;
232 }
233 return $results;
234}
235
236
237
bee165ef 238/*
3411d4ec 239 * Reads the output from the IMAP stream. If handle_errors is set to true,
240 * this will also handle all errors that are received. If it is not set,
241 * the errors will be sent back through $response and $message
bee165ef 242 */
b8c285ab 243
bc78cc6e 244function sqimap_read_data_list ($imap_stream, $tag, $handle_errors,
7c7b74b3 245 &$response, &$message, $query = '',
246 $filter = false, $outputstream = false, $no_return = false) {
9c737111 247 global $color, $squirrelmail_language;
9c737111 248 $read = '';
bc78cc6e 249 if (!is_array($message)) $message = array();
250 if (!is_array($response)) $response = array();
b8c285ab 251 $resultlist = array();
252 $data = array();
253 $read = sqimap_fgets($imap_stream);
ba8f367a 254 $i = 0;
bea3eb1e 255 while ($read) {
256 $char = $read{0};
257 switch ($char)
258 {
15bc7f66 259 case '+':
260 default:
261 $read = sqimap_fgets($imap_stream);
262 break;
263
264 case $tag{0}:
265 {
bea3eb1e 266 /* get the command */
267 $arg = '';
268 $i = strlen($tag)+1;
269 $s = substr($read,$i);
270 if (($j = strpos($s,' ')) || ($j = strpos($s,"\n"))) {
271 $arg = substr($s,0,$j);
272 }
273 $found_tag = substr($read,0,$i-1);
274 if ($arg && $found_tag==$tag) {
275 switch ($arg)
276 {
15bc7f66 277 case 'OK':
278 case 'BAD':
279 case 'NO':
280 case 'BYE':
281 case 'PREAUTH':
bc78cc6e 282 $response[$found_tag] = $arg;
283 $message[$found_tag] = trim(substr($read,$i+strlen($arg)));
284 if (!empty($data)) {
285 $resultlist[] = $data;
286 }
287 $aResponse[$tag] = $resultlist;
c0b23345 288 break 3; /* switch switch while */
329a7ca5 289 default:
bea3eb1e 290 /* this shouldn't happen */
bc78cc6e 291 $response[$found_tag] = $arg;
292 $message[$found_tag] = trim(substr($read,$i+strlen($arg)));
293 if (!empty($data)) {
294 $resultlist[] = $data;
295 }
296 $aResponse[$found_tag] = $resultlist;
c0b23345 297 break 3; /* switch switch while */
bea3eb1e 298 }
299 } elseif($found_tag !== $tag) {
bc78cc6e 300 /* not the tag we are looking for, continue */
301 if (!empty($data)) {
302 $resultlist[] = $data;
303 }
304 $aResponse[$found_tag] = $resultlist;
305 $resultlist = $data = array();
bea3eb1e 306 $read = sqimap_fgets($imap_stream);
bc78cc6e 307 if ($read === false) { /* error */
308 break 3; /* switch switch while */
309 }
bea3eb1e 310 break;
311 }
15bc7f66 312 } // end case $tag{0}
313
314 case '*':
315 {
bea3eb1e 316 if (preg_match('/^\*\s\d+\sFETCH/',$read)) {
317 /* check for literal */
318 $s = substr($read,-3);
319 $fetch_data = array();
320 do { /* outer loop, continue until next untagged fetch
321 or tagged reponse */
322 do { /* innerloop for fetching literals. with this loop
323 we prohibid that literal responses appear in the
324 outer loop so we can trust the untagged and
325 tagged info provided by $read */
326 if ($s === "}\r\n") {
327 $j = strrpos($read,'{');
328 $iLit = substr($read,$j+1,-3);
329 $fetch_data[] = $read;
7c7b74b3 330 $sLiteral = sqimap_fread($imap_stream,$iLit,$filter,$outputstream,$no_return);
329a7ca5 331 if ($sLiteral === false) { /* error */
332 break 4; /* while while switch while */
333 }
bea3eb1e 334 /* backwards compattibility */
335 $aLiteral = explode("\n", $sLiteral);
336 /* release not neaded data */
337 unset($sLiteral);
338 foreach ($aLiteral as $line) {
339 $fetch_data[] = $line ."\n";
340 }
341 /* release not neaded data */
342 unset($aLiteral);
343 /* next fgets belongs to this fetch because
344 we just got the exact literalsize and there
345 must follow data to complete the response */
329a7ca5 346 $read = sqimap_fgets($imap_stream);
347 if ($read === false) { /* error */
348 break 4; /* while while switch while */
349 }
c0b23345 350 $fetch_data[] = $read;
bea3eb1e 351 } else {
329a7ca5 352 $fetch_data[] = $read;
bea3eb1e 353 }
354 /* retrieve next line and check in the while
355 statements if it belongs to this fetch response */
356 $read = sqimap_fgets($imap_stream);
329a7ca5 357 if ($read === false) { /* error */
358 break 4; /* while while switch while */
359 }
bea3eb1e 360 /* check for next untagged reponse and break */
361 if ($read{0} == '*') break 2;
362 $s = substr($read,-3);
363 } while ($s === "}\r\n");
364 $s = substr($read,-3);
365 } while ($read{0} !== '*' &&
106d4087 366 substr($read,0,strlen($tag)) !== $tag);
329a7ca5 367 $resultlist[] = $fetch_data;
bea3eb1e 368 /* release not neaded data */
369 unset ($fetch_data);
370 } else {
371 $s = substr($read,-3);
372 do {
373 if ($s === "}\r\n") {
374 $j = strrpos($read,'{');
375 $iLit = substr($read,$j+1,-3);
376 $data[] = $read;
329a7ca5 377 $sLiteral = fread($imap_stream,$iLit);
c0b23345 378 if ($sLiteral === false) { /* error */
329a7ca5 379 $read = false;
380 break 3; /* while switch while */
381 }
c0b23345 382 $data[] = $sLiteral;
bea3eb1e 383 $fetch_data[] = sqimap_fgets($imap_stream);
384 } else {
329a7ca5 385 $data[] = $read;
bea3eb1e 386 }
387 $read = sqimap_fgets($imap_stream);
329a7ca5 388 if ($read === false) {
389 break 3; /* while switch while */
390 } else if ($read{0} == '*') {
106d4087 391 break;
392 }
bea3eb1e 393 $s = substr($read,-3);
394 } while ($s === "}\r\n");
395 break 1;
396 }
397 break;
15bc7f66 398 } // end case '*'
399 } // end switch
c0b23345 400 } // end while
401
402 /* error processing in case $read is false */
403 if ($read === false) {
404 unset($data);
405 set_up_language($squirrelmail_language);
406 require_once(SM_PATH . 'functions/display_messages.php');
407 $string = "<b><font color=$color[2]>\n" .
329a7ca5 408 _("ERROR : Connection dropped by imap-server.") .
409 "</b><br>\n" .
410 _("Query:") . ' '.
411 htmlspecialchars($query) . '<br>' . "</font><br>\n";
c0b23345 412 error_box($string,$color);
413 exit;
b8c285ab 414 }
c0b23345 415
15bc7f66 416 /* Set $resultlist array */
b8c285ab 417 if (!empty($data)) {
bc78cc6e 418 //$resultlist[] = $data;
9c737111 419 }
b8c285ab 420 elseif (empty($resultlist)) {
421 $resultlist[] = array();
422 }
15bc7f66 423
424 /* Return result or handle errors */
bee165ef 425 if ($handle_errors == false) {
bc78cc6e 426 return $aResponse;
bee165ef 427 return( $resultlist );
dd381002 428 }
bc78cc6e 429 switch ($response[$tag])
dd381002 430 {
431 case 'OK':
bc78cc6e 432 return $aResponse;
329a7ca5 433 break;
dd381002 434 case 'NO':
435 /* ignore this error from M$ exchange, it is not fatal (aka bug) */
9c737111 436 if (strstr($message, 'command resulted in') === false) {
441f2d33 437 set_up_language($squirrelmail_language);
098ea084 438 require_once(SM_PATH . 'functions/display_messages.php');
439 $string = "<b><font color=$color[2]>\n" .
b8c285ab 440 _("ERROR : Could not complete request.") .
441 "</b><br>\n" .
9b761dbd 442 _("Query:") . ' ' .
443 htmlspecialchars($query) . '<br>' .
b8c285ab 444 _("Reason Given: ") .
bc78cc6e 445 htmlspecialchars($message[$tag]) . "</font><br>\n";
098ea084 446 error_box($string,$color);
329a7ca5 447 echo '</body></html>';
052e0c26 448 exit;
9c737111 449 }
329a7ca5 450 break;
dd381002 451 case 'BAD':
9c737111 452 set_up_language($squirrelmail_language);
098ea084 453 require_once(SM_PATH . 'functions/display_messages.php');
bef6629c 454 $string = "<b><font color=$color[2]>\n" .
b8c285ab 455 _("ERROR : Bad or malformed request.") .
456 "</b><br>\n" .
9b761dbd 457 _("Query:") . ' '.
458 htmlspecialchars($query) . '<br>' .
b8c285ab 459 _("Server responded: ") .
bc78cc6e 460 htmlspecialchars($message[$tag]) . "</font><br>\n";
dd381002 461 error_box($string,$color);
329a7ca5 462 echo '</body></html>';
dd381002 463 exit;
464 case 'BYE':
465 set_up_language($squirrelmail_language);
466 require_once(SM_PATH . 'functions/display_messages.php');
467 $string = "<b><font color=$color[2]>\n" .
468 _("ERROR : Imap server closed the connection.") .
469 "</b><br>\n" .
470 _("Query:") . ' '.
471 htmlspecialchars($query) . '<br>' .
472 _("Server responded: ") .
bc78cc6e 473 htmlspecialchars($message[$tag]) . "</font><br>\n";
dd381002 474 error_box($string,$color);
329a7ca5 475 echo '</body></html>';
9c737111 476 exit;
dd381002 477 default:
478 set_up_language($squirrelmail_language);
479 require_once(SM_PATH . 'functions/display_messages.php');
480 $string = "<b><font color=$color[2]>\n" .
481 _("ERROR : Unknown imap response.") .
482 "</b><br>\n" .
483 _("Query:") . ' '.
484 htmlspecialchars($query) . '<br>' .
485 _("Server responded: ") .
bc78cc6e 486 htmlspecialchars($message[$tag]) . "</font><br>\n";
dd381002 487 error_box($string,$color);
329a7ca5 488 /* the error is displayed but because we don't know the reponse we
489 return the result anyway */
bc78cc6e 490 return $aResponse;
329a7ca5 491 break;
9c737111 492 }
9c737111 493}
494
7c7b74b3 495function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors,
496 &$response, &$message, $query = '',
497 $filter=false,$outputstream=false,$no_return=false) {
bc78cc6e 498
499 $tag_uid_a = explode(' ',trim($tag_uid));
500 $tag = $tag_uid_a[0];
501
502 $res = sqimap_read_data_list($imap_stream, $tag, $handle_errors,
7c7b74b3 503 $response, $message, $query,$filter,$outputstream,$no_return);
863936bb 504 /* sqimap_read_data should be called for one response
505 but since it just calls sqimap_read_data_list which
506 handles multiple responses we need to check for that
507 and merge the $res array IF they are seperated and
508 IF it was a FETCH response. */
509
ba8f367a 510// if (isset($res[1]) && is_array($res[1]) && isset($res[1][0])
511// && preg_match('/^\* \d+ FETCH/', $res[1][0])) {
512// $result = array();
513// foreach($res as $index=>$value) {
514// $result = array_merge($result, $res["$index"]);
515// }
516// }
863936bb 517 if (isset($result)) {
bc78cc6e 518 return $result[$tag];
56afb33f 519 }
56afb33f 520 else {
bc78cc6e 521 return $res;
56afb33f 522 }
9c737111 523}
524
3411d4ec 525/*
526 * Logs the user into the imap server. If $hide is set, no error messages
527 * will be displayed. This function returns the imap connection handle.
528 */
9c737111 529function sqimap_login ($username, $password, $imap_server_address, $imap_port, $hide) {
47a29326 530 global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;
85fc999e 531
eb2f6102 532 if (!isset($onetimepad) || empty($onetimepad)) {
533 sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION );
534 }
bd9829d7 535 $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
098ea084 536 $host=$imap_server_address;
537
538 if (($use_imap_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) {
539 /* Use TLS by prefixing "tls://" to the hostname */
540 $imap_server_address = 'tls://' . $imap_server_address;
541 }
47a29326 542
3411d4ec 543 $imap_stream = fsockopen ( $imap_server_address, $imap_port, $error_number, $error_string, 15);
85fc999e 544
3411d4ec 545 /* Do some error correction */
9c737111 546 if (!$imap_stream) {
547 if (!$hide) {
441f2d33 548 set_up_language($squirrelmail_language, true);
098ea084 549 require_once(SM_PATH . 'functions/display_messages.php');
550 $string = sprintf (_("Error connecting to IMAP server: %s.") .
551 "<br>\r\n", $imap_server_address) .
1f720b34 552 "$error_number : $error_string<br>\r\n";
098ea084 553 logout_error($string,$color);
9c737111 554 }
555 exit;
556 }
052e0c26 557
2f1f7a12 558 $server_info = fgets ($imap_stream, 1024);
559
560 /* Decrypt the password */
561 $password = OneTimePadDecrypt($password, $onetimepad);
562
098ea084 563 if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
fe0b18b3 564 // We're using some sort of authentication OTHER than plain or login
098ea084 565 $tag=sqimap_session_id(false);
566 if ($imap_auth_mech == 'digest-md5') {
567 $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
568 } elseif ($imap_auth_mech == 'cram-md5') {
569 $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
570 }
571 fputs($imap_stream,$query);
572 $answer=sqimap_fgets($imap_stream);
573 // Trim the "+ " off the front
574 $response=explode(" ",$answer,3);
575 if ($response[0] == '+') {
576 // Got a challenge back
577 $challenge=$response[1];
578 if ($imap_auth_mech == 'digest-md5') {
579 $reply = digest_md5_response($username,$password,$challenge,'imap',$host);
580 } elseif ($imap_auth_mech == 'cram-md5') {
581 $reply = cram_md5_response($username,$password,$challenge);
582 }
583 fputs($imap_stream,$reply);
584 $read=sqimap_fgets($imap_stream);
585 if ($imap_auth_mech == 'digest-md5') {
586 // DIGEST-MD5 has an extra step..
587 if (substr($read,0,1) == '+') { // OK so far..
588 fputs($imap_stream,"\r\n");
589 $read=sqimap_fgets($imap_stream);
590 }
591 }
592 $results=explode(" ",$read,3);
593 $response=$results[1];
594 $message=$results[2];
47a29326 595 } else {
098ea084 596 // Fake the response, so the error trap at the bottom will work
597 $response="BAD";
598 $message='IMAP server does not appear to support the authentication method selected.';
599 $message .= ' Please contact your system administrator.';
47a29326 600 }
fe0b18b3 601 } elseif ($imap_auth_mech == 'login') {
098ea084 602 // Original IMAP login code
fbb76d0e 603 $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
47a29326 604 $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
1e7fc1cb 605 } elseif ($imap_auth_mech == 'plain') {
098ea084 606 /* Replace this with SASL PLAIN if it ever gets implemented */
607 $response="BAD";
608 $message='SquirrelMail does not support SASL PLAIN yet. Rerun conf.pl and use login instead.';
609 } else {
610 $response="BAD";
611 $message="Internal SquirrelMail error - unknown IMAP authentication method chosen. Please contact the developers.";
612 }
47a29326 613
098ea084 614 /* If the connection was not successful, lets see why */
9c737111 615 if ($response != 'OK') {
616 if (!$hide) {
74424a43 617 if ($response != 'NO') {
3411d4ec 618 /* "BAD" and anything else gets reported here. */
098ea084 619 $message = htmlspecialchars($message);
9c737111 620 set_up_language($squirrelmail_language, true);
098ea084 621 require_once(SM_PATH . 'functions/display_messages.php');
9c737111 622 if ($response == 'BAD') {
bea3eb1e 623 $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
9c737111 624 } else {
bea3eb1e 625 $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
9c737111 626 }
1e7fc1cb 627 if (isset($read) && is_array($read)) {
bea3eb1e 628 $string .= '<br>' . _("Read data:") . "<br>\n";
9c737111 629 foreach ($read as $line) {
1f720b34 630 $string .= htmlspecialchars($line) . "<br>\n";
9c737111 631 }
632 }
098ea084 633 error_box($string,$color);
9c737111 634 exit;
165e24a7 635 } else {
3411d4ec 636 /*
637 * If the user does not log in with the correct
1c72b151 638 * username and password it is not possible to get the
639 * correct locale from the user's preferences.
640 * Therefore, apply the same hack as on the login
641 * screen.
3411d4ec 642 *
643 * $squirrelmail_language is set by a cookie when
1c72b151 644 * the user selects language and logs out
bee165ef 645 */
9be8198d 646
9c737111 647 set_up_language($squirrelmail_language, true);
bd9c880b 648 include_once(SM_PATH . 'functions/display_messages.php' );
098ea084 649 sqsession_destroy();
bd9c880b 650 logout_error( _("Unknown user or password incorrect.") );
9c737111 651 exit;
052e0c26 652 }
9c737111 653 } else {
052e0c26 654 exit;
9c737111 655 }
656 }
9c737111 657 return $imap_stream;
658}
f1e6f580 659
3411d4ec 660/* Simply logs out the IMAP session */
9c737111 661function sqimap_logout ($imap_stream) {
8d936b0c 662 /* Logout is not valid until the server returns 'BYE'
663 * If we don't have an imap_ stream we're already logged out */
26a2cc8b 664 if(isset($imap_stream) && $imap_stream)
8d936b0c 665 sqimap_run_command($imap_stream, 'LOGOUT', false, $response, $message);
9c737111 666}
667
487daa81 668function sqimap_capability($imap_stream, $capability='') {
9c737111 669 global $sqimap_capabilities;
9c737111 670 if (!is_array($sqimap_capabilities)) {
1c72b151 671 $read = sqimap_run_command($imap_stream, 'CAPABILITY', true, $a, $b);
672
9c737111 673 $c = explode(' ', $read[0]);
674 for ($i=2; $i < count($c); $i++) {
675 $cap_list = explode('=', $c[$i]);
3411d4ec 676 if (isset($cap_list[1])) {
9c737111 677 $sqimap_capabilities[$cap_list[0]] = $cap_list[1];
3411d4ec 678 } else {
9c737111 679 $sqimap_capabilities[$cap_list[0]] = TRUE;
3411d4ec 680 }
f1e6f580 681 }
9c737111 682 }
487daa81 683 if ($capability) {
098ea084 684 if (isset($sqimap_capabilities[$capability])) {
685 return $sqimap_capabilities[$capability];
686 } else {
687 return false;
688 }
f1e6f580 689 }
487daa81 690 return $sqimap_capabilities;
9c737111 691}
692
3411d4ec 693/* Returns the delimeter between mailboxes: INBOX/Test, or INBOX.Test */
9c737111 694function sqimap_get_delimiter ($imap_stream = false) {
3411d4ec 695 global $sqimap_delimiter, $optional_delimiter;
85fc999e 696
9c737111 697 /* Use configured delimiter if set */
698 if((!empty($optional_delimiter)) && $optional_delimiter != 'detect') {
699 return $optional_delimiter;
700 }
85fc999e 701
9c737111 702 /* Do some caching here */
703 if (!$sqimap_delimiter) {
704 if (sqimap_capability($imap_stream, 'NAMESPACE')) {
3411d4ec 705 /*
706 * According to something that I can't find, this is supposed to work on all systems
707 * OS: This won't work in Courier IMAP.
708 * OS: According to rfc2342 response from NAMESPACE command is:
709 * OS: * NAMESPACE (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES)
710 * OS: We want to lookup all personal NAMESPACES...
711 */
1c72b151 712 $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b);
f1e6f580 713 if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) {
9c737111 714 if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) {
f1e6f580 715 $pn = $data2[1];
9c737111 716 }
f1e6f580 717 $pna = explode(')(', $pn);
9c737111 718 while (list($k, $v) = each($pna)) {
862ff2d3 719 $lst = explode('"', $v);
720 if (isset($lst[3])) {
721 $pn[$lst[1]] = $lst[3];
722 } else {
74424a43 723 $pn[$lst[1]] = '';
862ff2d3 724 }
f1e6f580 725 }
726 }
727 $sqimap_delimiter = $pn[0];
728 } else {
729 fputs ($imap_stream, ". LIST \"INBOX\" \"\"\r\n");
730 $read = sqimap_read_data($imap_stream, '.', true, $a, $b);
731 $quote_position = strpos ($read[0], '"');
732 $sqimap_delimiter = substr ($read[0], $quote_position+1, 1);
733 }
734 }
735 return $sqimap_delimiter;
9c737111 736}
052e0c26 737
738
3411d4ec 739/* Gets the number of messages in the current mailbox. */
9c737111 740function sqimap_get_num_messages ($imap_stream, $mailbox) {
1f720b34 741 $read_ary = sqimap_run_command ($imap_stream, "EXAMINE \"$mailbox\"", false, $result, $message);
9c737111 742 for ($i = 0; $i < count($read_ary); $i++) {
85fc999e 743 if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
744 return $regs[1];
745 }
9c737111 746 }
1f720b34 747 return false; //"BUG! Couldn't get number of messages in $mailbox!";
9c737111 748}
749
cfe1a81e 750
91688e5f 751function parseAddress($address, $max=0) {
752 $aTokens = array();
753 $aAddress = array();
754 $iCnt = strlen($address);
755 $aSpecials = array('(' ,'<' ,',' ,';' ,':');
756 $aReplace = array(' (',' <',' ,',' ;',' :');
757 $address = str_replace($aSpecials,$aReplace,$address);
bc78cc6e 758 $i = $iAddrFound = $bGroup = 0;
91688e5f 759 while ($i < $iCnt) {
760 $cChar = $address{$i};
761 switch($cChar)
329a7ca5 762 {
763 case '<':
764 $iEnd = strpos($address,'>',$i+1);
765 if (!$iEnd) {
766 $sToken = substr($address,$i);
767 $i = $iCnt;
768 } else {
769 $sToken = substr($address,$i,$iEnd - $i +1);
770 $i = $iEnd;
771 }
772 $sToken = str_replace($aReplace, $aSpecials,$sToken);
773 $aTokens[] = $sToken;
774 break;
775 case '"':
776 $iEnd = strpos($address,$cChar,$i+1);
da1e42a1 777 if ($iEnd) {
778 // skip escaped quotes
779 $prev_char = $address{$iEnd-1};
780 while ($prev_char === '\\' && substr($address,$iEnd-2,2) !== '\\\\') {
781 $iEnd = strpos($address,$cChar,$iEnd+1);
782 if ($iEnd) {
783 $prev_char = $address{$iEnd-1};
784 } else {
785 $prev_char = false;
786 }
787 }
788 }
329a7ca5 789 if (!$iEnd) {
790 $sToken = substr($address,$i);
791 $i = $iCnt;
792 } else {
793 // also remove the surrounding quotes
794 $sToken = substr($address,$i+1,$iEnd - $i -1);
795 $i = $iEnd;
796 }
797 $sToken = str_replace($aReplace, $aSpecials,$sToken);
76c3ee28 798 if ($sToken) $aTokens[] = $sToken;
329a7ca5 799 break;
800 case '(':
801 $iEnd = strpos($address,')',$i);
802 if (!$iEnd) {
803 $sToken = substr($address,$i);
804 $i = $iCnt;
805 } else {
806 $sToken = substr($address,$i,$iEnd - $i + 1);
807 $i = $iEnd;
808 }
809 $sToken = str_replace($aReplace, $aSpecials,$sToken);
810 $aTokens[] = $sToken;
811 break;
812 case ',':
bc78cc6e 813 ++$iAddrFound;
329a7ca5 814 case ';':
bc78cc6e 815 if (!$bGroup) {
816 ++$iAddrFound;
817 } else {
818 $bGroup = false;
819 }
820 if ($max && $max == $iAddrFound) {
821 break 2;
822 } else {
823 $aTokens[] = $cChar;
824 break;
825 }
826 case ':':
827 $bGroup = true;
329a7ca5 828 case ' ':
829 $aTokens[] = $cChar;
830 break;
91688e5f 831 default:
329a7ca5 832 $iEnd = strpos($address,' ',$i+1);
833 if ($iEnd) {
834 $sToken = trim(substr($address,$i,$iEnd - $i));
835 $i = $iEnd-1;
91688e5f 836 } else {
329a7ca5 837 $sToken = trim(substr($address,$i));
838 $i = $iCnt;
91688e5f 839 }
329a7ca5 840 if ($sToken) $aTokens[] = $sToken;
91688e5f 841 }
329a7ca5 842 ++$i;
9c737111 843 }
91688e5f 844 $sPersonal = $sEmail = $sComment = $sGroup = '';
845 $aStack = $aComment = array();
846 foreach ($aTokens as $sToken) {
847 if ($max && $max == count($aAddress)) {
329a7ca5 848 return $aAddress;
092d4f2c 849 }
329a7ca5 850 $cChar = $sToken{0};
91688e5f 851 switch ($cChar)
329a7ca5 852 {
853 case '=':
854 case '"':
855 case ' ':
856 $aStack[] = $sToken;
857 break;
858 case '(':
859 $aComment[] = substr($sToken,1,-1);
860 break;
861 case ';':
862 if ($sGroup) {
863 $sEmail = trim(implode(' ',$aStack));
864 $aAddress[] = array($sGroup,$sEmail);
865 $aStack = $aComment = array();
866 $sGroup = '';
867 break;
868 }
869 case ',':
870 if (!$sEmail) {
871 while (count($aStack) && !$sEmail) {
872 $sEmail = trim(array_pop($aStack));
873 }
874 }
875 if (count($aStack)) {
876 $sPersonal = trim(implode('',$aStack));
877 } else {
878 $sPersonal = '';
bea3eb1e 879 }
329a7ca5 880 if (!$sPersonal && count($aComment)) {
881 $sComment = implode(' ',$aComment);
882 $sPersonal .= $sComment;
883 }
884 $aAddress[] = array($sEmail,$sPersonal);
885 $sPersonal = $sComment = $sEmail = '';
886 $aStack = $aComment = array();
887 break;
888 case ':':
889 $sGroup = implode(' ',$aStack); break;
890 $aStack = array();
891 break;
892 case '<':
893 $sEmail = trim(substr($sToken,1,-1));
894 break;
895 case '>':
896 /* skip */
897 break;
898 default: $aStack[] = $sToken; break;
33565ec4 899 }
7e3de682 900 }
91688e5f 901 /* now do the action again for the last address */
902 if (!$sEmail) {
903 while (count($aStack) && !$sEmail) {
329a7ca5 904 $sEmail = trim(array_pop($aStack));
91688e5f 905 }
7e3de682 906 }
91688e5f 907 if (count($aStack)) {
329a7ca5 908 $sPersonal = trim(implode('',$aStack));
098ea084 909 } else {
91688e5f 910 $sPersonal = '';
9c737111 911 }
329a7ca5 912 if (!$sPersonal && count($aComment)) {
91688e5f 913 $sComment = implode(' ',$aComment);
329a7ca5 914 $sPersonal .= $sComment;
91688e5f 915 }
916 $aAddress[] = array($sEmail,$sPersonal);
917 return $aAddress;
918}
919
920
85fc999e 921
9c737111 922/*
3411d4ec 923 * Returns the number of unseen messages in this folder
924 */
9c737111 925function sqimap_unseen_messages ($imap_stream, $mailbox) {
1f720b34 926 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (UNSEEN)", false, $result, $message);
ea7ff111 927 $i = 0;
1f720b34 928 $regs = array(false, false);
ea7ff111 929 while (isset($read_ary[$i])) {
930 if (ereg("UNSEEN ([0-9]+)", $read_ary[$i], $regs)) {
931 break;
932 }
933 $i++;
934 }
9c737111 935 return $regs[1];
936}
937
1f720b34 938/*
939 * Returns the number of unseen/total messages in this folder
940 */
941function sqimap_status_messages ($imap_stream, $mailbox) {
b8ec18ef 942 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (MESSAGES UNSEEN RECENT)", false, $result, $message);
1f720b34 943 $i = 0;
b8ec18ef 944 $messages = $unseen = $recent = false;
1f720b34 945 $regs = array(false,false);
946 while (isset($read_ary[$i])) {
947 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 948 $unseen = $regs[1];
949 }
1f720b34 950 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 951 $messages = $regs[1];
952 }
b8ec18ef 953 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
098ea084 954 $recent = $regs[1];
955 }
1f720b34 956 $i++;
957 }
b8ec18ef 958 return array('MESSAGES' => $messages, 'UNSEEN'=>$unseen, 'RECENT' => $recent);
1f720b34 959}
960
9c737111 961
962/*
3411d4ec 963 * Saves a message to a given folder -- used for saving sent messages
964 */
9c737111 965function sqimap_append ($imap_stream, $sent_folder, $length) {
966 fputs ($imap_stream, sqimap_session_id() . " APPEND \"$sent_folder\" (\\Seen) \{$length}\r\n");
85fc999e 967 $tmp = fgets ($imap_stream, 1024);
9c737111 968}
969
8813fb15 970function sqimap_append_done ($imap_stream, $folder='') {
1f720b34 971 global $squirrelmail_language, $color;
9c737111 972 fputs ($imap_stream, "\r\n");
973 $tmp = fgets ($imap_stream, 1024);
69146537 974 if (preg_match("/(.*)(BAD|NO)(.*)$/", $tmp, $regs)) {
975 set_up_language($squirrelmail_language);
1f720b34 976 require_once(SM_PATH . 'functions/display_messages.php');
098ea084 977 $reason = $regs[3];
978 if ($regs[2] == 'NO') {
979 $string = "<b><font color=$color[2]>\n" .
980 _("ERROR : Could not append message to") ." $folder." .
981 "</b><br>\n" .
982 _("Server responded: ") .
983 $reason . "<br>\n";
984 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
985 $string .= _("Solution: ") .
986 _("Remove unneccessary messages from your folder and start with your Trash folder.")
987 ."<br>\n";
988 }
989 $string .= "</font>\n";
990 error_box($string,$color);
991 } else {
8813fb15 992 $string = "<b><font color=$color[2]>\n" .
098ea084 993 _("ERROR : Bad or malformed request.") .
994 "</b><br>\n" .
995 _("Server responded: ") .
996 $tmp . "</font><br>\n";
997 error_box($string,$color);
8813fb15 998 exit;
098ea084 999 }
69146537 1000 }
9c737111 1001}
85fc999e 1002
bd9829d7 1003function sqimap_get_user_server ($imap_server, $username) {
bd9829d7 1004 if (substr($imap_server, 0, 4) != "map:") {
1005 return $imap_server;
1006 }
bd9829d7 1007 $function = substr($imap_server, 4);
1008 return $function($username);
1009}
1010
1011/* This is an example that gets imapservers from yellowpages (NIS).
1012 * you can simple put map:map_yp_alias in your $imap_server_address
1013 * in config.php use your own function instead map_yp_alias to map your
1014 * LDAP whatever way to find the users imapserver. */
1015
1016function map_yp_alias($username) {
1017 $yp = `ypmatch $username aliases`;
1018 return chop(substr($yp, strlen($username)+1));
1019}
1020
15e6162e 1021?>