Url encoding

Résolu
Lestat_2070 Messages postés 71 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 5 mars 2007 - 4 mars 2007 à 12:19
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007 - 5 mars 2007 à 21:27
Bonjour à tous,
Tout d'abord, j'espère que je ne me trompes pas de section, pour ce sujet. Ensuite, j'essaye de faire une fonction comparable à la fonction php urlencode(), mais j'ai un peu de mal . Pour ceux qui ne sauraient pas son utilité, voir son utilité http://fr.php.net/urlencode.
Donc, mon code en C se présente comme celà:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
    int i=0;
    int len=strlen("ïÍ)kÆu");
    char* final=new char[len];
    memcpy(final, "ïÍ)kÆu", (len+1));
    while(i != len)
    {
        printf("%%%X",(char)final[i++] & 0xFF);
    }
    printf("\n");
    system("pause");
    return 0;
}
Ma fonction en C affiche: %EF%CD%29%6B%C6%75, où PHP affiche: %EF%CD%29k%C6u. Que dois- je changer afin de mieux encoder mes caractères, comme PHP le fait ?
Merci d'avance .

16 réponses

vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
4 mars 2007 à 12:33
J'imagine qu'il te faut une table qui te dira si un char donné doit être transformé (par exemple 'Æ') ou pas (par exemple 'k')
Un truc du style
int transform[] = {0, 0, 1, 0, ...} // Tableau de 256 entiers

et après
while(i != len)
{
  char c = final[i++];
  if(transform[i]) printf("%%%X", c);
  else printf(c);
}

Sinon:
char* final=new char[len + 1];

_____________________________________
Un éditeur de ressources gratuit pour Windows
3
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
4 mars 2007 à 12:33
Pardon: if(transform[c])

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
Lestat_2070 Messages postés 71 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 5 mars 2007
4 mars 2007 à 14:21
Bonjour vecchio56, et merci pour ta réponse rapide .
J'ai commencé à créer le tableau nommé transform, c'est un peu long et délicat, mais j'aime bien ton idée . Pour savoir quels caractères je dois encoder (et surtout par flemme (désolé ), j'ai fait un simple script en PHP:
<?php
for ($i=0;$i < 256;$i++) {
        if (urlencode(chr($i)) == chr($i))
            echo '0',',';
        else echo '1',',';
?>
Ce qui m'a donné les valeurs à mettre dans mon tableau d'entiers, nommé transform. Mon programme me donne donc au final: %EF%CD%29k%C6u, ce qui correspond bien à ce que je voulais. Ton idée est vraiment géniale, c'est magnifique, merci !
0
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007
4 mars 2007 à 21:55
sinon tu vérifie si chaque caractère de ta chaine est dans une chaine validChars (plus léger) :

#include <stdio.h>
#include <string.h>

void URLencode(char * str)
{
  char * s = str;
  char * validChars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz:/.?=_-$(){}~&";
  char * isValidChar;

  do
  {
    isValidChar = strchr(validChars, *str);
    if(!isValidChar)
    {
        printf("%%%2X", *str);
    }
    else
    {
        printf("%c", *str);
    }
  }while(*++str);
  str = s;
}

int main()
{
    URLencode("while(*str++)sqfqsfq  ///\\ ");
}

Au lieu de faire un printf tu peut ajouter a un buffer...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
4 mars 2007 à 23:47
Plus léger?? Non sérieusement ta solution est très mauvaise en performance (un strchr pour chaque caractère dans ta solution, contre un simple accès indexé pour moi)

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
Lestat_2070 Messages postés 71 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 5 mars 2007
5 mars 2007 à 00:05
@Cphil51, et merci pour ta contribution
Je ne connaissait pas isValidChar, c'est bien partique quand même. Ta fonction n'est pas mal, merci
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
5 mars 2007 à 08:16
"Je ne connaissait pas isValidChar"

isValidChar c'est juste le nom de sa variable

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007
5 mars 2007 à 09:17
C'est vrai que c'est plus lourd xD. Après reflexion... Mais le code généré devrais quand méme être un poil plus petit. Le strchr peut être substitué par une fonction "maison" faite que pour ca. Donc plus rapide ; mais après ca devrais ressembler un peut à ta solution.
Il est quand même nécessaire de privilégier le plus rapide, donc ta solution dans l'immédiat.
 
En ce moment je travail sur un projet qui demande des accès HTTP, je retravaillerais donc surement sur mon encodeur en terme d'optimisation.
0
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007
5 mars 2007 à 10:17
Bon. Voila le travail... Normalement c'est TRES rapide maintenant :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char * url_encode(const unsigned char * str)
{
  unsigned char * s = str;
  unsigned char * t = NULL;
  unsigned char * ret;
  unsigned char isValidChar[] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //16
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //32
    0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, //48
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, //64
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //80
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, //96
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //112
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, //128
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // >128
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  };

  int lenght = 0;

  // calcul de la taille de la chaine urlEncodée
  do{
    if(!isValidChar[*s])
        lenght+=3; // %xx : 3 caractères
    else
        lenght++;  // sinon un seul
  }while(*++s); // avance d'un cran dans la chaine. Si on est pas à la fin, on continue...

  s = str;
  t = (char *)malloc(sizeof(unsigned char) * (lenght + 1)); // Allocation à la bonne taille
  if(!t) exit(EXIT_FAILURE);
  ret = t;

  //encodage
  do{
    if(!isValidChar[*s])
        sprintf(t, "%%%2X", *s), t+=3;
    else
        sprintf(t, "%c", *s), t++;
  }while(*++s);

  *t = 0; // 0 final
  return ret;
}

int main()
{
    unsigned char * urlEncoded = url_encode("C:\\Program Files\\Documents web\\index.html");
    printf("%s", urlEncoded);
    free(urlEncoded);
}

@+
0
Lestat_2070 Messages postés 71 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 5 mars 2007
5 mars 2007 à 17:43
Bonjour,
Sachant que je suis resté avec la solution de vecchio56, et que j'utilise le tableau transform (plus économique en cycles processeur), je possède un problème pour la chaine suivante: ¥¼½¾¿, ayant respectivement pour nombre ASCII: 165, 188, 189, 190 et 191. On peux voir ci-dessous que tout ces caractères ASCII sont supérieurs à 128, et que tout les indices de transform, à partir de là, sont à 1 (donc à convertir).
Aussi, j'obtien %A5%BC%BD¥%BF (en C) au lieu de %A5%BC%BD%BE%BF (en PHP).
Aussi, pour la chaine ¼¢½¾¿, j'obtiens %BCó%BD¥%BF, au lieu de %BC%A2%BD%BE%BF (en PHP). Je précise que j'utilise urlencode() pour vérifier. Résumé:

En utilisant le tableau transform suivant:

Et le code suivant:
    int i=0;
    int len=5;
    char*str='¥¼½¾¿';
    while(i < len)
    {
        c = str[i++];
        if (transform[c]) printf("%%%02X", c & 0xFF);
        else printf("%c",c);    
    }
D'où peut provenir mon erreur ? Merci d'avance
0
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007
5 mars 2007 à 20:18
Essai de transformer char*str='¥¼½¾¿';
en
unsigned char*str="¥¼½¾¿";
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
5 mars 2007 à 20:20
J'ai pas ce problème:

#include <stdio.h>

int transform[] = {
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};

char hexa[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

void encode(const char* input, char* output) {
  unsigned char c;
  while(c = (unsigned char)*input++) {
    if(!transform[c]) *output++ = c;
    else {
      output[0] = '%';
      output[1] = hexa[c >> 4];
      output[2] = hexa[c & 0xF];
      output += 3;
    }
  }
  *output = 0;
}

int main()
{
  char s[32];
  encode("¥¼½¾¿", s);
  puts(s);
}

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007
5 mars 2007 à 20:24
Parceque tu travaille en unsigned.
0
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007
5 mars 2007 à 20:29
Ca n'as rien a voir avec le signe en fait. Je pese que c'est a cause des ' ' qui ne sont pas comme les " " (on est pas dans le débat de PHP la...) ces symboles n'ont pas le mème sens!
0
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
5 mars 2007 à 20:53
En effet c'est pas pareil, j'ai supposé que c'était une erreur de frappe.
Ca ne vient pas du unsigned car tous les caractères sont supérieurs à 128 ici

Sinon la fonction que t'a mise et qui fait un malloc, c'est pas trop recommendé (gros risque d'oublier la libération). En général on demande plutot à l'appelant de fournir un buffer suffisamment grand.

_____________________________________
Un éditeur de ressources gratuit pour Windows
0
Cphil51 Messages postés 87 Date d'inscription jeudi 22 juin 2006 Statut Membre Dernière intervention 24 septembre 2007
5 mars 2007 à 21:27
C'est vrai qu'il faut penser a libérer la mémoire.Sinon il est facile de couper ma fonction en 2 distinctes du genre
  int  getURLencodedStringSize(char * str);
  char * URLencode(char * dest, char * str);

Je tacherais de tenir compte de ta remarque a l'avenir
0
Rejoignez-nous