More fixes to RFC 2231 code.
authorMichael M Slusarz <slusarz@curecanti.org>
Tue, 2 Dec 2008 21:39:07 +0000 (14:39 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Tue, 2 Dec 2008 21:39:07 +0000 (14:39 -0700)
framework/Mime/lib/Horde/Mime.php
framework/Mime/lib/Horde/Mime/Headers.php

index 3d54935..253f906 100644 (file)
@@ -335,22 +335,31 @@ class Horde_Mime
     static public function encodeParam($name, $val, $charset, $lang = null)
     {
         $encode = $wrap = false;
-        $i = 0;
         $output = array();
+        $curr = 0;
+
+        // 2 = '=', ';'
+        $pre_len = strlen($name) + 2;
 
         if (self::is8bit($val, $charset)) {
             $string = String::lower($charset) . '\'' . (is_null($lang) ? '' : String::lower($lang)) . '\'' . rawurlencode($val);
             $encode = true;
+            /* Account for trailing '*'. */
+            ++$pre_len;
         } else {
             $string = $val;
         }
 
-        // 4 = '*', 2x '"', ';'
-        $pre_len = strlen($name) + 4 + (($encode) ? 1 : 0);
         if (($pre_len + strlen($string)) > 75) {
+            /* Account for continuation '*'. */
+            ++$pre_len;
+            $wrap = true;
+
             while ($string) {
-                $chunk = 75 - $pre_len;
+                $chunk = 75 - $pre_len - strlen($curr);
                 $pos = min($chunk, strlen($string) - 1);
+
+                /* Don't split in the middle of an encoded char. */
                 if (($chunk == $pos) && ($pos > 2)) {
                     for ($i = 0; $i <= 2; ++$i) {
                         if ($string[$pos - $i] == '%') {
@@ -359,16 +368,17 @@ class Horde_Mime
                         }
                     }
                 }
+
                 $lines[] = substr($string, 0, $pos + 1);
                 $string = substr($string, $pos + 1);
+                ++$curr;
             }
-            $wrap = true;
         } else {
             $lines = array($string);
         }
 
-        foreach ($lines as $line) {
-            $output[$name . (($wrap) ? ('*' . $i++) : '') . (($encode) ? '*' : '')] = $line;
+        foreach ($lines as $i => $line) {
+            $output[$name . (($wrap) ? ('*' . $i) : '') . (($encode) ? '*' : '')] = $line;
         }
 
         return (self::$brokenRFC2231 && !isset($output[$name]))
@@ -420,29 +430,31 @@ class Horde_Mime
             /* Asterisk at end indicates encoded value. */
             if (($encode = substr($name, -1)) == '*') {
                 $name = substr($name, 0, -1);
-                $val = urldecode($val);
             }
 
             /* This asterisk indicates continuation parameter. */
             if (($pos = strrpos($name, '*')) === false) {
-                $ret['params'][$name] = $val;
-            } else {
-                $first_part = ($encode && (substr($name, -2) == '*0'));
                 $name = substr($name, 0, $pos);
-                if ($first_part) {
-                    $quote = strpos($val, "'");
-                    $convert[$name] = substr($val, 0, $quote);
-                    /* Ignore language. */
-                    $quote = strpos($val, "'", $quote + 1);
-                    $ret['params'][$name] = substr($val, $quote + 1);
-                } else {
-                    $ret['params'][$name] .= $val;
-                }
+            }
+
+            if (!isset($ret['params'][$name])) {
+                $ret['params'][$name] = '';
+            }
+            $ret['params'][$name] .= $val;
+
+            if ($encode) {
+                $convert[$name] = true;
             }
         }
 
-        foreach ($convert as $key => $val) {
-            $ret['params'][$key] = String::convertCharset($ret['params'][$key], $val, $charset);
+        foreach ($convert as $name) {
+            $val = $ret['params'][$name];
+            $quote = strpos($val, "'");
+            $orig_charset = substr($val, 0, $quote);
+            /* Ignore language. */
+            $quote = strpos($val, "'", $quote + 1);
+            substr($val, $quote + 1);
+            $ret['params'][$name] = String::convertCharset(urldecode(substr($val, $quote + 1)), $orig_charset, $charset);
         }
 
         return $ret;
index 6f9c411..5da47aa 100644 (file)
@@ -433,7 +433,7 @@ class Horde_Mime_Headers
      *
      * @return array  The list of headers, in lowercase.
      */
-    public function mimeParamFields()
+    static public function mimeParamFields()
     {
         return array('content-type', 'content-disposition');
     }
@@ -443,7 +443,7 @@ class Horde_Mime_Headers
      *
      * @return array  The list of valid mailing list headers.
      */
-    public function listHeaders()
+    static public function listHeaders()
     {
         return array(
             /* RFC 2369 */
@@ -516,7 +516,7 @@ class Horde_Mime_Headers
     {
         $headers = new Horde_Mime_Headers();
         $currheader = $currtext = null;
-        $mime = $this->mimeParamFields();
+        $mime = self::mimeParamFields();
 
         require_once 'Horde/String.php';
 
@@ -531,7 +531,7 @@ class Horde_Mime_Headers
             } else {
                 if (!is_null($currheader)) {
                     if (in_array(String::lower($currheader), $mime)) {
-                        $res = Horde_Mime::decodeParam($currtext);
+                        $res = Horde_Mime::decodeParam($currheader . ': ' . $currtext);
                         $headers->addHeader($currheader, $res['val'], array('decode' => true, 'params' => $res['params']));
                     } else {
                         $headers->addHeader($currheader, $currtext, array('decode' => true));