Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

HTML Purifier. Расширяем вероятности

Anna | 31.05.2014 | нет комментариев

Дословно пару абзацев я уделю внимание особенностям взаимодействия этой библиотеки с фреймворком Yii, остальное же в полной мере универсально и будет увлекательно каждому, кто использует либо планирует применять эту библиотеку

Если вы теснее отлично знакомы с Purifier то можете отважно начинать читать отсель

Немножко о HTML Purifier

Если вы не слышали о такой красивой библиотеке (а поиск на Прогре говорит о не такой уж огромный популярности) как HTML Purifier, то советую непременно к ней присмотреться, исключительно если ваши пользователи генерируют контент в html формате. Это может быть рядовой пользователь, модератор либо даже менеджер.
Что же делает эта библиотека?
Согласно конфигурации она очищает всякий html код от всех вредных, невалидных, запрещенных (вашей конфигурацией) частей кода, в том числе отдельные признаки.

Поменьше слов, огромнее кода

Думаю пару примеров скажут сами за себя.

        $config = HTMLPurifier_Config::createDefault();
        $config->set('Attr.AllowedClasses',array('header')); // либо Attr.ForbiddenClasses имеются ввиду CSS классы
        $config->set('AutoFormat.AutoParagraph',true); // авто добавление <p> в тексте при переносе
        $config->set('AutoFormat.RemoveEmpty',true); // удаляет пустые теги, есть исключения*
        $config->set('HTML.Doctype','HTML 4.01 Strict'); // обратите внимание как заменился тег <strike>
        $purifier = new HTMLPurifier($config);
        $clean_html = $purifier->purify($html);

* — Исключения RemoveEmpty

Начальный html:

        <p invalidAttribute="value">О, я хочу безрассудно <strike>жить</strike>:</p>
        <p>Всё сущее - <invalidTag>увековечить</invalidTag>,</p>
        <p>Безличное - вочеловечить,</p>
        Несбывшееся - воплотить!
        <script type="text/javascript">alert("hacked by Alexander Blok");</script>

Итог использования функции purify

        <p>О, я хочу безрассудно <span style="text-decoration:line-through;">жить</span>:</p>
        <p>Всё сущее - увековечить,</p>
        <p>Безличное - вочеловечить,</p>
        <p>Несбывшееся - воплотить!</p>

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

«Фиолетовые пуговицы»


Но не было бы этого поста, если бы как традиционно, нам не захотелось чего то особенного, а именно две вещи:

  1. Заменить все ссылки на внешние сайты нашей ссылкой вида site.ru/redirect?url=link
  2. Добавить ко каждому ссылкам пользователей признак target=_blank


Задачи не показались слишком трудными, по первой есть недурная статья в доках, а вторая вообще плевая — конфиг HTML.TargetBlank делает работу за нас.

Задача 1 — замена внешних ссылок

У Purifier есть восхитительный класс HTMLPurifier_URIFilter и не менее восхитительные примеры реализации вероятностей этого фильтра
Я взял за основу файл DisableExternalResources и стремительно переписал его под свои нужды, а именно замена внешней ссылки на внутреннюю.

Файл фильтра

Малое изложение:
В функции prepare мы получаем хост / <– $uri = $config->getDefinition(‘URI’); $uri->addFilter(new HTMLPurifier_URIFilter_MakeRedirect(), $config); $purifier->options = $config; $clean_html = $purifier->purify($html);

Cannot set directive after finalization invoked on line 127 in file /framework/web/widgets/CHtmlPurifier.php

Сейчас пуриферу не нравится, что мы определяем параметр двукратно. А делает это сам CHtmlPurifier в способе createNewHtmlPurifierInstance()

protected function createNewHtmlPurifierInstance()
	{
		$this->_purifier=new HTMLPurifier($this->getOptions());
		$this->_purifier->config->set('Cache.SerializerPath',Yii::app()->getRuntimePath());
		return $this->_purifier;
	}

Здесь, сознаюсь, я потратил не немного времени в поисках прекрасного решения, но увы. Ничего больше прекрасного, помимо как сделать класс GHtmlPurifier и унаследовать его от класса CHtmlPurifier, переписав способ createNewHtmlPurifierInstance(), я не обнаружил.
Новейший файл положил в папку protected/components/ и код наконец заработал.

        $htmlpurifier = new GHtmlPurifier();
        $config = HTMLPurifier_Config::createDefault();
        $config->set('Cache.SerializerPath',Yii::app()->getRuntimePath());
        $uri = $config->getDefinition('URI');
        $uri->addFilter(new HTMLPurifier_URIFilter_MakeRedirect(), $config);
        $htmlpurifier->options = $config;
        return $htmlpurifier->purify($text);
Задача 2 — добавление target=_blank

Не буду утруждать вас примерами нерабочего кода и скажу сразу, что HTML.TargetBlank работает только с внешними ссылками и его использование отпадает. А URI фильтры не могут получить доступ к тегу и его признакам.
Теснее привыкший к отличной документации по библиотеке, полез в маны, но увы, необходимый разделAdvanced API был пуст и там красовалась надпись «Filed under Development».
Ничего не оставалось, как погрузится в исходники и обнаружить как реализован модуль HTML.TargetBlank.
Вот он:

HTMLPurifier_AttrTransform_TargetBlank

/**
 * Adds target="blank" to all outbound links.  This transform is
 * only attached if Attr.TargetBlank is TRUE.  This works regardless
 * of whether or not Attr.AllowedFrameTargets
 */
class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform
{
    private $parser;

    public function __construct() {
        $this->parser = new HTMLPurifier_URIParser();
    }

    public function transform($attr, $config, $context) {

        if (!isset($attr['href'])) {
            return $attr;
        }

        // XXX Kind of inefficient
        $url = $this->parser->parse($attr['href']);
        $scheme = $url->getSchemeObj($config, $context);

        if ($scheme->browsable && !$url->isBenign($config, $context)) {
            $attr['target'] = '_blank';
        }

        return $attr;

    }

}

Было решено сделать личный модуль, тот, что не будет включать проверку на внешний адрес, а добавит target=_blank каждому ссылкам, которые обнаружит.
Думаю с копированием и удалением пары строк в способе transform совладает всякий. Следственно листинг приводить не буду. Значимо не позабыть поменять наименование вашего модуля, я назвал егоHTMLPurifier_AttrTransform_TargetBlankAll и положил в ту же папку /protected/components/.
Но этого оказалось не довольно, модуль механически не подцепляется, и нам нужно сделать класс, тот, что добавит модуль в нашу конфигурацию. В коде я добавил пару комментариев, что было ясно, что необходимо изменить, если вы захотите написать свой личный модуль.

HTMLPurifier_HTMLModule_TargetBlankAll.php

class HTMLPurifier_HTMLModule_TargetBlankAll extends HTMLPurifier_HTMLModule
{

    public $name = 'TargetBlankAll'; // Это имя будет применяться в конфиге. Не позабудьте его поменять

    public function setup($config) {
        $a = $this->addBlankElement('a'); // Указываем, что модуль должен использоваться ко каждому тегам A
        $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetBlankAll(); // Записываем наш конфиг в массив ПОСТфильтров
        // Так же есть массив ПРЕфильтров $a->attr_transform_pre[]
    }

}

Данный файл я так же сложил в папку /protected/components.
Сейчас осталось добавить данный модуль в наш конфиг

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB