From 0344b168276f80189e2254c75a762aff5b517b6b Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sun, 22 May 2016 06:32:57 -0400
Subject: [PATCH] Fix priority icon(s) position
---
program/lib/Roundcube/html.php | 226 ++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 161 insertions(+), 65 deletions(-)
diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php
index 8ff685a..8c2534a 100644
--- a/program/lib/Roundcube/html.php
+++ b/program/lib/Roundcube/html.php
@@ -1,11 +1,9 @@
<?php
-/*
+/**
+-----------------------------------------------------------------------+
- | program/include/html.php |
- | |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2011, The Roundcube Dev Team |
+ | Copyright (C) 2005-2013, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -13,30 +11,30 @@
| |
| PURPOSE: |
| Helper class to create valid XHTML code |
- | |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
-
/**
* Class for HTML code creation
*
* @package Framework
- * @subpackage HTML
+ * @subpackage View
*/
class html
{
protected $tagname;
- protected $attrib = array();
- protected $allowed = array();
protected $content;
+ protected $attrib = array();
+ protected $allowed = array();
public static $doctype = 'xhtml';
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');
+ public static $common_attrib = array('id','class','style','title','align','unselectable','tabindex','role');
+ public static $containers = array('iframe','div','span','p','h1','h2','h3','ul','form','textarea','table','thead','tbody','tr','th','td','style','script');
+ public static $bool_attrib = array('checked','multiple','disabled','selected','autofocus','readonly');
+
/**
* Constructor
@@ -68,13 +66,15 @@
* @param string $tagname Tag name
* @param array $attrib Tag attributes as key/value pairs
* @param string $content Optinal Tag content (creates a container tag)
- * @param array $allowed_attrib List with allowed attributes, omit to allow all
+ * @param array $allowed List with allowed attributes, omit to allow all
+ *
* @return string The XHTML tag
*/
- public static function tag($tagname, $attrib = array(), $content = null, $allowed_attrib = null)
+ public static function tag($tagname, $attrib = array(), $content = null, $allowed = null)
{
- if (is_string($attrib))
+ if (is_string($attrib)) {
$attrib = array('class' => $attrib);
+ }
$inline_tags = array('a','span','img');
$suffix = $attrib['nl'] || ($content && $attrib['nl'] !== false && !in_array($tagname, $inline_tags)) ? "\n" : '';
@@ -83,15 +83,17 @@
if (isset($content) || in_array($tagname, self::$containers)) {
$suffix = $attrib['noclose'] ? $suffix : '</' . $tagname . '>' . $suffix;
unset($attrib['noclose'], $attrib['nl']);
- return '<' . $tagname . self::attrib_string($attrib, $allowed_attrib) . '>' . $content . $suffix;
+ return '<' . $tagname . self::attrib_string($attrib, $allowed) . '>' . $content . $suffix;
}
else {
- return '<' . $tagname . self::attrib_string($attrib, $allowed_attrib) . '>' . $suffix;
+ return '<' . $tagname . self::attrib_string($attrib, $allowed) . '>' . $suffix;
}
}
/**
+ * Return DOCTYPE tag of specified type
*
+ * @param string $type Document type (html5, xhtml, 'xhtml-trans, xhtml-strict)
*/
public static function doctype($type)
{
@@ -115,6 +117,7 @@
*
* @param mixed $attr Hash array with tag attributes or string with class name
* @param string $cont Div content
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -123,6 +126,7 @@
if (is_string($attr)) {
$attr = array('class' => $attr);
}
+
return self::tag('div', $attr, $cont, array_merge(self::$common_attrib, array('onclick')));
}
@@ -131,6 +135,7 @@
*
* @param mixed $attr Hash array with tag attributes or string with class name
* @param string $cont Paragraph content
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -139,6 +144,7 @@
if (is_string($attr)) {
$attr = array('class' => $attr);
}
+
return self::tag('p', $attr, $cont, self::$common_attrib);
}
@@ -146,6 +152,7 @@
* Derrived method to create <img />
*
* @param mixed $attr Hash array with tag attributes or string with image source (src)
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -154,8 +161,9 @@
if (is_string($attr)) {
$attr = array('src' => $attr);
}
+
return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib,
- array('src','alt','width','height','border','usemap','onclick')));
+ array('src','alt','width','height','border','usemap','onclick','onerror')));
}
/**
@@ -163,6 +171,7 @@
*
* @param mixed $attr Hash array with tag attributes or string with link location (href)
* @param string $cont Link content
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -171,8 +180,9 @@
if (is_string($attr)) {
$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')));
}
/**
@@ -180,6 +190,7 @@
*
* @param mixed $attr Hash array with tag attributes or string with class name
* @param string $cont Tag content
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -188,6 +199,7 @@
if (is_string($attr)) {
$attr = array('class' => $attr);
}
+
return self::tag('span', $attr, $cont, self::$common_attrib);
}
@@ -196,6 +208,7 @@
*
* @param mixed $attr Hash array with tag attributes or string with 'for' attrib
* @param string $cont Tag content
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -204,6 +217,7 @@
if (is_string($attr)) {
$attr = array('for' => $attr);
}
+
return self::tag('label', $attr, $cont, array_merge(self::$common_attrib, array('for')));
}
@@ -211,6 +225,7 @@
* Derrived method to create <iframe></iframe>
*
* @param mixed $attr Hash array with tag attributes or string with frame source (src)
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -219,15 +234,17 @@
if (is_string($attr)) {
$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','allowfullscreen')));
}
/**
* Derrived method to create <script> tags
*
- * @param mixed $attr Hash array with tag attributes or string with script source (src)
+ * @param mixed $attr Hash array with tag attributes or string with script source (src)
* @param string $cont Javascript code to be placed as tag content
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -250,6 +267,8 @@
/**
* Derrived method for line breaks
*
+ * @param array $attrib Associative arry with tag attributes
+ *
* @return string HTML code
* @see html::tag()
*/
@@ -261,8 +280,9 @@
/**
* Create string with attributes
*
- * @param array $attrib Associative arry with tag attributes
+ * @param array $attrib Associative array with tag attributes
* @param array $allowed List of allowed attributes
+ *
* @return string Valid attribute string
*/
public static function attrib_string($attrib = array(), $allowed = null)
@@ -271,17 +291,27 @@
return '';
}
- $allowed_f = array_flip((array)$allowed);
+ $allowed_f = array_flip((array)$allowed);
$attrib_arr = array();
+
foreach ($attrib as $key => $value) {
// skip size if not numeric
if ($key == 'size' && !is_numeric($value)) {
continue;
}
- // ignore "internal" or not allowed attributes
- if ($key == 'nl' || ($allowed && !isset($allowed_f[$key])) || $value === null) {
+ // ignore "internal" or empty attributes
+ if ($key == 'nl' || $value === null) {
continue;
+ }
+
+ // ignore not allowed attributes, except aria-* and data-*
+ if (!empty($allowed)) {
+ $is_data_attr = @substr_compare($key, 'data-', 0, 5) === 0;
+ $is_aria_attr = @substr_compare($key, 'aria-', 0, 5) === 0;
+ if (!$is_aria_attr && !$is_data_attr && !isset($allowed_f[$key])) {
+ continue;
+ }
}
// skip empty eventhandlers
@@ -290,8 +320,9 @@
}
// attributes with no value
- if (in_array($key, array('checked', 'multiple', 'disabled', 'selected'))) {
+ if (in_array($key, self::$bool_attrib)) {
if ($value) {
+ // @TODO: minimize attribute in non-xhtml mode
$attrib_arr[] = $key . '="' . $key . '"';
}
}
@@ -307,6 +338,7 @@
* Convert a HTML attribute string attributes to an associative array (name => value)
*
* @param string Input string
+ *
* @return array Key-value pairs of parsed attributes
*/
public static function parse_attrib_string($str)
@@ -335,7 +367,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 +384,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 $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','pattern'
);
/**
@@ -374,8 +417,9 @@
/**
* Compose input tag
*
- * @param string $value Field value
+ * @param string $value Field value
* @param array $attrib Additional attributes to override
+ *
* @return string HTML output
*/
public function show($value = null, $attrib = null)
@@ -391,6 +435,7 @@
}
// set type
$this->attrib['type'] = $this->type;
+
return parent::show();
}
}
@@ -398,7 +443,8 @@
/**
* Class to create an HTML password field
*
- * @package HTML
+ * @package Framework
+ * @subpackage View
*/
class html_passwordfield extends html_inputfield
{
@@ -408,15 +454,15 @@
/**
* Class to create an hidden HTML input field
*
- * @package HTML
+ * @package Framework
+ * @subpackage View
*/
-
class html_hiddenfield extends html
{
protected $tagname = 'input';
- protected $type = 'hidden';
- protected $fields_arr = array();
+ protected $type = 'hidden';
protected $allowed = array('type','name','value','onchange','disabled','readonly');
+ protected $fields = array();
/**
* Constructor
@@ -437,7 +483,7 @@
*/
public function add($attrib)
{
- $this->fields_arr[] = $attrib;
+ $this->fields[] = $attrib;
}
/**
@@ -448,9 +494,10 @@
public function show()
{
$out = '';
- foreach ($this->fields_arr as $attrib) {
+ foreach ($this->fields as $attrib) {
$out .= self::tag($this->tagname, array('type' => $this->type) + $attrib);
}
+
return $out;
}
}
@@ -458,7 +505,8 @@
/**
* Class to create HTML radio buttons
*
- * @package HTML
+ * @package Framework
+ * @subpackage View
*/
class html_radiobutton extends html_inputfield
{
@@ -469,6 +517,7 @@
*
* @param string $value Value of the checked field
* @param array $attrib Additional attributes to override
+ *
* @return string HTML output
*/
public function show($value = '', $attrib = null)
@@ -488,7 +537,8 @@
/**
* Class to create HTML checkboxes
*
- * @package HTML
+ * @package Framework
+ * @subpackage View
*/
class html_checkbox extends html_inputfield
{
@@ -499,6 +549,7 @@
*
* @param string $value Value of the checked field
* @param array $attrib Additional attributes to override
+ *
* @return string HTML output
*/
public function show($value = '', $attrib = null)
@@ -518,7 +569,8 @@
/**
* Class to create an HTML textarea
*
- * @package HTML
+ * @package Framework
+ * @subpackage View
*/
class html_textarea extends html
{
@@ -531,6 +583,7 @@
*
* @param string $value Textbox value
* @param array $attrib Additional attributes to override
+ *
* @return string HTML output
*/
public function show($value = '', $attrib = null)
@@ -576,7 +629,8 @@
* print $select->show('CH');
* </pre>
*
- * @package HTML
+ * @package Framework
+ * @subpackage View
*/
class html_select extends html
{
@@ -590,16 +644,17 @@
*
* @param mixed $names Option name or array with option names
* @param mixed $values Option value or array with option values
+ * @param array $attrib Additional attributes for the option entry
*/
- public function add($names, $values = null)
+ public function add($names, $values = null, $attrib = array())
{
if (is_array($names)) {
foreach ($names as $i => $text) {
- $this->options[] = array('text' => $text, 'value' => $values[$i]);
+ $this->options[] = array('text' => $text, 'value' => $values[$i]) + $attrib;
}
}
else {
- $this->options[] = array('text' => $names, 'value' => $values);
+ $this->options[] = array('text' => $names, 'value' => $values) + $attrib;
}
}
@@ -608,6 +663,7 @@
*
* @param string $select Value of the selection option
* @param array $attrib Additional attributes to override
+ *
* @return string HTML output
*/
public function show($select = array(), $attrib = null)
@@ -630,7 +686,7 @@
$option_content = self::quote($option_content);
}
- $this->content .= self::tag('option', $attr, $option_content);
+ $this->content .= self::tag('option', $attr + $option, $option_content, array('value','label','class','style','title','disabled','selected'));
}
return parent::show();
@@ -641,7 +697,8 @@
/**
* Class to build an HTML table
*
- * @package HTML
+ * @package Framework
+ * @subpackage View
*/
class html_table extends html
{
@@ -649,8 +706,8 @@
protected $allowed = array('id','class','style','width','summary',
'cellpadding','cellspacing','border');
- private $header = array();
- private $rows = array();
+ private $header = array();
+ private $rows = array();
private $rowindex = 0;
private $colindex = 0;
@@ -661,8 +718,13 @@
*/
public function __construct($attrib = array())
{
- $default_attrib = self::$doctype == 'xhtml' ? array('summary' => '', 'border' => 0) : array();
- $this->attrib = array_merge($attrib, $default_attrib);
+ $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 +740,7 @@
}
$cell = new stdClass;
- $cell->attrib = $attr;
+ $cell->attrib = $attr;
$cell->content = $cont;
$this->rows[$this->rowindex]->cells[$this->colindex] = $cell;
@@ -702,16 +764,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)
{
@@ -745,7 +807,7 @@
$this->colindex = 0;
$this->rows[$this->rowindex] = new stdClass;
$this->rows[$this->rowindex]->attrib = $attr;
- $this->rows[$this->rowindex]->cells = array();
+ $this->rows[$this->rowindex]->cells = array();
}
/**
@@ -762,6 +824,11 @@
if ($index === null) {
$index = $this->rowindex;
+ }
+
+ // make sure row object exists (#1489094)
+ if (!$this->rows[$index]) {
+ $this->rows[$index] = new stdClass;
}
$this->rows[$index]->attrib = $attr;
@@ -787,12 +854,14 @@
* Build HTML output of the table data
*
* @param array $attrib Table attributes
+ *
* @return string The final table HTML code
*/
public function show($attrib = null)
{
- if (is_array($attrib))
+ if (is_array($attrib)) {
$this->attrib = array_merge($this->attrib, $attrib);
+ }
$thead = $tbody = "";
@@ -800,19 +869,20 @@
if (!empty($this->header)) {
$rowcontent = '';
foreach ($this->header as $c => $col) {
- $rowcontent .= self::tag('td', $col->attrib, $col->content);
+ $rowcontent .= self::tag($this->_head_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 +891,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 +904,7 @@
*/
public function size()
{
- return count($this->rows);
+ return count($this->rows);
}
/**
@@ -846,4 +916,30 @@
$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 row elements
+ */
+ private function _head_tagname()
+ {
+ static $head_tagnames = array('table' => 'th', '*' => 'span');
+ return $head_tagnames[$this->tagname] ?: $head_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