CGI-skripty, kterΘ jsme si ukßzali v poslednφm dφle serißlu, byly velmi jednoduchΘ. ZejmΘna proto, ₧e ke svΘ Φinnosti nepot°ebovaly ₧ßdnΘ informace od u₧ivatele. To vÜak nenφ p°φliÜ typick² p°φklad. Obvykle slou₧φ CGI-skripty jako rozhranφ pro prßci s r∙zn²mi databßzemi. U₧ivatel m∙₧e nap°φklad zadat klφΦovß slova, kterß ho zajφmajφ. KlφΦovß slova se p°edajφ CGI-skriptu a ten jako sv∙j v²sledek m∙₧e vygenerovat seznam vÜech Φlßnk∙ z databßze, kterΘ obsahujφ zadanß klφΦovß slova.
Z minula ji₧ vφme, ₧e parametry nejprve p°edß prohlφ₧eΦ serveru a ten je pak pomocφ rozhranφ CGI p°edß skriptu. Nejprve se tedy podφvßme na to, jak m∙₧e n∞jakß data poslat prohlφ₧eΦ serveru.
Existujφ dv∞ metody, jak p°enos dat uskuteΦnit. Prvnφ se jmenuje GET a slou₧φ pro p°enos kratÜφch informacφ. Pro p°enos v∞tÜφho mno₧stvφ dat pak slou₧φ metoda POST.
P°i pou₧itφ metody GET se vÜechny p°edßvanΘ informace p°ipojφ jako
dotaz za otaznφk na konec URL, kterΘ ukazuje na CGI-skript. V dotazu je
pot°eba provΘst drobnΘ ·pravy: vÜechny mezery se nahradφ znakem
'+
' a znaky se specißlnφm v²znamem se nahradφ sekvencφ
znak∙ '%xx
', kde xx je hexadecimßlnφ
k≤d znaku. Nap°φklad lomφtko se p°evede na sekvenci '%2F
'.
Pokud tedy chceme skriptu pokus.cgi
jako parametr p°edat
jmΘno 'Jan Novak', m∙₧eme pou₧φt jedno z nßsledujφcφch URL:
http://server/cgi-bin/pokus.cgi?Jan+Novak http://server/cgi-bin/pokus.cgi?Jan%20NovakV obou dvou p°φpadech jsme museli p°ek≤dovat mezeru tak, aby URL tvo°ilo jeden dlouh² nep°eruÜen² °et∞zec.
TakovΘto zadßvßnφ parametr∙ vÜak nenφ pro u₧ivatele zrovna pohodlnΘ. NaÜt∞stφ existuje n∞kolik u₧ivatelsky p°φjemn∞jÜφch zp∙sob∙, jak p°im∞t prohlφ₧eΦ k vygenerovßnφ pot°ebnΘho URL s parametry:
<ISINDEX>
. V
tomto p°φpad∞ si prohlφ₧eΦ od u₧ivatele vy₧ßdß zadßnφ textu do vstupnφho
pole. Obsah pole zak≤duje podle vÜech pravidel a metodou GET jej odeÜle
skriptu urΦenΘmu pomocφ
<BASE HREF="URL-skriptu">
.
ISMAP
.
Takto p°ipraven² obrßzek pak slou₧φ jako klikacφ mapa, kterou obsluhuje
server. Pokud n∞kam do obrßzku klikneme myÜφ, odeÜlou se metodu GET na
server sou°adnice kliknutφ. Na jejich zßklad∞ server obvykle vrßtφ
n∞jakou strßnku. Dnes se tento zp∙sob ji₧ p°φliÜ nevyu₧φvß, proto₧e
klientskΘ klikacφ mapy jsou mnohem efektivn∞jÜφ. I p°esto malß ukßzka:
<A HREF="http://www.nekde.cz/imagemap"> <IMG SRC="mapa.gif" ISMAP></A>Pokud u₧ivatel klikne na obrßzek
mapa.gif
nap°φklad na
sou°adnicφch (x,y)=(10,50), na server se odeÜle po₧adavek
http://www.nekde.cz/imagemap?10,50
.
FORM
) na strßnku. U formulß°e musφme specifikovat
p°enosovou metodu GET pomocφ atributu METHOD=GET
.
Formulß° m∙₧e obsahovat vstupnφ pole n∞kolika typ∙. ┌daje zadanΘ do
t∞chto vstupnφch polφ se p°ed odeslßnφm zak≤dujφ, p°i°adφ se jmΘnu
vstupnφho pole a navzßjem se odd∞lφ znakem '&'.
Zp∙sob zak≤dovßnφ ·daj∙ z formulß°e si p°edvedeme na malΘ ukßzce. P°edpoklßdejme nßÜ znßm² formulß° z p°edchozφch dφl∙:
<FORM ACTION="http://server/cgi-bin/obsluha.cgi" METHOD=GET> JmΘno: <INPUT TYPE=TEXT NAME=jmeno><BR> V∞k: <INPUT TYPE=TEXT NAME=vek><BR> <INPUT TYPE=SUBMIT VALUE="Odeslßnφ formulß°e"> </FORM>Pokud u₧ivatel vyplnφ jako jmΘno 'Pavel Severa' a jako v∞k '47', prohlφ₧eΦ po stisknutφ tlaΦφtka Odeslßnφ formulß°e vygeneruje nßsledujφcφ po₧adavek:
http://server/cgi-bin/obsluha.cgi?jmeno=Pavel+Severa&vek=47Vidφme, ₧e obsah jednotliv²ch polφ je identifikovßn sv²m jmΘnem a pole jsou odd∞lena znakem '
&
'.
U₧ vφme, jak m∙₧e prohlφ₧eΦ poslat data na server. Vra¥me se tedy k otßzce, jak server p°edß data naÜemu skriptu. Rozhranφ CGI nßm nabφzφ t°i mo₧nosti:
<ISINDEX>
nebo
sou°adnice na klikacφ map∞).
QUERY_STRING
.
Tento zp∙sob je typick² pro p°edßvßnφ dat z formulß°e odeslanΘho metodou
GET.
Prom∞nnß | Obsah |
---|---|
REQUEST_METHOD |
urΦuje zp∙sob p°edßvßnφ informacφ -- GET nebo POST
|
QUERY_STRING |
obsahuje data p°enßÜenß metodou GET
|
PATH_INFO | cesta, kterß mß b²t zpracovßna skriptem; nejΦast∞ji jde o Φßst cesty v URL za jmΘnem skriptu |
PATH_TRANSLATED |
cesta ke stejnΘmu souboru jako PATH_INFO ; v tomto
p°φpad∞ vÜak byla cesta p°emapovßna podle konfigurace
serveru
|
CONTENT_TYPE | MIME typ dat zasφlan²ch metodou POST |
CONTENT_LENGTH | dΘlka dat zasφlan²ch metodou POST |
SCRIPT_NAME | URL prßv∞ provßd∞nΘho skriptu |
SERVER_NAME | jmΘno serveru |
SERVER_PORT | Φφslo portu |
SERVER_SOFTWARE | jmΘno a verze programu pracujφcφho jako WWW-server |
SERVER_PROTOCOL |
jmΘno a verze protokolu, kter²m p°iÜel po₧adavek (typicky
HTTP/1.0 nebo HTTP/1.1 )
|
GATEWAY_INTERFACE |
oznaΦenφ a verze pou₧itΘho rozhranφ ke spuÜt∞nφ skriptu
(typicky CGI/1.1 )
|
REMOTE_HOST | domΘnovß adresa poΦφtaΦe, z n∞j₧ p°iÜel po₧adavek |
REMOTE_ADDR | IP-adresa poΦφtaΦe, z n∞j₧ p°iÜel po₧adavek |
AUTH_TYPE | zp∙sob pou₧itΘ autorizace u₧ivatele |
REMOTE_USER | v p°φpad∞, ₧e byl u₧ivatel autorizovßn, obsahuje tato prom∞nnß jeho jmΘno |
REMOTE_IDENT | informace o identit∞ zφskanß zp∞tn²m dotazem u klienta; tuto vlastnost p°φliÜ mnoho server∙ nevyu₧φvß |
Nynφ u₧ toho vφme dost na to, abychom si ukßzali CGI-skript, kter²
bude zpracovßvat parametry zadanΘ u₧ivatelem. Pou₧ijeme nßÜ osv∞dΦen²
p°φklad, kter² hodnotφ u₧ivatele podle jeho v∞ku. Zadßnφ ·daj∙ umo₧nφme
u₧ivateli v²Üe uveden²m formulß°em. Skript, kter² vyhodnotφ ·daje na
formulß°i, pojmenujeme obsluha.cgi
.
#!/bin/sh echo 'Content-type: text/html' echo echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">' echo '<HTML>' echo '<HEAD>' echo '<TITLE>Obsluha formulß°e</TITLE>' echo '</HEAD>' echo '<BODY>' echo '<H1>V²sledek obsluhy formulß°e</H1>' eval `echo $QUERY_STRING | awk 'BEGIN{RS="&"} {printf "WWW_%s\n",$1}' ` WWW_jmeno=`echo $WWW_jmeno | tr "+" "\040"` echo "$WWW_jmeno je" if [ $WWW_vek -lt 10 ]; then echo 'p∞knej mlφΦnßk' elif [ $WWW_vek -lt 20 ]; then echo 'teenager' elif [ $WWW_vek -lt 60 ]; then echo 'v nejlepÜφch letech' elif [ $WWW_vek -lt 100 ]; then echo 'je pravd∞podobn∞ prarodiΦ' else echo 'je n∞kde mezi stovkou a smrtφ' fi echo '</BODY>' echo '</HTML>'CGI-skript jsme op∞t zapsali v p°φkazovΘm interpretu
sh
.
P°edem upozor≥uji, ₧e po vyzkouÜenφ skriptu, je nejlepÜφ jej ihned
smazat. NßÜ skript toti₧ nenφ zdaleka bezpeΦn², jak si za chvφli
ukß₧eme.
Podφvejme se nynφ na skript troÜku podrobn∞ji. Prvnφ °ßdek obsahuje urΦenφ interpretu, kter² se na skript pou₧ije. Dßle pak generujeme HTTP hlaviΦku a kostru HTML strßnky.
Dva °ßdky na zaΦßtku t∞la strßnky jsou opravdu magickΘ. Prvnφ z nich
pro ka₧dΘ pole formulß°e, jeho₧ hodnota je p°edßna v prom∞nnΘ
QUERY_STRING
, vytvo°φ prom∞nnou
WWW_jmΘno-pole
s obsahem p°φsluÜnΘho pole. To
nßm usnadnφ dalÜφ prßci s p°edan²mi parametry. Druh² °ßdek v prom∞nnΘ
WWW_jmeno
(ta nese obsah vstupnφho pole jmeno
)
nahradφ vÜechny v²skyty znaku '+
' mezerou (ASCII k≤d 40 v
osmiΦkovΘ soustav∞).
Podmφnka [ $WWW_vek -lt n ]
je spln∞na pokud
je prom∞nnß $WWW_vek
menÜφ ne₧ n. N∞kolik
vno°en²ch podmφnek zajistφ vytiÜt∞nφ p°φsluÜnΘho komentß°e podle v∞ku
u₧ivatele.
Vidφme, ₧e tvorba skript∙ cestou p°φkazovΘho interpretu je urΦena spφÜe pro UnixovΘho guru, ne₧li pro "normßlnφho Φlov∞ka".
Pokud n∞kdo bude chtφt nßÜ skript zneu₧φt pro zjiÜt∞nφ d∙le₧it²ch informacφ o systΘmu, m∙₧e vyu₧φt n∞kterΘ mΘn∞ znßmΘ vlastnosti interpretu sh. Mezi n∞ pat°φ i to, ₧e na jednΘ °ßdce lze p°φkazy odd∞lovat pomocφ st°ednφku. Pokud tedy n∞jak² "chytrßk" zavolß nßÜ skript pomocφ nßsledujφcφho URL:
http://server/cgi-bin/obsluha.cgi?;whoDojde v CGI-skriptu k expanzi p°φkazu
echo $QUERY_STRING
na
echo ;who
. V²sledkem je, ₧e na v²stup skriptu se zapφÜe
prßzdnß °ßdka (p°φkaz echo
) a v²sledek programu
who
. Zcela kdokoliv tak m∙₧e zjistit, kdo v danou chvφli
pracuje na serveru. Mφsto p°φkazu who
m∙₧eme pou₧φt
libovoln² jin² p°φkaz. Pokud pou₧ijeme nap°. URL:
http://server/cgi-bin/obsluha.cgi?;cat</etc/passwdVrßtφ se nßm strßnka, kterß na svΘm zaΦßtku bude obsahovat v²pis informacφ o vÜech u₧ivatelφch systΘmu. Z tohoto v²pisu lze zjistit u₧ivatele, kte°φ heslo nemajφ nastaveno, a u t∞ch ostatnφch lze pom∞rn∞ snadno jejich heslo rozÜifrovat. Kdokoliv se pak pomocφ telnetu m∙₧e p°ipojit na server a provßd∞t tam tΘm∞° cokoliv.
Pokud tedy chceme vytvß°et bezpeΦnΘ skripty v interpretovan²ch jazycφch, musφme v₧dy p°φchozφ data zkontrolovat a p°ed jejich zpracovßnφm z nich eliminovat nebezpeΦnΘ znaky jako je st°ednφk.
OÜet°it vÜechny nebezpeΦnΘ kombinace vstupnφch parametr∙ nenφ vÜak v∙bec jednoduchΘ a je celkem pravd∞podobnΘ, ₧e na n∞jakou mo₧nost zapomeneme. Je proto lepÜφ CGI-skripty psßt v jazycφch, ve kter²ch je nutno program p°ed spuÜt∞nφm p°elo₧it do spustitelnΘ formy. V t∞chto jazycφch (C, C++, Java apod.) je pak v²Üe zmφn∞nΘ nebezpeΦφ obelst∞nφ skriptu do znaΦnΘ mφry eliminovßno.
Vid∞li jsme, ₧e CGI-skripty jsou jako ohe≥ -- dobr² sluha, ale Üpatn² pßn. V serißlu se budeme pro p°φÜt∞ zab²vat p°edevÜφm skriptovacφmi jazyky, kterΘ se vklßdajφ p°φmo do HTML strßnky, jako je PHP a ASP. Prßce s nimi je jednoduÜÜφ a v∞tÜinou i efektivn∞jÜφ. Pro specißlnφ aplikace vÜak m∙₧e b²t v²hodnΘ pou₧φt CGI-skripty -- nynφ ji₧ znßte princip jejich prßce a zp∙sob p°edßvßnφ parametr∙.
V p°φÜtφch pokraΦovßnφch serißlu se podφvßme na r∙znΘ druhy vstupnφch polφ, kterΘ lze pou₧φvat ve webovsk²ch formulß°φch.