[megoldva] UTF-8 + CGI

 ( arkhein | 2008. október 13., hétfő - 21:58 )

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ás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

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.

C-hez nem tudok ilyen libről.

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

Köszönöm!!!

This is perfect.