From 5a2d2a6f75b115183459997cc2aa787d9a085fe8 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Mon, 14 Oct 2013 02:53:34 -0400 Subject: [PATCH] Fix HTML part detection when encapsulated inside multipart/signed (#1489372) --- program/lib/Roundcube/html.php | 86 +++++++++++++++++++++++++++++++++---------- 1 files changed, 66 insertions(+), 20 deletions(-) diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php index a44f4d5..a367112 100644 --- a/program/lib/Roundcube/html.php +++ b/program/lib/Roundcube/html.php @@ -21,7 +21,7 @@ * Class for HTML code creation * * @package Framework - * @subpackage HTML + * @subpackage View */ class html { @@ -34,6 +34,7 @@ public static $lc_tags = true; 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 @@ -217,7 +218,7 @@ $attr = array('src' => $attr); } return self::tag('iframe', $attr, $cont, array_merge(self::$common_attrib, - array('src','name','width','height','border','frameborder'))); + array('src','name','width','height','border','frameborder','onload'))); } /** @@ -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); } } @@ -340,17 +350,18 @@ /** * Class to create an HTML input field * - * @package HTML + * @package Framework + * @subpackage View */ class html_inputfield extends html { protected $tagname = 'input'; protected $type = 'text'; protected $allowed = array( - 'type','name','value','size','tabindex','autocapitalize', + 'type','name','value','size','tabindex','autocapitalize','required', 'autocomplete','checked','onchange','onclick','disabled','readonly', - 'spellcheck','results','maxlength','src','multiple','placeholder', - 'autofocus', + 'spellcheck','results','maxlength','src','multiple','accept', + 'placeholder','autofocus', ); /** @@ -396,7 +407,8 @@ /** * Class to create an HTML password field * - * @package HTML + * @package Framework + * @subpackage View */ class html_passwordfield extends html_inputfield { @@ -406,9 +418,9 @@ /** * Class to create an hidden HTML input field * - * @package HTML + * @package Framework + * @subpackage View */ - class html_hiddenfield extends html { protected $tagname = 'input'; @@ -456,7 +468,8 @@ /** * Class to create HTML radio buttons * - * @package HTML + * @package Framework + * @subpackage View */ class html_radiobutton extends html_inputfield { @@ -486,7 +499,8 @@ /** * Class to create HTML checkboxes * - * @package HTML + * @package Framework + * @subpackage View */ class html_checkbox extends html_inputfield { @@ -516,7 +530,8 @@ /** * Class to create an HTML textarea * - * @package HTML + * @package Framework + * @subpackage View */ class html_textarea extends html { @@ -574,7 +589,8 @@ * print $select->show('CH'); * </pre> * - * @package HTML + * @package Framework + * @subpackage View */ class html_select extends html { @@ -639,7 +655,8 @@ /** * Class to build an HTML table * - * @package HTML + * @package Framework + * @subpackage View */ class html_table extends html { @@ -661,6 +678,11 @@ { $default_attrib = self::$doctype == 'xhtml' ? array('summary' => '', 'border' => 0) : array(); $this->attrib = array_merge($attrib, $default_attrib); + + if (!empty($attrib['tagname']) && $attrib['tagname'] != 'table') { + $this->tagname = $attrib['tagname']; + $this->allowed = self::$common_attrib; + } } /** @@ -762,6 +784,11 @@ $index = $this->rowindex; } + // make sure row object exists (#1489094) + if (!$this->rows[$index]) { + $this->rows[$index] = new stdClass; + } + $this->rows[$index]->attrib = $attr; } @@ -799,19 +826,20 @@ if (!empty($this->header)) { $rowcontent = ''; foreach ($this->header as $c => $col) { - $rowcontent .= self::tag('td', $col->attrib, $col->content); + $rowcontent .= self::tag($this->_col_tagname(), $col->attrib, $col->content); } - $thead = self::tag('thead', null, self::tag('tr', null, $rowcontent, parent::$common_attrib)); + $thead = $this->tagname == 'table' ? self::tag('thead', null, self::tag('tr', null, $rowcontent, parent::$common_attrib)) : + self::tag($this->_row_tagname(), array('class' => 'thead'), $rowcontent, parent::$common_attrib); } foreach ($this->rows as $r => $row) { $rowcontent = ''; foreach ($row->cells as $c => $col) { - $rowcontent .= self::tag('td', $col->attrib, $col->content); + $rowcontent .= self::tag($this->_col_tagname(), $col->attrib, $col->content); } if ($r < $this->rowindex || count($row->cells)) { - $tbody .= self::tag('tr', $row->attrib, $rowcontent, parent::$common_attrib); + $tbody .= self::tag($this->_row_tagname(), $row->attrib, $rowcontent, parent::$common_attrib); } } @@ -820,7 +848,7 @@ } // add <tbody> - $this->content = $thead . self::tag('tbody', null, $tbody); + $this->content = $thead . ($this->tagname == 'table' ? self::tag('tbody', null, $tbody) : $tbody); unset($this->attrib['cols'], $this->attrib['rowsonly']); return parent::show(); @@ -845,4 +873,22 @@ $this->rowindex = 0; } + /** + * Getter for the corresponding tag name for table row elements + */ + private function _row_tagname() + { + static $row_tagnames = array('table' => 'tr', 'ul' => 'li', '*' => 'div'); + return $row_tagnames[$this->tagname] ?: $row_tagnames['*']; + } + + /** + * Getter for the corresponding tag name for table cell elements + */ + private function _col_tagname() + { + static $col_tagnames = array('table' => 'td', '*' => 'span'); + return $col_tagnames[$this->tagname] ?: $col_tagnames['*']; + } + } -- Gitblit v1.9.1