charset encode / decode fixes
authorstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Fri, 28 Feb 2003 19:12:00 +0000 (19:12 +0000)
committerstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Fri, 28 Feb 2003 19:12:00 +0000 (19:12 +0000)
support for encoded personal names inside addresses
fix for headerrequest

git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@4564 7612ce4b-ef26-0410-bec9-ea0150e637f0

functions/i18n.php
functions/imap_general.php
functions/imap_messages.php
functions/mailbox_display.php
functions/mime.php

index cc9e3f9d3e00e9c540c24773d31b20e88bf7784c..5fccb12014ebb00aca793887e44fc6bcb5255242 100644 (file)
@@ -26,12 +26,7 @@ function charset_decode ($charset, $string) {
 
     /* All HTML special characters are 7 bit and can be replaced first */
     
-    /* NOTE Marc Groot Koerkamp: This is the wrong place to do 
-       htmlspecialchars, It should be done before the echo.
-       By doing it here we get double htmlspecialchars calls which translates
-        < => &lt; => &amp;lt;
-    */
-    //$string = htmlspecialchars ($string);
+    $string = htmlspecialchars ($string);
 
     $charset = strtolower($charset);
 
index 12174f51c23d279a2445587a35b558755ae4fcca..59c4dae46260ccf9f47a60fce70f5391ae9772f9 100755 (executable)
@@ -22,9 +22,9 @@ $sqimap_session_id = 1;
 function sqimap_session_id($unique_id = false) {
     global $data_dir, $username, $sqimap_session_id;
     if (!$unique_id) {
-       return( sprintf("A%03d", $sqimap_session_id++) );
+        return( sprintf("A%03d", $sqimap_session_id++) );
     } else {
-       return( sprintf("A%03d", $sqimap_session_id++) . ' UID' );
+        return( sprintf("A%03d", $sqimap_session_id++) . ' UID' );
     }
 }
 
@@ -34,10 +34,10 @@ function sqimap_session_id($unique_id = false) {
  */
 function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
     if ($imap_stream) {
-       $sid = sqimap_session_id($unique_id);
-       fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
-       $read = sqimap_read_data_list ($imap_stream, $sid, $handle_errors, $response, $message, $query );
-       return $read;
+        $sid = sqimap_session_id($unique_id);
+        fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
+        $read = sqimap_read_data_list ($imap_stream, $sid, $handle_errors, $response, $message, $query );
+        return $read;
     } else {
         global $squirrelmail_language, $color;
         set_up_language($squirrelmail_language);
@@ -46,7 +46,7 @@ function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$respon
                 _("ERROR : No available imapstream.") .
                 "</b></font>\n";
         error_box($string,$color);
-       return false;
+        return false;
     }
     
 }
@@ -54,9 +54,9 @@ function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$respon
 function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
     if ($imap_stream) {
         $sid = sqimap_session_id($unique_id);
-       fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
-       $read = sqimap_read_data ($imap_stream, $sid, $handle_errors, $response, $message, $query);
-       return $read;
+        fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
+        $read = sqimap_read_data ($imap_stream, $sid, $handle_errors, $response, $message, $query);
+        return $read;
     } else {
         global $squirrelmail_language, $color;
         set_up_language($squirrelmail_language);
@@ -65,7 +65,7 @@ function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response, &
                 _("ERROR : No available imapstream.") .
                 "</b></font>\n";
         error_box($string,$color);
-       return false;
+        return false;
     }
     
 }
@@ -151,21 +151,21 @@ function sqimap_read_data_list ($imap_stream, $pre, $handle_errors, &$response,
     /* 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" .
+            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);
+            error_box($string,$color);
             exit;
         }
     } 
     elseif ($response == 'BAD') {
         set_up_language($squirrelmail_language);
-       require_once(SM_PATH . 'functions/display_messages.php');
+        require_once(SM_PATH . 'functions/display_messages.php');
         $string = "<b><font color=$color[2]>\n" .
             _("ERROR : Bad or malformed request.") .
             "</b><br>\n" .
@@ -173,7 +173,7 @@ function sqimap_read_data_list ($imap_stream, $pre, $handle_errors, &$response,
             htmlspecialchars($query) . '<br>' .
             _("Server responded: ") .
             htmlspecialchars($message) . "</font><br>\n";
-       error_box($string,$color);    
+        error_box($string,$color);    
         exit;
     } 
     else {
@@ -217,12 +217,12 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
         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;
-       }
+        $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);
 
@@ -230,11 +230,11 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
     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) .
+            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);
+            logout_error($string,$color);
         }
         exit;
     }
@@ -244,77 +244,77 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
     /* Decrypt the password */
     $password = OneTimePadDecrypt($password, $onetimepad);
 
-       if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
+        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);
-                 }
-               }
-               $results=explode(" ",$read,3);
-               $response=$results[1];
-               $message=$results[2];
+          $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);
+                  }
+                }
+                $results=explode(" ",$read,3);
+                $response=$results[1];
+                $message=$results[2];
       } else {
-               // Fake the response, so the error trap at the bottom will work
-               $response="BAD";
-               $message='IMAP server does not appear to support the authentication method selected.';
-               $message .= '  Please contact your system administrator.';
+                // Fake the response, so the error trap at the bottom will work
+                $response="BAD";
+                $message='IMAP server does not appear to support the authentication method selected.';
+                $message .= '  Please contact your system administrator.';
       }
     } elseif ($imap_auth_mech == 'login') {
-         // Original IMAP login code
+          // Original IMAP login code
       $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.';
-       } else {
-               $response="BAD";
-               $message="Internal SquirrelMail error - unknown IMAP authentication method chosen.  Please contact the developers.";
-       }
+                /* 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.';
+        } else {
+                $response="BAD";
+                $message="Internal SquirrelMail error - unknown IMAP authentication method chosen.  Please contact the developers.";
+        }
     
-       /* If the connection was not successful, lets see why */
+        /* If the connection was not successful, lets see why */
     if ($response != 'OK') {
         if (!$hide) {
             if ($response != 'NO') {
                 /* "BAD" and anything else gets reported here. */
-               $message = htmlspecialchars($message);
+                $message = htmlspecialchars($message);
                 set_up_language($squirrelmail_language, true);
-               require_once(SM_PATH . 'functions/display_messages.php');
+                require_once(SM_PATH . 'functions/display_messages.php');
                 if ($response == 'BAD') {
                    $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
                 } else {
                    $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
                 }
                 if (isset($read) && is_array($read)) {
-                       $string .= '<br>' . _("Read data:") . "<br>\n";
+                        $string .= '<br>' . _("Read data:") . "<br>\n";
                     foreach ($read as $line) {
                         $string .= htmlspecialchars($line) . "<br>\n";
                     }
                 }
-               error_box($string,$color);
+                error_box($string,$color);
                 exit;
             } else {
                 /*
@@ -330,7 +330,7 @@ function sqimap_login ($username, $password, $imap_server_address, $imap_port, $
                 
                 set_up_language($squirrelmail_language, true);
                 include_once(SM_PATH . 'functions/display_messages.php' );
-               sqsession_destroy();
+                sqsession_destroy();
                 logout_error( _("Unknown user or password incorrect.") );
                 exit;
             }
@@ -365,11 +365,11 @@ function sqimap_capability($imap_stream, $capability='') {
         }
     }
     if ($capability) {
-       if (isset($sqimap_capabilities[$capability])) {
-           return $sqimap_capabilities[$capability];
-       } else {
-           return false;
-       }
+        if (isset($sqimap_capabilities[$capability])) {
+                return $sqimap_capabilities[$capability];
+        } else {
+                return false;
+        }
     }
     return $sqimap_capabilities;
 }
@@ -431,63 +431,126 @@ function sqimap_get_num_messages ($imap_stream, $mailbox) {
     return false; //"BUG! Couldn't get number of messages in $mailbox!";
 }
 
-
-/* Returns a displayable email address.
- *     Luke Ehresman <lehresma@css.tayloru.edu>
- *     "Luke Ehresman" <lehresma@css.tayloru.edu>
- *     <lehresma@css.tayloru.edu>
- *     lehresma@css.tayloru.edu (Luke Ehresman)
- *     lehresma@css.tayloru.edu
- * becomes: lehresma@css.tayloru.edu
- */
-function sqimap_find_email ($string) {
-    if (ereg("<([^>]+)>", $string, $regs)) {
-        $string = $regs[1];
-    } else if (ereg("([^ ]+@[^ ]+)", $string, $regs)) {
-        $string = $regs[1];
+function parseAddress($address, $max=0, $addr_ar = array(), $group = '', $host='') {
+    $pos = 0;
+    $j = strlen($address);
+    $personal = '';
+    $addr = '';
+    $comment = '';
+    if ($max && $max = count($addr_ar)) {
+        return $addr_ar;
     }
-    return trim($string);
-}
-
-
-/*
- * Takes the From: field and creates a displayable name.
- *     Luke Ehresman   <lkehresman@yahoo.com>
- *     "Luke Ehresman" <lkehresman@yahoo.com>
- *     lkehresman@yahoo.com (Luke Ehresman)
- * becomes: Luke Ehresman
- *     <lkehresman@yahoo.com>
- * becomes: lkehresman@yahoo.com
- */
-function sqimap_find_displayable_name ($string) {
-    $string = trim($string);
-
-    if ( ereg('^(.+)<.*>', $string, $regs) ) {
-        $orig_string = $string;
-        $string = str_replace ('"', '', $regs[1] );
-        if (trim($string) == '') {
-             $string = sqimap_find_email($orig_string);
+    while ($pos < $j) {
+        if ($max && $max = count($addr_ar)) {
+            return $addr_ar;
         }
-        if( $string == '' || $string == ' ' ){
-            $string = '&nbsp;';
+        $char = $address{$pos};
+        switch ($char) {
+            case '=':
+                if (preg_match('/^(=\?([^?]*)\?(Q|B)\?([^?]*)\?=)(.*)/Ui',substr($address,$pos),$reg)) {
+                    $personal = $reg[1];
+                    $pos += strlen($personal);
+                }
+                ++$pos;
+                break;
+            case '"': /* get the personal name */
+                ++$pos;
+                if ($address{$pos} == '"') {
+                    ++$pos;
+                } else {                
+                    $personal_start = $personal_end = $pos;
+                    while ($pos < $j) {
+                        $personal_end = strpos($address,'"',$pos);
+                        if (($personal_end-2)>0 && (substr($address,$personal_end-2,2) === '\\"' ||
+                            substr($address,$personal_end-2,2) === '\\\\')) {
+                            $pos = $personal_end+1;
+                        } else {
+                            $personal = substr($address,$personal_start,$personal_end-$personal_start);
+                            break;
+                        }
+                    }
+                    if ($personal_end) { /* prohibit endless loops due to very wrong addresses */
+                         $pos = $personal_end+1;
+                    } else {
+                         $pos = $j;
+                    }
+                }
+                break;
+            case '<':  /* get email address */
+                $addr_start = $pos;
+                $addr_end = strpos($address,'>',$addr_start);
+                $addr = substr($address,$addr_start+1,$addr_end-$addr_start-1);
+                $pos = $addr_end+1;
+                break;
+            case '(':  /* rip off comments */
+                $addr_start = $pos;
+                $pos = strpos($address,')');
+                if ($pos !== false) {
+                    $comment = substr($address, $addr_start+1,($pos-$addr_start-1));
+                    $address_start = substr($address, 0, $addr_start);
+                    $address_end   = substr($address, $pos + 1);
+                    $address       = $address_start . $address_end;
+                }
+                $j = strlen($address);
+                $pos = $addr_start + 1;
+                break;
+            case ',':  /* we reached a delimiter */
+                if ($addr == '') {
+                    $addr = substr($address, 0, $pos);
+                } else if ($personal == '') {
+                    $personal = trim(substr($address, 0, $addr_start));
+                }
+                if (!$personal && $comment) $personal = $comment;
+                if ($personal) $personal = decodeHeader($personal);
+                $addr_ar[] = array($addr,$personal);
+                $address = trim(substr($address, $pos+1));
+                $j = strlen($address);
+                $pos = 0;
+                $personal = '';
+                $addr = '';
+                break;
+            case ':':  /* process the group addresses */
+                /* group marker */
+                $group = substr($address, 0, $pos);
+                $address = substr($address, $pos+1);
+                $result = parseAddress($address, $max, $addr_ar, $group);
+                $addr_ar = $result[0];
+                $pos = $result[1];
+                $address = substr($address, $pos++);
+                $j = strlen($address);
+                $group = '';
+                break;
+            case ';':
+                if ($group) {
+                    $address = substr($address, 0, $pos - 1);
+                }
+                ++$pos;
+                break;
+            default:
+                ++$pos;
+                break;
         }
     }
-    elseif ( ereg('\((.*)\)', $string, $regs) ) {
-        if( ( $regs[1] == '' ) || ( $regs[1] == ' ' ) ){
-            if ( ereg('^(.+) \(', $string, $regs) ) {
-               $string = ereg_replace( ' \(\)$', '', $string );
-            } else {
-               $string = '&nbsp;';
-            }
-        } else {
-            $string = $regs[1];
-        }
+    if ($addr == '') {
+        $addr = substr($address, 0, $pos);
+    } else if ($personal == '') {
+        $personal = trim(substr($address, 0, $addr_start));
     }
-    else {
-        $string = str_replace ('"', '', sqimap_find_email($string));
+    if (!$personal && $comment) $personal = $comment;
+    $email = $addr;
+    if ($group && $addr == '') { /* no addresses found in group */
+        $personal = $group;
+        $addr_ar[] = array('',$personal);
+        return (array($addr_ar,$pos+1 ));
+    } elseif ($group) {
+        $addr_ar[] = array($addr,$personal);
+        return (array($addr_ar,$pos+1 ));
+    } else {
+        if ($personal || $addr) {
+            $addr_ar[] = array($addr, $personal);
+        }
     }
-
-    return trim($string);
+    return ($addr_ar);
 }
 
 /*
@@ -516,14 +579,14 @@ function sqimap_status_messages ($imap_stream, $mailbox) {
     $regs = array(false,false);
     while (isset($read_ary[$i])) {
         if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
-           $unseen = $regs[1];
-       }
+            $unseen = $regs[1];
+        }
         if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
-           $messages = $regs[1];
-       }
+            $messages = $regs[1];
+        }
         if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
-           $recent = $regs[1];
-       }        
+            $recent = $regs[1];
+        }        
         $i++;
     }
     return array('MESSAGES' => $messages, 'UNSEEN'=>$unseen, 'RECENT' => $recent);
@@ -545,29 +608,29 @@ function sqimap_append_done ($imap_stream, $folder='') {
     if (preg_match("/(.*)(BAD|NO)(.*)$/", $tmp, $regs)) {
         set_up_language($squirrelmail_language);
         require_once(SM_PATH . 'functions/display_messages.php');
-       $reason = $regs[3];
-       if ($regs[2] == 'NO') {
-          $string = "<b><font color=$color[2]>\n" .
-                 _("ERROR : Could not append message to") ." $folder." .
-                 "</b><br>\n" .
-                 _("Server responded: ") .
-                 $reason . "<br>\n";
-          if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
-             $string .= _("Solution: ") . 
-           _("Remove unneccessary messages from your folder and start with your Trash folder.") 
-             ."<br>\n";
-          }
-          $string .= "</font>\n";
-          error_box($string,$color);
-       } else {
+        $reason = $regs[3];
+        if ($regs[2] == 'NO') {
+           $string = "<b><font color=$color[2]>\n" .
+                  _("ERROR : Could not append message to") ." $folder." .
+                  "</b><br>\n" .
+                  _("Server responded: ") .
+                  $reason . "<br>\n";
+           if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
+              $string .= _("Solution: ") . 
+            _("Remove unneccessary messages from your folder and start with your Trash folder.") 
+              ."<br>\n";
+           }
+           $string .= "</font>\n";
+           error_box($string,$color);
+        } else {
            $string = "<b><font color=$color[2]>\n" .
-                 _("ERROR : Bad or malformed request.") .
-                 "</b><br>\n" .
-                 _("Server responded: ") .
-                 $tmp . "</font><br>\n";
-          error_box($string,$color);
+                  _("ERROR : Bad or malformed request.") .
+                  "</b><br>\n" .
+                  _("Server responded: ") .
+                  $tmp . "</font><br>\n";
+           error_box($string,$color);
            exit;
-       }
+        }
     }
 }
 
index 3cf506b8f0f182fdd9eb81328603ff64f57ac199..c8a98781965ed98f67eae3f8a1ceee0d25bc6ff8 100755 (executable)
@@ -66,15 +66,8 @@ function sqimap_toggle_flag($imap_stream, $id, $flag, $set, $handle_errors) {
     $read = sqimap_run_command ($imap_stream, "STORE $msgs_id ".$set_string."FLAGS ($flag)", $handle_errors, $response, $message, $uid_support);
 }
 
-
-/* Returns some general header information -- FROM, DATE, and SUBJECT */
-class small_header {
-    var $from = '', $subject = '', $date = '', $to = '', 
-        $priority = 0, $message_id = 0, $cc = '', $uid = '';
-}
-
 function sqimap_get_small_header ($imap_stream, $id, $sent) {
-    $res = sqimap_get_small_header_list($imap_stream, array($id), $sent);
+    $res = sqimap_get_small_header_list($imap_stream, $id, $sent);
     return $res[0];
 }
 
@@ -217,10 +210,10 @@ function sqimap_get_php_sort_order ($imap_stream, $mbxresponse) {
 
     if ($uid_support) {
         if (isset($mbxresponse['UIDNEXT']) && $mbxresponse['UIDNEXT']) {
-           $uidnext = $mbxresponse['UIDNEXT']-1;
-       } else {
-           $uidnext = '*';
-       }
+                $uidnext = $mbxresponse['UIDNEXT']-1;
+        } else {
+            $uidnext = '*';
+        }
         $uid_query = "$sid SEARCH UID 1:$uidnext\r\n";
         fputs($imap_stream, $uid_query);
         $uids = sqimap_read_data($imap_stream, $sid, true ,$response, $message);
@@ -431,6 +424,7 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list) {
     $sid = sqimap_session_id($uid_support);
 
     $maxmsg = sizeof($msg_list);
+
     $msgs_str = sqimap_message_list_squisher($msg_list);
     $messages = array();
     $read_list = array();
@@ -445,9 +439,9 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list) {
 
     $internaldate = getPref($data_dir, $username, 'internal_date_sort');
     if ($internaldate) {
-        $query = "$sid FETCH $msgs_str (FLAGS UID RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (Date To From Cc Subject X-Priority Content-Type)])\r\n";
+        $query = "$sid FETCH $msgs_str (FLAGS UID RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (Date To Cc From Subject X-Priority Content-Type)])\r\n";
     } else {
-        $query = "$sid FETCH $msgs_str (FLAGS UID RFC822.SIZE BODY.PEEK[HEADER.FIELDS (Date To From Cc Subject X-Priority Content-Type)])\r\n";
+        $query = "$sid FETCH $msgs_str (FLAGS UID RFC822.SIZE BODY.PEEK[HEADER.FIELDS (Date To Cc From Subject X-Priority Content-Type)])\r\n";
     }
     fputs ($imap_stream, $query);
     $readin_list = sqimap_read_data_list($imap_stream, $sid, false, $response, $message);
@@ -585,22 +579,22 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list) {
                     if (preg_match ($regpattern, $read_part, $regs)) {
                         switch ($id) {
                             case 1:
-                                $to = $regs[1];
+                                $to = trim($regs[1]);
                                 break;
                             case 2:
-                                $from = $regs[1];
+                                $from = trim($regs[1]);
                                 break;
                             case 3:
                                 $priority = $regs[1];
                                 break;
                             case 4:
-                                $cc = $regs[1];
+                                $cc = trim($regs[1]);
                                 break;
                             case 5:
                                 $date = $regs[1];
                                 break;
                             case 6:
-                                $subject = htmlspecialchars(trim($regs[1]));
+                                $subject = trim($regs[1]);
                                 if ($subject == "") {
                                     $subject = _("(no subject)");
                                 }
@@ -641,11 +635,13 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list) {
         
         $messages[$msgi]['TIME_STAMP'] = getTimeStamp($tmpdate);
         $messages[$msgi]['DATE_STRING'] = getDateString($messages[$msgi]['TIME_STAMP']);
-        $messages[$msgi]['FROM'] = decodeHeader($from);
-        $messages[$msgi]['SUBJECT'] = decodeHeader($subject);
-        $messages[$msgi]['TO'] = decodeHeader($to);
+        $messages[$msgi]['FROM'] = parseAddress($from);
+        $messages[$msgi]['SUBJECT'] = $subject;
+//        if (handleAsSent($mailbox)) {
+            $messages[$msgi]['TO'] = parseAddress($to);
+//        }
         $messages[$msgi]['PRIORITY'] = $priority;
-        $messages[$msgi]['CC'] = $cc;
+        $messages[$msgi]['CC'] = parseAddress($cc);
         $messages[$msgi]['SIZE'] = $size;
         $messages[$msgi]['TYPE0'] = $type[0];
         $messages[$msgi]['FLAG_DELETED'] = $flag_deleted;
@@ -655,7 +651,13 @@ function sqimap_get_small_header_list ($imap_stream, $msg_list) {
 
         /* non server sort stuff */
         if (!$allow_server_sort) {
-            $messages[$msgi]['FROM-SORT'] = strtolower(sqimap_find_displayable_name(decodeHeader($from)));
+           $from = parseAddress($from);
+           if ($from[0][1]) {
+               $from = decodeHeader($from[0][1]);
+           } else {
+               $from = $from[0][0];
+           }
+            $messages[$msgi]['FROM-SORT'] = $from;
             $subject_sort = strtolower(decodeHeader($subject));
             if (preg_match("/^(vedr|sv|re|aw):\s*(.*)$/si", $subject_sort, $matches)){
                 $messages[$msgi]['SUBJECT-SORT'] = $matches[2];
@@ -682,12 +684,12 @@ function sqimap_get_headerfield($imap_stream, $field) {
     foreach ($readin_list as $r) {
         $r = implode('',$r);
         /* first we unfold the header */
-       $r = str_replace(array("\r\n\t","\r\n\s"),array('',''),$r);
-       /* 
-        * now we can make a new header array with each element representing 
-        * a headerline
-        */
-       $r = explode("\r\n" , $r);  
+        $r = str_replace(array("\r\n\t","\r\n\s"),array('',''),$r);
+        /* 
+         * now we can make a new header array with each element representing 
+         * a headerline
+         */
+        $r = explode("\r\n" , $r);  
         if (!$uid_support) {
             if (!preg_match("/^\\*\s+([0-9]+)\s+FETCH/iAU",$r[0], $regs)) {
                 set_up_language($squirrelmail_language);
@@ -708,12 +710,12 @@ function sqimap_get_headerfield($imap_stream, $field) {
                      _("Unknown response from IMAP server: ") . ' 1.' .
                      $r[0] . "</font><br>\n";
             } else {
-               $id = $regs[2];
+                $id = $regs[2];
             }
         }
-       $field = $r[1];
-       $field = substr($field,strlen($field)+2);
-       $result[] = array($id,$field);
+        $field = $r[1];
+        $field = substr($field,strlen($field)+2);
+        $result[] = array($id,$field);
     }
     return $result;
 }
@@ -770,19 +772,6 @@ function sqimap_get_ent_header ($imap_stream, $id, $mailbox, $ent) {
     return $header;
 }
 
-
-/* Wrapper function that returns entity headers for use by decodeMime */
-/*
-function sqimap_get_entity_header ($imap_stream, &$read, &$type0, &$type1, &$bound, &$encoding, &$charset, &$filename) {
-    $header = sqimap_get_header($imap_stream, $read);
-    $type0 = $header["TYPE0"]; 
-    $type1 = $header["TYPE1"];
-    $bound = $header["BOUNDARY"];
-    $encoding = $header["ENCODING"];
-    $charset = $header["CHARSET"];
-    $filename = $header["FILENAME"];
-}
-
 /* function to get the mime headers */
 function sqimap_get_mime_ent_header ($imap_stream, $id, $mailbox, $ent) {
     global $uid_support;
@@ -793,9 +782,4 @@ function sqimap_get_mime_ent_header ($imap_stream, $id, $mailbox, $ent) {
     return $header;
 }
 
-/* Returns the body of a message. */
-function sqimap_get_message_body ($imap_stream, &$header) {
-//    return decodeMime($imap_stream, $header->id);
-}
-
 ?>
index d0b67efaa7f4e7f17a25f307b4c30f5bf7b664d7..79954364b39ed3b005ae1fa74b6397e14476d271 100644 (file)
@@ -20,6 +20,20 @@ require_once(SM_PATH . 'functions/imap_mailbox.php');
 /* Default value for page_selector_max. */
 define('PG_SEL_MAX', 10);
 
+function elapsed($start)
+{
+   $end = microtime();
+   list($start2, $start1) = explode(" ", $start);
+   list($end2, $end1) = explode(" ", $end);
+  $diff1 = $end1 - $start1;
+   $diff2 = $end2 - $start2;
+   if( $diff2 < 0 ){
+       $diff1 -= 1;
+       $diff2 += 1.0;
+  }
+   return $diff2 + $diff1;
+}
+
 function printMessageInfo($imapConnection, $t, $not_last=true, $key, $mailbox,
                           $start_msg, $where, $what) {
     global $checkall,
@@ -58,25 +72,29 @@ function printMessageInfo($imapConnection, $t, $not_last=true, $key, $mailbox,
 
     if (handleAsSent($mailbox)) {
        $msg['FROM'] = $msg['TO'];
+    }
        /*
         * This is done in case you're looking into Sent folders,
         * because you can have multiple receivers.
         */
-       $senderNames = explode(',', $msg['FROM']);
-       $senderName  = '';
-       if (sizeof($senderNames)){
-          foreach ($senderNames as $senderNames_part) {
+        
+    $senderNames = $msg['FROM'];
+    $senderName  = '';
+    if (sizeof($senderNames)){
+        foreach ($senderNames as $senderNames_part) {
             if ($senderName != '') {
                 $senderName .= ', ';
             }
-            $senderName .= sqimap_find_displayable_name($senderNames_part);
-          }
-       }
-    } else {
-       $senderName = sqimap_find_displayable_name($msg['FROM']);
-    }
+            if ($senderNames_part[1]) {
+                $senderName .= decodeHeader($senderNames_part[1]);
+            } else {
+                $senderName .= htmlspecialchars($senderNames_part[0]);
+            }
+        }
+    } 
+    
 
-    $subject = processSubject($msg['SUBJECT'], $indent_array[$msg['ID']]);
+    $subject = processSubject(decodeHeader($msg['SUBJECT']), $indent_array[$msg['ID']]);
 
     echo html_tag( 'tr','','','','VALIGN="top"') . "\n";
 
@@ -124,10 +142,19 @@ function printMessageInfo($imapConnection, $t, $not_last=true, $key, $mailbox,
                 $high_val   = strtolower($message_highlight_list_part['value']);
                 $match_type = strtoupper($message_highlight_list_part['match_type']);
                 if ($match_type == 'TO_CC') {
-                    if (strstr('^^' . strtolower($msg['TO']), $high_val) ||
-                        strstr('^^' . strtolower($msg['CC']), $high_val)) {
-                        $hlt_color = $message_highlight_list_part['color'];
-                        continue;
+                    foreach ($msg['TO'] as $address) {
+                        if (strstr('^^' . strtolower($address[0]), $high_val) ||
+                            strstr('^^' . strtolower($address[1]), $high_val)) {
+                            $hlt_color = $message_highlight_list_part['color'];
+                            continue;
+                        }
+                    }
+                    foreach ($msg['CC'] as $address) {
+                        if( strstr('^^' . strtolower($address[0]), $high_val) ||
+                            strstr('^^' . strtolower($address[1]), $high_val)) {
+                            $hlt_color = $message_highlight_list_part['color'];
+                            continue;
+                        }
                     }
                 } else {
                     if (strstr('^^' . strtolower($msg[$match_type]), $high_val)) {
@@ -155,7 +182,7 @@ function printMessageInfo($imapConnection, $t, $not_last=true, $key, $mailbox,
                 break;
             case 2: /* from */
                 echo html_tag( 'td',
-                               $italic . $bold . $flag . $fontstr . htmlentities($senderName) .
+                               $italic . $bold . $flag . $fontstr . $senderName .
                                $fontstr_end . $flag_end . $bold_end . $italic_end,
                                'left',
                                $hlt_color );
@@ -182,7 +209,7 @@ function printMessageInfo($imapConnection, $t, $not_last=true, $key, $mailbox,
                 $td_str .= '<a href="read_body.php?mailbox='.$urlMailbox
                         .  '&amp;passed_id='. $msg["ID"]
                         .  '&amp;startMessage='.$start_msg.$searchstr.'"';
-                $td_str .= ' ' .concat_hook_function('subject_link');
+                do_hook("subject_link");
                 if ($subject != $msg['SUBJECT']) {
                     $title = get_html_translation_table(HTML_SPECIALCHARS);
                     $title = array_flip($title);
@@ -250,13 +277,7 @@ function printMessageInfo($imapConnection, $t, $not_last=true, $key, $mailbox,
 
 function getServerMessages($imapConnection, $start_msg, $show_num, $num_msgs, $id) {
     if ($id != 'no') {
-        if ($start_msg + ($show_num - 1) < $num_msgs) {
-            $end_msg = $start_msg + ($show_num-1);
-        } else {
-            $end_msg = $num_msgs;
-        }
-        $id = array_slice($id, ($start_msg-1), ($end_msg));
-
+        $id = array_slice($id, ($start_msg-1), $show_num);
         $end = $start_msg + $show_num - 1;
         if ($num_msgs < $show_num) {
             $end_loop = $num_msgs;
@@ -303,7 +324,7 @@ function getSelfSortMessages($imapConnection, $start_msg, $show_num,
                     $start_msg = 1;
                 }
             }
-            $id = array_slice(array_reverse($id), ($start_msg-1), ($end_msg));
+            $id = array_slice(array_reverse($id), ($start_msg-1), $show_num);
             $end = $start_msg + $show_num - 1;
             if ($num_msgs < $show_num) {
                 $end_loop = $num_msgs;
@@ -313,7 +334,7 @@ function getSelfSortMessages($imapConnection, $start_msg, $show_num,
                 $end_loop = $show_num;
             }
         }
-        $msgs = fillMessageArray($imapConnection,$id,$end_loop);
+        $msgs = fillMessageArray($imapConnection,$id,$end_loop, $mailbox);
     }
     return $msgs;
 }
@@ -330,6 +351,7 @@ function showMessagesForMailbox($imapConnection, $mailbox, $num_msgs,
     global $msgs, $msort, $auto_expunge, $thread_sort_messages,
            $allow_server_sort, $server_sort_order;
 
+    $start = microtime();
     /* If autoexpunge is turned on, then do it now. */
     $mbxresponse = sqimap_mailbox_select($imapConnection, $mailbox);
     $srt = $sort;
@@ -443,6 +465,8 @@ function showMessagesForMailbox($imapConnection, $mailbox, $num_msgs,
 
     mail_message_listing_end($num_msgs, $paginator_str, $msg_cnt_str, $color); 
     echo '</td></tr></table>';
+    $t = elapsed($start);
+    echo("elapsed time = $t seconds\n");
 }
 
 function calc_msort($msgs, $sort) {
index 48866d6dff9a16853b566c7fe8d7612458cc48aa..ca43a355f07ce35059f53e6d4bcb64a1a83a167b 100644 (file)
@@ -271,7 +271,6 @@ function translateText(&$body, $wrap_at, $charset) {
             sqWordWrap($line, $wrap_at);
         }
         $line = charset_decode($charset, $line);
-       $line = htmlspecialchars($line);
         $line = str_replace("\t", '        ', $line);
 
         parseUrl ($line);
@@ -308,7 +307,6 @@ function translateText(&$body, $wrap_at, $charset) {
     $body = '<pre>' . implode("\n", $body_ary) . '</pre>';
 }
 
-
 /* This returns a parsed string called $body. That string can then
  * be displayed as the actual message in the HTML. It contains
  * everything needed, including HTML Tags, Attachments at the
@@ -409,7 +407,7 @@ function formatAttachments($message, $exclude_id, $mailbox, $id) {
         if ($type0 =='message' && $type1 == 'rfc822') {
             $default_page = '../src/read_body.php';
             $rfc822_header = $att->rfc822_header;
-            $filename = decodeHeader($rfc822_header->subject);
+            $filename = $rfc822_header->subject;
             if (trim( $filename ) == '') {
                 $filename = 'untitled-[' . $ent . ']' ;
            }           
@@ -419,16 +417,16 @@ function formatAttachments($message, $exclude_id, $mailbox, $id) {
             } else {
                 $from_name = _("Unknown sender");
             }
-            $from_name = decodeHeader(htmlspecialchars($from_name));
+            $from_name = decodeHeader(($from_name));
             $description = $from_name;
         } else {
             $default_page = '../src/download.php';
             if (is_object($header->disposition)) {
-                $filename = decodeHeader($header->disposition->getProperty('filename'));
+                $filename = $header->disposition->getProperty('filename');
                 if (trim($filename) == '') {
                     $name = decodeHeader($header->disposition->getProperty('name'));
                     if (trim($name) == '') {
-                        $name = decodeHeader($header->getParameter('name'));
+                        $name = $header->getParameter('name');
                         if(trim($name) == '') {
                             if (trim( $header->id ) == '') {
                                 $filename = 'untitled-[' . $ent . ']' ;
@@ -443,7 +441,7 @@ function formatAttachments($message, $exclude_id, $mailbox, $id) {
                     }
                 }
             } else {
-               $filename = decodeHeader($header->getParameter('name'));
+               $filename = $header->getParameter('name');
                if (!trim($filename)) {
                    if (trim( $header->id ) == '') {
                        $filename = 'untitled-[' . $ent . ']' ;
@@ -453,7 +451,7 @@ function formatAttachments($message, $exclude_id, $mailbox, $id) {
                }
            }
             if ($header->description) {
-                $description = htmlspecialchars($header->description);
+                $description = decodeHeader($header->description);
             } else {
                 $description = '';
             }
@@ -488,7 +486,7 @@ function formatAttachments($message, $exclude_id, $mailbox, $id) {
         $defaultlink = $hookresults[6];
 
         $attachments .= '<TR><TD>' .
-                        '<A HREF="'.$defaultlink.'">'.htmlspecialchars($display_filename).'</A>&nbsp;</TD>' .
+                        '<A HREF="'.$defaultlink.'">'.decodeHeader($display_filename).'</A>&nbsp;</TD>' .
                         '<TD><SMALL><b>' . show_readable_size($header->size) .
                         '</b>&nbsp;&nbsp;</small></TD>' .
                         "<TD><SMALL>[ $type0/$type1 ]&nbsp;</SMALL></TD>" .
@@ -545,7 +543,7 @@ function decodeBody($body, $encoding) {
  * RFC1522 (MIME Part Two: Message Header Extensions for Non-ASCII Text).
  * Patched by Christian Schmidt <christian@ostenfeld.dk>  23/03/2002
  */
-function decodeHeader ($string, $utfencode=true) {
+function decodeHeader ($string, $utfencode=true,$htmlsave=true) {
     global $languages, $squirrelmail_language;
     if (is_array($string)) {
         $string = implode("\n", $string);
@@ -557,33 +555,54 @@ function decodeHeader ($string, $utfencode=true) {
     }
 
     $i = 0;
-    while (preg_match('/^(.{' . $i . '})(.*)=\?([^?]*)\?(Q|B)\?([^?]*)\?=/Ui', 
-                      $string, $res)) {
-        $prefix = $res[1];
-        /* Ignore white-space between consecutive encoded-words. */
-        if (strspn($res[2], " \t") != strlen($res[2])) {
-            $prefix .= $res[2];
-        }
-
-        if (ucfirst($res[4]) == 'B') {
-            $replace = base64_decode($res[5]);
-            $replace = charset_decode($res[3],$replace);
-            
-        } else {
-            $replace = str_replace('_', ' ', $res[5]);
-            $replace = preg_replace('/=([0-9a-f]{2})/ie', 'chr(hexdec("\1"))', 
+    $aString = explode(' ',$string);
+    foreach ($aString as $chunk) {
+        $encoded = false;
+        $aString[$i] = '';
+        while (preg_match('/^(.*)=\?([^?]*)\?(Q|B)\?([^?]*)\?=(.*)$/Ui',$chunk,$res)) {
+            $aString[$i] .= $res[1];
+            $encoding = ucfirst($res[3]);
+            switch ($encoding)
+            {
+            case 'B':
+                $replace = base64_decode($res[4]);
+                $aString[$i] .= charset_decode($res[2],$replace);
+                break;
+            case 'Q':
+                
+                $replace = str_replace('_', ' ', $res[4]);
+                $replace = preg_replace('/=([0-9a-f]{2})/ie', 'chr(hexdec("\1"))', 
                                     $replace);
-            /* Only encode into entities by default. Some places
-             * don't need the encoding, like the compose form.
-             */
-            if ($utfencode) {
-                $replace = charset_decode($res[3], $replace);
+                /* Only encode into entities by default. Some places
+                 * don't need the encoding, like the compose form.
+                 */
+                if ($utfencode) {
+                    $replace = charset_decode($res[2], $replace);
+                } else {
+                    if ($htmlsave) {
+                        $replace = htmlspecialchars($res[4]);
+                    }
+                }
+                $aString[$i] .= $replace;
+                break;
+            default:
+                break;
             }
+            $chunk = $res[5];
+            $encoded = true;
+        } 
+        if (!$encoded && $htmlsave) {
+            $aString[$i] = htmlspecialchars($chunk);
+        } else {
+            $aString[$i] .= $chunk;
         }
-        $string = $prefix . $replace . substr($string, strlen($res[0]));
-        $i = strlen($prefix) + strlen($replace);
+        ++$i;
+    }
+    if (!$htmlsave) {
+       return implode(' ',$aString);
+    } else {
+       return implode('&nbsp;',$aString);
     }
-    return $string;
 }
 
 /*
@@ -602,27 +621,67 @@ function encodeHeader ($string) {
     // Encode only if the string contains 8-bit characters or =?
     $j = strlen($string);
     $l = strstr($string, '=?');         // Must be encoded ?
+    $max_l = 75 - strlen($default_charset) - 7;
+    $aRet = array();
     $ret = '';
+    $cur_l = 0;
     for($i = 0; $i < $j; ++$i) {
         switch($string{$i}) {
             case '=':
+                $cur_l+=3;
+                if ($cur_l > $max_l) {
+                    $aRet[] = "=?$default_charset?Q?$ret?=";
+                    $cur_l = 3;
+                    $ret = '';
+                }            
                 $ret .= '=3D';
                 break;
             case '?':
+                $cur_l+=3;
+                if ($cur_l > $max_l) {
+                    $aRet[] = "=?$default_charset?Q?$ret?=";
+                    $cur_l = 3;
+                    $ret = '';
+                }
                 $ret .= '=3F';
                 break;
             case '_':
+                $cur_l+=3;
+                if ($cur_l > $max_l) {
+                    $aRet[] = "=?$default_charset?Q?$ret?=";
+                    $cur_l = 3;
+                    $ret = '';
+                }                
                 $ret .= '=5F';
                 break;
             case ' ':
+                $cur_l++;
+                if ($cur_l > $max_l) {
+                    $aRet[] = "=?$default_charset?Q?$ret?=";
+                    $cur_l = 1;
+                    $ret = '';
+                }                
                 $ret .= '_';
                 break;
             default:
                 $k = ord($string{$i});
                 if ($k > 126) {
-                    $ret .= sprintf("=%02X", $k);
+                    $s = sprintf("=%02X", $k);
+                    $cur_l += strlen($s);
+                    if ($cur_l > $max_l) {
+                        $aRet[] = "=?$default_charset?Q?$ret?=";
+                        $cur_l = strlen($s);
+                        $ret = '';
+                    }                     
+                    $ret .= $s;
                     $l = TRUE;
                 } else {
+                    $cur_l++;
+                    if ($cur_l > $max_l) {
+                        $aRet[] = "=?$default_charset?Q?$ret?=";
+                        $cur_l = 1;
+                        $ret = '';
+                    }                     
                     $ret .= $string{$i};
                 }
                 break;
@@ -630,7 +689,7 @@ function encodeHeader ($string) {
     }
 
     if ($l) {
-        $string = "=?$default_charset?Q?$ret?=";
+        $string = implode('',$aRet) . "=?$default_charset?Q?$ret?=";
     }
 
     return $string;
@@ -1230,7 +1289,7 @@ function sq_fixstyle($message, $id, $content){
         $content = preg_replace("|url\(([\'\"])\s*https*:.*?([\'\"])\)|si",
                                 "url(\\1$secremoveimg\\2)", $content);
     }
-    
+   
     /**
      * Fix urls that refer to cid:
      */