如何检查HTML是否包含扩展实体,如<?

时间:2010-10-20 08:45:12

标签: perl

假设我们有一个像“2 < 4”

这样的html字符串

如何确定它是否包含任何这些扩展序列?

我在CPAN上找到了HTML :: Entities,但它没有提供'check'方法。

详细信息:修复'truncate'方法,以便不会像“2 &l”那样留下损坏的字符串,而不是做不必要的工作。看起来应该是这样的

$s = HTML::Entities::decode_entities ($s) if $has_ext_chars;
$s = substr ($s, 0, $len - 3) . '...' if length $s > $len;
$s = HTML::Entities::encode_entities ($s, "‚„-‰‹‘-™›\xA0¤¦§©«-®°-±µ-·»") if $has_ext_chars;

如何确定$ has_ext_chars?

4 个答案:

答案 0 :(得分:1)

可以在the W3C reference上找到完整的字符实体列表。

您还必须匹配\&#u?\d+;\&#x[a-fA-F0-9]+;

答案 1 :(得分:1)

来自perldoc HTML::Entities

  

该模块还可以导出   %char2entity和%entity2char          哈希,包含从所有字符到的字符的映射          相应的实体(反之亦然)。

您可以使用它们来构建正则表达式。例如,匹配实体:

use HTML::Entities '%entity2char';

my $regex = "&(?:" . join("|", map {s/;\z//; $_} keys %entity2char) . ");";

if ($str =~ /$regex/) {
    print "$str contains entities\n";
}

这会跳过像&#entity_number;这样的实体。

答案 2 :(得分:0)

您可以使用正则表达式

进行尝试
$str =~ /.*\&[^\s]+;.*/

答案 3 :(得分:0)

从您的代码示例中,您可能刚刚在您的应用程序中引入了跨站点脚本攻击。如果我要让您的代码处理&lt;script src="evil.example.com"&gt;&lt;/script&gt;之类的代码,您的代码会将其解码为有效的HTML,而不是将<>重新编码回实体。 (代码中的尖括号不是ASCII尖括号。)

如果要截断包含任何HTML标记或实体的字符串,如果使用简单的解决方案,则可能会破坏某些内容。您可能最好基于HTML解析模块构建解决方案。如果您只查看元素内部没有元素的文本,则可以获取文本,截断文本然后将其替换回元素。如果你必须处理混合内容,那将会更复杂。

但是为了解决不好的问题:

#treats each entity as one character "2 &lt; 4" is 5 characters long
$trunc_len = $len - 3;
$str =~ s/^((?>(?:[^&]|&[^\s;]+;?){$trunc_len}))(?:[^&]|&[^\s;]+;?){4,}/$1.../;

#abuses proceadural nature of the regexp engine 
#treats each input character as on character "2 &lt; 4" is 8 characters long
$str =~ s/^( (?:[^&]|&[^\s;]+;?)+ )(?(?{ $found = (pos() > ( $found ? $len - 3 : $len ))})(?!)).*$(?(?{pos() < $len })(?!))/$1.../x;

两者在允许常见浏览器怪癖的实体中相当宽容。