例
<><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 '>';
case isset($matches[1]): return '<';
default: return $matches[0];
}
}, $text);
}
結果
<><a href="http://hogehoge.com/><><"><B><b myattr="<><>">hogehoge<i>hoge<ins>hoge</ins></i></b></B><b<b<b>>>
削除する場合
コード
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 '>';
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>hoge<ins>hoge</ins></i></b><b<b<b>>></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>