Блог → PHP класс для фильтрации HTML кода
В свое время я писал функцию для фильтрации введенного пользователем HTML кода на языке Perl. Если кому интересно почитать можно здесь. Но так, как Perl уже давно не мейнстрим я решил переписать все это дело на PHP.
Пользоваться фильтром нужно следующим образом. Сначала подключаем класс и создаем объект представляющий из себя фильтр.
require_once "html_filter_class.php";
$html_filter = new html_filter();
Далее следует задать тэги для фильтрации. Например вот так:
$tags = array(
'h1' => array('id', 'class'),
'h2' => array('id', 'class'),
'h3' => array('id', 'class'),
'h4' => array('id', 'class'),
'h5' => array('id', 'class'),
'h6' => array('id', 'class'),
'p' => array('id', 'class'),
'span' => array('id', 'class'),
'a' => array('id', 'class', 'href'),
'img' => array('id', 'class', 'src', 'alt', FALSE),
'br' => array(FALSE),
'hr' => array(FALSE),
'pre' => array('id', 'class'),
'code' => array('id', 'class'),
'ul' => array('id', 'class'),
'ol' => array('id', 'class'),
'li' => array('id', 'class'),
'table' => array('id', 'class'),
'tr' => array('id', 'class'),
'td' => array('id', 'class'),
'th' => array('id', 'class'),
'thead' => array('id', 'class'),
'tbody' => array('id', 'class'),
'tfoot' => array('id', 'class'),
'cut' => array('text', FALSE),
'video' => array()
);
Как видим, для задания тэгов используется ассоциативный массив. Его ключами являются имена тэгов, а значениями массив допустимых атрибутов. Если тэг не требует закрывающего тэга, последним элементом массива нужно передать FALSE.
Затем нужно установить эти тэги, при помощи метода set_tags.
$html_filter->set_tags($tags);
По умолчанию все недопустимые тэги будут экранироваться. Если мы хотим, чтобы они удалялись нужно добавить следующую строчку:
$html_filter->del_invalid_tags(TRUE)
Все, наш фильтр настроен и можно им пользоваться.
$filtered_code = $html_filter->filter('Ваш HTML код');
Обратите внимание, на то, что фильтр работает с кодировкой UTF-8. Если вы используете CP1251, то сначала надо преобразовать код в UTF-8, затем прогнать его через фильтр, а после (полученный результат будет в UTF-8) перекодировать обратно в CP1251.
Вот список возможностей фильтра:
- Экранирует или удаляет все недопустимые тэги.
- Удаляет все недопустимые атрибуты тэгов.
- Экранирует спец. символы HTML в атрибутах тэгов и в тексте.
- Закрывает все незакрытые тэги.
- Все тэги заключенные в конструкцию <code></code> рассматривает как простой текст.
Ссылки
Исходный код с примером
Демонстрация работы фильтра
Отличный фильтр, легко приспособил его для фильтрации после Markdown, и вставил типограф. Возможно выпустить версию, работающую только с UTF-8 и не требующую iconv?
Ответить
Так фильтр и работает только с UTF-8.
Ответить
Упс, я ошибся, это в типографе используется iconv.
Ответить
А можно сразу с чтоб ваш класс с windows-1251 работал?
Ответить
Класс предназначен только для работы с utf-8. Если хотите, можете его изменить под cp1251, но я лично в этом не вижу смысла.
Ответить
Пользовался классом, но почему-то он обрезает лишнее, т.е. <img src="http://site.com/img.png" onLoad="javascript:window.alert('12345')" ##++&^%$$# alt="картинка" title=qqqq32> он обрезает до: <img>
Ответить
Вообще так обрезаться не должно. Смотрите как работает фильтр на демо страничке. В вашем случае, скорее всего, причина в следующем. Данные в фильтр передаются из формы, например через POST, а в настройках PHP включен режим Magic Quotes. Этот режим экранирует кавычки, и вследствие этого фильтр не может обработать атрибуты тэгов. Чтобы отключить этот режим напишите в .htaccess:
Ответить
Большое спасибо, помогло. А насчет класса хорош.. сам пока на такое не способен)
Ответить
вроде пашет
Ответить
Здравствуйте! А можно как-нибудь разрешить добавлять iframe только с определенного сайта?
Ответить
В данном фильтре такой возможности нет (т.е не предусмотрена возможность проверки аттрибутов тэгов). Нужно делать дополнительную проверку.
Ответить
А не могли бы Вы подсказать куда и как дописать дополнительную проверку?)
Ответить
Я имел в виду, что нужно делать проверку дополнительно от данного фильтра, своими силами (либо расширять мой класс). Конечно, без знаний PHP тут не обойтись. В более ранней версии фильтра, написанного на perl была возможность проверки аттрибутов, а в этой версии, я решил от нее отказаться.
Ответить