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:» и т. п. Регексы, разумеется, рулят.