/** * 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; } }
/** * 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_read_data_list($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '', $filter = false, $outputstream = false, $no_return = false) { global $color, $squirrelmail_language; $read = ''; $tag_uid_a = explode(' ', trim($tag_uid)); $tag = $tag_uid_a[0]; $resultlist = array(); $data = array(); $read = sqimap_fgets($imap_stream); $i = 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 ($arg && $found_tag == $tag) { switch ($arg) { case 'OK': case 'BAD': case 'NO': case 'BYE': case 'PREAUTH': $response = $arg; $message = trim(substr($read, $i + strlen($arg))); break 3; /* switch switch while */ /* switch switch while */ default: /* this shouldn't happen */ $response = $arg; $message = trim(substr($read, $i + strlen($arg))); break 3; /* switch switch while */ } } elseif ($found_tag !== $tag) { /* reset data array because we do not need this reponse */ $data = array(); $read = sqimap_fgets($imap_stream); 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); // check for numeric value to avoid that untagged responses like: // * OK [PARSE] Unexpected characters at end of address: {SET:debug=51} // will trigger literal fetching ({SET:debug=51} !== int ) if (is_numeric($iLit)) { $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; } } 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); set_up_language($squirrelmail_language); require_once SM_PATH . 'functions/display_messages.php'; $string = "<b><font color=\"{$color['2']}\">\n" . _("ERROR: Connection dropped by IMAP server.") . "</b><br />\n"; $cmd = explode(' ', $query); $cmd = strtolower($cmd[0]); if ($query != '' && $cmd != 'login') { $string .= "Query:" . ' ' . htmlspecialchars($query) . '<br />' . "</font><br />\n"; } error_box($string, $color); exit; } /* Set $resultlist array */ if (!empty($data)) { $resultlist[] = $data; } elseif (empty($resultlist)) { $resultlist[] = array(); } /* Return result or handle errors */ if ($handle_errors == false) { return $resultlist; } switch ($response) { case 'OK': return $resultlist; break; case 'NO': /* ignore this error from M$ exchange, it is not fatal (aka bug) */ if (strstr($message, 'command resulted in') === false) { set_up_language($squirrelmail_language); require_once SM_PATH . 'functions/display_messages.php'; $string = "<b><font color=\"{$color['2']}\">\n" . _("ERROR: Could not complete request.") . "</b><br />\n" . _("Query:") . ' ' . htmlspecialchars($query) . '<br />' . _("Reason Given:") . ' ' . htmlspecialchars($message) . "</font><br />\n"; error_box($string, $color); echo '</body></html>'; exit; } break; case 'BAD': set_up_language($squirrelmail_language); require_once SM_PATH . 'functions/display_messages.php'; $string = "<b><font color=\"{$color['2']}\">\n" . _("ERROR: Bad or malformed request.") . "</b><br />\n" . _("Query:") . ' ' . htmlspecialchars($query) . '<br />' . _("Server responded:") . ' ' . htmlspecialchars($message) . "</font><br />\n"; error_box($string, $color); echo '</body></html>'; exit; case 'BYE': set_up_language($squirrelmail_language); require_once SM_PATH . 'functions/display_messages.php'; $string = "<b><font color=\"{$color['2']}\">\n" . _("ERROR: IMAP server closed the connection.") . "</b><br />\n" . _("Query:") . ' ' . htmlspecialchars($query) . '<br />' . _("Server responded:") . ' ' . htmlspecialchars($message) . "</font><br />\n"; error_box($string, $color); echo '</body></html>'; exit; default: set_up_language($squirrelmail_language); require_once SM_PATH . 'functions/display_messages.php'; $string = "<b><font color=\"{$color['2']}\">\n" . _("ERROR: Unknown IMAP response.") . "</b><br />\n" . _("Query:") . ' ' . htmlspecialchars($query) . '<br />' . _("Server responded:") . ' ' . htmlspecialchars($message) . "</font><br />\n"; error_box($string, $color); /* the error is displayed but because we don't know the reponse we return the result anyway */ return $resultlist; break; } }
function sqimap_read_data_list($imap_stream, $tag_uid, $handle_errors, &$response, &$message, $query = '', $filter = false, $outputstream = false, $no_return = false) { $read = ''; $tag_uid_a = explode(' ', trim($tag_uid)); $tag = $tag_uid_a[0]; $resultlist = array(); $data = array(); $read = sqimap_fgets($imap_stream); $i = 0; while ($read) { $char = substr($read, 0, 1); switch ($char) { case '+': default: $read = sqimap_fgets($imap_stream); break; case substr($tag, 0, 1): /* 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 ($arg && $found_tag == $tag) { switch ($arg) { case 'OK': case 'BAD': case 'NO': case 'BYE': case 'PREAUTH': $response = $arg; $message = trim(substr($read, $i + strlen($arg))); break 3; /* switch switch while */ /* switch switch while */ default: /* this shouldn't happen */ $response = $arg; $message = trim(substr($read, $i + strlen($arg))); break 3; /* switch switch while */ } } elseif ($found_tag !== $tag) { /* reset data array because we do not need this reponse */ $data = array(); $read = sqimap_fgets($imap_stream); break; } // end case substr($tag, 0, 1) // end case substr($tag, 0, 1) 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 (substr($read, 0, 1) == '*') { break 2; } $s = substr($read, -3); } while ($s === "}\r\n"); $s = substr($read, -3); } while (substr($read, 0, 1) !== '*' && 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 */ } elseif (substr($read, 0, 1) == '*') { 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); echo date("d.m.Y @ G:i:s") . ": ERROR: Connection dropped by IMAP server.\n"; exit; } /* Set $resultlist array */ if (!empty($data)) { $resultlist[] = $data; } elseif (empty($resultlist)) { $resultlist[] = array(); } /* Return result or handle errors */ if ($handle_errors == false) { return $resultlist; } switch ($response) { case 'OK': return $resultlist; break; case 'NO': /* ignore this error from M$ exchange, it is not fatal (aka bug) */ if (strstr($message, 'command resulted in') === false) { echo date("d.m.Y @ G:i:s") . ": ERROR: Could not complete request.\n"; exit; } break; case 'BAD': echo date("d.m.Y @ G:i:s") . ": ERROR: Bad or malformed request.\n"; exit; case 'BYE': echo date("d.m.Y @ G:i:s") . ": ERROR: IMAP server closed the connection.\n"; exit; default: echo date("d.m.Y @ G:i:s") . ": ERROR: Unknown IMAP response.\n"; return $resultlist; break; } }