[megoldva] UTF-8 + CGI

Fórumok

Sziasztok!

Van egy C-ben írt CGI ami GET adatokat dolgoz fel és egy UTF-8-as kódolású adatbázisból kér le adatokat.


	char *data;
	data = getenv("QUERY_STRING"); 

A problémám az, hogy ha nem ASCII karaktereket kap bemenetként nem helyesen dolgozza fel. Ezen annyira nem is lepedők meg lévén a szokásos % formában érkeznek ezek a karakterek. A "szo" változó a problémás. Megpróbáltam ilconv-al visszakódolni de nem sikerült:


	
	int ntabla=0;		// hány táblából kérdezünk le
	char *szo;
	char *irany;
	char *illeszkedes;
	char *jelzo, *jelzet;
	char sep[] = "&=";
	jelzet = strtok(data, sep);
	while( jelzet != NULL ) {
		jelzo=strtok(NULL, sep);
		
		if (strcmp(jelzet, "szo")==0)
			szo=jelzo;
		else if (strcmp(jelzet, "irany")==0)
			irany=jelzo;
		else if (strcmp(jelzet, "tabla")==0)
			if (ntabla==0){
				ntabla=ntabla+atoi(jelzo);
			}
			else {ntabla=ntabla*atoi(jelzo);}
		else if (strcmp(jelzet, "illeszkedes")==0)
			illeszkedes=jelzo;
		
		jelzet=strtok(NULL, sep);
	}


        iconv_t cd;
//        char instr[]="áű";
        char *inbuf;
        char *outbuf;
        char *outptr;
        unsigned int insize=strlen(instr);
	unsigned int outputbufsize=10;
        unsigned int avail=outputbufsize;
        unsigned int nconv;
//        inbuf=instr;
        inbuf=szo;
        outbuf=(char *)malloc(outputbufsize);
	outptr=outbuf;
	memset(outbuf,'\0',outputbufsize);
        cd=iconv_open("utf-8","iso-8859-2");
        if(cd==(iconv_t)-1)
        {
                printf("fail.\n");
        }
        nconv=iconv(cd,&inbuf,&insize,&outptr,&avail);

        printf("%s\n", szo);

Nem vagyok programozó, és a C-hez is kevéssé értek, de meg tudnátok mondani hogy mit rontok el.

Vagy esetleg tudtok ajánlani egy másik módszert ami működik.

Hozzászólások

Az iconv nem fog neked abban segíteni, hogy például az "%C5%91" sztringből (6 byte) előállítsd azt a 2 byte-os sztringet, ami a hexa C5 és 91 byte-ból áll (ami mellesleg az ő betű UTF-8-ban). Ezt kézzel-lábbal kell megcsinálnod, vagy keresni valami libet ami megoldja.

Az iso-8859-2 -> utf-8 konverzió célját nem értem. A honlap iso-8859-2-ben van, a háttérben lévő adatbázis meg utf-8? Hosszútávon sokkal tisztább megoldás a honlapot is utf-8-ra alakítani, ekkor ez a lépés elhagyható lesz.

(Megj: a GET paraméterek a honlap kódolása szerint vannak kódolva, például latin2-es honlapon a formba beírsz egy ő betűt és elküldöd, akkor %F5 lesz, ha viszont utf-8-as a honlap, akkor a fent is írt %C5%91.)

A honlap és az adatbázis is utf-8.

Esetleg tudsz valami használható lib-et?
(Igazából végső elkeseredettségben próbáltam ezt meg, mert a szerver és a kliens is ISO-8859-2-es kódolást használ.)

Olvastam a Percent-encoding szócikket a wikipedia-án. És úgy vettem ki egy application/x-www-form-urlencoded meglehetne oldani a form-ban de nekem ez nem jött össze.

Az URLEncoding dekodolasa nagyon egyszeru. Keresni kell a stringben %-el kezdodo karaktereket (a % is ilyen karakterkent van lekodolva), majd a kovetkezo ket karaktert be kell olvasni, toupper, vegul ilyesmit kell csinalni:


n1 = c1 - '0' - (c1 > '9' ? 7 : 0);
n2 = c2 - '0' - (c2 > '9' ? 7 : 0);
ch = n1 * 16 + n2;

Ennek kovetkezteben a ch valtozoba kerul a valodi karakterertek, ez bekerul a vegleges kodba, az url dekodolasat pedig a kovetkezo karakterrel kell folytatni. Most tul faradt vagyok egy mukodo kod osszeutesehez, de ennek elegnek kell lenni.

--


()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Ezen a httpd_uri_decode() fv-en folyatsd a't a valtozodat (

httpd_uri_decode(szo,szo);

), me'g az iconv elott (vagy ahelyett):

                                                               
static int char_to_hex(int chr)
{
 if ( '0' <= chr && chr <= '9' )
        return(chr-'0');
 else if ( 'a' <= chr && chr <= 'f' )
        return(chr-'a'+10);
 else if ( 'A' <= chr && chr <= 'F' )
        return(chr-'A'+10);
 else
        return(-1);
}

int httpd_uri_decode(char *uri,char *out)
{
 int    hex1,hex2;

 while ( *uri )
  {     if ( *uri=='+' )
         {      *out=' ',
                out++,
                uri++;
         }
        else if ( *uri=='%' && (hex1=char_to_hex(*(uri+1)))>=0 && (hex2=char_to_hex(*(uri+2)))>=0 )
         {      *out=hex1*16+hex2;
                out++;
                uri+=3;
         }
        else
         {      *out=*uri;
                out++;
                uri++;
         }
  }
 *out=0;                
                
 return(0);
}