+ $sRead .= $sReadRem;
+ $iRetrieved += $iRemainder;
+ unset($sReadRem);
+ }
+ $filter($sRead);
+ }
+ if ($outputstream) {
+ if (is_resource($outputstream)) {
+ fwrite($outputstream,$sRead);
+ } else if ($outputstream == 'php://stdout') {
+ echo $sRead;
+ }
+ }
+ if ($no_return) {
+ $sRead = '';
+ }
+ $results .= $sRead;
+ }
+ if (!$results && !$bFinished) {
+ $sRead = fread($imap_stream,($iSize - ($iRetrieved)));
+ if ($filter) {
+ $filter($sRead);
+ }
+ if ($outputstream) {
+ if (is_resource($outputstream)) {
+ fwrite($outputstream,$sRead);
+ } else if ($outputstream == 'php://stdout') { // FIXME
+ echo $sRead;
+ }
+ }
+ if ($no_return) {
+ $sRead = '';
+ }
+ $results .= $sRead;
+ }
+ return $results;
+}
+/* obsolete function, inform plugins that use it */
+function sqimap_read_data_list($imap_stream, $tag, $handle_errors,
+ &$response, &$message, $query = '') {
+ global $color, $squirrelmail_language;
+ set_up_language($squirrelmail_language);
+ require_once(SM_PATH . 'functions/display_messages.php');
+ $string = "<b><font color=$color[2]>\n" .
+ _("ERROR : Bad function call.") .
+ "</b><br>\n" .
+ _("Reason:") . ' '.
+ 'There is a plugin installed which make use of the <br>' .
+ 'SquirrelMail internal function sqimap_read_data_list.<br>'.
+ 'Please adapt the installed plugin and let it use<br>'.
+ 'sqimap_run_command or sqimap_run_command_list instead<br><br>'.
+ 'The following query was issued:<br>'.
+ htmlspecialchars($query) . '<br>' . "</font><br>\n";
+ error_box($string,$color);
+ echo '</body></html>';
+ exit;
+}
+
+function sqimap_error_box($title, $query = '', $message_title = '', $message = '')
+{
+ global $color, $squirrelmail_language;
+
+ set_up_language($squirrelmail_language);
+ require_once(SM_PATH . 'functions/display_messages.php');
+ $string = "<font color=$color[2]><b>\n" . $title . "</b><br>\n";
+ $cmd = explode(' ',$query);
+ $cmd= strtolower($cmd[0]);
+
+ if ($query != '' && $cmd != 'login')
+ $string .= _("Query:") . ' ' . htmlspecialchars($query) . '<br>';
+ if ($message_title != '')
+ $string .= $message_title;
+ if ($message != '')
+ $string .= htmlspecialchars($message);
+ $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();
+ $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}
+
+ 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) {
+ 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;
+ return( $resultlist ); //?? Why this?
+ }
+ 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;
+ }
+}
+
+function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors,
+ &$response, &$message, $query = '',
+ $filter=false,$outputstream=false,$no_return=false) {
+
+ $tag_uid_a = explode(' ',trim($tag_uid));
+ $tag = $tag_uid_a[0];
+
+ $res = sqimap_retrieve_imap_response($imap_stream, $tag, $handle_errors,
+ $response, $message, $query,$filter,$outputstream,$no_return);
+ /* sqimap_read_data should be called for one response
+ but since it just calls sqimap_retrieve_imap_response which
+ handles multiple responses we need to check for that
+ and merge the $res array IF they are seperated and
+ IF it was a FETCH response. */
+
+// if (isset($res[1]) && is_array($res[1]) && isset($res[1][0])
+// && preg_match('/^\* \d+ FETCH/', $res[1][0])) {
+// $result = array();
+// foreach($res as $index=>$value) {
+// $result = array_merge($result, $res["$index"]);
+// }
+// }
+ if (isset($result)) {
+ return $result[$tag];
+ }
+ else {
+ return $res;
+ }
+}
+
+/*
+ * Logs the user into the imap server. If $hide is set, no error messages
+ * will be displayed. This function returns the imap connection handle.
+ */
+function sqimap_login ($username, $password, $imap_server_address, $imap_port, $hide) {
+ global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;
+
+ if (!isset($onetimepad) || empty($onetimepad)) {
+ sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION );
+ }
+ $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
+ $host=$imap_server_address;
+
+ if (($use_imap_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) {
+ /* Use TLS by prefixing "tls://" to the hostname */
+ $imap_server_address = 'tls://' . $imap_server_address;
+ }
+
+ $imap_stream = fsockopen ( $imap_server_address, $imap_port, $error_number, $error_string, 15);
+
+ /* Do some error correction */
+ if (!$imap_stream) {
+ if (!$hide) {
+ set_up_language($squirrelmail_language, true);
+ require_once(SM_PATH . 'functions/display_messages.php');
+ $string = sprintf (_("Error connecting to IMAP server: %s.") .
+ "<br>\r\n", $imap_server_address) .
+ "$error_number : $error_string<br>\r\n";
+ logout_error($string,$color);
+ }
+ exit;
+ }
+
+ $server_info = fgets ($imap_stream, 1024);
+
+ /* Decrypt the password */
+ $password = OneTimePadDecrypt($password, $onetimepad);
+
+ if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
+ // We're using some sort of authentication OTHER than plain or login
+ $tag=sqimap_session_id(false);
+ if ($imap_auth_mech == 'digest-md5') {
+ $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
+ } elseif ($imap_auth_mech == 'cram-md5') {
+ $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
+ }
+ fputs($imap_stream,$query);
+ $answer=sqimap_fgets($imap_stream);
+ // Trim the "+ " off the front
+ $response=explode(" ",$answer,3);
+ if ($response[0] == '+') {
+ // Got a challenge back
+ $challenge=$response[1];
+ if ($imap_auth_mech == 'digest-md5') {
+ $reply = digest_md5_response($username,$password,$challenge,'imap',$host);
+ } elseif ($imap_auth_mech == 'cram-md5') {
+ $reply = cram_md5_response($username,$password,$challenge);
+ }
+ fputs($imap_stream,$reply);
+ $read=sqimap_fgets($imap_stream);
+ if ($imap_auth_mech == 'digest-md5') {
+ // DIGEST-MD5 has an extra step..
+ if (substr($read,0,1) == '+') { // OK so far..
+ fputs($imap_stream,"\r\n");
+ $read=sqimap_fgets($imap_stream);