【问题标题】:Remove on* JS event attributes from HTML tags从 HTML 标记中删除 on* JS 事件属性
【发布时间】:2012-03-16 18:05:38
【问题描述】:

请帮助解析 PHP 简单的 html 字符串(php regexp)。 我需要从 html 代码中删除 html-js 事件。 我对 php 正则表达式非常了解。

代码示例:

<button onclick="..javascript instruction..">

结果: <button>

<button onclick="..javascript instruction.." value="..">

结果: <button value="..">

<button onclick=..javascript instruction..>

结果: <button>

<button onclick=..javascript instruction.. value>

结果: <button value>

我需要在不带引号和带引号的情况下执行此操作,因为所有现代浏览器都允许在不带引号的情况下执行属性。

注意:我需要解析的不仅仅是onclick..都是属性,都是从'on'开始的。

注意(2):不要尝试建议 HTML 解析器,因为它会是非常大的 DOM 树进行解析..

已更新:感谢您的回复!现在,我使用 HTMLPurifier 组件在我编写的一个小框架上。

【问题讨论】:

  • 不要尝试用正则表达式解析 HTML,这不是工作。
  • 当然是the consequence
  • 所以.. 我认为我会比使用 php 爆炸或在客户端解析它更好)
  • 我只是希望这些问题不再每天出现在这里。有四个原因:1. 人们一直链接到他们不理解且错误的 THAT ANSWER,2. 人们回答使用 DOM 解析器,但没有别的,这不能回答问题,3. how to parse and process HTML 有一个规范和 4. 无论如何,所有这些问题都是重复的。

标签: php javascript html regex events


【解决方案1】:

使用正则表达式进行标记并没有错。但是使用正则表达式制作一个完整的 HTML 标记器需要大量的工作并且很难做到正确。我建议使用适当的解析器,因为您可能需要删除脚本标签等。

假设不需要完整的标记器,可以使用以下正则表达式和代码从 HTML 标记中删除 on* 属性。 因为没有使用适当的分词器,所以即使在脚本、cmets、CDATA 等中,它也会匹配看起来像标签的字符串。

不能保证所有输入/浏览器组合的所有事件属性都会被删除!请参阅下面的注释。


容错注意事项

浏览器通常会容忍错误。 因此,当存在“无效”数据时,很难标记化标签并获取属性,因为浏览器会看到它们。 由于浏览器之间的容错和处理方式不同,因此不可能制定出适用于所有情况的解决方案。

因此:某些浏览器(当前、过去或将来的版本)可以将我的代码认为不是标签的东西视为标签,并执行 JS 代码。

在我的代码中,我试图模仿最近 Google Chrome 版本的标签(和容错/处理)的标记化。 Firefox 似乎也是这样做的。

IE 7 有所不同,在某些情况下它不那么宽容(这比它更宽容的情况要好)。 (IE 6 - 让我们不要去那里。见XSS Filter Evasion Cheat Sheet


相关链接:


代码

$redefs = '(?(DEFINE)
    (?<tagname> [a-z][^\s>/]*+    )
    (?<attname> [^\s>/][^\s=>/]*+    )  # first char can be pretty much anything, including =
    (?<attval>  (?>
                    "[^"]*+" |
                    \'[^\']*+\' |
                    [^\s>]*+            # unquoted values can contain quotes, = and /
                )
    ) 
    (?<attrib>  (?&attname)
                (?: \s*+
                    = \s*+
                    (?&attval)
                )?+
    )
    (?<crap>    [^\s>]    )             # most crap inside tag is ignored, will eat the last / in self closing tags
    (?<tag>     <(?&tagname)
                (?: \s*+                # spaces between attributes not required: <b/foo=">"style=color:red>bold red text</b>
                    (?>
                        (?&attrib) |    # order matters
                        (?&crap)        # if not an attribute, eat the crap
                    )
                )*+
                \s*+ /?+
                \s*+ >
    )
)';


// removes onanything attributes from all matched HTML tags
function remove_event_attributes($html){
    global $redefs;
    $re = '(?&tag)' . $redefs;
    return preg_replace("~$re~xie", 'remove_event_attributes_from_tag("$0")', $html);
}

// removes onanything attributes from a single opening tag
function remove_event_attributes_from_tag($tag){
    global $redefs;
    $re = '( ^ <(?&tagname) ) | \G \s*+ (?> ((?&attrib)) | ((?&crap)) )' . $redefs;
    return preg_replace("~$re~xie", '"$1$3"? "$0": (preg_match("/^on/i", "$2")? " ": "$0")', $tag);
}


示例用法

Online example:

$str = '
<button onclick="..javascript instruction..">
<button onclick="..javascript instruction.." value="..">
<button onclick=..javascript_instruction..>
<button onclick=..javascript_instruction.. value>
<hello word "" ontest = "hai"x="y"onfoo=bar/baz  />
';

echo $str . "\n----------------------\n";

echo remove_event_attributes($str);

输出:

<button onclick="..javascript instruction..">
<button onclick="..javascript instruction.." value="..">
<button onclick=..javascript_instruction..>
<button onclick=..javascript_instruction.. value>
<hello word "" ontest = "hai"x="y"onfoo=bar/baz  />

----------------------

<button >
<button  value="..">
<button >
<button  value>
<hello word "" x="y"   />

【讨论】:

    【解决方案2】:

    使用 DOMDocument 可能会更好。

    您可以使用它来遍历您尝试解析的 HTML 文件表示的 DOM 树,查找您想要删除的各种 on* 属性。

    这种方法更有可能成功,因为 DOMDocument 实际上理解 HTML 文件的语义,而 regex 只是一个愚蠢的字符串解析器,不足以可靠地解析 HTML。

    【讨论】:

    • 请不要尝试给我 DOM Parser 的建议。我只需要正则表达式,因为 DOM 的大小对于解析来说非常大..!
    • 这只会让使用合适的工具变得更加重要。
    • 所以。我知道有效的解决方案,但我需要强大的解决方案 =)
    • DOMDocument 在解析 HTML 方面比 Regex 强大得多
    • DOMDocument - 内存泄漏注意)但正则表达式没有将大标签树保存到内存中......
    猜你喜欢
    • 2011-07-27
    • 2011-11-20
    • 2023-04-02
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 2011-03-02
    • 1970-01-01
    相关资源
    最近更新 更多