Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
让PHP停止替换'';$\u GET或$\u POST数组中的字符?_Php_Regex_Postback - Fatal编程技术网

让PHP停止替换'';$\u GET或$\u POST数组中的字符?

让PHP停止替换'';$\u GET或$\u POST数组中的字符?,php,regex,postback,Php,Regex,Postback,如果我通过$传递名称中带有的PHP变量,那么PHP会自动将它们替换为字符。例如: <?php echo "url is ".$_SERVER['REQUEST_URI']."<p>"; echo "x.y is ".$_GET['x.y'].".<p>"; echo "x_y is ".$_GET['x_y'].".<p>"; 。。。我的问题是:有什么方法可以让这一切停止吗?我一辈子都不知道我做了什么才配得到这个 我运行的PHP版本是5.2.4-2ub

如果我通过$传递名称中带有
的PHP变量,那么PHP会自动将它们替换为
字符。例如:

<?php
echo "url is ".$_SERVER['REQUEST_URI']."<p>";
echo "x.y is ".$_GET['x.y'].".<p>";
echo "x_y is ".$_GET['x_y'].".<p>";
。。。我的问题是:有什么方法可以让这一切停止吗?我一辈子都不知道我做了什么才配得到这个


我运行的PHP版本是5.2.4-2ubuntu5.3。

发生这种情况的原因是PHP的旧register\u globals功能。这个字符不是变量名中的有效字符,因此PHP将其转换为下划线以确保兼容性


简而言之,在URL变量中使用句点不是一个好的做法。

下面是PHP.net对其使用原因的解释:

传入变量名中的点 通常,PHP不会改变 变量的名称,当它们是 传递到脚本中。但是, 应该注意的是,点(周期, 句号)不是中的有效字符 PHP变量名。因此,, 看看它:

<?php
$varname.ext;  /* invalid variable name */
?>

现在,什么 解析器看到的是一个名为 $varname,后跟字符串 串联运算符,后跟 裸字符串(即无引号的字符串 与任何已知的密钥或 保留字“ext”。显然,这 没有达到预期的效果

因此,重要的是 请注意,PHP将自动 替换传入变量中的任何点 带下划线的名称

那是我的

此外,根据这些规则,其他字符将转换为下划线:

PHP转换为(下划线)的字段名字符的完整列表如下(不仅仅是点):

  • chr(32)((空格)
  • chr(46)()(dot)
  • chr(91)([)(开方括号)
  • chr(128)-chr(159)(各种)

因此,看起来您似乎被它困住了,所以您必须使用(我只是使用)将脚本中的下划线转换回点。

早就回答了这个问题,但实际上有一个更好的答案(或解决方法)。PHP允许您使用,所以您可以这样做:

$query_string = file_get_contents('php://input');
这将为您提供查询字符串格式的$\u POST数组,句点应为

如果需要,您可以解析它(根据)


我对这个问题的解决方案既快又脏,但我仍然喜欢它。我只是想发布一个在表单上检查过的文件名列表。我使用
base64\u encode
对标记中的文件名进行编码,然后在使用它们之前用
base64\u decode
对其进行解码。

发生这种情况是因为一个句点是一个字符变量名中的无效字符,该字符在PHP实现中非常深入,因此没有简单的修复方法(目前)

同时,您可以通过以下方式解决此问题:

  • 通过
    php://input
    用于发布数据或
    $\u服务器['QUERY\u STRING']
    用于获取数据
  • 使用转换函数
  • 下面的转换函数(PHP>=5.4)将每个键值对的名称编码为十六进制表示,然后执行常规的
    parse_str()
    ;完成后,它会将十六进制名称恢复为原始形式:

    function parse_qs($data)
    {
        $data = preg_replace_callback('/(?:^|(?<=&))[^=[]+/', function($match) {
            return bin2hex(urldecode($match[0]));
        }, $data);
    
        parse_str($data, $values);
    
        return array_combine(array_map('hex2bin', array_keys($values)), $values);
    }
    
    // work with the raw query string
    $data = parse_qs($_SERVER['QUERY_STRING']);
    

    在研究了Rok的解决方案后,我提出了一个版本,该版本解决了我下面的答案、crb的上面以及Rok的解决方案中的局限性。请参阅a


    @crb的回答是一个良好的开端,但也存在一些问题

    • 它会重新处理所有内容,这太过分了;只有那些名称中有“.”的字段需要重新处理
    • 它无法以与本机PHP处理相同的方式处理数组,例如对于“foo.bar[]”之类的键
    下面的解决方案现在解决了这两个问题(请注意,它自最初发布以来已经更新)。这比我在测试中的上述答案快50%左右,但不会处理数据具有相同密钥(或提取的密钥相同,例如foo.bar和foo_bar都提取为foo_bar)的情况


    这种方法是Rok Kralj的改进版本,但需要进行一些调整,以提高效率(避免对未受影响的密钥进行不必要的回调、编码和解码)并正确处理数组密钥

    A是可用的,欢迎任何反馈或建议

    public function fix(&$target, $source, $keep = false) {                        
        if (!$source) {                                                            
            return;                                                                
        }                                                                          
        $keys = array();                                                           
    
        $source = preg_replace_callback(                                           
            '/                                                                     
            # Match at start of string or &                                        
            (?:^|(?<=&))                                                           
            # Exclude cases where the period is in brackets, e.g. foo[bar.blarg]
            [^=&\[]*                                                               
            # Affected cases: periods and spaces                                   
            (?:\.|%20)                                                             
            # Keep matching until assignment, next variable, end of string or   
            # start of an array                                                    
            [^=&\[]*                                                               
            /x',                                                                   
            function ($key) use (&$keys) {                                         
                $keys[] = $key = base64_encode(urldecode($key[0]));                
                return urlencode($key);                                            
            },                                                                     
        $source                                                                    
        );                                                                         
    
        if (!$keep) {                                                              
            $target = array();                                                     
        }                                                                          
    
        parse_str($source, $data);                                                 
        foreach ($data as $key => $val) {                                          
            // Only unprocess encoded keys                                      
            if (!in_array($key, $keys)) {                                          
                $target[$key] = $val;                                              
                continue;                                                          
            }                                                                      
    
            $key = base64_decode($key);                                            
            $target[$key] = $val;                                                  
    
            if ($keep) {                                                           
                // Keep a copy in the underscore key version                       
                $key = preg_replace('/(\.| )/', '_', $key);                        
                $target[$key] = $val;                                              
            }                                                                      
        }                                                                          
    }                                                                              
    
    公共函数修复(&$target,$source,$keep=false){
    如果(!$source){
    返回;
    }                                                                          
    $keys=array();
    $source=preg\u replace\u回调(
    '/                                                                     
    #在字符串或&
    
    (?:^ |)(?这个函数的工作是我在2013年暑假期间想到的一个好主意

    它符合标准并具有深度数组支持,例如
    a.a[x][b.a]=10
    。它在后台使用
    parse_str()
    ,并进行一些有针对性的预处理

    function fix($source) {
        $source = preg_replace_callback(
            '/(^|(?<=&))[^=[&]+/',
            function($key) { return bin2hex(urldecode($key[0])); },
            $source
        );
    
        parse_str($source, $post);
    
        $result = array();
        foreach ($post as $key => $val) {
            $result[hex2bin($key)] = $val;
        }
        return $result;
    }
    

    对于低于5.4的PHP:如果要查找任何方法来让PHP停止替换$get或$POST数组中的“.”字符,请使用
    base64_encode
    而不是
    base64_decode

    (在这种情况下,它相对简单)

    警告:修改PHP C源代码是一个高级选项

    也可以看到这一点,这表明同样的修改

    要进行探索,您需要:

    • 下载
    • 禁用更换检查
      // handle posted data (this only works with application/x-www-form-urlencoded)
      $data = parse_qs(file_get_contents('php://input'));
      
      <?php
      
      public function fix2(&$target, $source, $keep = false) {                       
          if (!$source) {                                                            
              return;                                                                
          }                                                                          
          preg_match_all(                                                            
              '/                                                                     
              # Match at start of string or &                                        
              (?:^|(?<=&))                                                           
              # Exclude cases where the period is in brackets, e.g. foo[bar.blarg]
              [^=&\[]*                                                               
              # Affected cases: periods and spaces                                   
              (?:\.|%20)                                                             
              # Keep matching until assignment, next variable, end of string or   
              # start of an array                                                    
              [^=&\[]*                                                               
              /x',                                                                   
              $source,                                                               
              $matches                                                               
          );                                                                         
      
          foreach (current($matches) as $key) {                                      
              $key    = urldecode($key);                                             
              $badKey = preg_replace('/(\.| )/', '_', $key);                         
      
              if (isset($target[$badKey])) {                                         
                  // Duplicate values may have already unset this                    
                  $target[$key] = $target[$badKey];                                  
      
                  if (!$keep) {                                                      
                      unset($target[$badKey]);                                       
                  }                                                                  
              }                                                                      
          }                                                                          
      }                                                                              
      
      public function fix(&$target, $source, $keep = false) {                        
          if (!$source) {                                                            
              return;                                                                
          }                                                                          
          $keys = array();                                                           
      
          $source = preg_replace_callback(                                           
              '/                                                                     
              # Match at start of string or &                                        
              (?:^|(?<=&))                                                           
              # Exclude cases where the period is in brackets, e.g. foo[bar.blarg]
              [^=&\[]*                                                               
              # Affected cases: periods and spaces                                   
              (?:\.|%20)                                                             
              # Keep matching until assignment, next variable, end of string or   
              # start of an array                                                    
              [^=&\[]*                                                               
              /x',                                                                   
              function ($key) use (&$keys) {                                         
                  $keys[] = $key = base64_encode(urldecode($key[0]));                
                  return urlencode($key);                                            
              },                                                                     
          $source                                                                    
          );                                                                         
      
          if (!$keep) {                                                              
              $target = array();                                                     
          }                                                                          
      
          parse_str($source, $data);                                                 
          foreach ($data as $key => $val) {                                          
              // Only unprocess encoded keys                                      
              if (!in_array($key, $keys)) {                                          
                  $target[$key] = $val;                                              
                  continue;                                                          
              }                                                                      
      
              $key = base64_decode($key);                                            
              $target[$key] = $val;                                                  
      
              if ($keep) {                                                           
                  // Keep a copy in the underscore key version                       
                  $key = preg_replace('/(\.| )/', '_', $key);                        
                  $target[$key] = $val;                                              
              }                                                                      
          }                                                                          
      }                                                                              
      
      function fix($source) {
          $source = preg_replace_callback(
              '/(^|(?<=&))[^=[&]+/',
              function($key) { return bin2hex(urldecode($key[0])); },
              $source
          );
      
          parse_str($source, $post);
      
          $result = array();
          foreach ($post as $key => $val) {
              $result[hex2bin($key)] = $val;
          }
          return $result;
      }
      
      $_POST   = fix(file_get_contents('php://input'));
      $_GET    = fix($_SERVER['QUERY_STRING']);
      $_COOKIE = fix($_SERVER['HTTP_COOKIE']);
      
      Array ( [a.a] => Array ( [0] => bb [1] => BB ) [c_c] => dd )
      <input name="data[database.username]">  
      <input name="data[database.password]">  
      <input name="data[something.else.really.deep]">  
      
      <input name="database.username"> 
      <input name="database.password"> 
      <input name="something.else.really.deep">  
      
      $posdata = $_POST['data'];
      
        <input type='text' value='First-.' name='alpha.beta[a.b][]' /><br>
        <input type='text' value='Second-.' name='alpha.beta[a.b][]' /><br>
        <input type='text' value='First-_' name='alpha_beta[a.b][]' /><br>
        <input type='text' value='Second-_' name='alpha_beta[a.b][]' /><br>
      
        'alpha_beta' => 
          array (size=1)
            'a.b' => 
              array (size=4)
                0 => string 'First-.' (length=7)
                1 => string 'Second-.' (length=8)
                2 => string 'First-_' (length=7)
                3 => string 'Second-_' (length=8)
      
        'alpha.beta' => 
          array (size=1)
            'a.b' => 
              array (size=2)
                0 => string 'First-.' (length=7)
                1 => string 'Second-.' (length=8)
        'alpha_beta' => 
          array (size=1)
            'a.b' => 
              array (size=2)
                0 => string 'First-_' (length=7)
                1 => string 'Second-_' (length=8)
      
      function getRealPostArray() {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {#Nothing to do
            return null;
        }
        $neverANamePart = '~#~'; #Any arbitrary string never expected in a 'name'
        $postdata = file_get_contents("php://input");
        $post = [];
        $rebuiltpairs = [];
        $postraws = explode('&', $postdata);
        foreach ($postraws as $postraw) { #Each is a string like: 'xxxx=yyyy'
          $keyvalpair = explode('=',$postraw);
          if (empty($keyvalpair[1])) {
            $keyvalpair[1] = '';
          }
          $pos = strpos($keyvalpair[0],'%5B');
          if ($pos !== false) {
            $str1 = substr($keyvalpair[0], 0, $pos);
            $str2 = substr($keyvalpair[0], $pos);
            $str1 = str_replace('.',$neverANamePart,$str1);
            $keyvalpair[0] = $str1.$str2;
          } else {
            $keyvalpair[0] = str_replace('.',$neverANamePart,$keyvalpair[0]);
          }
          $rebuiltpair = implode('=',$keyvalpair);
          $rebuiltpairs[]=$rebuiltpair;
        }
        $rebuiltpostdata = implode('&',$rebuiltpairs);
        parse_str($rebuiltpostdata, $post);
        $fixedpost = [];
        foreach ($post as $key => $val) {
          $fixedpost[str_replace($neverANamePart,'.',$key)] = $val;
        }
        return $fixedpost;
      }
      
      <?php
      unset($_POST);
      $_POST = array();
      $p0 = explode('&',file_get_contents('php://input'));
      foreach ($p0 as $key => $value)
      {
       $p1 = explode('=',$value);
       $_POST[$p1[0]] = $p1[1];
       //OR...
       //$_POST[urldecode($p1[0])] = urldecode($p1[1]);
      }
      print_r($_POST);
      ?>
      
      function parseQueryString($data)
      {
          $data = rawurldecode($data);   
          $pattern = '/(?:^|(?<=&))[^=&\[]*[^=&\[]*/';       
          $data = preg_replace_callback($pattern, function ($match){
              return bin2hex(urldecode($match[0]));
          }, $data);
          parse_str($data, $values);
      
          return array_combine(array_map('hex2bin', array_keys($values)), $values);
      }
      
      $_GET = parseQueryString($_SERVER['QUERY_STRING']);