378 votes

urlencode vs rawurlencode?

Si je veux créer une URL en utilisant une variable, j'ai deux choix pour encoder la chaîne. urlencode() et rawurlencode() .

Quelles sont exactement les différences et qui est préféré?

323voto

Jonathan Fingland Points 26224

Cela dépendra de votre objectif. Si l'interopérabilité avec d'autres systèmes est important, alors il semble rawurlencode est le chemin à parcourir. La seule exception est l'héritage des systèmes qui attendent la chaîne de requête pour suivre la forme-le style d'encodage des espaces codés comme des + au lieu de %20 (dans ce cas, vous avez besoin de la fonction urlencode).

rawurlencode suit RFC 1738 avant PHP 5.3.0 et RFC 3986 par la suite (voir http://us2.php.net/manual/en/function.rawurlencode.php)

Renvoie une chaîne dans laquelle tous les caractères non-alphanumériques sauf -_.~ ont été remplacés par un pourcentage (%) signe suivi de deux chiffres hexadécimaux. C'est l'encodage décrit dans la » RFC 3986 pour la protection des caractères interprétés comme des URL spéciale délimiteurs, et pour protéger Url mutilé par des supports de transmission avec les conversions de caractères (comme certains systèmes de messagerie).

Note sur la RFC 3986 vs 1738. rawurlencode avant php 5.3 codé le caractère tilde (~) selon la RFC 1738. Depuis PHP 5.3, cependant, rawurlencode suit RFC 3986 qui ne nécessite pas de codage tilde caractères.

urlencode code pour les espaces comme des signes plus (pas comme %20 comme le fait le rawurlencode)(voir http://us2.php.net/manual/en/function.urlencode.php)

Renvoie une chaîne dans laquelle tous les caractères non-alphanumériques sauf -_. ont été remplacés par un pourcentage (%) signe suivi de deux chiffres hexadécimaux et des espaces codés comme des signes plus ( + ). Il est codé de la même manière que les données publiées, à partir d'un formulaire web est codé, qui est de la même manière que dans l'application/x-www-form-urlencoded type de média. Cela diffère de la » RFC 3986 de codage (voir rawurlencode()) que pour des raisons historiques, les espaces sont codés comme des signes plus ( + ).

Cela correspond à la définition de l'application/x-www-form-urlencoded dans la RFC 1866.

Lectures Supplémentaires:

Vous pouvez également voir la discussion à http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode.

Aussi, la RFC 2396 vaut le coup d'oeil. La RFC 2396 définit l'URI valide la syntaxe. La partie principale qui nous intéresse, c'est de 3,4 Composant de Requête:

Au sein d'un composant de requête, les personnages ";", "/", "?", ":", "@", sont réservés.

Comme vous pouvez le voir, l'
est un caractère réservé dans la chaîne de requête, et, donc, doivent être codées conformément à la RFC 3986 (comme dans rawurlencode).

213voto

Incognito Points 10637

La preuve est dans le code source de PHP.

Je vais vous emmener à travers un processus rapide de la façon de trouver ce genre de chose sur votre propre, dans l'avenir, à tout moment vous voulez. Ours avec moi, il y a beaucoup de code source C, vous pouvez effleurer (je l'expliquer). Si vous voulez pinceau sur un peu de C, un bon endroit pour commencer est de notre wiki.

Télécharger de la source (ou de l'utilisation http://lxr.php.net/ le parcourir en ligne), grep tous les fichiers pour le nom de la fonction, vous trouverez quelque chose comme ceci:

PHP 5.3.6 (les plus récentes au moment de la rédaction) décrit les deux fonctions dans leur propre C de code dans le fichier url.c.

RawUrlEncode()

PHP_FUNCTION(rawurlencode)
{
    char *in_str, *out_str;
    int in_str_len, out_str_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
                              &in_str_len) == FAILURE) {
        return;
    }

    out_str = php_raw_url_encode(in_str, in_str_len, &out_str_len);
    RETURN_STRINGL(out_str, out_str_len, 0);
}

La fonction UrlEncode()

PHP_FUNCTION(urlencode)
{
    char *in_str, *out_str;
    int in_str_len, out_str_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
                              &in_str_len) == FAILURE) {
        return;
    }

    out_str = php_url_encode(in_str, in_str_len, &out_str_len);
    RETURN_STRINGL(out_str, out_str_len, 0);
}

Ok, donc ce qui est différent ici?

Ils sont, en substance, appelant les deux différentes fonctions internes respectivement: php_raw_url_encode et php_url_encode

Allez donc regarder pour ces fonctions!

Permet de regarder php_raw_url_encode

PHPAPI char *php_raw_url_encode(char const *s, int len, int *new_length)
{
    register int x, y;
    unsigned char *str;

    str = (unsigned char *) safe_emalloc(3, len, 1);
    for (x = 0, y = 0; len--; x++, y++) {
        str[y] = (unsigned char) s[x];
#ifndef CHARSET_EBCDIC
        if ((str[y] < '0' && str[y] != '-' && str[y] != '.') ||
            (str[y] < 'A' && str[y] > '9') ||
            (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||
            (str[y] > 'z' && str[y] != '~')) {
            str[y++] = '%';
            str[y++] = hexchars[(unsigned char) s[x] >> 4];
            str[y] = hexchars[(unsigned char) s[x] & 15];
#else /*CHARSET_EBCDIC*/
        if (!isalnum(str[y]) && strchr("_-.~", str[y]) != NULL) {
            str[y++] = '%';
            str[y++] = hexchars[os_toascii[(unsigned char) s[x]] >> 4];
            str[y] = hexchars[os_toascii[(unsigned char) s[x]] & 15];
#endif /*CHARSET_EBCDIC*/
        }
    }
    str[y] = '\0';
    if (new_length) {
        *new_length = y;
    }
    return ((char *) str);
}

Et bien sûr, php_url_encode:

PHPAPI char *php_url_encode(char const *s, int len, int *new_length)
{
    register unsigned char c;
    unsigned char *to, *start;
    unsigned char const *from, *end;

    from = (unsigned char *)s;
    end = (unsigned char *)s + len;
    start = to = (unsigned char *) safe_emalloc(3, len, 1);

    while (from < end) {
        c = *from++;

        if (c == ' ') {
            *to++ = '+';
#ifndef CHARSET_EBCDIC
        } else if ((c < '0' && c != '-' && c != '.') ||
                   (c < 'A' && c > '9') ||
                   (c > 'Z' && c < 'a' && c != '_') ||
                   (c > 'z')) {
            to[0] = '%';
            to[1] = hexchars[c >> 4];
            to[2] = hexchars[c & 15];
            to += 3;
#else /*CHARSET_EBCDIC*/
        } else if (!isalnum(c) && strchr("_-.", c) == NULL) {
            /* Allow only alphanumeric chars and '_', '-', '.'; escape the rest */
            to[0] = '%';
            to[1] = hexchars[os_toascii[c] >> 4];
            to[2] = hexchars[os_toascii[c] & 15];
            to += 3;
#endif /*CHARSET_EBCDIC*/
        } else {
            *to++ = c;
        }
    }
    *to = 0;
    if (new_length) {
        *new_length = to - start;
    }
    return (char *) start;
}

Rapide, peu de connaissances avant de m'avancer, EBCDIC est un autre jeu de caractères, semblable à l'ASCII, mais un total concurrent. PHP tente de composer avec les deux. Mais fondamentalement, cela signifie octet EBCDIC 0x4c octet n'est pas l' L en ASCII, c'est en fait un <. Je suis sûr que vous voyez la confusion ici.

Ces deux fonctions gérer EBCDIC si le serveur web a défini.

Aussi, ils utilisent tous les deux un tableau de caractères (pensez au type de chaîne) hexchars de recherche pour obtenir des valeurs, le tableau est décrit comme tel:

/* rfc1738:

   ...The characters ";",
   "/", "?", ":", "@", "=" and "&" are the characters which may be
   reserved for special meaning within a scheme...

   ...Thus, only alphanumerics, the special characters "$-_.+!*'(),", and
   reserved characters used for their reserved purposes may be used
   unencoded within a URL...

   For added safety, we only leave -_. unencoded.
 */

static unsigned char hexchars[] = "0123456789ABCDEF";

Au-delà, les fonctions sont vraiment différents, et je vais expliquer en ASCII et EBCDIC.

Les différences en ASCII:

URLENCODE:

  • Calcule un début/fin de la longueur de la chaîne en entrée, alloue de la mémoire
  • Promenades à travers un certain temps, en boucle par incréments jusqu'à ce que nous atteignons la fin de la chaîne
  • Attrape le caractère actuel
  • Si le personnage est égal à caractères ASCII dans le fichier 0x20 (c'est à dire, un "espace"), ajouter un + signe de la chaîne de sortie.
  • Si ce n'est pas un espace, et il n'est pas non alphanumériques (isalnum(c)), et n'est pas également et _, -ou . caractère, puis nous , sortie de une % signe de la matrice de la position 0, faire un tableau regarde à l' hexchars tableau pour une liste de choix pour os_toascii tableau (un tableau à partir d' Apache qui se traduit par char à code hex) pour la clé de c (le caractère actuel), nous avons ensuite au niveau du bit décalage à droite par 4, affecter cette valeur à l'caractères 1 et position 2 nous attribuer la même recherche, sauf que nous préforme dans une logique de voir si la valeur est de 15 (0xF), et retour à 1 dans ce cas, ou 0 sinon. À la fin, vous vous retrouverez avec quelque chose de codé.
  • Si elle se retrouve ce n'est pas un espace, c'est alphanumérique ou l'une de l' _-. caractères, il génère exactement ce que c'est.

RAWURLENCODE:

  • Alloue de la mémoire pour la chaîne
  • Parcourt-il en fonction de la durée prévue dans l'appel de fonction (pas calculé en fonction avec la fonction URLENCODE).

Remarque: de Nombreux programmeurs n'ont probablement jamais vu une boucle pour parcourir cette façon, il est un peu hackish et non pas à la convention standard utilisé avec la plupart pour des boucles, attention, il attribue x et y, les contrôles pour la sortie sur len d'atteindre 0, et incrémente les deux x et y. Je sais, ce n'est pas ce que vous attendez, mais c'est le code valide.

  • Attribue la présente le caractère d'une correspondance de la position d'un caractère dans str.
  • Il vérifie si le caractère est alphanumérique, ou de l'une de la _-. caractères, et si elle ne l'est pas, nous le faisons presque la même mission qu'avec URLENCODE où il préformes recherches, cependant, on incrémente de façon différente, avec y++ plutôt que d' to[1], c'est parce que les cordes sont en train d'être construit de différentes façons, mais atteindre le même objectif à la fin de toute façon.
  • Quand la boucle est terminée et la longueur de l'allée, Il termine la chaîne, de l'affectation de la \0 octet.
  • Elle retourne la chaîne codée.

Différences:

  • UrlEncode vérifie l'espace, attribue un signe+, RawURLEncode ne le fait pas.
  • UrlEncode n'attribue pas d' \0 d'octets de la chaîne, RawUrlEncode (cela peut être un point discutable)
  • Ils itérer differntly, on peut être enclin à débordement avec la malformation de cordes, je suis suggère simplement que cette et je n'ai pas réellement étudié.

En gros, ils itérer différemment, on attribue un signe + dans le cas de l'ASCII 20.

Les différences dans EBCDIC:

URLENCODE:

  • Même itération de l'installation comme avec l'ASCII
  • Toujours de traduire le caractère "espace" pour un + signe. Remarque: je pense que ce doit être compilé en EBCDIC ou vous vous retrouverez avec un bug? Quelqu'un peut-il modifier et confirmer cela?
  • Il vérifie si le char est un char avant d' 0, à l'exception de la un . ou -, OU moins de A mais de plus de char 9, OU de plus de Z et moins de a mais pas un _. OU supérieure à z (ouais, EBCDIC est un peu foiré à travailler). Si elle correspond à l'un de ces, faire une semblable recherche, comme dans la version ASCII (il n'a tout simplement pas besoin d'une recherche dans os_toascii).

RAWURLENCODE:

  • Même itération de l'installation comme avec l'ASCII
  • Même vérification que décrit dans l'EBCDIC version de les Encoder, à l'exception que si il est plus grand que z, il exclut ~ à partir de l'URL de l'encodage.
  • Même affectation que l'ASCII RawUrlEncode
  • Encore l'ajout de la \0 d'octets de la chaîne avant le retour.

Grand Résumé

  • Les deux utilisent le même hexchars table de recherche
  • URIEncode ne pas mettre fin à une chaîne avec des \0, raw.
  • Si vous travaillez en EBCDIC je suggérerais à l'aide de RawUrlEncode, car il gère la ~ que UrlEncode ne le fait pas (c'est une question). Il est intéressant de noter que l'ASCII et EBCDIC 0x20 sont les deux espaces.
  • Ils itérer différemment, on peut être plus rapide, on peut être enclin à mémoire ou chaîne de caractères en fonction des exploits.
  • URIEncode fait d'un espace en +, RawUrlEncode fait d'un espace en %20 via la matrice de recherches.

Avertissement: je n'ai pas touché C depuis des années, et je n'ai pas regardé EBCDIC dans un très très long moment. Si je me trompe quelque part, laissez-moi savoir.

Suggéré implémentations

Basé sur tout cela, rawurlencode est la façon de passer la plupart du temps. Comme vous le voyez dans Jonathan Fingland réponse, rester avec elle dans la plupart des cas. Il traite avec le schéma moderne pour URI composants, où que urlencode fait des choses de la old school, où " + " signifie "espace".

Si vous essayez de convertir entre l'ancien format et de nouveaux formats, assurez-vous que votre code n'est pas gaffe et tourner à quelque chose qui est décodé signe + dans l'espace par mégarde le double encodage, ou similaire "oups" scénarios autour de cet espace/20%/+ question.

Si vous travaillez sur un ancien système avec des logiciels plus anciens qui ne préfère pas le nouveau format, le bâton avec urlencode, je crois cependant qu' %20 sera effectivement compatible, comme sous l'ancienne norme %20 travaillé, je n'ai pas de préférence. Donner un coup de feu si vous êtes pour jouer, laissez-nous savoir comment il a travaillé pour vous.

Fondamentalement, vous devriez coller avec la matière première, à moins que votre EBCDIC système vraiment vous hait. La plupart des programmeurs ne sera jamais exécuté en EBCDIC sur tout autre système après l'an 2000, peut-être même des années 1990 (qui pousse, mais toujours probable à mon avis).

37voto

jitter Points 35805
 echo rawurlencode('http://www.google.com/index.html?id=asd asd');
 

rendements

 http%3A%2F%2Fwww.google.com%2Findex.html%3Fid%3Dasd%20asd
 

tandis que

 echo urlencode('http://www.google.com/index.html?id=asd asd');
 

rendements

 http%3A%2F%2Fwww.google.com%2Findex.html%3Fid%3Dasd+asd
 

La différence étant le asd%20asd vs asd+asd

urlencode diffère de RFC 1738 en codant des espaces comme + au lieu de %20

28voto

Neven Boyanov Points 356

Une raison pratique pour choisir entre l'un ou l'autre est si vous allez utiliser le résultat dans un autre environnement, par exemple en JavaScript.

En PHP urlencode('test 1') retours 'test+1' tout rawurlencode('test 1') retours 'test%201' comme résultat.

Mais si vous avez besoin de "décoder" ce en JavaScript à l'aide de decodeURI() fonction d' decodeURI("test+1") vous donnera "test+1" tout decodeURI("test%201") vous donnera "test 1" comme résultat.

En d'autres termes, l'espace (" ") codée par urlencode de plus ("+") en PHP ne sera pas correctement décodé par decodeURI en JavaScript.

Dans de tels cas, le rawurlencode fonction PHP doit être utilisé.

21voto

Salman A Points 60620

Je crois que les espaces doivent être codées comme:

  • %20 lorsqu'il est utilisé dans l'URL du chemin
  • + lorsqu'il est utilisé dans l'URL de requête composant ou de la forme des données (voir 17.13.4 Forme de types de contenu)

L'exemple suivant montre l'utilisation correcte de l' rawurlencode et urlencode:

echo "http://example.com"
    . "/category/" . rawurlencode("latest songs")
    . "/search?q=" . urlencode("lady gaga");

Sortie:

http://example.com/category/latest%20songs/search?q=lady+gaga

Qu'advient-il si vous encodez chemin d'accès et la chaîne de requête de composants dans l'autre sens? Pour l'exemple suivant:

http://example.com/category/latest+songs/search?q=lady%20gaga
  • Le serveur va chercher le répertoire latest+songs au lieu de latest songs
  • Le paramètre de chaîne de requête q contiendra lady gaga

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X