Switch to html-sanitizer (issue #92)

Squashed commit of the following:

commit 504fb82beea5eff26591e117496d41c88f3737e4
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Jan 25 16:59:05 2019 +0000

    Fix coding style issue

commit 0ae14f0d90f131d65894abdc36f787032c7c97db
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Jan 25 16:57:26 2019 +0000

    html-sanitizer output differs slightly from HTMLPurifier

commit c5912312e0c8a41dbd7f7e52489e516d9784bc26
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Jan 25 16:56:54 2019 +0000

    Use html-sanitizer instead of HTMLPruifier, consolidate logic into a trait

commit 563b5b5ae8e2ef9c5aeb87214acab8fa9b0683ce
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Jan 25 16:56:10 2019 +0000

    Add html-sanitizer instead of HTMLPurifier
This commit is contained in:
Jonny Barnes 2019-01-25 17:21:32 +00:00
parent 427b79f278
commit ae77ef3423
6 changed files with 211 additions and 87 deletions

View file

@ -5,12 +5,13 @@ declare(strict_types=1);
namespace App\Models;
use Mf2;
use HTMLPurifier;
use HTMLPurifier_Config;
use App\Traits\FilterHtml;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
use FilterHtml;
protected $fillable = ['url'];
/**
@ -48,27 +49,11 @@ class Like extends Model
$mf2 = Mf2\parse($value, $this->url);
if (array_get($mf2, 'items.0.properties.content.0.html')) {
return $this->filterHTML(
return $this->filterHtml(
$mf2['items'][0]['properties']['content'][0]['html']
);
}
return $value;
}
/**
* Filter some HTML with HTMLPurifier.
*
* @param string $html
* @return string
*/
private function filterHTML(string $html): string
{
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.SerializerPath', storage_path() . '/HTMLPurifier');
$config->set('HTML.TargetBlank', true);
$purifier = new HTMLPurifier($config);
return $purifier->purify($html);
}
}

View file

@ -6,14 +6,15 @@ namespace App\Models;
use Cache;
use Twitter;
use HTMLPurifier;
use HTMLPurifier_Config;
use App\Traits\FilterHtml;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Database\Eloquent\Model;
use Jonnybarnes\WebmentionsParser\Authorship;
class WebMention extends Model
{
use FilterHtml;
/**
* The database table used by the model.
*
@ -92,7 +93,7 @@ class WebMention extends Model
}
$microformats = json_decode($this->mf2, true);
if (isset($microformats['items'][0]['properties']['content'][0]['html'])) {
return $this->filterHTML($microformats['items'][0]['properties']['content'][0]['html']);
return $this->filterHtml($microformats['items'][0]['properties']['content'][0]['html']);
}
return null;
@ -130,20 +131,4 @@ class WebMention extends Model
return $url;
}
/**
* Filter the HTML in a reply webmention.
*
* @param string $html
* @return string
*/
private function filterHTML(string $html): string
{
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.SerializerPath', storage_path() . '/HTMLPurifier');
$config->set('HTML.TargetBlank', true);
$purifier = new HTMLPurifier($config);
return $purifier->purify($html);
}
}

24
app/Traits/FilterHtml.php Normal file
View file

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\Traits;
use HtmlSanitizer\Sanitizer;
trait FilterHtml
{
public function filterHtml(string $html): string
{
return Sanitizer::create([
'extensions' => [
'basic',
'code',
'image',
'list',
'table',
'extra',
],
])->sanitize($html);
}
}

View file

@ -7,7 +7,6 @@
"require": {
"php": ">=7.2.0",
"cviebrock/eloquent-sluggable": "~4.3",
"ezyang/htmlpurifier": "~4.6",
"fideloper/proxy": "~4.0",
"guzzlehttp/guzzle": "~6.0",
"indieauth/client": "~0.1",
@ -31,6 +30,7 @@
"sensiolabs/security-checker": "^5.0",
"spatie/browsershot": "~3.0",
"spatie/commonmark-highlighter": "^1.0",
"tgalopin/html-sanitizer": "^1.1",
"thujohn/twitter": "~2.0"
},
"require-dev": {

225
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "e64d4d2f1552ebf50112a6122f6ee690",
"content-hash": "7b2e4aa6adaf2233e1a256802d898d0f",
"packages": [
{
"name": "aws/aws-sdk-php",
@ -922,53 +922,6 @@
],
"time": "2018-03-08T01:11:30+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "d85d39da4576a6934b72480be6978fb10c860021"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021",
"reference": "d85d39da4576a6934b72480be6978fb10c860021",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"require-dev": {
"simpletest/simpletest": "^1.1"
},
"type": "library",
"autoload": {
"psr-0": {
"HTMLPurifier": "library/"
},
"files": [
"library/HTMLPurifier.composer.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"time": "2018-02-23T01:58:20+00:00"
},
{
"name": "fideloper/proxy",
"version": "4.1.0",
@ -2599,6 +2552,138 @@
],
"time": "2018-12-22T17:56:55+00:00"
},
{
"name": "league/uri-parser",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-parser.git",
"reference": "671548427e4c932352d9b9279fdfa345bf63fa00"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-parser/zipball/671548427e4c932352d9b9279fdfa345bf63fa00",
"reference": "671548427e4c932352d9b9279fdfa345bf63fa00",
"shasum": ""
},
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.0",
"phpstan/phpstan": "^0.9.2",
"phpstan/phpstan-phpunit": "^0.9.4",
"phpstan/phpstan-strict-rules": "^0.9.0",
"phpunit/phpunit": "^6.0"
},
"suggest": {
"ext-intl": "Allow parsing RFC3987 compliant hosts",
"league/uri-schemes": "Allow validating and normalizing URI parsing results"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Uri\\": "src"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ignace Nyamagana Butera",
"email": "nyamsprod@gmail.com",
"homepage": "https://nyamsprod.com"
}
],
"description": "userland URI parser RFC 3986 compliant",
"homepage": "https://github.com/thephpleague/uri-parser",
"keywords": [
"parse_url",
"parser",
"rfc3986",
"rfc3987",
"uri",
"url"
],
"time": "2018-11-22T07:55:51+00:00"
},
{
"name": "masterminds/html5",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/Masterminds/html5-php.git",
"reference": "b5d892a4bd058d61f736935d32a9c248f11ccc93"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/b5d892a4bd058d61f736935d32a9c248f11ccc93",
"reference": "b5d892a4bd058d61f736935d32a9c248f11ccc93",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-dom": "*",
"ext-libxml": "*",
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35",
"sami/sami": "~2.0",
"satooshi/php-coveralls": "1.0.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
}
},
"autoload": {
"psr-4": {
"Masterminds\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matt Butcher",
"email": "technosophos@gmail.com"
},
{
"name": "Asmir Mustafic",
"email": "goetas@gmail.com"
},
{
"name": "Matt Farina",
"email": "matt@mattfarina.com"
}
],
"description": "An HTML5 parser and serializer.",
"homepage": "http://masterminds.github.io/html5-php",
"keywords": [
"HTML5",
"dom",
"html",
"parser",
"querypath",
"serializer",
"xml"
],
"time": "2018-12-27T22:03:43+00:00"
},
{
"name": "mf2/mf2",
"version": "0.4.6",
@ -5181,6 +5266,50 @@
],
"time": "2019-01-03T09:07:35+00:00"
},
{
"name": "tgalopin/html-sanitizer",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/tgalopin/html-sanitizer.git",
"reference": "286e4f3d13cf0294d968a6022647e5d6bc708b60"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tgalopin/html-sanitizer/zipball/286e4f3d13cf0294d968a6022647e5d6bc708b60",
"reference": "286e4f3d13cf0294d968a6022647e5d6bc708b60",
"shasum": ""
},
"require": {
"ext-dom": "*",
"league/uri-parser": "^1.4.1",
"masterminds/html5": "^2.4",
"php": ">=7.1",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^7.4",
"symfony/var-dumper": "^4.1"
},
"type": "library",
"autoload": {
"psr-4": {
"HtmlSanitizer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Titouan Galopin",
"email": "galopintitouan@gmail.com"
}
],
"description": "Sanitize untrustworthy HTML user input",
"time": "2018-12-01T15:16:40+00:00"
},
{
"name": "themattharris/tmhoauth",
"version": "0.8.4",

View file

@ -39,6 +39,7 @@ class LikesTest extends TestCase
HTML;
$htmlFiltered = <<<HTML
<p>Hello</p>
<img />
HTML;
$like = new Like();
$like->url = 'https://example.org/post/123';