Skip to content

Commit

Permalink
Merge ffc98aa into 7678a90
Browse files Browse the repository at this point in the history
  • Loading branch information
xemlock committed May 30, 2020
2 parents 7678a90 + ffc98aa commit db942b8
Show file tree
Hide file tree
Showing 13 changed files with 661 additions and 8 deletions.
59 changes: 59 additions & 0 deletions library/HTMLPurifier/AttrDef/HTML/FontSize.php
@@ -0,0 +1,59 @@
<?php

/**
* Validates 'size' attribute of deprecated FONT tag
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/font#attr-size
*/
class HTMLPurifier_AttrDef_HTML_FontSize extends HTMLPurifier_AttrDef_CSS_Number
{
/**
* @param string $string
* @param HTMLPurifier_Config $config
* @param HTMLPurifier_Context $context
* @return bool|string
*/
public function validate($string, $config, $context)
{
$string = trim($string);

switch (substr($string, 0, 1)) {
case '+':
$sign = 1;
break;

case '-':
$sign = -1;
break;

default:
$sign = 0;
break;
}

if ($sign) {
$string = substr($string, 1);
}

if (($string = parent::validate($string, $config, $context)) === false) {
return false;
}

// Browsers truncate float 'size' values to integers, so we do the same
$value = (int) $string;

// Size values range from 1 to 7 with 1 being the smallest and 3 the
// default. It can be defined using a relative value, like +2 or -3,
// which set it relative to the default value.
// This means that the relative values are between -2 and +4 (inclusive).

if ($sign) {
$value = max(-2, min(4, $sign * $value));
$value = $value >= 0 ? '+' . $value : $value;
} else {
$value = max(1, min(7, $value));
}

return (string) $value;
}
}
28 changes: 28 additions & 0 deletions library/HTMLPurifier/AttrTransform/HTML5/FrameBorder.php
@@ -0,0 +1,28 @@
<?php

/**
* Pre-transform that changes deprecated IFRAME frameborder attribute to CSS.
*/
class HTMLPurifier_AttrTransform_HTML5_FrameBorder extends HTMLPurifier_AttrTransform
{
/**
* @param array $attr
* @param HTMLPurifier_Config $config
* @param HTMLPurifier_Context $context
* @return array
*/
public function transform($attr, $config, $context)
{
if (!isset($attr['frameborder'])) {
return $attr;
}

$frameBorder = (int) $this->confiscateAttr($attr, 'frameborder');

if ($frameBorder === 0) {
$this->prependCSS($attr, 'border:0;');
}

return $attr;
}
}
13 changes: 9 additions & 4 deletions library/HTMLPurifier/HTML5Config.php
Expand Up @@ -2,7 +2,7 @@

class HTMLPurifier_HTML5Config extends HTMLPurifier_Config
{
const REVISION = 2019080701;
const REVISION = 2020053001;

/**
* @param string|array|HTMLPurifier_Config $config
Expand Down Expand Up @@ -73,6 +73,12 @@ public function __construct(HTMLPurifier_ConfigSchema $schema, HTMLPurifier_Prop
$schema->add('HTML.IframeAllowFullscreen', false, 'bool', false);
}

// HTMLPurifier doesn't define %CSS.DefinitionID, but it's required for
// customizing CSS definition object (in the future)
if (empty($schema->info['CSS.DefinitionID'])) {
$schema->add('CSS.DefinitionID', null, 'string', true);
}

parent::__construct($schema, $parent);

$this->set('HTML.Doctype', 'HTML5');
Expand All @@ -84,11 +90,10 @@ public function getDefinition($type, $raw = false, $optimized = false)
{
// Setting HTML.* keys removes any previously instantiated HTML
// definition object, so set up HTML5 definition as late as possible
$needSetup = $type === 'HTML' && !isset($this->definitions[$type]);
if ($needSetup) {
if ($type === 'HTML' && empty($this->definitions[$type])) {
if ($def = parent::getDefinition($type, true, true)) {
/** @var HTMLPurifier_HTMLDefinition $def */
HTMLPurifier_HTML5Definition::setupDefinition($def);
HTMLPurifier_HTML5Definition::setupHTMLDefinition($def, $this);
}
}
return parent::getDefinition($type, $raw, $optimized);
Expand Down
11 changes: 7 additions & 4 deletions library/HTMLPurifier/HTML5Definition.php
@@ -1,15 +1,16 @@
<?php

class HTMLPurifier_HTML5Definition
abstract class HTMLPurifier_HTML5Definition
{
/**
* Adds HTML5 element and attributes to a provided definition object.
*
* @param HTMLPurifier_HTMLDefinition $def
* @param HTMLPurifier_Config $config
* @return HTMLPurifier_HTMLDefinition
* @throws HTMLPurifier_Exception
* @internal
*/
public static function setupDefinition(HTMLPurifier_HTMLDefinition $def)
public static function setupHTMLDefinition(HTMLPurifier_HTMLDefinition $def, HTMLPurifier_Config $config)
{
$def->manager->doctypes->register(
'HTML5',
Expand All @@ -24,8 +25,10 @@ public static function setupDefinition(HTMLPurifier_HTMLDefinition $def)
// Unsafe:
'HTML5_Scripting', 'HTML5_Interactive', 'Object', 'HTML5_Forms',
'HTML5_Iframe',
// Transitional:
'HTML5_Legacy',
),
array('Tidy_Transitional', 'Tidy_Proprietary'),
array('Tidy_HTML5'),
array()
);

Expand Down
113 changes: 113 additions & 0 deletions library/HTMLPurifier/HTMLModule/HTML5/Legacy.php
@@ -0,0 +1,113 @@
<?php

/**
* Legacy module defines elements that were obsoleted / deprecated in HTML5
* but are still supported by browsers.
*
* This module requires Tidy module to be enabled to avoid invalid HTML5 output.
* It provides definitions for obsolete attributes and elements that have fixes
* defined in Tidy_HTML5 module.
*/
class HTMLPurifier_HTMLModule_HTML5_Legacy extends HTMLPurifier_HTMLModule
{
/**
* @type string
*/
public $name = 'HTML5_Legacy';

/**
* @param HTMLPurifier_Config $config
*/
public function setup($config)
{
// Setup additional obsolete / deprecated elements

$this->addElement('center', 'Block', 'Flow', 'Common');

$this->addElement('dir', 'Block', 'Required: li', 'Common');

$this->addElement('font', 'Inline', 'Inline', array('Core', 'I18N'), array(
'color' => 'Color',
'face' => new HTMLPurifier_AttrDef_CSS_FontFamily(),
'size' => new HTMLPurifier_AttrDef_HTML_FontSize(),
));

$this->addElement('menu', 'Block', 'Required: li', 'Common');

$strike = $this->addElement('strike', 'Inline', 'Inline', 'Common');
$strike->formatting = true;

// Setup modifications to old elements

$align = 'Enum#left,right,center,justify';

$br = $this->addBlankElement('br');
$br->attr['clear'] = 'Enum#all,left,right,none';

$caption = $this->addBlankElement('caption');
$caption->attr['align'] = 'Enum#top,bottom,left,right';

$div = $this->addBlankElement('div');
$div->attr['align'] = $align;

for ($i = 1; $i <= 6; $i++) {
$h = $this->addBlankElement("h$i");
$h->attr['align'] = $align;
}

$hr = $this->addBlankElement('hr');
$hr->attr['align'] = $align;
$hr->attr['noshade'] = 'Bool#noshade';
$hr->attr['size'] = 'Pixels';
$hr->attr['width'] = 'Length';

$img = $this->addBlankElement('img');
$img->attr['align'] = 'IAlign';
$img->attr['border'] = 'Pixels';
$img->attr['hspace'] = 'Pixels';
$img->attr['vspace'] = 'Pixels';

$li = $this->addBlankElement('li');
$li->attr['value'] = new HTMLPurifier_AttrDef_Integer();
$li->attr['type'] = 'Enum#s:1,i,I,a,A,circle,disc,square';

$p = $this->addBlankElement('p');
$p->attr['align'] = $align;

$pre = $this->addBlankElement('pre');
$pre->attr['width'] = 'Number';

$table = $this->addBlankElement('table');
$table->attr['align'] = 'Enum#left,center,right';
$table->attr['bgcolor'] = 'Color';

$tr = $this->addBlankElement('tr');
$tr->attr['bgcolor'] = 'Color';

$th = $this->addBlankElement('th');
$th->attr['bgcolor'] = 'Color';
$th->attr['height'] = 'Length';
$th->attr['nowrap'] = 'Bool#nowrap';
$th->attr['width'] = 'Length';

$td = $this->addBlankElement('td');
$td->attr['bgcolor'] = 'Color';
$td->attr['height'] = 'Length';
$td->attr['nowrap'] = 'Bool#nowrap';
$td->attr['width'] = 'Length';

$ul = $this->addBlankElement('ul');
$ul->attr['type'] = 'Enum#circle,disc,square';

// Setup modifications to "unsafe" elements

$iframe = $this->addBlankElement('iframe');
$iframe->attr['frameborder'] = 'Enum#0,1';

$input = $this->addBlankElement('input');
$input->attr['align'] = 'IAlign';

$legend = $this->addBlankElement('legend');
$legend->attr['align'] = 'LAlign';
}
}
3 changes: 3 additions & 0 deletions library/HTMLPurifier/HTMLModule/HTML5/List.php
Expand Up @@ -26,5 +26,8 @@ public function setup($config)
// Attributes that were deprecated in HTML4, but reintroduced in HTML5
$ol->attr['start'] = new HTMLPurifier_AttrDef_Integer();
$ol->attr['type'] = 'Enum#s:1,a,A,i,I';

$li = $this->info['li'];
$li->attr['value'] = new HTMLPurifier_AttrDef_Integer();
}
}
36 changes: 36 additions & 0 deletions library/HTMLPurifier/HTMLModule/Tidy/HTML5.php
@@ -0,0 +1,36 @@
<?php

class HTMLPurifier_HTMLModule_Tidy_HTML5 extends HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4
{
public $name = 'Tidy_HTML5';

/**
* This is the lenient level. If a tag or attribute is about to be removed
* because it isn't supported by the doctype, Tidy will step in and change
* into an alternative that is supported.
* @var string
*/
public $defaultLevel = 'light';

/**
* @return array
*/
public function makeFixes()
{
$fixes = parent::makeFixes();

// Remove transforms for valid HTML5 elements
unset(
$fixes['u'],
$fixes['s'],
$fixes['ol@type']
);

$fixes['font'] = new HTMLPurifier_TagTransform_Font2();
$fixes['strike'] = new HTMLPurifier_TagTransform_Simple('s');

$fixes['iframe@frameborder'] = new HTMLPurifier_AttrTransform_HTML5_FrameBorder();

return $fixes;
}
}

0 comments on commit db942b8

Please sign in to comment.