Need to escape $oldway in the print statement.
[squirrelmail.git] / functions / imap_general.php
index 92bb13f4d914c99de2645c927512694573b63819..b53a2104e84b728b2986f34b8fa95d9a8f7392a6 100755 (executable)
@@ -187,62 +187,47 @@ function sqimap_fread($imap_stream,$iSize,$filter=false,
     if (!$filter || !$outputstream) {
         $iBufferSize = $iSize;
     } else {
-        $iBufferSize = 62400; // multiple of 78 in case of base64 decoding.
+        // see php bug 24033. They changed fread behaviour %$^&$%
+        $iBufferSize = 7800; // multiple of 78 in case of base64 decoding.
+    }
+    if ($iSize < $iBufferSize) {
+        $iBufferSize = $iSize;
     }
-    $iRet = $iSize - $iBufferSize;
     $iRetrieved = 0;
-    $i = 0;
-    $results = $sReadRem = '';
-    $bFinished = $bBufferSizeAdapted =  $bBufferIsOk = false;
-    while (($iRetrieved < ($iSize - $iBufferSize))) {
+    $results = '';
+    $sRead = $sReadRem = '';
+    // NB: fread can also stop at end of a packet on sockets. 
+    while ($iRetrieved < $iSize) {
         $sRead = fread($imap_stream,$iBufferSize);
+        $iLength = strlen($sRead);
+        $iRetrieved += $iLength ;
+        $iRemaining = $iSize - $iRetrieved;
+        if ($iRemaining < $iBufferSize) {
+            $iBufferSize = $iRemaining;
+        }
         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);
-           }
+        if ($sReadRem) {
+            $sRead = $sReadRem . $sRead;
+            $sReadRem = '';
+        }
+        if (substr($sRead,-1) !== "\n") {  
+            $i = strrpos($sRead,"\n");
+            if ($i !== false && $iRetrieved<$iSize) {
+                ++$i;
+                $sReadRem = substr($sRead,$i);
+                $sRead = substr($sRead,0,$i);
+            } else if ($iLength && $iRetrieved<$iSize) { // linelength > received buffer
+                $sReadRem = $sRead;
+                $sRead = '';
+            }
+        } 
+        if ($filter && $sRead) {
            $filter($sRead);
         }
-        if ($outputstream) {
+        if ($outputstream && $sRead) {
            if (is_resource($outputstream)) {
                fwrite($outputstream,$sRead);
            } else if ($outputstream == 'php://stdout') {
@@ -251,28 +236,13 @@ function sqimap_fread($imap_stream,$iSize,$filter=false,
         }
         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;
-           }
+        } else {    
+            $results .= $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 = '') {
@@ -294,6 +264,26 @@ function sqimap_read_data_list($imap_stream, $tag, $handle_errors,
     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,
@@ -461,14 +451,7 @@ function sqimap_retrieve_imap_response($imap_stream, $tag, $handle_errors,
     /* 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" .
-                  _("Query:") . ' '.
-                  htmlspecialchars($query) . '<br>' . "</font><br>\n";
-        error_box($string,$color);    
+        sqimap_error_box(_("ERROR : Connection dropped by imap-server."), $query);
         exit;
     }
     
@@ -483,67 +466,30 @@ function sqimap_retrieve_imap_response($imap_stream, $tag, $handle_errors,
     /* Return result or handle errors */
     if ($handle_errors == false) {
         return $aResponse;
-        return( $resultlist );
+        return( $resultlist ); //?? Why this?
     }
-    switch ($response[$tag])
-    {
+    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) {
-            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[$tag]) . "</font><br>\n";
-            error_box($string,$color);
+            sqimap_error_box(_("ERROR : Could not complete request."), $query, _("Reason Given: "), $message[$tag]);
             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[$tag]) . "</font><br>\n";
-        error_box($string,$color);
+        sqimap_error_box(_("ERROR : Bad or malformed request."), $query, _("Server responded: "), $message[$tag]);
         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[$tag]) . "</font><br>\n";
-        error_box($string,$color);
+        sqimap_error_box(_("ERROR : Imap server closed the connection."), $query, _("Server responded: "), $message[$tag]);
         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[$tag]) . "</font><br>\n";
-        error_box($string,$color);
+        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;    
@@ -662,9 +608,22 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
       $query = 'LOGIN "' . quoteimap($username) .  '" "' . quoteimap($password) . '"';
       $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
     } elseif ($imap_auth_mech == 'plain') {
-                /* Replace this with SASL PLAIN if it ever gets implemented */
-                $response="BAD";
-                $message='SquirrelMail does not support SASL PLAIN yet. Rerun conf.pl and use login instead.';
+                /* SASL PLAIN */
+                $tag=sqimap_session_id(false);
+                $auth = base64_encode("$username\0$username\0$password");
+                  
+                $query = $tag . " AUTHENTICATE PLAIN\r\n";
+                fputs($imap_stream, $query);
+                $read=sqimap_fgets($imap_stream);
+
+                if (substr($read,0,1) == '+') { // OK so far..
+                    fputs($imap_stream, "$auth\r\n");
+                    $read = sqimap_fgets($imap_stream);
+                }
+                
+                $results=explode(" ",$read,3);
+                $response=$results[1];
+                $message=$results[2];
         } else {
                 $response="BAD";
                 $message="Internal SquirrelMail error - unknown IMAP authentication method chosen.  Please contact the developers.";
@@ -787,6 +746,7 @@ function sqimap_get_delimiter ($imap_stream = false) {
         } else {
             fputs ($imap_stream, ". LIST \"INBOX\" \"\"\r\n");
             $read = sqimap_read_data($imap_stream, '.', true, $a, $b);
+            $read = $read['.'][0];     //sqimap_read_data() now returns a tag array of response array
             $quote_position = strpos ($read[0], '"');
             $sqimap_delimiter = substr ($read[0], $quote_position+1, 1);
         }
@@ -795,9 +755,17 @@ function sqimap_get_delimiter ($imap_stream = false) {
 }
 
 
+function sqimap_encode_mailbox_name($what)
+{
+       if (ereg("[\"\\\r\n]", $what))
+               return '{' . strlen($what) . "}\r\n" . $what;   /* 4.3 literal form */
+       return '"' . $what . '"';       /* 4.3 quoted string form */
+}
+
+
 /* Gets the number of messages in the current mailbox. */
 function sqimap_get_num_messages ($imap_stream, $mailbox) {
-    $read_ary = sqimap_run_command ($imap_stream, "EXAMINE \"$mailbox\"", false, $result, $message);
+    $read_ary = sqimap_run_command ($imap_stream, 'EXAMINE ' . sqimap_encode_mailbox_name($mailbox), false, $result, $message);
     for ($i = 0; $i < count($read_ary); $i++) {
         if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
             return $regs[1];
@@ -982,7 +950,7 @@ function parseAddress($address, $max=0) {
  * Returns the number of unseen messages in this folder
  */
 function sqimap_unseen_messages ($imap_stream, $mailbox) {
-    $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (UNSEEN)", false, $result, $message);
+    $read_ary = sqimap_run_command ($imap_stream, 'STATUS ' . sqimap_encode_mailbox_name($mailbox) . ' (UNSEEN)', false, $result, $message);
     $i = 0;
     $regs = array(false, false);
     while (isset($read_ary[$i])) {
@@ -995,10 +963,10 @@ function sqimap_unseen_messages ($imap_stream, $mailbox) {
 }
 
 /*
- * Returns the number of unseen/total messages in this folder
+ * Returns the number of total/unseen/recent messages in this folder
  */
 function sqimap_status_messages ($imap_stream, $mailbox) {
-    $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (MESSAGES UNSEEN RECENT)", false, $result, $message);
+    $read_ary = sqimap_run_command ($imap_stream, 'STATUS ' . sqimap_encode_mailbox_name($mailbox) . ' (MESSAGES UNSEEN RECENT)', false, $result, $message);
     $i = 0;
     $messages = $unseen = $recent = false;
     $regs = array(false,false);
@@ -1022,7 +990,7 @@ function sqimap_status_messages ($imap_stream, $mailbox) {
  *  Saves a message to a given folder -- used for saving sent messages
  */
 function sqimap_append ($imap_stream, $sent_folder, $length) {
-    fputs ($imap_stream, sqimap_session_id() . " APPEND \"$sent_folder\" (\\Seen) \{$length}\r\n");
+    fputs ($imap_stream, sqimap_session_id() . ' APPEND ' . sqimap_encode_mailbox_name($sent_folder) . " (\\Seen) \{$length}\r\n");
     $tmp = fgets ($imap_stream, 1024);
 }