代码之家  ›  专栏  ›  技术社区  ›  Justin Grant

PHP:比较不同百分比编码的uri

  •  1
  • Justin Grant  · 技术社区  · 15 年前

    在PHP中,我想比较两个相对url的相等性。注意: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(对相同字符的编码/解码变体、编码字符中的大写/小写十六进制数字进行计数,以及 + 与。 %20 对于空间),以及 FALSE 如果他们不一样。

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

    3 回复  |  直到 15 年前
        1
  •  4
  •   webbiedave    15 年前
    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

        2
  •  0
  •   Jared    15 年前

    编辑: 请看韦比戴夫的回答。他的好得多(我甚至不知道PHP中有一个函数可以做到这一点)。。每天学习新的东西)

    您必须解析字符串以查找匹配的内容 %## 查找这些百分比编码的发生率。然后从上面取下号码,你就可以把它传给 chr() 函数获取这些百分比编码的字符。重建字符串,然后您应该能够匹配它们。

    不确定这是最有效的方法,但是考虑到url通常不会那么长,所以不应该对性能造成太大的影响。

        3
  •  0
  •   Krassmus    8 年前

    我知道这个问题似乎是韦比戴夫解决的,但我有自己的问题。

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

    第二个问题:文件夹%20(2)和文件夹%20%282%29都是有效的urlencoded uri,它们指向相同的位置,尽管它们是不同的uri。

    第三个问题:如果去掉url编码的字符,我有两个具有相同URI的位置,比如bla%2fblub和bla/blubb。

    那该怎么办呢?为了比较两个uri,我需要对它们进行规范化,以便在所有组件中对它们进行拆分,对所有路径和查询部分进行urldecode一次,对它们进行rawurlcode并将它们粘在一起,然后再进行比较。

    这可能是规范化它的函数:

    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;
    }
    

    现在你可以把韦比戴夫的功能改成:

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

    应该可以。是的,这比我想象的要复杂得多。

    推荐文章