2010-10-08 77 views
1

在PHP中,我想比较两个相对的URL是否相等。 catch:URL在百分比编码方面可能不同,例如PHP:比较不同百分比编码的URI

  • /dir/file+file/dir/file%20file
  • /dir/file(file)/dir/file%28file%29
  • /dir/file%5bfile/dir/file%5Bfile

RFC 3986,服务器应该同样对待这些URI。但是,如果我使用==进行比较,那么最终会出现不匹配。

所以我正在寻找一个PHP函数,它将接受两个字符串,并返回TRUE,如果它们表示相同的URI(对同一个char进行编码/解码的变体,编码字符中的大写/小写十六进制数字,+%20(空格))和FALSE(如果它们不同)。

我事先知道只有ASCII字符在这些字符串中 - 没有unicode。

回答

4
function uriMatches($uri1, $uri2) 
{ 
    return urldecode($uri1) == urldecode($uri2); 
} 

echo uriMatches('/dir/file+file', '/dir/file%20file');  // TRUE 
echo uriMatches('/dir/file(file)', '/dir/file%28file%29'); // TRUE 
echo uriMatches('/dir/file%5bfile', '/dir/file%5Bfile'); // TRUE 

urldecode

+0

哈。多么简单明显的解决方案!不错。 +1 – 2010-10-08 21:59:28

0

编辑:请看看@ webbiedave的响应。他更好(我甚至没有意识到在PHP中有这样的功能可以做到这一点..每天学点新东西)

你将不得不解析字符串来寻找匹配%##的东西来找到这些百分比编码。然后从这些数字中取出数字,您应该能够通过它,以便chr()函数获得这些百分比编码的字符。重建字符串,然后你应该能够匹配它们。

不知道这是最有效的方法,但考虑到URL通常不会那么长,它不应该是太多的性能影响。

0

我知道这里的问题似乎是通过webbiedave解决的,但是我有自己的问题。

第一个问题:编码字符不区分大小写。所以%C3和%c3都是完全相同的字符,尽管它们与URI不同。所以这两个URI指向相同的位置。

问题二:文件夹%20(2)和文件夹的%20%282%29都是有效的URI urlencoded进行,这点到相同的位置,尽管它们是不同的URI。

第三个问题:如果我摆脱了url编码字符,我有两个位置具有相同的URI,如bla%2Fblubb和bla/blubb。

那么该怎么做呢?为了比较两个URI,我需要以这种方式对它们进行规范化,以便将它们分解到所有组件中,对所有路径和查询部分进行一次url解码,rawurlencode并将它们粘合在一起,然后我可以对它们进行比较。

而且这可能是功能正常化它:

function normalizeURI($uri) { 
    $components = parse_url($uri); 
    $normalized = ""; 
    if ($components['scheme']) { 
     $normalized .= $components['scheme'] . ":"; 
    } 
    if ($components['host']) { 
     $normalized .= "//"; 
     if ($components['user']) { //this should never happen in URIs, but still probably it's anything can happen thursday 
      $normalized .= rawurlencode(urldecode($components['user'])); 
      if ($components['pass']) { 
       $normalized .= ":".rawurlencode(urldecode($components['pass'])); 
      } 
      $normalized .= "@"; 
     } 
     $normalized .= $components['host']; 
     if ($components['port']) { 
      $normalized .= ":".$components['port']; 
     } 
    } 
    if ($components['path']) { 
     if ($normalized) { 
      $normalized .= "/"; 
     } 
     $path = explode("/", $components['path']); 
     $path = array_map("urldecode", $path); 
     $path = array_map("rawurlencode", $path); 
     $normalized .= implode("/", $path); 
    } 
    if ($components['query']) { 
     $query = explode("&", $components['query']); 
     foreach ($query as $i => $c) { 
      $c = explode("=", $c); 
      $c = array_map("urldecode", $c); 
      $c = array_map("rawurlencode", $c); 
      $c = implode("=", $c); 
      $query[$i] = $c; 
     } 
     $normalized .= "?".implode("&", $query); 
    } 
    return $normalized; 
} 

现在你可以改变webbiedave的功能,这一点:

function uriMatches($uri1, $uri2) { 
    return normalizeURI($uri1) === normalizeURI($uri2); 
} 

这应该做的。是的,它比我想要的要复杂得多。