function sqimap_asearch_error_box($response, $query, $message, $link = '') { global $color; // Error message titles according to IMAP server returned code $imap_error_titles = array('OK' => '', 'NO' => _("ERROR: Could not complete request."), 'BAD' => _("ERROR: Bad or malformed request."), 'BYE' => _("ERROR: IMAP server closed the connection."), '' => _("ERROR: Connection dropped by IMAP server.")); if (!array_key_exists($response, $imap_error_titles)) { $title = _("ERROR: Unknown IMAP response."); } else { $title = $imap_error_titles[$response]; } if ($link == '') { $message_title = _("Reason Given:"); } else { $message_title = _("Possible reason:"); } $message_title .= ' '; sqimap_error_box($title, $query, $message_title, $message, $link); }
function sqimap_asearch_error_box($response, $query, $message, $link = '') { global $color; // Error message titles according to imap server returned code $imap_error_titles = array('OK' => '', 'NO' => _("ERROR : Could not complete request."), 'BAD' => _("ERROR : Bad or malformed request."), 'BYE' => _("ERROR : Imap server closed the connection."), '' => _("ERROR : Connection dropped by imap-server.")); if (!array_key_exists($response, $imap_error_titles)) { $title = _("ERROR : Unknown imap response."); } else { $title = $imap_error_titles[$response]; } if ($link == '') { $message_title = _("Reason Given: "); } else { $message_title = _("Possible reason : "); } if (function_exists('sqimap_error_box')) { sqimap_error_box($title, $query, $message_title, $message, $link); } else { //Straight copy of 1.5 imap_general.php:sqimap_error_box(). Can be removed at a later time global $color; require_once SM_PATH . 'functions/display_messages.php'; $string = "<font color=\"{$color['2']}\"><b>\n" . $title . "</b><br />\n"; if ($query != '') { $string .= _("Query:") . ' ' . htmlspecialchars($query) . '<br />'; } if ($message_title != '') { $string .= $message_title; } if ($message != '') { $string .= htmlspecialchars($message); } if ($link != '') { $string .= $link; } $string .= "</font><br />\n"; error_box($string, $color); } }
/** * Reads the output from the IMAP stream. If handle_errors is set to true, * this will also handle all errors that are received. If it is not set, * the errors will be sent back through $response and $message. */ function sqimap_retrieve_imap_response($imap_stream, $tag, $handle_errors, &$response, &$message, $query = '', $filter = false, $outputstream = false, $no_return = false) { global $color, $squirrelmail_language; $read = ''; if (!is_array($message)) { $message = array(); } if (!is_array($response)) { $response = array(); } $aResponse = ''; $resultlist = array(); $data = array(); $read = sqimap_fgets($imap_stream); $i = $k = 0; while ($read) { $char = $read[0]; switch ($char) { case '+': default: $read = sqimap_fgets($imap_stream); break; case $tag[0]: /* get the command */ $arg = ''; $i = strlen($tag) + 1; $s = substr($read, $i); if (($j = strpos($s, ' ')) || ($j = strpos($s, "\n"))) { $arg = substr($s, 0, $j); } $found_tag = substr($read, 0, $i - 1); if ($found_tag) { switch ($arg) { case 'OK': case 'BAD': case 'NO': case 'BYE': case 'PREAUTH': $response[$found_tag] = $arg; $message[$found_tag] = trim(substr($read, $i + strlen($arg))); if (!empty($data)) { $resultlist[] = $data; } $aResponse[$found_tag] = $resultlist; $data = $resultlist = array(); if ($found_tag == $tag) { break 3; /* switch switch while */ } break; default: /* this shouldn't happen */ $response[$found_tag] = $arg; $message[$found_tag] = trim(substr($read, $i + strlen($arg))); if (!empty($data)) { $resultlist[] = $data; } $aResponse[$found_tag] = $resultlist; $data = $resultlist = array(); if ($found_tag == $tag) { break 3; /* switch switch while */ } } } $read = sqimap_fgets($imap_stream); if ($read === false) { /* error */ break 3; /* switch switch while */ } break; // end case $tag{0} // end case $tag{0} case '*': if (preg_match('/^\\*\\s\\d+\\sFETCH/', $read)) { /* check for literal */ $s = substr($read, -3); $fetch_data = array(); do { /* outer loop, continue until next untagged fetch or tagged reponse */ do { /* innerloop for fetching literals. with this loop we prohibid that literal responses appear in the outer loop so we can trust the untagged and tagged info provided by $read */ if ($s === "}\r\n") { $j = strrpos($read, '{'); $iLit = substr($read, $j + 1, -3); $fetch_data[] = $read; $sLiteral = sqimap_fread($imap_stream, $iLit, $filter, $outputstream, $no_return); if ($sLiteral === false) { /* error */ break 4; /* while while switch while */ } /* backwards compattibility */ $aLiteral = explode("\n", $sLiteral); /* release not neaded data */ unset($sLiteral); foreach ($aLiteral as $line) { $fetch_data[] = $line . "\n"; } /* release not neaded data */ unset($aLiteral); /* next fgets belongs to this fetch because we just got the exact literalsize and there must follow data to complete the response */ $read = sqimap_fgets($imap_stream); if ($read === false) { /* error */ break 4; /* while while switch while */ } $fetch_data[] = $read; } else { $fetch_data[] = $read; } /* retrieve next line and check in the while statements if it belongs to this fetch response */ $read = sqimap_fgets($imap_stream); if ($read === false) { /* error */ break 4; /* while while switch while */ } /* check for next untagged reponse and break */ if ($read[0] == '*') { break 2; } $s = substr($read, -3); } while ($s === "}\r\n"); $s = substr($read, -3); } while ($read[0] !== '*' && substr($read, 0, strlen($tag)) !== $tag); $resultlist[] = $fetch_data; /* release not neaded data */ unset($fetch_data); } else { $s = substr($read, -3); do { if ($s === "}\r\n") { $j = strrpos($read, '{'); $iLit = substr($read, $j + 1, -3); $data[] = $read; $sLiteral = fread($imap_stream, $iLit); if ($sLiteral === false) { /* error */ $read = false; break 3; /* while switch while */ } $data[] = $sLiteral; $data[] = sqimap_fgets($imap_stream); } else { $data[] = $read; } $read = sqimap_fgets($imap_stream); if ($read === false) { break 3; /* while switch while */ } else { if ($read[0] == '*') { break; } } $s = substr($read, -3); } while ($s === "}\r\n"); break 1; } break; // end case '*' } // end switch } // end while /* error processing in case $read is false */ if ($read === false) { // try to retrieve an untagged bye respons from the results $sResponse = array_pop($data); if ($sResponse !== NULL && strpos($sResponse, '* BYE') !== false) { if (!$handle_errors) { $query = ''; } sqimap_error_box(_("ERROR : Imap server closed the connection."), $query, _("Server responded:"), $sResponse); echo '</body></html>'; exit; } else { if ($handle_errors) { unset($data); sqimap_error_box(_("ERROR : Connection dropped by imap-server."), $query); exit; } } } /* Set $resultlist array */ if (!empty($data)) { //$resultlist[] = $data; } elseif (empty($resultlist)) { $resultlist[] = array(); } /* Return result or handle errors */ if ($handle_errors == false) { return $aResponse; } switch ($response[$tag]) { case 'OK': return $aResponse; break; case 'NO': /* ignore this error from M$ exchange, it is not fatal (aka bug) */ if (strstr($message[$tag], 'command resulted in') === false) { sqimap_error_box(_("ERROR : Could not complete request."), $query, _("Reason Given: "), $message[$tag]); echo '</body></html>'; exit; } break; case 'BAD': sqimap_error_box(_("ERROR : Bad or malformed request."), $query, _("Server responded: "), $message[$tag]); echo '</body></html>'; exit; case 'BYE': sqimap_error_box(_("ERROR : Imap server closed the connection."), $query, _("Server responded: "), $message[$tag]); echo '</body></html>'; exit; default: sqimap_error_box(_("ERROR : Unknown imap response."), $query, _("Server responded: "), $message[$tag]); /* the error is displayed but because we don't know the reponse we return the result anyway */ return $aResponse; break; } }
/** * Connects to the IMAP server and returns a resource identifier for use with * the other SquirrelMail IMAP functions. Does NOT login! * @param string server hostname of IMAP server * @param int port port number to connect to * @param integer $tls whether to use plain text(0), TLS(1) or STARTTLS(2) when connecting. * Argument was boolean before 1.5.1. * @param array $stream_options Stream context options, see config_local.php * for more details (OPTIONAL) * @return imap-stream resource identifier * @since 1.5.0 (usable only in 1.5.1 or later) */ function sqimap_create_stream($server, $port, $tls = 0, $stream_options = array()) { global $squirrelmail_language; if (strstr($server, ':') && !preg_match("/^\\[.*\\]\$/", $server)) { // numerical IPv6 address must be enclosed in square brackets $server = '[' . $server . ']'; } // NB: Using "ssl://" ensures the highest possible TLS version // will be negotiated with the server (whereas "tls://" only // uses TLS version 1.0) // if ($tls == 1) { if (check_php_version(4, 3) and extension_loaded('openssl')) { if (function_exists('stream_socket_client')) { $server_address = 'ssl://' . $server . ':' . $port; $ssl_context = @stream_context_create($stream_options); $connect_timeout = ini_get('default_socket_timeout'); // null timeout is broken if ($connect_timeout == 0) { $connect_timeout = 15; } $imap_stream = @stream_socket_client($server_address, $error_number, $error_string, $connect_timeout, STREAM_CLIENT_CONNECT, $ssl_context); } else { $imap_stream = @fsockopen('ssl://' . $server, $port, $error_number, $error_string, 15); } } else { require_once SM_PATH . 'functions/display_messages.php'; logout_error(sprintf(_("Error connecting to IMAP server: %s."), $server) . '<br />' . _("TLS is enabled, but this version of PHP does not support TLS sockets, or is missing the openssl extension.") . '<br /><br />' . _("Please contact your system administrator and report this error."), sprintf(_("Error connecting to IMAP server: %s."), $server)); } } else { $imap_stream = @fsockopen($server, $port, $error_number, $error_string, 15); } /* Do some error correction */ if (!$imap_stream) { set_up_language($squirrelmail_language, true); require_once SM_PATH . 'functions/display_messages.php'; logout_error(sprintf(_("Error connecting to IMAP server: %s."), $server) . "<br />\r\n{$error_number} : {$error_string}<br />\r\n", sprintf(_("Error connecting to IMAP server: %s."), $server)); exit; } $server_info = fgets($imap_stream, 1024); /** * Implementing IMAP STARTTLS (rfc2595) in php 5.1.0+ * http://www.php.net/stream-socket-enable-crypto */ if ($tls === 2) { if (function_exists('stream_socket_enable_crypto')) { // check starttls capability, don't use cached capability version if (!sqimap_capability($imap_stream, 'STARTTLS', false)) { // imap server does not declare starttls support sqimap_error_box(sprintf(_("Error connecting to IMAP server: %s."), $server), '', '', _("IMAP STARTTLS is enabled in SquirrelMail configuration, but used IMAP server does not support STARTTLS.")); exit; } // issue starttls command and check response sqimap_run_command($imap_stream, 'STARTTLS', false, $starttls_response, $starttls_message); // check response if ($starttls_response != 'OK') { // starttls command failed sqimap_error_box(sprintf(_("Error connecting to IMAP server: %s."), $server), 'STARTTLS', _("Server replied:") . ' ', $starttls_message); exit; } // start crypto on connection. suppress function errors. if (@stream_socket_enable_crypto($imap_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { // starttls was successful /** * RFC 2595 requires to discard CAPABILITY information after successful * STARTTLS command. We don't follow RFC, because SquirrelMail stores CAPABILITY * information only after successful login (src/redirect.php) and cached information * is used only in other php script connections after successful STARTTLS. If script * issues sqimap_capability() call before sqimap_login() and wants to get initial * capability response, script should set third sqimap_capability() argument to false. */ //sqsession_unregister('sqimap_capabilities'); } else { /** * stream_socket_enable_crypto() call failed. Possible issues: * - broken ssl certificate (uw drops connection, error is in syslog mail facility) * - some ssl error (can reproduce with STREAM_CRYPTO_METHOD_SSLv3_CLIENT, PHP E_WARNING * suppressed in stream_socket_enable_crypto() call) */ sqimap_error_box(sprintf(_("Error connecting to IMAP server: %s."), $server), '', '', _("Unable to start TLS.")); /** * Bug: stream_socket_enable_crypto() does not register SSL errors in * openssl_error_string() or stream notification wrapper and displays * them in E_WARNING level message. It is impossible to retrieve error * message without own error handler. */ exit; } } else { // php install does not support stream_socket_enable_crypto() function sqimap_error_box(sprintf(_("Error connecting to IMAP server: %s."), $server), '', '', _("IMAP STARTTLS is enabled in SquirrelMail configuration, but used PHP version does not support functions that allow to enable encryption on open socket.")); exit; } } return $imap_stream; }