Skip to content

Commit

Permalink
Merge 6247dac into 9e8a342
Browse files Browse the repository at this point in the history
  • Loading branch information
bytestream committed May 18, 2021
2 parents 9e8a342 + 6247dac commit fb8b327
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 3 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ Apart from HTML Purifier's built-in [configuration directives](http://htmlpurifi
When enabled it causes `xml:lang` attribute to take precedence over `lang`,
when both attributes are present on the same element.

* __HTML.Link__

Version added: 0.1.12\
Type: [Boolean](http://htmlpurifier.org/live/configdoc/plain.html#type-list)\
Default: `array()`

Permit use of the `<link>` element on specific URLs.
Use `Attr.AllowedRel` to control permitted link types.

## Supported HTML5 elements

Expand Down
28 changes: 28 additions & 0 deletions library/HTMLPurifier/AttrDef/HTML/LinkRel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/*
* Keywords that are body-ok affect whether link elements are allowed in the body.
* The body-ok keywords are dns-prefetch, modulepreload, pingback, preconnect, prefetch, preload, prerender,
* and stylesheet.
*
* https://html.spec.whatwg.org/multipage/links.html#body-ok
*
* @note We cannot use Enum because multiple values are allowed.
*/
class HTMLPurifier_AttrDef_HTML_LinkRel extends HTMLPurifier_AttrDef_HTML5_ARel
{
/**
* Lookup table for valid values
* @var array
*/
protected static $values = array(
'dns-prefetch' => true,
'modulepreload' => true,
'pingback' => true,
'preconnect' => true,
'prefetch' => true,
'preload' => true,
'prerender' => true,
'stylesheet' => true,
);
}
2 changes: 1 addition & 1 deletion library/HTMLPurifier/AttrDef/HTML5/ARel.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public function validate($string, $config, $context)
if (empty($allowedRel)) {
$allowed = array();
} else {
$allowed = array_intersect_key($allowedRel, self::$values);
$allowed = array_intersect_key($allowedRel, static::$values);
}
$this->allowed = $allowed;
}
Expand Down
6 changes: 5 additions & 1 deletion library/HTMLPurifier/HTML5Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class HTMLPurifier_HTML5Config extends HTMLPurifier_Config
{
const REVISION = 2020061401;
const REVISION = 2021061404;

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

if (empty($schema->info['HTML.Link'])) {
$schema->add('HTML.Link', array(), 'list', 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'])) {
Expand Down
2 changes: 1 addition & 1 deletion library/HTMLPurifier/HTML5Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static function setupHTMLDefinition(HTMLPurifier_HTMLDefinition $def, HTM
'HTML5_CommonAttributes', 'HTML5_Text', 'HTML5_Hypertext', 'HTML5_List',
'HTML5_Edit', 'HTML5_Bdo', 'Tables', 'Image',
'StyleAttribute', 'HTML5_Media', 'HTML5_Ruby', 'Name',
'HTML5_SafeForms',
'HTML5_SafeForms', 'HTML5_Link',
// Unsafe:
'HTML5_Scripting', 'HTML5_Interactive', 'Object', 'HTML5_Forms',
'HTML5_Iframe',
Expand Down
27 changes: 27 additions & 0 deletions library/HTMLPurifier/HTMLModule/HTML5/Link.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/*
* https://html.spec.whatwg.org/dev/semantics.html#the-link-element
*/
class HTMLPurifier_HTMLModule_HTML5_Link extends HTMLPurifier_HTMLModule
{
/**
* @type string
*/
public $name = 'HTML5_Link';

/**
* @param HTMLPurifier_Config $config
*/
public function setup($config)
{
$allowed = $config->get('HTML.Link');

// https://html.spec.whatwg.org/dev/semantics.html#the-link-element
$this->addElement('link', 'Flow', 'Empty', null, array(
'rel*' => new HTMLPurifier_AttrDef_HTML_LinkRel,
'type' => new HTMLPurifier_AttrDef_Enum(array('text/css')),
'href*' => new HTMLPurifier_AttrDef_Enum($allowed, true),
));
}
}
89 changes: 89 additions & 0 deletions tests/HTMLPurifier/HTMLModule/HTML5/LinkTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

class HTMLPurifier_HTMLModule_HTML5_LinkTest extends BaseTestCase
{
protected function setUp()
{
parent::setUp();

$this->config->set('Attr.AllowedRel', array('stylesheet', 'preload'));
$this->config->set('HTML.Link', array('https://localhost/foo.css'));
}

public function testClosingTag()
{
$this->assertPurification(
'<link></link>',
''
);
}

public function testSelfClosing()
{
$this->assertPurification(
'<link>',
''
);
}

public function testNoHref()
{
$this->assertPurification(
'<link rel="stylesheet">',
''
);
}

public function testNoRel()
{
$this->assertPurification(
'<link href="foo">',
''
);
}

public function testInvalidUrl()
{
$this->assertPurification(
'<link href="foo" rel="stylesheet">',
''
);
}

public function testGood()
{
$this->assertPurification(
'<link href="https://localhost/foo.css" rel="stylesheet">',
'<link href="https://localhost/foo.css" rel="stylesheet">'
);
}

public function testWhitelistCapitalised()
{
$this->assertPurification(
'<link href="https://localhost/FOO.css" rel="stylesheet">',
''
);
}

public function testGoodWithAutoclosedTag()
{
$this->assertPurification(
'<link href="https://localhost/foo.css" rel="stylesheet"></link>',
'<link href="https://localhost/foo.css" rel="stylesheet">'
);

$this->assertPurification(
'<link href="https://localhost/foo.css" rel="stylesheet" />',
'<link href="https://localhost/foo.css" rel="stylesheet">'
);
}

public function testMultiRel()
{
$this->assertPurification(
'<link href="https://localhost/foo.css" rel="stylesheet preload">',
'<link href="https://localhost/foo.css" rel="stylesheet preload">'
);
}
}

0 comments on commit fb8b327

Please sign in to comment.