Удалить атрибуты событий * JS из тегов HTML - PullRequest
2 голосов
/ 27 февраля 2012

Пожалуйста, помогите разобрать в 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>

Мне нужно делать это без кавычек и с, потому что все современные браузеры позволяют делать атрибуты без кавычек.

Примечание: Я должен анализировать не только по нажатию кнопки ... это все атрибуты, которые начинаются с 'on'.

Примечание (2): НЕ ПЫТАЙТЕСЬ СОВЕТИТЬ ПАРСЕРУ HTML, ПОТОМУ ЧТО ЭТО БУДЕТ ОЧЕНЬ БОЛЬШОЙ DREE TREE ДЛЯ PARSE ..

ОБНОВЛЕНО : Спасибо за Ваш ответ!Теперь я использую компонент HTMLPurifier на написанном мной небольшом фреймворке.

Ответы [ 2 ]

5 голосов
/ 27 февраля 2012

В токенизации с регулярным выражением нет ничего плохого.Но сделать полный 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"   />
4 голосов
/ 27 февраля 2012

Возможно, вам лучше использовать DOMDocument.

Вы можете использовать его для перебора дерева DOM, представленного HTML-файлом, который вы пытаетесь проанализировать, ища различные атрибуты on *, которые вы хотите удалить.

Скорее всего, этот подход будет успешным, потому что DOMDocument фактически понимает семантику HTML-файла, в то время как регулярное выражение является просто синтаксическим анализатором строк и не подходит для надежного анализа HTML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...