LoginSignup
4
5

More than 5 years have passed since last update.

特定のHTMLタグのみ表示を許可する

Last updated at Posted at 2013-07-12

<><a href="http://hogehoge.com/><><"><B><b myattr="<><>">hogehoge<i>hoge<ins>hoge</ins></i></b></B><b<b<b>>>

に対して、タグ a, b, i を許可する

CASE1: Tidyが使えない場合

※ タグの入れ子が正しいかどうかを考慮していません

HTMLエンティティに置換する場合

コード
function filter_text($text, $allow_tags = array()) {

    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(<)|(>)@i";
    return preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[2]): return '&gt;';
            case isset($matches[1]): return '&lt;';
            default:                 return $matches[0];
        }
    }, $text);

}
結果
&lt;&gt;<a href="http://hogehoge.com/><><"><B><b myattr="<><>">hogehoge<i>hoge&lt;ins&gt;hoge&lt;/ins&gt;</i></b></B>&lt;b&lt;b<b>&gt;&gt;

削除する場合

コード
function filter_text($text, $allow_tags = array()) {

    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(</[\\w-]++ *+>|<[\\w-]++{$attr}*+ *+/? *+>|<[^<>]*+>|[<>])@i";
    return preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[1]): return '';
            default:                 return $matches[0];
        }
    }, $text);

}
結果
<a href="http://hogehoge.com/><><"><B><b myattr="<><>">hogehoge<i>hogehoge</i></b></B>bb<b>

CASE2: Tidyが使える場合

php_tidy.dll は php.ini の設定で有効化することが出来ます。
Tidyを使えば、不足している閉じタグを適切に補正してくれます。
また、存在しない属性もカットしてくれます。
ついでにhref属性内の未エンコード文字を自動的にURLエンコードしてくれます。

HTMLエンティティに置換する場合

コード
function filter_text($text, $allow_tags = array()) {

    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(<)|(>)@i";
    $text = preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[2]): return '&gt;';
            case isset($matches[1]): return '&lt;';
            default:                 return $matches[0];
        }
    }, $text);
    $tidy = new Tidy;
    return $tidy->repairString($text, array(
        'wrap'           => 0    ,
        'show-body-only' => true ,
    ), 'utf8');

}
結果
&lt;&gt;<a href="http://hogehoge.com/%3E%3C%3E%3C"><b>hogehoge<i>hoge&lt;ins&gt;hoge&lt;/ins&gt;</i></b>&lt;b&lt;b<b>&gt;&gt;</b></a>

削除する場合

コード
function filter_text($text, $allow_tags = array()) {

    $tags = implode('|', $allow_tags);
    $attr = '(?: ++[\\w-]++(?:=(?:[\\w-]++|"[^"]*+"|\'[^\']*+\'))?+)';
    $keep = $tags !== '' ?
        "</(?:{$tags}) *+>|<(?:{$tags}){$attr}*+ *+/? *+>|":
        ''
    ;
    $pattern = "@{$keep}(</[\\w-]++ *+>|<[\\w-]++{$attr}*+ *+/? *+>|<[^<>]*+>|[<>])@i";
    $text = preg_replace_callback($pattern, function ($matches) {
        switch (true) {
            case isset($matches[1]): return '';
            default:                 return $matches[0];
        }
    }, $text);
    $tidy = new Tidy;
    return $tidy->repairString($text, array(
        'wrap'           => 0    ,
        'show-body-only' => true ,
    ), 'utf8');

}
結果
<a href="http://hogehoge.com/%3E%3C%3E%3C"><b>hogehoge<i>hogehoge</i></b>bb</a>
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5