2010-10-08 20 views
1

En PHP, je veux comparer deux URL relatives pour l'égalité. La capture: les URL peuvent différer en pourcentage d'encodage, par ex.PHP: comparer les URI qui diffèrent par le codage en pourcentage

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

Selon RFC 3986, les serveurs doivent traiter ces URIs de manière identique. Mais si j'utilise == pour comparer, je vais me retrouver avec une discordance. Donc je cherche une fonction PHP qui acceptera deux chaînes et retournera TRUE si elles représentent le même URI (décompter des variantes encodées/décodées du même caractère, majuscules/minuscules hexadécimales en caractères codés , et + par rapport à %20 pour les espaces), et FALSE si elles sont différentes.

Je sais d'avance que seuls les caractères ASCII sont dans ces chaînes - pas unicode.

Répondre

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

hah. quelle solution simple et évidente! agréable. +1 –

0

EDIT: S'il vous plaît consulter la réponse de @ webbiedave. Son est beaucoup mieux (je n'étais même pas conscient qu'il y avait une fonction en PHP pour faire cela .. apprendre quelque chose de nouveau tous les jours)

Vous devrez analyser les chaînes pour trouver quelque chose correspondant %## pour trouver les occurrences de ces pourcentages d'encodage. Ensuite, en prenant le nombre de ceux-ci, vous devriez être en mesure de le passer afin que la fonction chr() pour obtenir le caractère de ces codages pour cent. Reconstruisez les chaînes et vous devriez être capable de les faire correspondre.

Nous ne sommes pas sûr que ce soit la méthode la plus efficace, mais étant donné que les URL ne sont généralement pas très longues, elles ne devraient pas être trop touchées.

0

Je sais que ce problème semble être résolu par webbiedave, mais j'ai eu mes propres problèmes.

Premier problème: les caractères codés sont insensibles à la casse. Donc,% C3 et% c3 sont tous les deux exactement le même caractère, bien qu'ils soient différents comme URI. Les deux URI pointent donc vers le même emplacement.

Deuxième problème: le dossier% 20 (2) et le dossier% 20% 282% 29 sont tous deux des URI valablement codés en url, qui pointent vers le même emplacement, bien qu'il s'agisse d'URI différents.

Troisième problème: Si je me débarrasse des caractères codés en url, j'ai deux emplacements ayant le même URI comme bla% 2Fblubb et bla/blubb.

Alors que faire alors? Afin de comparer deux URIs, j'ai besoin de les normaliser tous les deux de manière à les séparer dans tous les composants, urdecoder tous les chemins et parties de requêtes pour une fois, les écraser et les coller ensemble et ensuite les comparer.

Et cela pourrait être la fonction de la normaliser:

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

Maintenant, vous pouvez modifier la fonction de webbiedave à ceci:

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

Cela devrait faire. Et oui, c'est plus compliqué que je ne le voulais.