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