Skip to content

ホワイトリストによる要素名と属性のチェックを行うHTMLフィルターです。 HTMLバリデーションは行いません。

License

Notifications You must be signed in to change notification settings

esperecyan/html-filter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HTMLフィルター

ホワイトリストによる要素名と属性のチェックを行うHTMLフィルターです。 HTMLバリデーションは行いません。

<?php
require_once 'vendor/autoload.php';

use esperecyan\webidl\TypeError;
use esperecyan\url\URL;

$filter = new \esperecyan\html_filter\Filter([
    '*' => [
        'dir' => ['ltr', 'rtl', 'auto'],
        'lang' => '/^[a-z]+(-[0-9a-z]+)*$/iu',
        'title',
        'translate' => ['', 'yes', 'no'],
    ],
    'a' => ['href' => 'isURLWithNetworkScheme'],
    'br',
    'img' => ['alt', 'src' => 'isURLWithNetworkScheme'],
    'p',
    'time' => 'datetime',
]);
$filter->setLogger(new class extends \Psr\Log\AbstractLogger {
    public function log($level, $message, array $context = []) {
        echo "$level: $message\n";
    }
});
var_dump($filter->filter(<<<'EOD'
<script>
    window.alert('foobar');
</script>
<a href="https://example.com/">例示用ドメイン</a>
<a href="./file.html" title="テスト">相対URL</a>
<bR data-clear="">
<p dir="ltr" lang='"invalid"'>アリス</p>
<p dir="LtR" LanG='ja'>ボブ</p>
EOD
));

function isURLWithNetworkScheme(string $value): bool {
    try {
        $url = new URL($value);
    } catch (TypeError $exception) {
        return false;
    }
    return in_array($url->protocol, ['ftp:', 'http:', 'https:']);
}

上の例の出力は以下となります。

notice: <script> タグの使用は許可されていません。
notice: <a> タグの href 属性値 "./file.html" は許可されていません。
notice: <br> タグの data-clear 属性の使用は許可されていません。
notice: <p> タグの lang 属性値 "&quot;invalid&quot;" は許可されていません。
notice: <p> タグの dir 属性値 "LtR" は許可されていません。
example.php:33:
string(179) "
    window.alert('foobar');

<a href="https://example.com/">例示用ドメイン</a>
<a title="テスト">相対URL</a>
<br />
<p dir="ltr">アリス</p>
<p lang="ja">ボブ</p>"

インストール

composer require esperecyan/html-filter

Composer のインストール方法については、Composer のグローバルインストール - Qiitaなどをご覧ください。

要件

  • PHP 7.0 以上

使い方

esperecyan\html_filter\Filterコンストラクタの第1引数に、ホワイトリストを与えます。 インスタントのfilterメソッドの第1引数に入力文字列を与えると、HTMLとしてもXHTMLとしても扱える文字列を返します。

当ライブラリは、body要素の子孫としての断片的なHTMLしか扱えません。 また、xmlns属性を含む文書は正常に取り扱うことができず、 http://www.w3.org/1999/xhtml 以外の名前空間を持つ要素 (svg要素、math要素)、およびその子孫は強制的に取り除かれます。 また、コメントなども取り除かれます。

ホワイトリスト

$whitelistの例 説明
['em', 'strong'] em要素とstrong要素を許可し、属性は一切許可しません。
['a' => 'href', 'em', 'strong'] a要素とem要素とstrong要素を許可し、a要素に限りhref属性を許可します。
['a' => ['href', 'title']] a要素を許可し、a要素のhref属性とtitle属性を許可します。
['a' => ['href' => '#^https://#u'] a要素を許可し、正規表現 (PCRE) のパターン「#^https://#u」に合致するhref属性のみを許可します。
[['span' => ['class' => ['foo', 'bar', 'foo bar']]]] span要素を許可し、属性値が「foo」「bar」「foo bar」のいずれかに完全一致するclass属性のみを許可します。(文字大小区別)
[['*' => ['id' => function (string $id): bool { return !in_array($id, ['foo', 'bar']); }], 'h1', 'h2', 'h3'] h1要素とh2要素とh3要素を許可し、コールバック関数が真を返すid属性のみを許可します。
null フィルタリングを行わず、整形のみを行います。(※コメントなどの強制的な除去を除く)

コメントは常にフィルタリング対象となります。

オプション

esperecyan\html_filter\Filterコンストラクタの第2引数に連想配列で与えます。 各オプションにnullを与えた場合、指定は無視されます。

キー
before フィルタリング処理前 (HTMLの構文解析後) の文書木に対して処理を行うコールバック関数を指定します。第1引数でbody要素のDOMElementを受け取ります。この関数が false (同じ型) を返した場合、そこで処理を停止し、filterメソッドはから文字列を返します。
after フィルタリング処理後 (HTMLの直列化前) の文書木に対して処理を行うコールバック関数を指定します。他は before と同じです。

ロギング

esperecyan\html_filter\FilterPSR-3: Logger InterfacePsr\Log\LoggerAwareInterfaceを実装しています。

ログレベル 説明・例
Psr\Log\LogLevel::ERROR HTMLとして読み込めなかった場合。
Psr\Log\LogLevel::WARNING masterminds/html5が処理したエラー。 < に対応する > が無いなど、HTMLとして壊れている場合。
Psr\Log\LogLevel::NOTICE フィルタリングを行った場合。

Psr\Log\LogLevel::NOTICEの場合のコンテキスト

キー
node 対象のノードの型を表す定数。整数。
element 対象の要素名。
attribute フィルタリング対象が属性である場合、その属性名。
value フィルタリング対象が属性である、かつ属性値が規則に合致しないためにフィルタリングされた場合、その属性値。

注意

まったくログが発せられなくとも、入力をXHTMLとしては取り扱えない場合があります。 XHTMLとして埋め込む場合、出力時にはesperecyan\html_filter\Filter->filter()を通してください。

<?php
$filter = new \esperecyan\html_filter\Filter(['a', 'blockquote', 'code', 'h1', 'h2', 'pre']);
$filter->setLogger(new class extends \Psr\Log\AbstractLogger {
    public function log($level, $message, array $context = []) use ($logged) {
        $logged = true;
    }
});
$output = $filter->filter($input);

$storage = $logged ? $output : $input;
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>XHTML文書</title>
    </head>
    <body>
        <?= (new \esperecyan\html_filter\Filter())->filter($storage) ?>
    </body>
</html>

Contribution

Pull Request、または Issue よりお願いいたします。

セマンティック バージョニング

当ライブラリはセマンティック バージョニングを採用しています。 パブリックAPIは、esperecyan\html_filter\Filterクラスのpublicメソッドのみです。

ライセンス

当ライブラリのライセンスは Mozilla Public License Version 2.0 (MPL-2.0) です。

About

ホワイトリストによる要素名と属性のチェックを行うHTMLフィルターです。 HTMLバリデーションは行いません。

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages