From cb3e2fe0c2e36e0f41d93015fb1b604d195f9047 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Fri, 31 May 2013 09:42:22 -0400
Subject: [PATCH] Fix displaying messages with invalid self-closing HTML tags (#1489137)

---
 CHANGELOG                               |    1 +
 program/lib/Roundcube/rcube_washtml.php |   17 ++++++++---------
 tests/Framework/Washtml.php             |   13 +++++++++++++
 3 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 012be67..1fdd371 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Fix displaying messages with invalid self-closing HTML tags (#1489137)
 - Fix PHP warning when responding to a message with many Return-Path headers (#1489136)
 - Added user preference to open all popups as standard windows
 - Fix unintentional compose window resize (#1489114)
diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php
index a11371c..6b2efcc 100644
--- a/program/lib/Roundcube/rcube_washtml.php
+++ b/program/lib/Roundcube/rcube_washtml.php
@@ -113,10 +113,9 @@
         'type', 'rows', 'cols', 'disabled', 'readonly', 'checked', 'multiple', 'value'
     );
 
-    /* Block elements which could be empty but cannot be returned in short form (<tag />) */
-    static $block_elements = array('div', 'p', 'pre', 'blockquote', 'a', 'font', 'center',
-        'table', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'dl', 'strong',
-        'i', 'b', 'u', 'span',
+    /* Elements which could be empty and be returned in short form (<tag />) */
+    static $void_elements = array('area', 'base', 'br', 'col', 'command', 'embed', 'hr',
+        'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'
     );
 
     /* State for linked objects in HTML */
@@ -134,8 +133,8 @@
     /* Ignore these HTML tags but process their content */
     private $_ignore_elements = array();
 
-    /* Block elements which could be empty but cannot be returned in short form (<tag />) */
-    private $_block_elements = array();
+    /* Elements which could be empty and be returned in short form (<tag />) */
+    private $_void_elements = array();
 
     /* Allowed HTML attributes */
     private $_html_attribs = array();
@@ -152,9 +151,9 @@
         $this->_html_elements   = array_flip((array)$p['html_elements']) + array_flip(self::$html_elements) ;
         $this->_html_attribs    = array_flip((array)$p['html_attribs']) + array_flip(self::$html_attribs);
         $this->_ignore_elements = array_flip((array)$p['ignore_elements']) + array_flip(self::$ignore_elements);
-        $this->_block_elements  = array_flip((array)$p['block_elements']) + array_flip(self::$block_elements);
+        $this->_void_elements   = array_flip((array)$p['void_elements']) + array_flip(self::$void_elements);
 
-        unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['block_elements']);
+        unset($p['html_elements'], $p['html_attribs'], $p['ignore_elements'], $p['void_elements']);
 
         $this->config = $p + array('show_washed' => true, 'allow_remote' => false, 'cid_map' => array());
     }
@@ -321,7 +320,7 @@
                 else if (isset($this->_html_elements[$tagName])) {
                     $content = $this->dumpHtml($node, $level);
                     $dump .= '<' . $tagName . $this->wash_attribs($node) .
-                        ($content != '' || isset($this->_block_elements[$tagName]) ? ">$content</$tagName>" : ' />');
+                        ($content === '' && isset($this->_void_elements[$tagName]) ? ' />' : ">$content</$tagName>");
                 }
                 else if (isset($this->_ignore_elements[$tagName])) {
                     $dump .= '<!-- ' . htmlspecialchars($tagName, ENT_QUOTES) . ' not allowed -->';
diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php
index 526b933..cb72343 100644
--- a/tests/Framework/Washtml.php
+++ b/tests/Framework/Washtml.php
@@ -55,4 +55,17 @@
         $this->assertEquals('<!-- html ignored --><!-- body ignored --><p>test</p>', $washed, "HTML invalid comments (#1487759)");
     }
 
+    /**
+     * Test fixing of invalid self-closing elements (#1489137)
+     */
+    function test_self_closing()
+    {
+        $html = "<textarea>test";
+
+        $washer = new rcube_washtml;
+        $washed = $washer->wash($html);
+
+        $this->assertRegExp('|<textarea>test</textarea>|', $washed, "Self-closing textarea (#1489137)");
+    }
+
 }

--
Gitblit v1.9.1