Is there an alternative to PHP's strip_tags()


Is there an alternative to PHP's strip_tags()

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

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

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

这与strip_tags()的作用正好相反。

我该如何做到这一点?

更新日期: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);
    }
}

这根本不应该发生。

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

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

我通常使用htmLawed lib,您可以使用它来过滤、保护&清除HTML

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

我认为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?

当然,这只是剥去标签,而不是它们之间的东西。这就是你想要的吗?你没有在问题中具体说明。