+ return $results;
+}
+
+function sqimap_fread($imap_stream,$iSize,$filter=false,
+ $outputstream=false, $no_return=false) {
+ if (!$filter || !$outputstream) {
+ $iBufferSize = $iSize;
+ } else {
+ $iBufferSize = 62400; // multiple of 78 in case of base64 decoding.
+ }
+ $iRet = $iSize - $iBufferSize;
+ $iRetrieved = 0;
+ $i = 0;
+ $results = $sReadRem = '';
+ $bFinished = $bBufferSizeAdapted = $bBufferIsOk = false;
+ while (($iRetrieved < ($iSize - $iBufferSize))) {
+ $sRead = fread($imap_stream,$iBufferSize);
+ if (!$sRead) {
+ $results = false;
+ break;
+ }
+ $iRetrieved += $iBufferSize;
+ if ($filter) {
+ // in case line-endings do not appear at position 78 we adapt the buffersize so we can base64 decode on the fly
+ if (!$bBufferSizeAdapted) {
+ $i = strpos($sRead,"\n");
+ if ($i) {
+ ++$i;
+ $iFragments = floor($iBufferSize / $i);
+ $iNewBufferSize = $iFragments * $i;
+ $iRemainder = $iNewBufferSize + $i - $iBufferSize;
+ if ($iNewBufferSize == $iBufferSize) {
+ $bBufferIsOk = true;
+ $iRemainder = 0;
+ $iNewBufferSize = $iBufferSize;
+ $bBufferSizeAdapted = true;
+ }
+ if (!$bBufferIsOk && ($iRemainder + $iBufferSize) < $iSize) {
+ $sReadRem = fread($imap_stream,$iRemainder);
+ } else if (!$bBufferIsOk) {
+ $sReadRem = fread($imap_stream,$iSize - $iBufferSize);
+ $bFinished = true;
+ }
+ if (!$sReadRem && $sReadRem !== '') {
+ $results = false;
+ break;
+ }
+ $iBufferSize = $iNewBufferSize;
+ $bBufferSizeAdapted = true;
+ } else {
+ $sReadRem = fread($imap_stream,$iSize - $iBufferSize);
+ $bFinished = true;
+ if (!$sReadRem) {
+ $results = false;
+ break;
+ }
+ }
+ $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;
+}
+
+/*
+ * 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