CGI scripty


Co je to CGI script?

Z pocatku WWW server posilal klientum pouze staticke dokumenty, ktere byly predem pripraveny a vystaveny na serveru.

Brzy se vsak ukazalo, ze by bylo vyhodne, kdyby server mohl ovlivnit data dokumentu dynamicky v dobe pozadavku. Klasickym pripadem jsou databazove aplikace. Neni vhodne mit vsechny mozne vystupy predem staticky pripraveny vzhledem k objemu a hlavne promenlivosti dat. Je vyhodne sestavovat odpoved presne podle pozadavku az v dobe pozadavku. Ukoly tohoto typu resi zavedeni tzv. dynamickych (virtualnich) dokumentu. Pokud klient zada virtualni dokument, predstavuje URL v dotazu program, ktery ma server spustit. Vysledek programu pak ma server predat klientovi. Programy tohoto typu se nazyvaji CGI programy nebo CGI scripty.

CGI script je externi program, ktery je na pozadavek od uzivatele spusteny WWW serverem jako samostatny proces.

CGI script je libovolny script nebo program. Jedinou podminkou je schopnost programu komunikovat v WWW serverem. Program musi umet data prebirat od WWW serveru a musi umet predat serveru zpet vysledek. WWW server musi umet tento program nebo script spustit. Jako CGI muze pracovat program tj. spustitelny soubor vznikly prekladem zdrojoveho textu napsaneho napr. v jazyce C. Nebo script (procedura) tj. sekvence prikazu interpretovane napr. programem Perl, Shellem v Unixu apod. Dale budu v textu pouzivat termin CGI script.

CGI scripty jsou casto vytvareny ve scriptovem jazyce Perl nebo v nekterem shellu OS Unix. Z programovacich jazyku se pouziva napr. jazyk C nebo C++, Visual Basic. Vyber jazyka zavisi pouze na autorovi CGI scriptu, a take na tom, jaky jazyk ma autor k dispozici.

Pravidla komunikace (rozhrani) mezi CGI scriptem a WWW serverem definuje norma CGI - Common Gateway Interface dostupna na http://hoohoo.ncsa.uiuc.edu/cgi. Existuje i cesky preklad teto normy. Diky existenci normy pro CGI rozhrani je mozne pouzivat CGI scripty ve spojeni s vetsinou existujicich serveru a zpusob pouziti je ve vsech pripadech stejny.

CGI scripty prebiraji data zadana uzivatelem, zpracovavaji je a jako vysledek vytvareji vetsinou html stranky. Tyto dynamicky vytvorene stranky pak WWW server posila zpet klientovi. Pomoci CGI muze server provadet vypocty, vyhledavat data v databazi nebo napr. odesilat objednavky. Vysledkem scriptu muze byt nejen html stranka vytvorena podle pozadavku uzivatele ale i obrazek v gif formatu, nebo jina data, ktera je mozno zobrazit prohlizecem.

Komunikaci mezi klientem, serverem a CGI scriptem uvadi obrazek.

Kroky zpracovani CGI pozadavku

V pripade, ze klient pozaduje od serveru staticky dokument, server tento dokument vyhleda o odesle zpet klientovi.

V pripade, ze klient posle CGI pozadavek, pracuje server pouze jako prostrednik mezi klientem a CGI scriptem.

Kroky komunikace pri zpracovani CGI pozadavku:

  1. Klient posle pozadavek serveru.

  2. Pokud server rozhodne, ze jde o CGI pozadavek, zalozi CGI proces. Jedinym ucelem tohoto procesu je nastavit komunikaci mezi CGI procesem a serverem. Tento proces je jednim z procesu, ktere ma server alokovane, je proto treba zajistit dostatecne mnozstvi alokovanych procesu. Pokud CGI script bezi prilis dlouho ma server o jeden proces mene k obslouzeni dalsich prichozich pozadavku. Jelikoz je CGI proces kopii procesu serveru ma pristup k informacim z CGI dotazu. Napr.:

  • CGI porces ulozi informace z pozadavku do pomennych prostredi. CGI proces take vytvori spojeni mezi serverem a externim (CGI) programem. Tj. server muze poslat pragramu data od klienta a CGI script muze poslat odpoved zpet klientovi prostrednictvim serveru. CGI proces muze poslat data CGI programu na standardni vstup.

  • Po zpracovani dotazu externim programem, odesle CGI proces data serveru, ktery je vrati klientovi. Obsah odpovedi posila CGI script pres svuj standardni vystup. Server prevezme odpoved od scriptu, prida k ni vysledkovy kod a nezbytne hlavicky a posle ji klientovi.
    Je take mozne poslat odpoved vytvorenou CGI scriptem primo klientovi jako tzv. nonparsed header dokument. V takovem pripade vsak musi odpoved obsahovat vsechny potrebne nalezitosti, aby byla platnou odpovedi v HTTP protokolu a klient umel tuto odpoved spravne zobrazit uzivateli.

    Bezpecnost a CGI scripty

    CGI scripty jsou vhodnym nastrojem pro interakci s uzivateli, mohou vsak predstavovat urcite bezpecnostni riziko. Pri vytvareni CGI scriptu je treba dodrzovat tato pravidla:

    Pristup k CGI pres URL

    Server pri obdrzeni dotazu od klienta musi urcit, zda jde o dotaz na staticky dokument nebo o dotaz na CGI script a ma tedy CGI script spustit. K rozpoznani CGI dotazu pouziva server dve metody. Zadna v techto metod neni pouzivana serverem implicitne, jeji volba se provadi v konfiguraci serveru.
    1. Je mozne specifikovat MIME typ pro CGI script a ulozit script do adresare spolu s html dokumenty. Pri pouziti teto metody je kazdy soubor s priponou cgi spusten jako CGI script. Tato moznost je pruznejsi, ale vyzaduje opatrnost, o ktere jsme mluvili v odstavci o bezpecnosti.

    2. Je mozne specifikovat adresar, ve kterem budou CGI scripty ulozene. Tato metoda poskytuje vetsi kontrolu nad tim, kdo scripty vytvari a kdo k nim ma pristup. V konfiguraci serveru se namapuje adresar s cgi scripty na virtualni cestu. Kazde URL, ktere ukazuje na soubor v tomto adresari je serverem interpretovano jako pozadavek na spusteni CGI scriptu. Casto se pouziva virtualni adresar cgi-bin, ktery se mapuje na adresar cgi-bin pod root adresarem WWW serveru.
    V konfiguraci serveru je take potreba povolit spousteni CGI scriptu. Pokud se pri pokusu o spusteni scriptu objevi chybova hlaska v errorlogu nebo se text programu zobrazi v klientove okne, pak nejsou CGI aktivovany v konfiguraci.

    Rozsirujici informace v URL

    URL, ktere spousti CGI script je mozne rozdelit do tri casti:

    [virtualni cesta][doplnkove informace]?[vstupni retezec]

    Volani CGI scriptu je mozne pomoci linky v html strance. Tabulka uvadi priklady URL, ktere ukazuji na CGI. Ve vsech prikladech je jmeno CGI programu /misc/search.cgi a root serveru je fyzicky adresar /netscape/dosc. Zpusob predani dat do CGI scritpu bude vysvetlen pozdeji.

    Na disku predpokladame nasledujici adresarovou strukturu:

    URLPopis
    http://www.server.cz/misc/search.cgiJednoduche URL na CGI script ulozeny v adresari /netscape/docs/misc/search.cgi bez extra informaci a vstupniho retezce
    http://www.server.cz/misc/search.cgi/type=minimalToto URL pouziva doplnkove informace type=minimal. Efekt je podobny jako poslani stejnych informaci pomoci vstupniho retezce
    http://www.server.cz/misc/search.cgi/misc/movies.mdbJe predavana doplnkova informace /data/movies.ndb napr. pro vyhledani cehosi v databazi /netscape/dosc/data/movies.mdb
    http://www.server.cz/misc/search.cgi?netscapeURL pro automaticke vyhledani slova netscape bez zadavani uzivatelem
    http://www.server.cz/misc/search.cgi/data/movies.mdb?netscape URL pro automaticke vyhledani slova netscape v databazi /netscape/dosc/data/movies.mdb
    (Tabulka predpoklada metodu GET).

    Vstup od uzivatele

    Existuji tri zpusoby, jak muze klient predat data CGI scriptu:

    HTML formular

    Pokud jsou zadana data do formulare jsou pred prenosem na server kodovana metodou aplication/x-www-form-urlencoded. Toto kodovani ma dve pravidla:
    1. Mezery jsou nahrazeny znakem +.
    2. Nektere znaky jsou nahrazeny sekvenci %xx, kde xx je hexadecimalni hodnota puvodniho znaku. Tabulka uvadi nektere z casto pouzivanych znaku:

      ZnakKodovani
       : (dvojtecka) %3A
       \ (obracene lomitko) %5C
       / (lomitko) %2F
       % (procento) %25
       " (uvozovky) %22
       , (carka) %2C
       & (amprsand) %26
       ( (leva zavorka) %28
       ) (prava zavorka) %29

      Nekoduji se znaky anglicke abecedy, cislice, tecka, pomlcka a podtrzitko.

    Priklad: Takto vyplneny formular

    odesle klient pri pouziti metody POST dotaz ve tvaru:

    POST /cgi-bin/objed.pl HTTP/1.0
    Accept: text/html
    Accept: image/gif
    Accept: image/jpeg
    Accept: video/mpeg
    User-Agent: Mozilla/3.1N
    From: novak@poc.firma.cz
    Content-Type: application/x-www-form-urlencoded
    Content-length: 104
       * prazdny radek *
    reply=novak@firma.cz
    &nazev=Tvorba+WWW
    &jmeno=Jan+Novak
    &ulice=Pod+lesem+25%2F113
    &mesto=Veseli+nad+Luznici
    &stravovani=ano
    &ubytovani=ano
    

    odesle klient pri pouziti metody GET dotaz ve tvaru:

    GET /cgi-bin/objed.pl?reply=novak@firma.cz&nazev=Tvorba+WWW&jmeno=Jan+Novak
    &ulice=Pod+lesem+25%2F113&mesto=Veseli+nad+Luznici&stravovani=ano
    &ubytovani=ano HTTP/1.0
    Accept: text/html
    Accept: image/gif
    Accept: image/jpeg
    Accept: video/mpeg
    User-Agent: Mozilla/3.1N
    From: novak@poc.firma.cz
       * prazdny radek *
    
    

    Pro uplnost uvadim i zdrojovy text formulare:

    <H1>Objednavka</H1> <HR SIZE=7><P> <FORM METHOD="POST" ACTION="/cgi-bin/objed.pl"> <INPUT TYPE=HIDDEN NAME=subject VALUE="Objednavka zbozi"> <TABLE> <TR><TD><B>Odesilatel (e-mail):</B></TD> <TD><INPUT NAME=reply SIZE=40 MAXLENGTH=40></TD> <TR><TD><STRONG>Nazev seminare:</STRONG></TD> <TD><INPUT TYPE=TEXT NAME=nazev SIZE=40></TD> <TR><TD><STRONG>Jmeno a prijmeni</STRONG></TD> <TD><INPUT TYPE=TEXT NAME=jmeno SIZE=40></TD> <TR><TD><STRONG>Adresa:</STRONG></TD> <TD><INPUT TYPE=TEXT NAME=ulice SIZE=40></TD> <TR><TD><STRONG></STRONG></TD> <TD><INPUT TYPE=TEXT NAME=mesto SIZE=40></TD> <TR><TD><B>Objednavame:</B></TD> <TD><INPUT TYPE=CHECKBOX NAME=ubytovani VALUE=ano>ubytovani</TD> <TR><TD></TD><TD><INPUT TYPE=CHECKBOX NAME=stravovani VALUE=ano>stravovani<BR> </TABLE> <HR> <TABLE> <TR><TD><INPUT TYPE=SUBMIT VALUE="Odeslani objednavky"></TD> <TD><INPUT TYPE=RESET VALUE="Vymazani zadanych hodnot"</TD> </TABLE> </FORM>

    Data jsou predavana CGI scriptu v zavislosti na pouzite metode, ktera je specifikovana v atributu METHOD ve formulari.

    Pouziti metody GET je limitovano mnozstvim informaci odesilanych v dotazu. Ve formularich je vyhodne pouzivat metodu POST.

    Vzdy maji data tento tvar: jmeno1=hodnota1&jmeno1=hodnota1...&jmenon=hodnotan
    kde & je oddelovacem jednotlivych polozek a jmenoi je oznaceni polozky ve formulari.
    Pokud se v hodnotach vyskytne znak = nebo & je kodovan zminenych kodovanim.

    CGI script tedy musi data dekodovat. Musi nejprve rozdelit jednotlive casti vstupu tj. odstranit znaky & a pote nahradit sekvence %xx puvodnim znakem. Poradi polozek na vstupu je totozne s poradim polozek ve formulari.

    Jednotlive typy vstupnich poli formulare maji sva pravidla pri predavani hodnot:

    Vstupni pole ISINDEX

    Pri pouziti pole ISINDEX jsou data predana jako parametr prikazoveho radku. Dekodovani provadi CGI proces. Vas CGI script tedy obdrzi data jako argument prikazoveho radku jiz dekodovana.

    Dnes jiz se tato moznost prilis nepouziva, nebot pomoci formulare je mozne resit stejny problem konfortneji.

    Citliva mapa

    V pripade citlive mapy jsou data predavana pomoci promenne prostredi QUERY_STRING a maji tvar xx,yy kde xx a yy jsou souradnice bodu na mape. Script, ktery ma tato data zpracovat je urceny primo v konfiguraci serveru.

    Pouziti promennych prostredi

    Promenne prostredi jsou casto pouzivane. Do promennych prostredi server uklada nejen data predana v URL, ale i informace o spojeni s klientem a informace o serveru samotnem.

    Cgi scripty mohou prevzit informace z promennych prostredi ruznym zpusobem. Zpusob se lisi podle pouziteho programovaciho nebo scriptoveho jazyka. Promenne prostredi jsou oznaceny jmenem a obsahuji hodnotu ve tvaru textoveho retezce. Uvedme priklady pouziti promennych prostredi pro nektere jazyky:

    V C a C++
    se pouzije knihovna getenv, tedy:
    #include <STDLIB.h>
    char *rhost = getenv("REMOTE_HOST");
    
    V Perlu
    jsou promenne prostredi pristupne pomoci pole @ENV, tedy:
    $rhost = $ENV{'REMOTE_HOST'};
    
    V Bourne shellu (/bin/sh)
    jsou promenne prostredi pristupne jako vsechny promenne shellu, tedy:
    RHOST=$REMOTE_HOST
    

    Promenne prostredi

    Nasledujici promenne prostredi nejsou zavisle na pozadavku klienta a jsou nastavovany vzdy.
    SERVER_SOFTWARE
    Jmeno a verze softwaru serveru, s nimz bude CGI script komunikovat.
    Format: jmeno/verze
    Priklad: Netscape-Comunication/1.1
    SERVER_NAME
    Internetovska adresa nebo jmeno serveru.
    Format: Plne domenove jmeno nebo IP adresa
    Priklad: 194.149.119.37 nebo info.pvt.net
    GATEWAY_INTERFACE
    Verze CGI, kterou server pouziva.
    Format: CGI/verze
    Priklad: CGI/1.1
    Nasledujici promenne prostredi jsou zavisle na pozadavku klienta a naplnuje je server.
    SERVER_PROTOCOL
    Jmeno a verze protokolu, kterym zadal klient o dokument.
    Format: protokol/verze
    Priklad: HTTP/1.0
    SERVER_PORT
    Cislo portu, na ktery byl poslan pozadavek od klienta. V podstate cislo portu, na kterem ceka server, ktery spustil nas CGI program.
    Format: cislo od 1 do 65535
    Priklad: 80
    REQUEST_METHOD
    Metoda, kterou klient pouzil pri odesilani pozadavku. Pro HTTP to muze byt GET, POST, HEAD. Pri aktivaci linky v html dokumentu se pouzije metoda GET.
    Format: metoda
    Priklad: GET
    PATH_INFO
    Zde jsou predavany extra informace napr. jmeno adresare. Tyto informace jsou uvedeny v URL za cestou ke scriptu.
    Format: /adr1/adr2...
    Priklad: /html/obr/puntik.gif
    PATH_TRANSLATED
    Obsahuje preklad promenne PATH_INFO na fyzickou cestu, tj. vztazenou ke korenovemu adresari filesystemu.
    Format: /adr1/adr2...
    Priklad: /netscape/html/obr/puntik.gif
    SCRIPT_NAME
    Zde je uvedeno jmeno spusteneho scriptu i s virtualni cestou.
    Format: /adr1/adr2/jmeno_skriptu
    Priklad: /cgi-bin/prg1.pl
    QUERY_STRING
    Informace predavane scriptu pomoci metody GET,ISINDEX. Cast URL nasledujici za ?.
    Format: ruzny
    Priklad:tlac1=on&tlac2=off nebo Jan+Novak
    REMOTE_HOST
    Pocitac, ktery vyvolal pozadavek. V pripade, ze server tuto informaci nezna, musi nastavit REMOTE_ADDR a nechat tuto pololku prazdnou.
    Format: host.subdomena.domena
    Priklad: info.pvt.net
    REMOTE_ADDR
    IP adresa pocitace, ktery vyvolal pozadavek.
    Format: n.n.n.n
    Priklad: 194.149.199.45
    AUTH_TYPE
    V pripade, ze server podporuje overeni autenticnosti a CGI program je chranen, pak je zde uvedena autentifikacni metoda, uzivana pro overeni uzivatele.
    Priklad: basic
    REMOTE_USER
    V pripade, ze server podporuje overeni autenticnosti a CGI program je chranen, pak je zde uvedeno jmeno pod jakym je uzivatel identifikovan.
    Priklad:novak
    CONTENT_TYPE
    Pro pozadavky, ktere maji pridavne informace, jako jsou metody HTTP protokolu POST a PUT, je zde uveden typ dat. Informace jsou stejne jako v hlavicce HTTP protokolu Content-type. Pokud klient posle application/x-www-form-urlencoded, je promenna prazdna.
    Format: typ/podtyp
    CONTENT_LENGTH
    Delka dat v bytech predavanych klientem. V pripade, ze zadna data predavana nejsou, pak neni tato promenna nastavena.
    Priklad: Content-Length: 65
    K temto promennym mohou pribyvat dalsi. Dalsi hodnoty jsou polozky z HTTP hlavicky pozadavku a byvaji ulozeny v promennych prostredi se jmenem zacinajicim HTTP_. Pismena nazvu polozky jsou prevedena vzdy na velka pismena a znak - na _. Server nemusi v tomto tvaru ulozit polozky, ktere jsou dostupne v jinych promennych, napr: CONTENT-TYPE, CONTENT-LENGTH. Data z polozek jsou pouze prepsana do promenne. Kdyz je v HTTP hlacicce vice polozek stejneho jmena, pak data z techto polozek, jsou spojena do jedne promenne prostredi.

    Jako priklad uvedu nekolik promennych:

    HTTP_ACCEPT
    MIME typy, ktere muze klient prijmout. Toto se v HTTP protokolu zadava v hlavicce Accept. Typy budou ulozeny v teto promenne oddeleny carkami, stejne jako v HTTP.
    Format: typ/podtyp, typ/podtyp
    Priklad: image/gif, image/jpeg
    HTTP_USER_AGENT
    HTML prohlizec, krery vyvolal pozadavek.
    Format: ruzny
    Priklad: Mozilla/3.1N (Windows)

    Pouziti standardniho vstupu

    Pokud pouzije klient pri odeslani pozadavku metodu POST, jsou data predavana na standardni vstup CGI scriptu. Pomoci promenne CONTENT_LENGTH je mozne urcit pocet bytu, ktere je potreba precist ze standardniho vstupu. Neni zaruceno, ze na konci dat bude uveden znak pro konec souboru (EOF).

    Pouziti parametru prikazoveho radku

    Predavani dat do CGI scriptu jako parametr prikazove radky se pouziva pouze pri pouziti vstupniho pole ISINDEX na puvodni html strance. Tento zpusob je mozne pouzit pouse v metode GET a HEAD, nelze pouzit ve formularich. Pozadavek chapeme jako ISINDEX pokud URL obsahuje za ? retezec bez znaku = (nekodovaneho). Jednotlive casti retezce za otaznikem jsou oddeleny znakem +. Kodovane znaky jsou CGI procesem dekodovany a predany CGI scriptu.

    Vystup z CGI scriptu

    Obvykle CGI program posila odpoved klientovi prostrednictvim serveru. Proto se CGI program nemusi starat o hlavicky tykajici se protokolu. CGI script tedy muze byt jednodussi a nezavisly na zmene protokolu. CGI script musi generovat pouze hlavicky vztahujici k obsahu odpovedi. Pokud, ale mate dobre znalosti HTTP protokolu, muzete poslat odpoved klientovi primo pouzitim nonparsed header vlastnosti.

    Jako odpoved na CGI dotaz dostane klient odpoved ve tvaru:

    stavovy radek
    http hlavicka
    http hlavicka
    ..
    http hlavicka
    
    data
    
    - doplni server
    - nektere doplni server
    .
    - nektere generuje CGI script
    .
    - CRLF generuje CGI script
    - generuje CGI script

    Priklad jednoduche odpovedi generovane CGI scriptem:

    Content-type: text/html
    
    <HTML><HEAD>
    <TITLE>Vystup z CGI scriptu</TITLE>
    </HEAD><BODY>
    <H1>Jednoduchy vystup</H1>
    Co si o <STRONG>tom</STRONG> myslite?
    </BODY></HTML>
    

    Nonparsed headers - vynechani serveru pri odpovedi

    Nonparsed headers umoznuji vynechat pri posilani server a poslat odpoved primo klientovi.

    Tato metoda se napr. u serveru NCSA, Netscape, Apache aktivuje pokud jmeno CGI scriptu zacina prefixem nph-. Jakmile aktivujete tuto metodu, je CGI script odpovedny za vsechny hlavicky a vysledkovy kod vztahujici se k protokolu jak je patrne z prikladu:

    HTTP/1.0 200 OK
    Date: Monday, 13-JAN-97 12:31:05 GMT
    Server: Netscape-Comunication/1.1
    MIME-version: 1.0
    
    <HTML><HEAD>
    <TITLE>Vystup z CGI scriptu</TITLE>
    </HEAD><BODY>
    <H1>NPH vystup</H1>
    Telo dokumentu
    </BODY></HTML>
    

    CGI script musi odpovedet presne podle HTTP protokolu,kterym komunikuje klient. Pokud to neni nezbytne nutne je lepe tuto metodu nepouzivat.

    Hlavicky nejcasteji generovane CGI scriptem

    Odpoved generovana CGI scriptem posilana serveru musi zacinat obecnymi hlavickami. Hlavicky jsou textove radky ve tvaru: jmeno: hodnota, jde o hlavicky HTTP protokolu. Konec zahlavi odpovedi je indikovan prazdnou radkou. Po obdrzeni prazdne radky konci server s analyzou hlavicek a posila zbytek dat klientovi nezmeneny. CGI script muze generovat libovolnou hlavicku a server ji odesle klientovi. Nektere z bezne pouzivanych hlavicek uvedeme. Dalsi jsou soucasti popisu HTTP protokolu. Pokud nekterou z uvedenych hlavicek vygeneruje CGI script, pak tuto hlavicku server jiz nemodifikuje.

    Vysledkovy kod

    Pokud by chtel CGI script nastavit jiny nez implicitni vysledkovy kod (200 OK nebo 302 Found v pripade presmerovani) muze odeslat na standardni vystup retezec:

    Status: XXX doprovodny text

    kde XXX je pozadovany navratovy kod.

    Techniky CGI scriptu

    V prostredi Unixu, jsou CGI scripty casto psany v Bourne shellu, C-shellu a Perlu.

    Je-li CGI script napsan v Unixu, pak se operacnimu systemu musi sdelit, jaky interpret ma spustit, na prvni radce cgi scriptu se uvede cesta k interpretu pouziteho jazyka. Tato prvni radka je napr.:

    Je-li CGI script napsan jako spustitelny (zaveditelny) program napr. v jazyce C, pak tuto skutecnost operacni system sam pozna. Priklad jednoducheho Scriptu, ktery klientovi zasle vypis systemovych promennych. Script je napsany v C shellu:

    #!/bin/sh
    echo "Content-Type:text/html"
    echo ""
    echo "<TITLE>Systemove promenne </TITLE>"
    echo "<H1>Obsah systemovych promennych pri provadeni CGI </H1>"
    echo "<PRE>"
    set
    echo "<-PRE>"
    

    Soubor obsahujici CGI script musi mit nastaveno pravo pro spusteni. V OS Unix nastaveni zajisti prikaz:
    chmod 755 jmeno_souboru
    .


    PEGASNETPEGASNET

    PEGASNETPEGASNET

    PEGASNETPEGASNET

    PEGASNETPEGASNET