strip_tags禁止某些标签。

7
根据strip_tags文档,第二个参数指定允许的标签。然而在我的情况下,我想要相反的效果。也就是说,我会接受script_tags通常(默认)接受的标签,但只去掉<script>标签。是否有可能实现这一点?任何相关的建议将不胜感激。

这通常可以通过正则表达式完成。查看手册页面,我看到用户注释中有这个:'@<script[^>]?.?</script>@siu'。 - user557846
3
你可以了解一下HTML Purifier。如果你使用strip_tags()来清除标记,请注意不要这么做。 - Jared Farrish
2
使用HTML Purifier,您可以使用HTML.ForbiddenElements,我认为这将实现您想要的功能(黑名单而不是白名单元素)。个人建议仍然使用白名单,并使用帮助函数来给出黑名单组的反向结果。 - Jared Farrish
我看到了你的评论,让我看一下并将其添加到我的答案中。请给我几分钟时间。 - Jared Farrish
看到我的编辑了吗?我试着回答你的评论,但是我不确定。如果在我重新访问之前你找到如何设置HTML.ForbiddenElementsarray值,请在答案下留言告诉我。 - Jared Farrish
显示剩余3条评论
5个回答

6

编辑

要使用HTML Purifier的HTML.ForbiddenElements配置指令,似乎您需要执行以下操作:

require_once '/path/to/HTMLPurifier.auto.php';

$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.ForbiddenElements', array('script','style','applet'));
$purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($dirty_html);

http://htmlpurifier.org/docs

HTML.ForbiddenElements 应该设置为一个数组。我不知道数组成员应该采取什么形式:

array('script','style','applet')

或者:

array('<script>','<style>','<applet>')

还是......其他什么?

我认为它是第一种形式,没有分隔符;HTML.AllowedElements使用了一种配置字符串形式,这种形式在TinyMCE的valid elements语法中相当常见:

tinyMCE.init({
    ...
    valid_elements : "a[href|target=_blank],strong/b,div[align],br",
    ...
});

所以我猜测它只是术语,不需要提供属性(因为你正在禁止元素...虽然也有一个HTML.ForbiddenAttributes)。但这只是一个猜测。
我还会添加来自HTML.ForbiddenAttributes文档的这个注释:
警告:此指令补充了%HTML.ForbiddenElements,因此请查看该指令以讨论为什么在使用此指令之前应三思而后行。
黑名单并不像白名单一样“强大”,但你可能有你的理由。只要小心谨慎。
没有测试,我不确定该怎么告诉你。我会继续寻找答案,但我可能会先睡觉。现在已经很晚了。 :)
虽然我认为你真的应该使用HTML Purifier并利用它的HTML.ForbiddenElements配置指令,但如果你真的非常想使用strip_tags(),那么从黑名单中派生出一个白名单是一个合理的选择。换句话说,删除你不想要的内容,然后使用剩下的内容。

例如:

function blacklistElements($blacklisted = '', &$errors = array()) {
    if ((string)$blacklisted == '') {
        $errors[] = 'Empty string.';
        return array();
    }

    $html5 = array(
        "<menu>","<command>","<summary>","<details>","<meter>","<progress>",
        "<output>","<keygen>","<textarea>","<option>","<optgroup>","<datalist>",
        "<select>","<button>","<input>","<label>","<legend>","<fieldset>","<form>",
        "<th>","<td>","<tr>","<tfoot>","<thead>","<tbody>","<col>","<colgroup>",
        "<caption>","<table>","<math>","<svg>","<area>","<map>","<canvas>","<track>",
        "<source>","<audio>","<video>","<param>","<object>","<embed>","<iframe>",
        "<img>","<del>","<ins>","<wbr>","<br>","<span>","<bdo>","<bdi>","<rp>","<rt>",
        "<ruby>","<mark>","<u>","<b>","<i>","<sup>","<sub>","<kbd>","<samp>","<var>",
        "<code>","<time>","<data>","<abbr>","<dfn>","<q>","<cite>","<s>","<small>",
        "<strong>","<em>","<a>","<div>","<figcaption>","<figure>","<dd>","<dt>",
        "<dl>","<li>","<ul>","<ol>","<blockquote>","<pre>","<hr>","<p>","<address>",
        "<footer>","<header>","<hgroup>","<aside>","<article>","<nav>","<section>",
        "<body>","<noscript>","<script>","<style>","<meta>","<link>","<base>",
        "<title>","<head>","<html>"
    );

    $list = trim(strtolower($blacklisted));
    $list = preg_replace('/[^a-z ]/i', '', $list);
    $list = '<' . str_replace(' ', '> <', $list) . '>';
    $list = array_map('trim', explode(' ', $list));

    return array_diff($html5, $list);
}

然后运行它:
$blacklisted = '<html> <bogus> <EM> em li ol';
$whitelist = blacklistElements($blacklisted);

if (count($errors)) {
    echo "There were errors.\n";
    print_r($errors);
    echo "\n";
} else {
    // Do strip_tags() ...
}

http://codepad.org/LV8ckRjd

如果您传入不想允许的内容,它将以数组形式返回HTML5元素列表,然后将其连接成字符串并馈入strip_tags()函数进行处理。
$stripped = strip_tags($html, implode('', $whitelist)));

买方自负

现在,我已经将这个东西拼凑在一起了,但我知道还有一些问题没有考虑到。例如,从$allowable_tags参数的strip_tags()手册页中可以看出:

注意:

此参数不应包含空格。 strip_tags()将标签视为大小写不敏感的字符串,介于<和第一个空格或>之间。这意味着strip_tags("<br/>", "<br>")将返回一个空字符串。

现在已经很晚了,由于某种原因我无法完全理解这对这种方法意味着什么。所以我必须明天再想一想。我还从这个MDN文档页面编译了函数的$html5元素的HTML元素列表。眼尖的读者可能会注意到所有标记都是这种形式:

<tagName>

我不确定这会对结果产生什么影响,是否需要考虑对短标签<tagName/>的使用进行变化,以及一些比较奇怪的变体。当然,还有更多的标签在那里。 所以它可能还没有准备好用于生产环境。但你已经有了想法。

感谢您的建议和详细的解释。我已经明白了,现在我正在研究HTMLPurifier。 - Leandro Garcia

2

首先,看一下别人对这个主题说了什么:

如何使用 PHP 去除 <script> 标签及其之间的内容?

以及

如何从 HTML 内容中删除 script 标记

看起来你有两个选择,一个是正则表达式解决方案,以上两个链接都提供了。第二种方法是使用HTML Purifier

如果你是为了除去脚本标记而不是消毒用户内容,则可以使用正则表达式解决方案。然而,正如每个人所警告的那样,如果你正在消毒输入,请使用 HTML Purifier。


1

PHP(5或更高版本)解决方案:

如果您想删除<script>标签(或任何其他标签),并且您还想删除标签内的内容,则应使用以下方法:

选项1(最简单):

preg_replace('#<script(.*?)>(.*?)</script>#is', '', $text);

选项2(更多功能):
<?php

$html = "<p>Your HTML code</p><script>With malicious code</script>"

$dom = new DOMDocument();

$dom->loadHTML($html);

$script = $dom->getElementsByTagName('script');

$remove = [];
foreach($script as $item)
{
  $item->parentNode->removeChild($item);
}

$html = $dom->saveHTML();

然后$html将是:

"<p>Your HTML code</p>"

1
不错的答案,但一个foreach循环就足够了。 - Adam Jimenez

0

这是我用来剥禁止标签列表的方法,可以同时删除包裹内容的标签和包含内容的标签,还能去除多余的空白。

$description = trim(preg_replace([
    # Strip tags around content
    '/\<(.*)doctype(.*)\>/i',
    '/\<(.*)html(.*)\>/i',
    '/\<(.*)head(.*)\>/i',
    '/\<(.*)body(.*)\>/i',
    # Strip tags and content inside
    '/\<(.*)script(.*)\>(.*)<\/script>/i',
], '', $description));

输入示例:

$description = '<html>
<head>
</head>
<body>
    <p>This distinctive Mini Chopper with Desire styling has a powerful wattage and high capacity which makes it a very versatile kitchen accessory. It also comes equipped with a durable glass bowl and lid for easy storage.</p>
    <script type="application/javascript">alert('Hello world');</script>
</body>
</html>';

输出结果:

<p>This distinctive Mini Chopper with Desire styling has a powerful wattage and high capacity which makes it a very versatile kitchen accessory. It also comes equipped with a durable glass bowl and lid for easy storage.</p>

0

我使用以下内容:

function strip_tags_with_forbidden_tags($input, $forbidden_tags)
{
    foreach (explode(',', $forbidden_tags) as $tag) {
        $tag = preg_replace(array('/^</', '/>$/'), array('', ''), $tag);
        $input = preg_replace(sprintf('/<%s[^>]*>([^<]+)<\/%s>/', $tag, $tag), '$1', $input);
    }

    return $input;
}

然后你可以这样做:

echo strip_tags_with_forbidden_tags('<cancel>abc</cancel>xpto<p>def></p><g>xyz</g><t>xpto</t>', 'cancel,g');

输出:'abcxpto<p>def></p>xyz<t>xpto</t>'

echo strip_tags_with_forbidden_tags('<cancel>abc</cancel> xpto <p>def></p> <g>xyz</g> <t>xpto</t>', 'cancel,g');

输出:'abc xpto <p>def></p> xyz <t>xpto</t>'


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