CGI Script
2
Az elôzô részben ha még emlékszünk összeszedtük mindazt, ami egy
CGI Script megírásához és elhelyezéséhez szükséges lehet. Ebben
a részben inkább arról lesz szó, hogyan is tudjuk a Scriptünk
megírását megkönnyíteni, illetve mit, milyen szabályokat tartsunk
be akkor, ha CGI Scriptet kívánunk írni.
Elsôként
talán a legfontosabb, hogy amennyiben nem tudjuk még, hogy konkrétan
milyen platformon is kell majd futnia a Scriptünknek, akkor lehetôség
szerint kizárólag Unix-os C fordítók által is emészthetô kódot
generáljunk. Ez azt jelenti, hogy jópár utasítást (gyakorlatilag
minden gépspecifikus utasítást, illetve a különbözô C fordítók
és környezetek által bevezetett új, vagy a szabványostól eltérô
utasításokat) jobb ha mellôzünk, így nem fog bennünket kellemetlen
meglepetéssel meglepni egy-egy alkalmilag velünk összefutó fordító.
A
fileműveletek terén is korlátozzuk magunkat az stdio által biztosított
lehetôségekre, és mellôzzünk mindenféle PC-s, Amigás vagy bármilyen
egyéb dos könnyítést, és mindenféle gépspecifikus dolgokat (remélem
senkinek eszébe nem jutott WindowsNT szerverre Amigás asyncio
stuffot gyártani). Egyrészt ugye ezek a dolgok nem fognak mindenhol
lefordulni, másrészt meg elôfordul, hogy a dolog lefordul, de
nem azt csinálja, amit kellene. (Szokta is az ember a fogát szívni
debuggoláskor.)
További
fontos követelmény, hogy minden oldalról biztosítsuk be magunkat.
Ez rendszerbarát program írásakor ugyan Amigán alapkövetelmény,
de lényeg a lényeg, ellenôrizzen a programunk mindent, és ne vegyünk
semmit adottnak. Ha például egy 300 elemű tömbünk van az stdin-en
keresztül érkezô adatok fogadására, akkor ez esetben akkor is
ellenôrizzük, hogy a beérkezô adatfolyam ezt a számot nem haladja
meg, ha a html-ben limitálva van az adatbevitel.
Vegyük
továbbá figyelembe, hogy cgi-scriptünk kedvelt célpontját fogja
majd képezni a rendszerbe betörni igyekvôknek (legalábbis ha a
server egyébként épeszű védelmet képes felmutatni, és így a hacker
alternatív megoldások után kezd el keresgélni), ezért érdemes
megérdeklôdni szakavatott emberkétôl, hogy az adott környezetben
mivel vigyázzunk CGI Scriptünkkel kapcsolatban (ha azt mondja,
hogy semmire, vagy csak értetlenül bámul ránk, akkor menjünk el
egy tényleg hozzáértôt keresni). Annak is érdemes utánanéznünk,
hogy a CGI Script milyen jogokkal fog rendelkezni, amikor külsô
böngészôbôl meghívásra kerül. Linux esetén például maximumként
is csak a létrehozójának teljes jogkörét kaphatja meg, a rendszergazda
tehát nem feltétlenül fogja halálra izgulni magát amiatt, hogy
most feltörhetôre, vagy nem feltörhetôre is írjuk meg a programunkat,
hiszen "több is veszett mohácsnál" felkiáltással csakis a saját
adatainkat veszthetjük, illetve azon alkönyvtárak tartalmát, amelyekben
használhatóbb jogaink vannak.
Ennyit
röviden azon szabályokról, amelyeket nem árt ha szem elôtt tartunk.
Ha pedig továbbra is CGI írásra adjuk fejünket, alighanem két
alapvetô problémával fogjuk szembetalálni magunkat.
Az
elsô amivel szembetalálhatjuk magunkat, hogy feltehetôen meglehetôsen
kevesen üzemeltetnek otthon webservert, és így - pláne internetes
kapcsolat híján - komoly nehézségekbe ütközhet CGI scriptünk tesztelése.
Mi
is jelenti tulajdonképpen a problémát? Elsôsorban az, hogy a programunk
a servertôl jónéhány bemeneti információt kap, amelyeket azonban
ha egyszerűen csak elindítjuk server híján nem fog megkapni.
A
probléma látszólag nagy, a megoldás viszont annál egyszerűbb.
Hozzunk létre egy változót, amelynek értéke azt lesz hivatott
jelezni, hogy a végleges, serverre kerülô verziót fordítjuk-e,
vagy még csak otthon akarunk tesztelgetni, és a megfelelô helyre
illesszünk be egy if feltételt, amely ezen változó értékét megvizsgálva
tesztfordítás esetén a setenv parancs segítségével beállítja környezeti
változóinkat. Ez a változóink túlnyomó többségénél rendkívül egyszerű,
problémát csak az adatbevitel okot, amelyet most kicsit bôvebben
is kifejtünk.
A CGI scriptünk kétféleképpen kaphat adatokat a html-tôl (akár
párhuzamosan is), ahogyan azt az elôzô cikkünkben elmondtuk már:
egyszer kaphat az EV.Query_String változónkon keresztül, ha az
adatátviteli mód default (ellenkezô esetben még mindig adhatunk
meg paramétereket, ha a html kódban a cgi url-je után kérdôjel
következik, és utána a paramétereink), illetve a stdin-en keresztül,
ha az adatátviteli mód http-post. Ez utóbbi esetben generálnunk
kell egy file-t, ami az érkezô adatokat tárolja majd, és tesztelésnél
ezt kell megadni a programunk standard inputjának. Nem szabad
elfeledkeznünk azonban arról sem, hogy az EV.Content_Length változónkban
majd megadjuk ennek a file-nak a hosszát a programunk számára!
Az
adatok, érkezzenek akár default, akár http-post módon a következôképpen
épülnek fel:
mezônév=mezôérték&következômezô=mezôérték&etc...
Természetesen,
mint az elôzô részben már említettük, ezek az adatok konverzión
esnek át, amit ha szimulálni akarjuk a servert, nekünk is végre
kell hajtanunk. A szóköz karakterek "+" jellé alakulnak át, és
minden egyéb extra karakter (ékezetek, írásjelek, etc.) egy "%"
jellé és a hexadecimális értékükként érkeznek meg. (Ez három karaktert
jelent, a százalékjelet, és a hexadecimális érték két számjegyét)
Ha
ezt pontosan végrehajtjuk, akkor gyakorlatilag tökéletesen tudjuk
szimulálni a servert. A programunk által visszaküldött html-ünket
pedig egyszerűen megkaphatjuk, ha a programunk outputját átirányítjuk
egy file-ba, majd azt böngészôben megtekintjük.
Végezetül
mivel az adatok a programunk számára "%" jellel jelölt hexadecimális
értékké konvertált karakterekként is érkezhetnek (az amerikaiak
amikor ezt kitalálták nemigen gondoltak éppen arra, mit fognak
ezzel más nemzetek fiai szívni) esetenként érdemes elôállítani
az eredeti karaktersort. Az alábbi, well, nem túl elegáns, mint
inkább primitív, de mindenképpen megfelelô megoldás ezt a célt
igyekezne szolgálni (feltételezve, hogy az elküldött adatok még
nem lettek beolvasva az stdin-rôl):
int i;
int j;
int k;
int contentlength;
char posted[256];
char converted[256];
// beolvassuk az stdin-en várakozó
adatokat a posted tömbbe
contentlength = atoi(EV.Content_Length);
for (i=0;i<contentlength;i++)
{
posted[i] = getchar(); // printf("%c",a);
}
//atkonvertaljuk ekezetesse, az
eredmény a converted tömbbe kerül
contentlength = atoi(EV.Content_Length);
k=0; //converted i-je, mivel menetkozben az i-t valtoztatni fogjuk
for (i=0;i<=contentlength;i++)
{
if (posted[i]==37) // 37 a % kódja
{
j=0;
//az elsô szám megvizsgálása (nem kell nevetgélni, lehet ezt egyszerűbben)
if (posted[i+1]==48){j=j+(0*16);}
if (posted[i+1]==49){j=j+(1*16);}
if (posted[i+1]==50){j=j+(2*16);}
if (posted[i+1]==51){j=j+(3*16);}
if (posted[i+1]==52){j=j+(4*16);}
if (posted[i+1]==53){j=j+(5*16);}
if (posted[i+1]==54){j=j+(6*16);}
if (posted[i+1]==55){j=j+(7*16);}
if (posted[i+1]==56){j=j+(8*16);}
if (posted[i+1]==57){j=j+(9*16);}
if (posted[i+1]==65){j=j+(10*16);}
if (posted[i+1]==66){j=j+(11*16);}
if (posted[i+1]==67){j=j+(12*16);}
if (posted[i+1]==68){j=j+(13*16);}
if (posted[i+1]==69){j=j+(14*16);}
if (posted[i+1]==70){j=j+(15*16);}
//a második szám megvizsgálása (szintén nem kell nevetgélni)
if (posted[i+2]==48){j=j+0;}
if (posted[i+2]==49){j=j+1;}
if (posted[i+2]==50){j=j+2;}
if (posted[i+2]==51){j=j+3;}
if (posted[i+2]==52){j=j+4;}
if (posted[i+2]==53){j=j+5;}
if (posted[i+2]==54){j=j+6;}
if (posted[i+2]==55){j=j+7;}
if (posted[i+2]==56){j=j+8;}
if (posted[i+2]==57){j=j+9;}
if (posted[i+2]==65){j=j+10;}
if (posted[i+2]==66){j=j+11;}
if (posted[i+2]==67){j=j+12;}
if (posted[i+2]==68){j=j+13;}
if (posted[i+2]==69){j=j+14;}
if (posted[i+2]==70){j=j+15;}
converted[k]=j;
i=i+2; //elôreallitjuk a mutatót,
hogy a %xx-ból ne törôdjön az xx-ekkel
}
else
{
if (posted[i] == 43) // ez a kovertált szóköznek megfelelô +
{
converted[k] = 32; // ez pedig a szóköz kódja
}
else
{
converted[k]=posted[i]; // nem spec. karakter esetén szimplán
másolunk
}
}
k=k+1;
}
A
fentebbi kód persze messze picit(?) primitív, de azt hiszem az
elmélet egész jól kivehetô belôle. Ennyi lett volna mára a CGI
scriptbôl, remélem az elôzô számban leírt alapok, és a most ismertetett
néhány extra után már mindenki képes lesz nagyszerű CGI scripteket
írni. Sok sikert a fordítgatásokhoz...
Emeric
SH