PHP: сравнение URI, которые отличаются процентным кодированием - PullRequest
1 голос
/ 09 октября 2010

В 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 - нет юникода.

Ответы [ 3 ]

4 голосов
/ 09 октября 2010
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 голосов
/ 22 января 2018

Я знаю, что эта проблема, похоже, решается с помощью webbiedave, но у меня были свои проблемы с ней.

Первая проблема: в кодированных символах не учитывается регистр.Таким образом,% C3 и% c3 являются абсолютно одинаковыми символами, хотя они отличаются в качестве URI.Таким образом, оба URI указывают на одно и то же местоположение.

Вторая проблема: папка% 20 (2) и папка% 20% 282% 29 оба являются URI с правильно заданным URL-адресом, которые указывают на одно и то же местоположение, хотя и являются разными URI.

Третья проблема: если я избавлюсь от символов, закодированных по URL, у меня будет два местоположения с одинаковым URI, например, bla% 2Fblubb и bla / blubb.

Так что же делать дальше?Чтобы сравнить два URI, мне нужно нормализовать оба из них так, чтобы я разделил их по всем компонентам, за один раз кодировал все пути и части запроса, кодировал их rawurlen и снова склеивал, а затем мог сравнить их.

И это может быть функция для ее нормализации:

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

Это должно сработать.И да, все гораздо сложнее, чем я хотел.

0 голосов
/ 09 октября 2010

РЕДАКТИРОВАТЬ: Пожалуйста, посмотрите на ответ @ webbiedave. Он намного лучше (я даже не знал, что в PHP есть функция, которая делает это… каждый день учится чему-то новому)

Вам нужно будет проанализировать строки, чтобы найти что-то, совпадающее с %##, чтобы найти случаи кодирования этих процентов. Затем, взяв число из них, вы сможете передать его так, чтобы функция chr () получала символ этих процентных кодировок. Восстановите строки, и тогда вы сможете их сопоставить.

Не уверен, что это самый эффективный метод, но, учитывая, что URL-адреса обычно не такие длинные, это не должно сильно сказываться на производительности.

...