Now properly quote personal part of encoded addresses when replying
authorpdontthink <pdontthink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Mon, 21 Jun 2010 07:58:11 +0000 (07:58 +0000)
committerpdontthink <pdontthink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Mon, 21 Jun 2010 07:58:11 +0000 (07:58 +0000)
git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@13953 7612ce4b-ef26-0410-bec9-ea0150e637f0

class/mime/AddressStructure.class.php
class/mime/Rfc822Header.class.php
doc/ChangeLog
src/compose.php

index a443894..90f5ef9 100644 (file)
@@ -51,9 +51,11 @@ class AddressStructure {
      * Return address information from mime headers.
      * @param boolean $full return full address (true) or only personal if it exists, otherwise email (false)
      * @param boolean $encoded (since 1.4.0) return rfc2047 encoded address (true) or plain text (false).
+     * @param boolean $unconditionally_quote (since 1.4.21/1.5.2) when TRUE, always quote the personal part, whether or not it is encoded, otherwise quoting is only added if the personal part is not encoded
+     *
      * @return string
      */
-    function getAddress($full = true, $encoded = false) {
+    function getAddress($full = true, $encoded = false, $unconditionally_quote = FALSE) {
         $result = '';
         if (is_object($this)) {
             $email = ($this->host ? $this->mailbox.'@'.$this->host
@@ -69,10 +71,11 @@ class AddressStructure {
                     if ($personal !== $personal_encoded) {
                         $personal = $personal_encoded;
                     } else {
+                        //FIXME: this probably adds quotes around an encoded string which itself is already quoted
                         $personal = '"' . $this->personal . '"';
                     }
                 } else {
-                    if (!$is_encoded) {
+                    if (!$is_encoded || $unconditionally_quote) {
                         $personal = '"' . $this->personal . '"';
                     }
                 }
@@ -91,11 +94,13 @@ class AddressStructure {
     /**
      * Shorter version of getAddress() function
      * Returns full encoded address.
+     * @param boolean $unconditionally_quote (since 1.4.21/1.5.2) when TRUE, always quote the personal part, whether or not it is encoded, otherwise quoting is only added if the personal part is not encoded
+     *
      * @return string
      * @since 1.4.0
      */
-    function getEncodedAddress() {
-        return $this->getAddress(true, true);
+    function getEncodedAddress($unconditionally_quote=FALSE) {
+        return $this->getAddress(true, true, $unconditionally_quote);
     }
     
     /**
index 090deba..02c983a 100644 (file)
@@ -862,14 +862,20 @@ class Rfc822Header {
      * @param mixed $arr string or array of strings
      * @param string $separator
      * @param boolean $encoded (since 1.4.0) return encoded or plain text addresses
+     * @param boolean $unconditionally_quote (since 1.4.21/1.5.2) When TRUE, always
+     *                                                      quote the personal part,
+     *                                                      whether or not it is
+     *                                                      encoded, otherwise quoting
+     *                                                      is only added if the
+     *                                                      personal part is not encoded
      * @return string
      */
-    function getAddr_s($arr, $separator = ', ', $encoded=false) {
+    function getAddr_s($arr, $separator = ', ', $encoded=false, $unconditionally_quote=FALSE) {
         $s = '';
 
         if (is_array($arr)) {
             foreach($arr as $arg) {
-                if ($this->getAddr_s($arg, $separator, $encoded)) {
+                if ($this->getAddr_s($arg, $separator, $encoded, $unconditionally_quote)) {
                     $s .= $separator;
                 }
             }
@@ -880,9 +886,9 @@ class Rfc822Header {
                 foreach ($addr as $addr_o) {
                     if (is_object($addr_o)) {
                         if ($encoded) {
-                            $s .= $addr_o->getEncodedAddress() . $separator;
+                            $s .= $addr_o->getEncodedAddress($unconditionally_quote) . $separator;
                         } else {
-                            $s .= $addr_o->getAddress() . $separator;
+                            $s .= $addr_o->getAddress(TRUE, FALSE, $unconditionally_quote) . $separator;
                         }
                     }
                 }
@@ -890,9 +896,9 @@ class Rfc822Header {
             } else {
                 if (is_object($addr)) {
                     if ($encoded) {
-                        $s .= $addr->getEncodedAddress();
+                        $s .= $addr->getEncodedAddress($unconditionally_quote);
                     } else {
-                        $s .= $addr->getAddress();
+                        $s .= $addr->getAddress(TRUE, FALSE, $unconditionally_quote);
                     }
                 }
             }
index 28d0913..e200d38 100644 (file)
@@ -343,6 +343,7 @@ Version 1.5.2 - SVN
   - Reduced default time security tokens stay valid from 30 days to 2 days
     (reduces chances of session data growing too large)
   - Fixed minor vulnerability in Mail Fetch plugin [CVE-2010-1637/TEHTRI-SA-2010-009]
+  - Now properly quote personal part of encoded addresses when replying.
 
 Version 1.5.1 (branched on 2006-02-12)
 --------------------------------------
index 0f746c9..8358938 100644 (file)
@@ -196,12 +196,10 @@ function replyAllString($header) {
     $url_replytoallcc = '';
     foreach( $url_replytoall_ar as $email => $personal) {
         if ($personal) {
-            // if personal name contains address separator then surround
-            // the personal name with double quotes.
-            if (strpos($personal,',') !== false) {
-                $personal = '"'.$personal.'"';
-            }
-            $url_replytoallcc .= ", $personal <$email>";
+            // always quote personal name (can't just quote it if
+            // it contains a comma separator, since it might still
+            // be encoded)
+            $url_replytoallcc .= ", \"$personal\" <$email>";
         } else {
             $url_replytoallcc .= ', '. $email;
         }
@@ -955,20 +953,22 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
                 } else {
                     $send_to_cc = replyAllString($orig_header);
                     $send_to_cc = decodeHeader($send_to_cc,false,false,true);
+                    $send_to_cc = str_replace('""', '"', $send_to_cc);
                 }
             case ('reply'):
                 // skip this if send_to was already set right above here
                 if(!$send_to) {
                     $send_to = $orig_header->reply_to;
                     if (is_array($send_to) && count($send_to)) {
-                        $send_to = $orig_header->getAddr_s('reply_to');
+                        $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
                     } else if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */
-                        $send_to = $orig_header->getAddr_s('reply_to');
+                        $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
                     } else {
-                        $send_to = $orig_header->getAddr_s('from');
+                        $send_to = $orig_header->getAddr_s('from', ',', FALSE, TRUE);
                     }
                 }
                 $send_to = decodeHeader($send_to,false,false,true);
+                $send_to = str_replace('""', '"', $send_to);
                 $subject = decodeHeader($orig_header->subject,false,false,true);
                 $subject = str_replace('"', "'", $subject);
                 $subject = trim($subject);