是否有替代PHP strip_tags()

时间:2012-03-20 14:21:12

标签: php

strip_tags() documentation告诉我们除了第二个参数中的标签之外的所有标签都被剥离。此函数执行的操作与其名称完全相反。它应该被命名为strip_all_tags_except()

让我们忘记这个名字,然后来看看我想问的问题。我想要只删除我在第二个参数中提到的标签的功能。即。我希望以下内容删除标记<iframe><script><style><embed><object>并允许所有其他标记。

my_strip_tags($data,'<iframe><script><style><embed><object>');

strip_tags()的做法完全相反。

我该如何实现?

4 个答案:

答案 0 :(得分:3)

根本不应该发生。

strip_tags仅在没有任何参数的情况下使用。否则,您将在允许的任何标记中使用XSS。

事实上,您的关注不仅应该是标签,还应该是属性。因此,请使用某种HTML净化器。

答案 1 :(得分:3)

更新2012-06-23;主要的安全漏洞。

这是来自另一个应该做你正在寻找的项目的课程:

final class Filter {
    private function __construct() {}

    const SafeTags = 'a abbr acronym address b bdo big blockquote br caption center cite code col colgroup dd del dfn dir div dl dt em font h1 h2 h3 h4 h5 h6 hr i img ins kbd legend li ol p pre q s samp small span strike strong sub sup table tbody td tfoot th thead tr tt u ul var article aside figure footer header nav section rp rt ruby dialog hgroup mark time';
    const SafeAttributes = 'href src title alt type rowspan colspan lang';
    const URLAttributes  = 'href src';

    public static function HTML($html) {
        # Get array representations of the safe tags and attributes:
        $safeTags = explode(' ', self::SafeTags);
        $safeAttributes = explode(' ', self::SafeAttributes);
        $urlAttributes = explode(' ', self::URLAttributes);

        # Parse the HTML into a document object:
        $dom = new DOMDocument();
        $dom->loadHTML('<div>' . $html . '</div>');

        # Loop through all of the nodes:
        $stack = new SplStack();
        $stack->push($dom->documentElement);

        while($stack->count() > 0) {
            # Get the next element for processing:
            $element = $stack->pop();

            # Add all the element's child nodes to the stack:
            foreach($element->childNodes as $child) {
                if($child instanceof DOMElement) {
                    $stack->push($child);
                }
            }

            # And now, we do the filtering:
            if(!in_array(strtolower($element->nodeName), $safeTags)) {
                # It's not a safe tag; unwrap it:
                while($element->hasChildNodes()) {
                    $element->parentNode->insertBefore($element->firstChild, $element);
                }

                # Finally, delete the offending element:
                $element->parentNode->removeChild($element);
            } else {
                # The tag is safe; now filter its attributes:
                for($i = 0; $i < $element->attributes->length; $i++) {
                    $attribute = $element->attributes->item($i);
                    $name = strtolower($attribute->name);

                    if(!in_array($name, $safeAttributes) || (in_array($name, $urlAttributes) && substr($attribute->value, 0, 7) !== 'http://')) {
                        # Found an unsafe attribute; remove it:
                        $element->removeAttribute($attribute->name);
                        $i--;
                    }
                }
            }
        }

        # Finally, return the safe HTML, minus the DOCTYPE, <html> and <body>:
        $html  = $dom->saveHTML();
        $start = strpos($html, '<div>');
        $end   = strrpos($html, '</div>');

        return substr($html, $start + 5, $end - $start - 5);
    }
}

答案 2 :(得分:1)

我通常使用htmLawed lib,你可以使用它来过滤,保护&amp;清理HTML

http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/more.htm

答案 3 :(得分:0)

我认为strip_tags()功能与其名称相匹配。这都是透视问题。 :-)没有第二个参数,它会删除所有标签。第二个参数提供基本功能的例外。

您想要的似乎是strip_some_tags()

用正则表达式做什么呢?

function strip_some_tags($input, $taglist) {
  $output=$input;
  foreach ($taglist as $thistag) {
    if (preg_match('/^[a-z]+$/i', $thistag)) {
      $patterns=array(
        '/' . "<".$thistag."\/?>" . '/',
        '/' . "<\/".$thistag.">" . '/'
      );
    } else
    if (preg_match('/^<[a-z]+>$/i', $thistag)) {
      $patterns=array(
        '/' . str_replace('>', "?>", $thistag) . '/',
        '/' . str_replace('<', "<\/?", $thistag) . '/'
      );
    }
    else {
      $patterns=array();
    }
    $output=preg_replace($patterns, "", $output);
  }
  return $output;
}

$to_strip=array( "iframe", "script", "style", "embed", "object" );

$sampletext="Testing. <object>Am I an object?</object>\n";

print strip_some_tags($sampletext, $to_strip);

返回:

Testing. Am I an object?

当然,这只是剥离标签,而不是它们之间的东西。那是你要的吗?你没有在你的问题中指明。