В токенизации с регулярным выражением нет ничего плохого.Но сделать полный HTML-токенайзер с регулярным выражением - это большая работа, и ее трудно понять.Я бы порекомендовал использовать правильный синтаксический анализатор, потому что вам, вероятно, все равно придется удалять теги сценариев и тому подобное.
Предполагая, что полный токенизатор не требуется, следующие регулярные выражения и код можно использовать для удаления on*
атрибуты из тегов HTML.Поскольку правильный токенизатор не используется, он будет соответствовать строкам, которые выглядят как теги даже в сценариях, комментариях, CDATA и т. Д.
Нет гарантии, что все атрибуты события будут удалены для всех входных данных /комбинации браузеров! См. примечания ниже.
Примечание о допустимости ошибок :
Браузеры обычно прощают ошибки.Из-за этого сложно маркировать теги и получать атрибуты, поскольку браузер будет их видеть при наличии «недействительных» данных.Поскольку устойчивость к ошибкам и обработка ошибок в разных браузерах различаются, невозможно найти решение, которое будет работать для них всех во всех случаях.
Таким образом : некоторые браузеры (текущие, прошлые или будущие)версия) может обрабатывать то, что мой код не считает тегом, как тег и выполнять код JS.
В своем коде я попытался имитировать токенизацию тегов (и устойчивость к ошибкам / обработку)последние версии Google Chrome.Firefox, похоже, делает это аналогичным образом.
IE 7 отличается, в некоторых случаях он не так терпим (что лучше, чем если бы он был более терпимым).(IE 6 - не пойдем туда. См. Шпаргалку по уклонению от фильтров XSS )
Соответствующие ссылки:
Код
$redefs = '(?(DEFINE)
(?<tagname> [a-z][^\s>/]*+ )
(?<attname> [^\s>/][^\s=>/]*+ ) # first char can be pretty much anything, including =
(?<attval> (?>
"[^"]*+" |
\'[^\']*+\' |
[^\s>]*+ # unquoted values can contain quotes, = and /
)
)
(?<attrib> (?&attname)
(?: \s*+
= \s*+
(?&attval)
)?+
)
(?<crap> [^\s>] ) # most crap inside tag is ignored, will eat the last / in self closing tags
(?<tag> <(?&tagname)
(?: \s*+ # spaces between attributes not required: <b/foo=">"style=color:red>bold red text</b>
(?>
(?&attrib) | # order matters
(?&crap) # if not an attribute, eat the crap
)
)*+
\s*+ /?+
\s*+ >
)
)';
// removes onanything attributes from all matched HTML tags
function remove_event_attributes($html){
global $redefs;
$re = '(?&tag)' . $redefs;
return preg_replace("~$re~xie", 'remove_event_attributes_from_tag("$0")', $html);
}
// removes onanything attributes from a single opening tag
function remove_event_attributes_from_tag($tag){
global $redefs;
$re = '( ^ <(?&tagname) ) | \G \s*+ (?> ((?&attrib)) | ((?&crap)) )' . $redefs;
return preg_replace("~$re~xie", '"$1$3"? "$0": (preg_match("/^on/i", "$2")? " ": "$0")', $tag);
}
Пример использования
Онлайн пример :
$str = '
<button onclick="..javascript instruction..">
<button onclick="..javascript instruction.." value="..">
<button onclick=..javascript_instruction..>
<button onclick=..javascript_instruction.. value>
<hello word "" ontest = "hai"x="y"onfoo=bar/baz />
';
echo $str . "\n----------------------\n";
echo remove_event_attributes($str);
Выход:
<button onclick="..javascript instruction..">
<button onclick="..javascript instruction.." value="..">
<button onclick=..javascript_instruction..>
<button onclick=..javascript_instruction.. value>
<hello word "" ontest = "hai"x="y"onfoo=bar/baz />
----------------------
<button >
<button value="..">
<button >
<button value>
<hello word "" x="y" />