Как стать автором
Обновить

Комментарии 20

Для данной задачи лучше не использовать чёрный список, т.к. слишком высока вероятность того, что что-то будет упущенно, а также потребуется переодически дополнять его.

Также, иногда для атак используются незакрытые теги или теги с незакрытыми аттрибутами, которые исправляет уже браузер. Скорее всего, решение с loadHTML не сможет обработать такие ситуации.
НЛО прилетело и опубликовало эту надпись здесь
Тут скорее вопрос полезности комбинации множества решений, когда есть тот же HTML Purifier и аналоги.
Статья описывает интересный подход к решению проблемы, который будет сложно применить на практике.
С моей точки зрения полезность предлагаемого решения в его универсальности — XSLT это универсальное средство, которое может быть применено на почти любом языке программирования, в почти любом фреймворке и не требует для понимания дополнительных знаний кроме знания XSLT.

Можно сказать что по сравнению с HTML Purifier и аналогами это то же самое что и XSLT-шаблоны по сравнению со Smarty и аналогами.
Белые списки не могут описать все нюансы, например использование зловредного кода внутри разрешённого href. А раз так, и всё равно придётся использовать чёрные списки, то можно обойтись только ими, либо использовать и то, и другое.
Можно требовать чтобы href начинался с разрешенного списка префиксов, например http:// https:// ftp:// и // — это тоже вид белого списка. Да теряем, например, ссылки вида torrent:// но для ряда проектов это может быть некритично.
Если вам на вход придет html-документ, не являющийся валидным xml, xslt шаблон не сможет его преобразовать, и это большая проблема.

Наиболее частые проблемы, из-за которых html документ может оказаться невалидным xml (но при этом валидным html)
  • незакрытые теги переноса строки (<br> вместо <br />)
  • незакрытые изображения, input и т.д. (<img src=""> вместо <img src="" />)
  • аттрибуты без значений (<option selected /> вместо <option selected="selected" />)
  • неопределенные сущности (&nbsp; вместо &#160;)
  • символ <, который не открывает тег (например <script> if(a < b)</script> вместо <script> if(a &lt; b)</script>)


Любая из этих проблем порушит ваш xslt-фильтр, при этом в принципе все они достаточно часто встречаются в коде, который генерируется визивиг-редакторами.
Привести невалидный документ к валидному не очень сложно, и после этого уже проходится xslt — Вам же в любом случае нужен валидный HTML на страничке, так?

Я это делаю с помощью SAX парсера (а можно делать и кучей других уже готовых вариантов). принцип простой:
  1. получили открывающй элемент, положили в стэк
  2. встретили открывающий элемент, который не должен пресекаться с верхнем элементом стэка — закрыли его, убрали со стэка, положили в стэк новый
  3. иначе просто положили в стэк новый
  4. при встрече закрывающего элемента, не совпадающего с верхнем элементом стэка — пропустили его
  5. иначе убрали со стэка


Вобщем както так )
Описанный принцип реализует только закрытие незакрытых элементов (2 проблемы из 5).

Понятно, что привести HTML документ к xHTML в автоматическом режиме вполне возможно (есть даже уже написанные конвертеры, например на JS), вопрос в том, насколько оправдано поддерживать целый html -> xhtml конвертер ради такой простой задачи как фильтрация «опасных» тегов и аттрибутов в пользовательском вводе.

На мой взгляд, для большинства прикладных задач — неоправданно.

Вам же в любом случае нужен валидный HTML на страничке, так?

Так я поэтому в первом комментарии и заметил что ни одна из обохзначенных мной проблем не делает html невалидным.
Я считаю что приводить пользовательский ввод к XHTML вполне оправданно. Это позволяет как минимум отдавать полностью корректный HTML в браузеры. Я знаю что стандарт HTML не требует закрытия всех тегов и обязательного использования кавычек для значений атрибутов, например, но такое преобразования позволяет гарантировать корректность отдаваемого посетителю документа и минимизировать возможные проблемы.

Возможно я идеалист, но пока убедительных для меня доводов против использования XHTML я не встречал.
Ну, неужели я должен был полностью листинг привести? :-D
Я показал пример как привести тэги — это самое сложное из всего перечисленного — все остальное реализуется регспами в пару строчек. Честно :)
Верю :-)

Но автор предложил решение лучше, без использования самописных парсеров и регулярок, пользоваться стандартными методами php (loadHtml)
Насколько понимаю, в PHP loadHTML фиксит некорректный html и выдает на выходе корректное DOM-дерево к которому xslt применяется без проблем. По крайней мере распространенные проблемы (отсутствие закрывающих тегов и т.п.) он обрабатывает точно, хотя специально я его не ломал.

В других языках программирования HTML тоже есть библиотеки, способные разобрать «поломанный» HTML и построить корректный DOM.

Да, вы правы.

Упустил момент что шаблон применяется к вводу, который загружен с использованием loadHTML
Имхо, тут имеет смысл двигаться от обратного: не описывать исключения, а обрабатывать лишь те элементы, которые нам нужны, посылая всё остальное либо в «мусор» либо в простой текстовый вывод.

Например, у нас таким образом выводится весь контент (как пользовательский, так и редакционный): если в каком-то месте проекта не предполагается вывод ссылок, то неважно, кто их добавил — они будут проигнорированы, и выведется только содержание текста ссылки.

Хотя, у всех задачи разные. И спасибо за rel=«nofollow» — отличное решение. Мне почему-то не приходило в голову, что можно внешним ссылкам ставить этот атрибут. :)
Исключительно проблема движков, которые зачем–то используют HTML вместо bbCode, Creole и т. п.
Ну, например, diary.ru разрешает использовать html. Многие wysiwyg редакторы отдают на выходе html, а не bbcode. Поэтому я бы не сказал что это проблема только движков. Но и bbcode, к сожалению, не панацея — как он поможет если нужно гибко настроить разрешения — обычные пользователи могут использовать ограниченный набор тегов, модераторы — расширенный, администраторы — без ограничений? Все равно фильтрация в той или иной форме потребуется.
Вот в X-Wiki, которую я применяю, WYSIWIG тоже отдаёт HTML. Ну так его и конвертировать надо в нормальный формат. И конвертируется, и работает. И в IPB 3, и в X-Wiki.

Произвольный HTML и скрипты в X-Wiki тоже можно вставлять, но если его просто так вставить, он при преобразовании в X-Wiki прожуётся и выкинется. В самом редакторе сделаны крючки для плагинов так, чтобы блок, рендерящийся плагином, нельзя было редактировать в WYSIWIG на уровне гипертекста, можно было только редактировать его через меню WYSIWIG. Например, «содержание» или «сноски» — такие блоки, рендерящиеся плагинами, и редактировать их нельзя. HTML — тоже такой блок, и редактирование его напрямую невозможно, можно только в меню редактирования блока зайти и там писать чистый HTML.

bbCode, сколько я его видел, очень замечательно настраивается на права. Несанкционированные теги просто не обрабатываются при показе конечного текста. В некоторых разделах форума нельзя делать гиперссылки — типичный пример. То же и в X-Wiki. Некоторые блоки отображаются только, если страницу написал администратор.
Конструкцию choose-when-otherwise лучше по возможности не применять. На мой взгляд конечно. Т.к. элемент <xsl:template match="..."> уже является кейсом.
Да, наверное вы правы. У меня еще немного опыта с XSLT, поэтому кое-что сделал достаточно прямолинейно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации