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 | 109 ++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 77 insertions(+), 32 deletions(-) diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php index 8ff685a..a367112 100644 --- a/program/lib/Roundcube/html.php +++ b/program/lib/Roundcube/html.php @@ -2,8 +2,6 @@ /* +-----------------------------------------------------------------------+ - | program/include/html.php | - | | | This file is part of the Roundcube Webmail client | | Copyright (C) 2005-2011, The Roundcube Dev Team | | | @@ -13,7 +11,6 @@ | | | PURPOSE: | | Helper class to create valid XHTML code | - | | +-----------------------------------------------------------------------+ | Author: Thomas Bruederli <roundcube@gmail.com> | +-----------------------------------------------------------------------+ @@ -24,7 +21,7 @@ * Class for HTML code creation * * @package Framework - * @subpackage HTML + * @subpackage View */ class html { @@ -37,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 @@ -172,7 +170,7 @@ $attr = array('href' => $attr); } return self::tag('a', $attr, $cont, array_merge(self::$common_attrib, - array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup'))); + array('href','target','name','rel','onclick','onmouseover','onmouseout','onmousedown','onmouseup'))); } /** @@ -220,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'))); } /** @@ -290,7 +288,7 @@ } // attributes with no value - if (in_array($key, array('checked', 'multiple', 'disabled', 'selected'))) { + if (in_array($key, array('checked', 'multiple', 'disabled', 'selected', 'autofocus'))) { if ($value) { $attrib_arr[] = $key . '="' . $key . '"'; } @@ -335,7 +333,16 @@ */ public static function quote($str) { - return @htmlspecialchars($str, ENT_COMPAT, RCMAIL_CHARSET); + static $flags; + + if (!$flags) { + $flags = ENT_COMPAT; + if (defined('ENT_SUBSTITUTE')) { + $flags |= ENT_SUBSTITUTE; + } + } + + return @htmlspecialchars($str, $flags, RCUBE_CHARSET); } } @@ -343,16 +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', + 'spellcheck','results','maxlength','src','multiple','accept', + 'placeholder','autofocus', ); /** @@ -398,7 +407,8 @@ /** * Class to create an HTML password field * - * @package HTML + * @package Framework + * @subpackage View */ class html_passwordfield extends html_inputfield { @@ -408,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'; @@ -458,7 +468,8 @@ /** * Class to create HTML radio buttons * - * @package HTML + * @package Framework + * @subpackage View */ class html_radiobutton extends html_inputfield { @@ -488,7 +499,8 @@ /** * Class to create HTML checkboxes * - * @package HTML + * @package Framework + * @subpackage View */ class html_checkbox extends html_inputfield { @@ -518,7 +530,8 @@ /** * Class to create an HTML textarea * - * @package HTML + * @package Framework + * @subpackage View */ class html_textarea extends html { @@ -576,7 +589,8 @@ * print $select->show('CH'); * </pre> * - * @package HTML + * @package Framework + * @subpackage View */ class html_select extends html { @@ -641,7 +655,8 @@ /** * Class to build an HTML table * - * @package HTML + * @package Framework + * @subpackage View */ class html_table extends html { @@ -663,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; + } } /** @@ -678,7 +698,7 @@ } $cell = new stdClass; - $cell->attrib = $attr; + $cell->attrib = $attr; $cell->content = $cont; $this->rows[$this->rowindex]->cells[$this->colindex] = $cell; @@ -702,16 +722,16 @@ } $cell = new stdClass; - $cell->attrib = $attr; - $cell->content = $cont; + $cell->attrib = $attr; + $cell->content = $cont; $this->header[] = $cell; } - /** + /** * Remove a column from a table * Useful for plugins making alterations - * - * @param string $class + * + * @param string $class */ public function remove_column($class) { @@ -764,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; } @@ -791,8 +816,9 @@ */ public function show($attrib = null) { - if (is_array($attrib)) + if (is_array($attrib)) { $this->attrib = array_merge($this->attrib, $attrib); + } $thead = $tbody = ""; @@ -800,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); } } @@ -821,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(); @@ -834,7 +861,7 @@ */ public function size() { - return count($this->rows); + return count($this->rows); } /** @@ -846,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