Regex vs. strip_tags()

Обнаружил дырку в комментариях. Тэги фильтровались с помощью strip_tags(), который не следит за атрибутами, что давало возможность используя разрешенные тэги делать неразрешенные вещи:

<b style="color: #f00">red bold text</b>

<a href="#" onclick="return false &(document.title='whatever')">
click here to change title
</a>

Пришлось писать свой регекс, который выкидывает все лишние атрибуты у тегов. Получилось вот что:

$t = preg_replace (
'/\<( *)(\S+?)(?(?<=\<a)fuckoff) (.+?)\>/si',
'<\\2>',
$t);

Тут фишка в том, что атрибуты выкидываются у всех тэгов, кроме <a>, так как у него у единственного есть нужный и важный атрибут href. Регекс работает так:

  • \<( *)(\S+?) Начало тэга: знак «меньше»; возможно, пробелы и как минимум один не пробел;
  • (?(?<=\<a)fuckoff) Проверка, вдруг это тэг <a>, тогда заставляем matcher найти ещё и fuckoff (которого нет);
  • (.+?)\> Всевозможная другая фигня.

Вот. Потом отдельно парсится <a> на предмет возможных «javascript:» и т. п. Регексы, разумеется, рулят.

Дальше
Мои книги