Пожалуйста, помогите разобрать в PHP простые строки html (php regexp). Мне нужно удалить html-js-события из html-кода. Я знаю, что регулярные выражения php очень плохие.
Примеры кода:
<button onclick="..javascript instruction..">
Результат: <button>
<button onclick="..javascript instruction.." value="..">
Результат: <button value="..">
<button onclick=..javascript instruction..>
Результат: <button>
<button onclick=..javascript instruction.. value>
Результат: <button value>
Мне нужно сделать это без кавычек и с, потому что все современные браузеры позволяют делать атрибуты без клятв.
Примечание. Я не изучал синтаксический анализ не только onclick .. это все атрибуты, начинающиеся с «on».
Примечание (2): НЕ ПОПРОБУЙТЕ СОВЕТУ HTML PARSER, ПОТОМУ ЧТОБЫ БУДЕТ ОЧЕНЬ БОЛЬШОЙ ДОМА ДЛЯ ДОМА.
ОБНОВЛЕНО : Спасибо, за ваш ответ! Теперь я использую компонент HTMLPurifier, написанный мной небольшим фреймворком.
Нет ничего плохого в токенизации с регулярным выражением. Но создание полноценного HTML-токенизатора с регулярным выражением – это большая работа и трудно получить право. Я бы рекомендовал использовать правильный синтаксический анализатор, потому что вам, вероятно, потребуется удалить теги скриптов и так далее.
Предполагая, что полный токенизатор не нужен, следующее выражение и код можно использовать для удаления атрибутов on*
из тегов HTML. Поскольку правильный токенизатор не используется, он будет соответствовать строкам, которые выглядят как теги даже в сценариях, комментариях, CDATA и т. Д.
Нет гарантии, что все атрибуты событий будут удалены для всех комбинаций ввода / браузера! См. Примечания ниже.
Обратите внимание на допуски ошибок :
Браузеры обычно прощают ошибки. Из-за этого трудно маркировать теги и получать атрибуты, поскольку браузер увидит их, когда присутствуют «недействительные» данные. Поскольку погрешность и обработка различаются между браузерами, невозможно создать решение, которое работает для них во всех случаях.
Таким образом : Некоторые браузеры (текущая, прошлая или будущая версия) могут обрабатывать то, что мой код не считает тегом, как тегом, и выполнять JS-код.
В моем коде я попытался имитировать токенизацию тегов (и допустимость / обработку ошибок) последних версий Google Chrome. Firefox, похоже, делает это аналогичным образом.
IE 7 отличается, в некоторых случаях он не является толерантным (что лучше, чем если бы оно было более терпимым). (IE 6 – не позволяет туда попасть. См. XSS Filter Evasion Cheat Sheet )
Соответствующие ссылки:
$redefs = '(?(DEFINE) (?<tagname> [az][^\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" />
Возможно, вам лучше использовать DOMDocument.
Вы можете использовать его для итерации по дереву DOM, представленному файлом HTML, который вы пытаетесь проанализировать, ищите различные атрибуты *, которые вы хотите удалить.
Этот подход с большей вероятностью преуспеет, потому что DOMDocument действительно понимает семантику HTML-файла, тогда как регулярное выражение – просто нечетный синтаксический анализатор строк и неадекватно для надежного анализа HTML.