Комментарии 86
А мысль-то свежа...
так еще можно добиться w3c валидности
можно просто преобразовать в DOMDocument
А что если будет два неверно вложенных тега..?
А что если будет два неверно вложенных тега..?
Предварительно tidy надо бы ещё применить, а то парсинг не пройдет
НЛО прилетело и опубликовало эту надпись здесь
1. strip_tags не могут удалить у
2. регулярки для вырезания тегов выглядят очень устрашающе.
3. в PHP5 DOM встроен в ядро PHP, в отличие от SafeHTML.
А здесь мы имеем построенный (распарсеный) на сервере DOM, из которого мы удобно удаляем все что нам не надо, не боясь что регулярка пропустит какую-то новую хитрую HTML инструкцию.
2. регулярки для вырезания тегов выглядят очень устрашающе.
3. в PHP5 DOM встроен в ядро PHP, в отличие от SafeHTML.
А здесь мы имеем построенный (распарсеный) на сервере DOM, из которого мы удобно удаляем все что нам не надо, не боясь что регулярка пропустит какую-то новую хитрую HTML инструкцию.
strip_tags не могут удалить <img src="..." onclick="..." />
А там на сервере дом парсится не регулярками штоле, а волшебным заклятьем? У волшебного заклятья есть 100% гарантия надежности?
Опять двадцать пять....
Самоцель этого метода не в том чтобы починить неверный HTML, а в том чтобы упростить процедуру удаления из него опасных элементов.
1. Для адекватной работы такого подхода мы должны иметь более менее нормально размеченый HTML на входе. Видимо пришедший в WYSIWYG редактора.
2. Первичный DOM строится в памяти сервера и никакие опасные конструкции не могут там ничего сделать. Затем он очищается от ненужных тегов и аттрибутов, при необходимости модифицируется, а затем сохраняется как XML.
Самоцель этого метода не в том чтобы починить неверный HTML, а в том чтобы упростить процедуру удаления из него опасных элементов.
1. Для адекватной работы такого подхода мы должны иметь более менее нормально размеченый HTML на входе. Видимо пришедший в WYSIWYG редактора.
2. Первичный DOM строится в памяти сервера и никакие опасные конструкции не могут там ничего сделать. Затем он очищается от ненужных тегов и аттрибутов, при необходимости модифицируется, а затем сохраняется как XML.
Вы в самом деле считаете, что регулярными выражениями можно удалить теги из документа?
DOM — это хорошо, если б ещё без багов. Впрочем, с такой простой задачей DOM-расширение PHP5 вполне справится.
Нужно ещё не забыть перед созданием DOM-документа добавить в начало исходного HTML-кода корректный DOCTYPE, дабы на выходе не появилось сюрпризов типа <br></br>, <hr></hr> и т. д.
Нужно ещё не забыть перед созданием DOM-документа добавить в начало исходного HTML-кода корректный DOCTYPE, дабы на выходе не появилось сюрпризов типа <br></br>, <hr></hr> и т. д.
про DOCTYPE, так как используется saveXML, то
, полностью исключены.
, полностью исключены.
<br></br> <hr></hr>
Я б не писал, если б не сталкивался. ;-)
так я проверил прежде чем писать. :)
Сейчас, к сожалению, указанный мною результат воспроизвести не могу, но в процессе экспериментов с DOM-расширением он точно проскакивал. В данном же случае без DOCTYPE происходит не менее некорректное закрытие пустых элементов в XML-стиле:
<div></div> → <div/>
<p></div> → <p/>
и т.д.
После добавления DOCTYPE элементы начинают закрываться корректно (в соответствии с DTD): <br />, <hr />, но <div></div>, <p></p> и т. д.
<div></div> → <div/>
<p></div> → <p/>
и т.д.
После добавления DOCTYPE элементы начинают закрываться корректно (в соответствии с DTD): <br />, <hr />, но <div></div>, <p></p> и т. д.
очепятка:
<p></p> → <p/>
<p></p> → <p/>
А зачем вам пустые дивы и абазацы? В моей cleanNode я просто их удаляю.
Но за информацию про DOCTYPE спасибо, позже я добавлю ее в текст топика.
Но за информацию про DOCTYPE спасибо, позже я добавлю ее в текст топика.
его вовсе не обязательно парсить
а что, как вы думаете, делает объект DOMDocument? Не парсит? Угадывает?
хотя, конечно, если закрыть глаза на производительность…
Естественно угадывает! А как же иначе.
Я даже не знаю что вам ответить. Бессмысленность вашего комментария поразила.
Я даже не знаю что вам ответить. Бессмысленность вашего комментария поразила.
Красивое.
Но иногда отсутствие уязвимостей не так очевидно, каким может показаться. Неужели такое решение никак не обойти и не сломать? :)
Но иногда отсутствие уязвимостей не так очевидно, каким может показаться. Неужели такое решение никак не обойти и не сломать? :)
Абсолютно авторитетно автору темы хочу заявить, что его метод работать НЕ будет.
Проблема в том, что настоящий парсер HTML-кода должен уметь парсить НЕ правильный html-код, т.е. такой код, где есть ошибки... DOM не сможет распарсить XML с ошибками и поэтому он совершенно не поможет, а вот любой браузер HTML-код с ошибкой все же выведет.
В результате использования DOM-модели при проверке тегов у злоумышленника откроются огромные возможности по "запудриванию" HTML-кода с целью вставки туда вредоносного кода.
На языке Perl есть модуль HTML::TreeBuilder, который отлично парсит любой HTML-код (даже с ошибками). На PHP подобного модуля я так и не нашел, хотя много раз искал.
Др. метод - если у тебя Windows-сервер - использовать DOM-модель браузера Explorer, тогда точно правильно HTML-код распарсишь.
P.S. Несколько строчек PHP-кода с регулярными выражениями так же совершенно не помогут правильно распарсить неправильный HTML-код. Это задача доволно сложная.
Проблема в том, что настоящий парсер HTML-кода должен уметь парсить НЕ правильный html-код, т.е. такой код, где есть ошибки... DOM не сможет распарсить XML с ошибками и поэтому он совершенно не поможет, а вот любой браузер HTML-код с ошибкой все же выведет.
В результате использования DOM-модели при проверке тегов у злоумышленника откроются огромные возможности по "запудриванию" HTML-кода с целью вставки туда вредоносного кода.
На языке Perl есть модуль HTML::TreeBuilder, который отлично парсит любой HTML-код (даже с ошибками). На PHP подобного модуля я так и не нашел, хотя много раз искал.
Др. метод - если у тебя Windows-сервер - использовать DOM-модель браузера Explorer, тогда точно правильно HTML-код распарсишь.
P.S. Несколько строчек PHP-кода с регулярными выражениями так же совершенно не помогут правильно распарсить неправильный HTML-код. Это задача доволно сложная.
Абсолютно авторитетно заявляю, что этот код 100% рабочий и проверенный лично. Как вы совершенно правильно сказали XML с ошибками не парсится, а HTML - да. О чем я и написал в комментариях.
Я еще раз уточняю что основная цель этого примера, не починить неправильный HTML, а надежный способ удаления нод DOM-документа его-же методами.
Я еще раз уточняю что основная цель этого примера, не починить неправильный HTML, а надежный способ удаления нод DOM-документа его-же методами.
Так в том-то и дело, что неправлильные с точки зрения DOM теги могут быть пропущены, а вот браузеры их выполнят. В этом и кроется угроза безопасности.
Я написал свой коммент не для того, чтобы вас унизить и т.п., а лишь только для того, чтобы предостеречь вас от проблем. Но поступайте как хотите.
Я написал свой коммент не для того, чтобы вас унизить и т.п., а лишь только для того, чтобы предостеречь вас от проблем. Но поступайте как хотите.
:) вы не совсем видимо понимаете суть. Суть в том что я получаю в PHP DOMDocument и САМ удаляю из нее те теги и аттрибуты, которые САМ считаю опасными. Только делаю это не регулярками и проходом по дереву DOM и его методами removeChild и removeAttribute. Потом сохраняю готовый результат как XML, этим самым добиваясь валидной верстки и кладу его в кеш-таблицу.
Я вас понимаю, и с DOM на PHP я работаю, имею представление об этой технологии. Больше не буду развивать свою мысль, но уверен, что в процессе эксплуатации данной схемы вы столкнетесь с проблемами, хотя желаю вам только успехов.
В данный момент я тоже работаю над социальным проектом, где есть пользовательский ввод. В результате анализа вашей проблемы (у меня аналогичная проблема была) я все же пока отказался от разрешения html-тегов в пользовательских сообщениях и буду использовать только bb-теги. Конечно, это существенно ограничивает свободу пользователей, зато на 100% решает проблемы с безопасностью.
В данный момент я тоже работаю над социальным проектом, где есть пользовательский ввод. В результате анализа вашей проблемы (у меня аналогичная проблема была) я все же пока отказался от разрешения html-тегов в пользовательских сообщениях и буду использовать только bb-теги. Конечно, это существенно ограничивает свободу пользователей, зато на 100% решает проблемы с безопасностью.
А вариант такой не подходит?:
пользователю разрешается вставлять все html тэги — ничего не вырезается.
в момент парсинга текста от пользователя все <, >, & заменяются на их мнемокод (lt, gt, quot), а потом с помощью регулярных выражение в стиле /<b>/i заменяем данный текст на и так далее. Только что самому в голову в результате чтения ваших комментариев — о бажности судить не могу =)
пользователю разрешается вставлять все html тэги — ничего не вырезается.
в момент парсинга текста от пользователя все <, >, & заменяются на их мнемокод (lt, gt, quot), а потом с помощью регулярных выражение в стиле /<b>/i заменяем данный текст на и так далее. Только что самому в голову в результате чтения ваших комментариев — о бажности судить не могу =)
Кстати, к вопросу о removeAttribute: у DOM-расширения PHP5 с этим тоже, к сожалению, туговато. Мне удалось гарантированно удалять атрибуты только путём создания нового такого же элемента с последующим копированием в него из исходного элемента только разрешённых атрибутов.
Ну а как к примеру можно избавиться от таких ситуаций:
user text here
Как убрать лушние элементы? Регулярками такое будет сложно сделать.
user text here
Как убрать лушние элементы? Регулярками такое будет сложно сделать.
Вероятно в оригинале был HTML-код, который хабр пострипал.
Сори, хабр съел теги =( Так вот:
<span style="..."><span style="..."><span style="...">user text here</span></span></span>
<span style="..."><span style="..."><span style="...">user text here</span></span></span>
а какие из них лишние?
что сделать надо?
а. убрать все span (тривиально)
b. слепить все span stylе в один тег span, где style будет из все спанов.
c. убрать конкретный span
что сделать надо?
а. убрать все span (тривиально)
b. слепить все span stylе в один тег span, где style будет из все спанов.
c. убрать конкретный span
НЛО прилетело и опубликовало эту надпись здесь
я искренне считаю что люди, использующие @ в php должны умирать самой жестокой смертью, которая только может быть.
Думаю, здесь собака оправдана.
@ не оправдана. Лучше отловить ошибку try catch и обработать html другим способом :)
не забываем, что try catch начинается с php5
Да и try-catch здесь тоже не оправдан, потому как ошибка пользователя при вводе данных - это вообщем то не исключение какое-то, а обычная ситуация, при том что данные обрабатываются DOMDocument-ом обработаются коррекно, вообще левые теги - вырежутся автоматом, недостающие - допишет сам ДОМ.
Вообще сам метод такой обработки спорный, и при его использовании следует поймать ответ от loadHTML-я (а он вернет false, если данные пришли хреновые) и решить следует ли продолжать, а его ворнинг просто напросто поймать обработчиком ошибок, как и все остальные ворнинги от пхпшных функций и поместить её в лог например.
Вообще сам метод такой обработки спорный, и при его использовании следует поймать ответ от loadHTML-я (а он вернет false, если данные пришли хреновые) и решить следует ли продолжать, а его ворнинг просто напросто поймать обработчиком ошибок, как и все остальные ворнинги от пхпшных функций и поместить её в лог например.
try...catch ловит exception'ы, а мы имеем дело с обычным ворнингом. Я бы в данном случае пожертвовал своими религиозными убеждениями и сделал так, как удобно, хоть и против религии. А собака тут удобна. Альтернатива - подготовить валидный XML средствами tidy или другой либы, но это ведь геммор, да и потом, не факт что они окажутся на сервере. DOM куда универсальнее.
Вот! Вы меня правильно поняли. Нет никакого смысла видеть эти ошибки в эррор логе. Там должны быть важные сообщения, а не "Invalid or misplaced tag in DOMDocument...". И пожертовать тактами на собачку выгоднее, чем запускать tidy или делать перехват вывода ошибок.
Вот те кто х**ню в ЖЖ пишут должны «выхватить ебвальником» и умереть самой жестокой смертью.
А не х**ню писать.
А не х**ню писать.
Недавно наткнулся на отечественную разработку, которая решает похожую задачу - http://jevix.ru/project/
Вместо удаления ненужных тегов и атрибутов не лучше ли описать нужные теги и нужные у них атрибуты, после чего оставить только их? Тогда уж точно черный властелин не прокрадется через забытое опасное.
зачем писать 5 строк если достаточно preg_replace('|]+>|','',$text) ?
preg_replace('|< [^> ]+>|','',$text)
это если все вырезать надо, а если все кроме тех, которые в Whitelist?
мда?! а если текст будет:
потеряем часть текста - не страшно?
... а приведенном примере если a<b, то ... а если a>b, то ...
потеряем часть текста - не страшно?
Хороший вопрос!
интересно. буду думать.
интересно. буду думать.
Вы меня запутали. Из WYSIWYG ввод должен придти в виде ... а приведенном примере если a<b, то ... а если a>b, то ... :)
... а приведенном примере если a<b, то ... а если a>b, то ...
1. Совсем не обязательно, все зависит от редактора. В большинстве есть редактирование HTML, которое можно сохранить (отправить вашем скрипту).
2. Редактор может прислать любой код по сути. Если вы не словили частности, это не значит что ваш RegExp будет работать всегда - в таком виде как у вас, точно не будет. Можно придумать много примеров, я вам показал самый простой.
3. Ваша тема "удаление ненужных HTML тегов из пользовательского ввода" а не "удаление ненужных HTML тегов из HTML текста переданного от WYSIWYG редактора".
2. Редактор может прислать любой код по сути. Если вы не словили частности, это не значит что ваш RegExp будет работать всегда - в таком виде как у вас, точно не будет. Можно придумать много примеров, я вам показал самый простой.
3. Ваша тема "удаление ненужных HTML тегов из пользовательского ввода" а не "удаление ненужных HTML тегов из HTML текста переданного от WYSIWYG редактора".
Бред полный. Это то же самое , что сказать:
"отправляйте почту с помошью метода sendEmail(), а реализацию этого метода я оставляю на ваше усмотрение."
Автор, предложите свое решение проблемы. Или хотя бы потрудитесь сделать обзор уже существующих.
"отправляйте почту с помошью метода sendEmail(), а реализацию этого метода я оставляю на ваше усмотрение."
Автор, предложите свое решение проблемы. Или хотя бы потрудитесь сделать обзор уже существующих.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
удаление ненужных HTML тегов из пользовательского ввода.