【问题标题】:Regex match for php tags ignoring xml tagsphp标签的正则表达式匹配忽略xml标签
【发布时间】:2012-05-17 07:37:22
【问题描述】:

我想抛出验证错误,如果 -

  • 用户输入包含php标签<?php(也适用于短标签<?
  • 但如果没有检测到 php 标签,我想允许 XML 标签 (<?xml)。
  • 在两者都存在的情况下,我想抛出错误。

我现在已经使用了以下正则表达式 -

`(.*?)<\?(php)?[^xml](.*?)`

但如果输入仅包含 PHP 短标签,则不匹配。

我想匹配以下 -

PHP 短标签

<?

PHP 标记

<?php

PHP标签中存在xml标签

<?php ?>
<?xml

以下不匹配

<?xml

更新

如果输入仅包含&lt;?,没有任何结尾空格,则使用此正则表达式(.*?)&lt;\?[^x](.*?) 不会检测到&lt;? 字符。我想我只需要在以下位置添加一个条件以进一步检查是否有更多字符 -

         |
         v
`(.*?)<\?[^x](.*?)`

如果我尝试这个 - (.*?)&lt;\?([^x]?)(.*?),它不再排除 xml。你看到我挂在哪里了吗?我想这里有一些正则表达式允许的东西。有什么想法吗?

【问题讨论】:

    标签: regex


    【解决方案1】:

    你需要正则表达式吗?为什么不这样做:

    if file contains '<?php'
        throw an error
    if file contains '<?' but *doesn't* contain '<?xml'
        throw an error
    

    EDIT 如 cmets 中所述,这不会涵盖包含 &lt;?&lt;?xml 的文件(尽管您可以计算 &lt;? 的出现次数,如果这大于&lt;?xml的数量,然后抛出错误)。

    重新正则表达式,您有几个选择。如果您的正则表达式支持负前瞻,您可以查找 不是 后跟“x”的&lt;?

    <\?(?!x)
    

    或者如果它不支持负前瞻,你可以试试

    <\?([^x]|$)
    

    其中任何一个都会查找 PHP 标志的存在。

    【讨论】:

    • 感谢您的回答。当我只需要检查 PHP 标签的存在时,我最初没有使用正则表达式。后来,当我需要额外检查 XML 标签时,我选择了正则表达式。我想,我不太清楚何时切换到正则表达式匹配的基本原理。在我的情况下,正则表达式会过分吗?无论如何,如果输入仅包含&lt;?,没有任何结尾空格,则使用此正则表达式(.*?)&lt;\?[^x](.*?) 不会检测到&lt;? 字符。有什么想法吗?
    • 如果我使用此逻辑if (file contains '&lt;?php') or (file contains '&lt;?' but *doesn't* contain '&lt;?xml'),则包含&lt;?&lt;?xml 的输入不会引发错误(此输入不会引发错误-&lt;?&lt;?xml)。我想,如果必须进行非正则表达式检查,我需要进一步检查一些位置信息或每个匹配项的计数。那么,您认为在这种情况下,正则表达式检查会更好吗?
    • 太棒了!我正在寻找的是负前瞻。顺便说一句,我们在生产中使用了 PHP 5。在推出之前如何确保?对此有何想法?
    【解决方案2】:

    您要查找的正则表达式是:

    /<\?(?!xml)(?:php|.{0,3})/s
    

    这是 PHP 示例代码:

    if (preg_match("/<\?(?!xml)(?:php|.{0,3})/s", $str))
      echo "Not allowed\n";
    

    【讨论】:

      【解决方案3】:

      如果你使用这个正则表达式,请记住:

      <\?(?!x)
      

      <\?([^x]|$)
      

      启用 short_open_tags 后,您仍然容易受到攻击。此行将输出 Hello World:

      <?xml_error_string(1); echo 'Hello World!'; ?>
      

      我只能想出这个正则表达式

      <(\?([^x]|xml_.*?)|\%)
      

      但是你仍然留下这个片段......

      error_string(1); echo 'Hello World'; ?>
      

      我厌倦了寻找更好的解决方案,但它仍然比可以运行的代码更好。 ;-)

      【讨论】:

      • 我认为在 OP 的情况下,解析输入比使用正则表达式更合适。