質問

PHPでは、平等について2つの相対URLを比較したいと考えています。キャッチ:URLはエンコードパーセントが異なる場合があります。

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

によると RFC 3986, 、サーバーはこれらのURIを同じように処理する必要があります。しかし、私が使用する場合 == 比較するために、私はミスマッチになります。

だから私は2つの文字列と返品を受け入れるPHP関数を探しています TRUE それらが同じURIを表している場合(エンコードされたCHARSのエンコード/デコードされたバリアント、エンコードされたCHARの上部/低ケースの16進数、および測定されます。 + vs。 %20 スペース用)、および FALSE それらが違う場合。

私は、これらの文字列にあるASCII charのみがあることを事前に知っています - ユニコードはありません。

役に立ちましたか?

解決

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

他のヒント

編集: @webbiedaveの応答をご覧ください。彼の方がはるかに優れています(PHPにそれを行う機能があることを知りませんでした。毎日何か新しいことを学びます)

一致するものを探すために文字列を解析する必要があります %## それらのパーセントエンコーディングの発生を見つけるため。その後、それらから番号を取ると、あなたはそれを渡すことができるはずですので chr() これらのパーセントエンコーディングの特性を取得する機能。文字列を再構築すると、それらを一致させることができるはずです。

それが最も効率的な方法であるかどうかはわかりませんが、URLが通常それほど長くないことを考慮すると、パフォーマンスのヒットはそれほど多くないはずです。

ここでこの問題はWebbiedaveによって解決されているように見えることを知っていますが、私はそれについて私自身の問題を抱えていました。

最初の問題:エンコードされた文字はケース非感受性です。したがって、%C3と%C3は両方ともまったく同じ文字ですが、URIとは異なります。したがって、両方のウリスは同じ場所を指しています。

2番目の問題:フォルダー%20(2)とフォルダー%20%282%29はどちらも有効にurlencoded urisです。

3番目の問題:URLエンコードされた文字を取り除くと、BLA%2FBLUBBやBLA/BLUBBと同じURIを持つ2つの場所があります。

それで、何をすべきか? 2つのURIを比較するには、すべてのコンポーネントでそれらを分割し、すべてのパスとクエリパートを1回分割する方法で両方のURIを正規化する必要があります。

そして、これはそれを正常化する機能かもしれません:

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

それはすべきです。そして、はい、それは私が望んでいたよりも非常に複雑です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top