在PHP中,我想比较两个相对URL的相等性。 catch:URL可能在百分比编码方面有所不同,例如:
/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。
答案 0 :(得分: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
答案 1 :(得分:0)
编辑:请查看@ webbiedave的回复。他的状况要好得多(我甚至不知道PHP中有一个函数可以做到这一点......每天都学到新东西)
您必须解析字符串以查找与%##
匹配的内容,以查找这些百分比编码的出现次数。然后从这些数字中取出数字,您应该能够通过它chr()函数来获取这些百分比编码的字符。重建字符串然后你应该能够匹配它们。
不确定这是最有效的方法,但考虑到URL通常不会那么长,它不应该太过性能损失。
答案 2 :(得分:0)
我知道这个问题似乎是通过webbiedave解决的,但我有自己的问题。
第一个问题:编码字符不区分大小写。所以%C3和%c3都是完全相同的字符,尽管它们作为URI是不同的。所以两个URI都指向同一个位置。
第二个问题:文件夹%20(2)和文件夹%20%282%29都是有效的urlencoded URI,它们指向相同的位置,尽管它们是不同的URI。
第三个问题:如果我删除了url编码的字符,我有两个具有相同URI的位置,如bla%2Fblubb和bla / blubb。
那么该怎么做?为了比较两个URI,我需要按照我在所有组件中拆分它们的方式对它们进行规范化,urldecode所有路径和查询部分一次,rawurlencode它们并将它们粘合在一起然后我可以比较它们。 / p>
这可能是规范它的功能:
scanf
现在你可以改变webbiedave的功能:
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;
}
应该这样做。是的,它比我想要的要复杂得多。