符合HTML5标准的HTML过滤器

57

有没有一种简单的方法来为HTMLPurifier添加HTML5规则集?

可以通过以下方式配置HP来识别新标签:

// setup configurable HP instance
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.DefinitionID', 'html5 draft');
$config->set('HTML.DefinitionRev', 1);
$config->set('Cache.DefinitionImpl', null); // no caching
$def = $config->getHTMLDefinition(true);

// add a new tag
$form = $def->addElement(
  'article',   // name
  'Block',     // content set
  'Flow',      // allowed children
  'Common',    // attribute collection
  array(       // attributes
  )
);

// add a new attribute
$def->addAttribute('a', 'contextmenu', "ID");

然而,这显然需要一些工作。因为有很多新的HTML5标签和属性需要注册。并且新的全局属性应该可以与现有的HTML 4标签结合使用。(从文档中很难判断如何增强核心规则)。那么,有没有更有用的配置格式/数组结构来将新的和更新的标签+属性+上下文配置(内联/块状/空/流/...)输入到HTMLPurifier中?
# mostly confused about how to extend existing tags:
$def->addAttribute('input', 'type', "...|...|...");

# or how to allow data-* attributes (if I actually wanted that):
$def->addAttribute("data-*", ...

当然,并非所有新的HTML5标签都适合无限制地使用。HTMLPurifier专注于内容过滤,定义值约束是关键所在。例如,<canvas>出现在用户内容中可能并不重要,因为它没有JavaScript几乎是无用的(而HP已经过滤了JavaScript)。但其他标签和属性可能是不可取的,因此灵活的配置结构对于启用/禁用标签及其相关属性至关重要。(“我猜我应该更新一些研究...”)但仍然没有实用的汇编/规范(不,XML DTD不是)适用于HP配置。 (嗯,HTML5已不再是草案。)

你问过能行的人了吗?https://dev59.com/uW455IYBdhLWcg3wD_sB#4567261 - thirtydot
@thirtydot:那可能是在他添加PH5P解析器之前。但这并不重要,因为您可以添加新标签,HTML4解析技术应该足以在HTML5上正常工作。 - mario
2
你应该意识到HTML 5仍然是一个草案(即使它已经“最后呼叫”超过2年了)...因此可能会发生变化...因此今天支持的HTML 5不一定是明天的支持。 - Eugene
2
主要问题实际上是,正如Mario所指出的那样,需要手动筛选所有属性并逐一批准。这是一件好事,因为我非常仔细地审核了HTML Purifier当前属性集中的每个属性。虽然需要一些功夫,但对于足够有动力的个人来说应该不会太难。可惜,我目前不是那个人。 - Edward Z. Yang
1
这就是我不喜欢赏金系统的原因之一:对于一个足够难的问题,可能会有人因错误答案而获得赏金 :-) - Edward Z. Yang
5个回答

12

你可以将整洁的cleanAndRepair封装在自己的类中,并与strip_tags和htmlspecialchars混合使用。Tidy还有一个裸选项,可以去除专有属性,也许这会有所帮助。 - chris
7
tidy_clean_repair() 最适合重新格式化你自己的代码。drop-proprietary-attributes 参数有趣地移除了任何新的 HTML5 属性,但保留了 onClick= 等属性。因此,它并不是 HTMLPurifier 的替代品。 - mario
但是,您可以使用 new-block-tags 等来定义它们。 - Levi Morrison

7

这是HTMLpurify的一个配置,允许使用更新的HTML5标签。

来源: https://github.com/kennberg/php-htmlpurfier-html5

.

<?php
/**
 * Load HTMLPurifier with HTML5, TinyMCE, YouTube, Video support.
 *
 * Copyright 2014 Alex Kennberg (https://github.com/kennberg/php-htmlpurifier-html5)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

require_once(LIB_DIR . 'third-party/htmlpurifier/HTMLPurifier.safe-includes.php');


function load_htmlpurifier($allowed) {
  $config = HTMLPurifier_Config::createDefault();
  $config->set('HTML.Doctype', 'HTML 4.01 Transitional');
  $config->set('CSS.AllowTricky', true);
  $config->set('Cache.SerializerPath', '/tmp');

  // Allow iframes from:
  // o YouTube.com
  // o Vimeo.com
  $config->set('HTML.SafeIframe', true);
  $config->set('URI.SafeIframeRegexp', '%^(http:|https:)?//(www.youtube(?:-nocookie)?.com/embed/|player.vimeo.com/video/)%');

  $config->set('HTML.Allowed', implode(',', $allowed));

  // Set some HTML5 properties
  $config->set('HTML.DefinitionID', 'html5-definitions'); // unqiue id
  $config->set('HTML.DefinitionRev', 1);

  if ($def = $config->maybeGetRawHTMLDefinition()) {
    // http://developers.whatwg.org/sections.html
    $def->addElement('section', 'Block', 'Flow', 'Common');
    $def->addElement('nav',     'Block', 'Flow', 'Common');
    $def->addElement('article', 'Block', 'Flow', 'Common');
    $def->addElement('aside',   'Block', 'Flow', 'Common');
    $def->addElement('header',  'Block', 'Flow', 'Common');
    $def->addElement('footer',  'Block', 'Flow', 'Common');

    // Content model actually excludes several tags, not modelled here
    $def->addElement('address', 'Block', 'Flow', 'Common');
    $def->addElement('hgroup', 'Block', 'Required: h1 | h2 | h3 | h4 | h5 | h6', 'Common');

    // http://developers.whatwg.org/grouping-content.html
    $def->addElement('figure', 'Block', 'Optional: (figcaption, Flow) | (Flow, figcaption) | Flow', 'Common');
    $def->addElement('figcaption', 'Inline', 'Flow', 'Common');

    // http://developers.whatwg.org/the-video-element.html#the-video-element
    $def->addElement('video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', array(
      'src' => 'URI',
      'type' => 'Text',
      'width' => 'Length',
      'height' => 'Length',
      'poster' => 'URI',
      'preload' => 'Enum#auto,metadata,none',
      'controls' => 'Bool',
    ));
    $def->addElement('source', 'Block', 'Flow', 'Common', array(
      'src' => 'URI',
      'type' => 'Text',
    ));

    // http://developers.whatwg.org/text-level-semantics.html
    $def->addElement('s',    'Inline', 'Inline', 'Common');
    $def->addElement('var',  'Inline', 'Inline', 'Common');
    $def->addElement('sub',  'Inline', 'Inline', 'Common');
    $def->addElement('sup',  'Inline', 'Inline', 'Common');
    $def->addElement('mark', 'Inline', 'Inline', 'Common');
    $def->addElement('wbr',  'Inline', 'Empty', 'Core');

    // http://developers.whatwg.org/edits.html
    $def->addElement('ins', 'Block', 'Flow', 'Common', array('cite' => 'URI', 'datetime' => 'CDATA'));
    $def->addElement('del', 'Block', 'Flow', 'Common', array('cite' => 'URI', 'datetime' => 'CDATA'));

    // TinyMCE
    $def->addAttribute('img', 'data-mce-src', 'Text');
    $def->addAttribute('img', 'data-mce-json', 'Text');

    // Others
    $def->addAttribute('iframe', 'allowfullscreen', 'Bool');
    $def->addAttribute('table', 'height', 'Text');
    $def->addAttribute('td', 'border', 'Text');
    $def->addAttribute('th', 'border', 'Text');
    $def->addAttribute('tr', 'width', 'Text');
    $def->addAttribute('tr', 'height', 'Text');
    $def->addAttribute('tr', 'border', 'Text');
  }

  return new HTMLPurifier($config);
}

不错的发现。你可能想摘录相关部分,并进行基本归属说明。链接经常变得无法访问(特别是对于Github;很少有互联网存档缓存)。-- 它至少注册了基本标签;但缺少许多新属性,只列出了一些选定的data-*属性作为示例。 - mario
知道了,现在帖子中已包含完整清单。 - Christoffer Bubach
酷脚本。HTML净化器似乎仍然会删除<video>标签中的(替代)文本内容,尽管配置告诉它不要这样做("Flow")。有什么想法,为什么会这样? - BurninLeo

4
我正在使用 WordPress 的修复方法,但这个方法可能也能帮到你(至少在数组部分上)。
这里有两个链接可以参考:http://nicolasgallagher.com/using-html5-elements-in-wordpress-post-content/http://hybridgarden.com/blog/misc/adding-html5-capability-to-wordpress/
此外,这里还有一个链接:http://code.google.com/p/html5lib/,它提供了基于 WHATWG HTML5 规范的 HTML 解析器的 Python 和 PHP 实现,以实现与主要桌面 Web 浏览器的最大兼容性。

不确定 WP 片段,但 html5lib 听起来非常有前途。它可能没有 HP 的功能集,但至少可以成为一个出色的过渡解决方案。 - mario

3

我知道这个主题很老,但由于它仍然相关,所以我决定回应。特别是当自原问题被提出以来情况已经发生了变化。

你可以使用https://github.com/xemlock/htmlpurifier-html5,它通过符合规范的HTML5元素和属性扩展了HTML Purifier。

使用方法与原始的HTML Purifier几乎相同,你只需要将 HTMLPurifier_Config 替换为 HTMLPurifier_HTML5Config

$config = HTMLPurifier_HTML5Config::createDefault();
$purifier = new HTMLPurifier($config);

$clean_html5 = $purifier->purify($dirty_html5);

免责声明:本人是该扩展的作者。


0

1
PH5P是HTMLPurifier的一部分。据我所了解,它只是根据HTML5 SGML-esque序列化实现解析规则。我认为它没有增强HP输出过滤器(或者我只是没让它工作)。@EZY可能还没有时间集成或完成它。 - mario
1
如果需要的话,您可以将PH5P与HTML Purifier一起使用。但这并不会为HTML Purifier添加所需的属性集。 - Edward Z. Yang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接