From 4fdaa02ac724e597479a4a48388a8a10101000fd Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sat, 06 Apr 2013 13:28:47 -0400
Subject: [PATCH] Fix handling of invalid characters in message headers and output (#1489032)

---
 CHANGELOG                                      |    1 +
 program/steps/mail/compose.inc                 |    8 ++++----
 program/steps/mail/func.inc                    |    2 +-
 program/lib/Roundcube/rcube_message.php        |   15 ++++++---------
 program/steps/mail/show.inc                    |    2 +-
 program/lib/Roundcube/rcube_message_header.php |    7 ++++++-
 program/lib/Roundcube/html.php                 |   12 +++++++++++-
 7 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 8a04931..a9121fc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Fix handling of invalid characters in message headers and output (#1489032)
 - Fix selecting collapsed rows on select-all (#1489036)
 - Fix possible header duplicates when using additional headers (#1489033)
 - Fix session issues with use_https=true (#1488986)
diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php
index 5927203..7b30e60 100644
--- a/program/lib/Roundcube/html.php
+++ b/program/lib/Roundcube/html.php
@@ -35,6 +35,7 @@
     public static $common_attrib = array('id','class','style','title','align');
     public static $containers = array('iframe','div','span','p','h1','h2','h3','form','textarea','table','thead','tbody','tr','th','td','style','script');
 
+
     /**
      * Constructor
      *
@@ -332,7 +333,16 @@
      */
     public static function quote($str)
     {
-        return @htmlspecialchars($str, ENT_COMPAT, RCUBE_CHARSET);
+        static $flags;
+
+        if (!$flags) {
+            $flags = ENT_COMPAT;
+            if (defined('ENT_SUBSTITUTE')) {
+                $flags |= ENT_SUBSTITUTE;
+            }
+        }
+
+        return @htmlspecialchars($str, $flags, RCUBE_CHARSET);
     }
 }
 
diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php
index 41a114f..69735fc 100644
--- a/program/lib/Roundcube/rcube_message.php
+++ b/program/lib/Roundcube/rcube_message.php
@@ -85,12 +85,13 @@
 
         $this->headers = $this->storage->get_message($uid);
 
-        if (!$this->headers)
+        if (!$this->headers) {
             return;
+        }
 
         $this->mime = new rcube_mime($this->headers->charset);
 
-        $this->subject = $this->mime->decode_mime_string($this->headers->subject);
+        $this->subject = $this->headers->get('subject');
         list(, $this->sender) = each($this->mime->decode_address_list($this->headers->from, 1));
 
         $this->set_safe((intval($_GET['_safe']) || $_SESSION['safe_messages'][$this->folder.':'.$uid]));
@@ -125,15 +126,11 @@
      */
     public function get_header($name, $raw = false)
     {
-        if (empty($this->headers))
+        if (empty($this->headers)) {
             return null;
+        }
 
-        if ($this->headers->$name)
-            $value = $this->headers->$name;
-        else if ($this->headers->others[$name])
-            $value = $this->headers->others[$name];
-
-        return $raw ? $value : $this->mime->decode_header($value);
+        return $this->headers->get($name, !$raw);
     }
 
 
diff --git a/program/lib/Roundcube/rcube_message_header.php b/program/lib/Roundcube/rcube_message_header.php
index 274ae7f..2c5e2b6 100644
--- a/program/lib/Roundcube/rcube_message_header.php
+++ b/program/lib/Roundcube/rcube_message_header.php
@@ -215,7 +215,12 @@
             $value = $this->others[$name];
         }
 
-        return $decode ? rcube_mime::decode_header($value, $this->charset) : $value;
+        if ($decode) {
+            $value = rcube_mime::decode_header($value, $this->charset);
+            $value = rcube_charset::clean($value);
+        }
+
+        return $value;
     }
 
     /**
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 36c6d96..b787ca1 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -220,9 +220,9 @@
     }
   }
   else if ($compose_mode == RCUBE_COMPOSE_DRAFT) {
-    if ($MESSAGE->headers->others['x-draft-info']) {
+    if ($draft_info = $MESSAGE->headers->get('x-draft-info')) {
       // get reply_uid/forward_uid to flag the original message when sending
-      $info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']);
+      $info = rcmail_draftinfo_decode($draft_info);
 
       if ($info['type'] == 'reply')
         $COMPOSE['reply_uid'] = $info['uid'];
@@ -239,8 +239,8 @@
       }
     }
 
-    if ($MESSAGE->headers->in_reply_to)
-      $COMPOSE['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
+    if ($in_reply_to = $MESSAGE->headers->get('in-reply-to'))
+      $COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>';
 
     $COMPOSE['references']  = $MESSAGE->headers->references;
   }
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 274c40b..6333cf4 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -896,7 +896,7 @@
  * return table with message headers
  */
 function rcmail_message_headers($attrib, $headers=null)
-  {
+{
   global $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL;
   static $sa_attrib;
 
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index 552c180..1947c0f 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -109,7 +109,7 @@
     $OUTPUT->set_env('skip_deleted', true);
   if ($CONFIG['display_next'])
     $OUTPUT->set_env('display_next', true);
-  if ($MESSAGE->headers->others['list-post'])
+  if ($MESSAGE->headers->get('list-post', false))
     $OUTPUT->set_env('list_post', true);
   if ($CONFIG['forward_attachment'])
     $OUTPUT->set_env('forward_attachment', true);

--
Gitblit v1.9.1