Ohjelmistotekniikan seminaari
12.12.1997
Sisältö
Tämä seminaariesitelmä käsittelee CGI-ohjelmoinnin
perusteita ja pyrkii opastamaan CGI-ohjelmien kirjoittamista aloittavia. Se ei
kuitenkaan käsittele yhtä CGI-ohjelmoinnin tärkeää
osa-aluetta, tietoturvaa, koska siihen syventyminen edellyttäisi parempia
pohjatietoja muilta alueilta. Tekstissä tarkastellaan myös SSI:a,
jotka eivät varsinaisesti ole CGI-ohjelmia, mutta jotka usein
yhdistetään CGI-ohjelmointiin ja auttavat välttymään
turhien ohjelmien kirjoittamiselta.
Common Gateway Interface on suomennettu yleinen yhdyskäytävä
liitäntä ("Tietotekniikan tietosanakirja", Suomen
ATK-kustannus 1997, 2. uudistettu laitos). Koska englanninkielinen termi on
kuitenkin yleisesti käytössä ja tunnettu, käytän koko
ajan alkuperäistä nimitystä.
Tekstissä keskitytään CGI-ohjelmien toteutukseen
Unix-pohjaisille palvelimille, koska suurin osa käytössä
olevista WWW-palvelimista on Unix/Linux-palvelimia. NT-palvelimet sivutetaan
lähes täysin, mutta liitteiden WWW-osoitteista löytyy tietoa
CGI-ohjelmoinnista Windowsille ja MacOs:lle.
Common Gateway Interface (CGI) on rajapinta, jolla voidaan luoda interaktiivisia sovelluksia www-sivuille. CGI-rajapintaa käyttäviä ohjelmia kutsutaan usein CGI-ohjelmiksi, niin myös tässä tekstissä. Ohjelmat voivat ottaa vastaan käyttäjän antamaa tietoa ja lähettää sitten vastauksensa tiedot lähettäneelle selaimelle. Eli CGI on se palvelimen osa, jolla saadaan palvelimella olevat ohjelmat käyttöön. Sen avulla palvelin voi kutsua ulkoisia ohjelmia ja välittää niille käyttäjän antamaa tietoa. Ohjelman ei tarvitse välttämättä lähettää vakiomuotoista tulostetta, vaan se voi generoida tulosteen käyttäjän syötteen mukaan. Esimerkkejä CGI-ohjelmista ovat mm. hakurobotit, vieraskirjat ja laskurit. Verkkokaupankäynnin lisääntyessä, lisääntyy myös myyntisovellusten tarve. CGI:tä käyttämällä voidaan helposti toteuttaa näitä sovelluksia.
WWW-palvelin ei välitä kielestä, jolla CGI-ohjelma on
kirjoitettu. Yleisimmin Unix-palvelimissa käytetty kieli on Perl. Se on
tulkattava kieli, joka vaatii palvelimeen oman Perl-tulkin. Perl
yhdistetäänkin usein CGI-ohjelmointiin ja CGI-ohjelmointi Perliin.
Muita Unixissa CGI-ohjelmointiin käytettyjä kieliä ovat C, C++,
Tcl ja Python. NT-palvelimissa käytetään yleensä Visual
Basicia, Delphiä, Perlia C:tä ja C++:aa. Macintoshissa
käytetään C:tä, C++:aa ja AppleScriptiä. Yleisesti
CGI-ohjelmien kirjoittamiseen riittää se, että ohjelmointikieli
osaa ottaa vastaan tietoa palvelimelta ja lähettää sitä
takaisin.
Vaikka Perl on ollutkin käytetyin ohjelmointikieli CGI-ohjelmoinnissa, on
C++:n käyttö koko ajan lisääntynyt. Perlin etu ja haitta on
se, että se on tulkattava kieli. Suuremmissa sovelluksissa se on hidas ja
vie paljon muistia, mutta Perl-tulkkeja on saatavissa lähes jokaiseen
käyttöjärjestelmään. Suosionsa ansiosta Perlille on
olemassa paljon valmiita aliohjelmakirjastoja, jotka helpottavat huomattavasti
ohjelmien kirjoittamista. Myös CGI:ssä tärkeät
merkkijonojen käsittely operaatiot ovat Perlissä huomattavasti C++:a
paremmin toteutettu. C++:n etuina Perliin verrattuna on nopeus ja
käännettyjen ohjelmien pieni koko. Myös C++:lle on tullut
valmiita aliohjelmakirjastoja syötteiden käsittelyyn. C++:n
vahvuutena ovat myös Perliä paremmat olio-ominaisuudet. Kielen
valinta on kuitenkin pitkälle tapauskohtaista, johon vaikuttavat
myös ohjelmoijan taidot. On luonnollista käyttää
kieltä, jonka hallitsee hyvin kuin lähteä opettelemaan uutta
kieltä ohjelman kirjoittamisen yhteydessä.
CGI:n ja JavaScriptin vastakkain asettelu on viime aikoina lisääntynyt. Sinänsä ne eivät taistele toisiaan vastaan CGI:n ollessa palvelimen käyttämä rajapinta ja JavaScript asiakkaan selaimen tulkkaama ohjelmointikieli. JavaScript sopii CGI:tä paremmin WWW-sivuille tehtäviin ohjelmiin ja CGI paremmin käsittelemään sivuilta saatavaa tietoa. Eräs ratkaiseva tekijä valintaa suoritettaessa on se, että CGI-ohjelmat pystyvät tallettamaan tietoa palvelimelle toisin kuten JavaScript-ohjelmat.
Ohjelmat sijoitetaan yleensä palvelimella cgi-bin-nimiseen hakemistoon. Tällöin tietoturvaan liittyviä ongelmia voidaan helpommin valvoa. Yleensä cgi-bin-hakemistolle annetaan suuremmat oikeudet kuin html-hakemistoille. Yleensä cgi-bin-hakemistosta ei saada tiedostostolistausta, mikäli tiedosto index.html puuttuu. Unixissa pitää lisäksi varmistaa, että ohjelmatiedostoon on annettu kaikille luku- ja suoritusoikeus. Myös mahdollisiin talletustiedostoihin on annettava kirjoitusoikeus. Turvallisuuden parantamiseksi tämä voidaan myös antaa ohjelmassa ennen talletusta ja ottaa pois, kun talletus on suoritettu.
CGI-ohjelmalle parametrit välitetään joko URLin avulla
lähetystapaa GET käyttäen tai lomakkeen
lähettämän pyynnön tekstirungossa lähetystapaa
POST käyttäen. POST-tapa on yleisempi, koska se ei
aseta yhtä suuria rajoituksia syötteen koolle kuin GET.
Lähetystavan ohjaa <form>-komennon method-attribuutti.
Esimerkiksi
Lähetystavalla GET vastaanottava ohjelma saa lomakkeen
sisällön yhtenä merkkijonona parametrikseen. Merkkijono on
luettavissa ympäristömuuttujasta QUERY_STRING. Merkkijonossa kaikki
parit nimi=arvo on eroteltu toisistaan &-merkillä. Koska
parametrit lähetetään osana URL-osoitetta, ei mukana saa olla
välilyöntejä eikä muita URL:n käyttämiä
erikoismerkkejä. Tämän vuoksi "skandit" ja monet erikoismerkit
esitetään heksakoodattuina ja välilyönnit
esitetään +-merkkeinä.
Esimerkiksi kutsuttaessa vieraskirjaa ylläpitävää
CGI-ohjelmaa saattaisi URL näyttää seuraavalta:
POST-tapaa käytettäessä siirtyvät parametrit HTTP-pyynnön runko-osassa. Tällöin palvelin ohjaa nämä syöttövirtaan (STDIN). Yhtenäisyyden vuoksi myös POST-metodilla lähetetyt tiedot ovat samassa muodossa kuin GET-metodilla lähetetyt. On huomattava, että jos lähetystapaa ei erityisesti määritellä niin oletusarvona on GET.
Perlille on saatavana mm. seuraavat aliohjelmakirjastot
Cgi-lib.pl on helppokäyttöinen aliohjelmakirjasto Perlille. Se on
saatavana WWW-osoitteesta
http://cgi-lib.stanford.edu/cgi-lib/.
CGI.pm on oliopohjainen moduli Perlille. Hyvin dokumentoitu moduli on
löytyy URLista
http://www-genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html.
C:lle ja C++:lle löytyy myös useita vastaavia kirjastoja.
Un-CGI muuttaa POST-metodilla lähetetyn lomakkeen tiedot
ympäristömuuttujiksi WWW_kentännimi, jossa
ympäristömuuttuja sisältää kentän arvon valmiiksi
dekoodattuna. Se on saatavilla WWW-osoitteesta
http://www.midwinter.com/~koreth/uncgi.html.
LibCGI++ on oliopohjainen luokkakirjasto, joka valmiiksi dekoodaa myös
kenttien arvot. Olio-ominaisuuksiensa vuoksi toimii se ainoastaan
C++-kääntäjissä. LibCGI++:aan voi tutustua tarkemmin
osoitteessa
http://www.ncsa.uiuc.edu/People/daman/cgi++/.
CGI-ohjelma voi tulostuksessa osoittaa selaimelle jonkun olemassa olevan
dokumentin tai luoda itse virtuaalisen dokumentin. UNIXissa ohjelmat tulostavat
kaksiosaisen tietolohkon. Lohkon ensimmäinen osa on HTTP-otsikko.
Siinä kerrotaan sitä seuraavan datan muoto, joka muodostaa toisen
lohkon.
Ohjelman tulee aloittaa tulostus HTTP-dataotsikon tulostuksella. Yleensä
tulostus aloitetaan dataosan tyypin määrittelemisellä. Tyypin
määrittelyssä käytetään sisältölajeja,
jotka läheisesti muistuttvat MIME-tyyppejä. Yleisimmin
käyttetyjä sisältölajeja ovat text (alalajeja mm. html ja
plain) sekä image (alalajeja mm. jpeg ja gif). Kaikki tulostus tapahtuu
tulostusvirran (STDOUT) kautta.
Ohjelma, joka sen URLia kutsuttaessa tulostaisi näytölle tekstin
"Hello World", voidaan toteuttaa Unixissa komentotiedostona seuraavaalla
tavalla:
Tulostettavan dokumentin osoite voi olla joko täydellinen tai suhteellinen.
Yleisin CGI-ohjelmien käyttömuoto laskureiden lisäksi on erilaisten lomakkeiden käsittely. Lomakkeet ovat HTML-kieltä, joten niiden syntaksiin ei tässä yhteydessä puututa.
Lomakkeiden komponenteista yksinkertaisimpia syötteenä ovat normaalit
teksti- ja salasanakentät. Näissä ainoastaan erikoismerkit
tulevat QUERY_STRING:ssä heksakoodattuna tekstinä.
Erikoismerkeiksi luokitellaan normaaleja aakkosia (ei sisällä
"skandeja"), numeroita sekä pistettä (.), väliviivaa (-) ja
alaviivaa (_) lukuunottamatta lähes kaikki merkit. Textarea-komponentti
toimii muuten samalla tavalla, mutta rivin vaihto lisää merkkijonoon
"CR"- ja "LF"-merkit (...%0D%0A...).
Radiopainikkeissa (radiobutton) pitää kaikilla saman ryhmän
painikkeilla olla asetettuna jokin arvo value-attribuuttia
käyttäen. Tällöin QUERY_STRING
sisältää ryhmän nimen jälkeen valitun radiopainikkeen
arvon. Samoin toimivat valintaruudut (checkbox). Koska jokainen valintaruutu on
eri niminen, ei niissä välttämättä tarvitse
käyttää value-attribuuttia. Mikäli valintaruutu on
rastitettu, sisältää QUERY_STRING valintaruudun arvona
"on", jos mitään arvoa ei ole erikseen asetettu. Jos ruutua
ei ole valittu, ei arvoa lähetetä.
Click here for Picture
<select>-komento toimii joko kuten valintaruutu tai kuten
radiopainike. Tämä voidaan valita multible-attribuuttia
käyttämällä. Jos sallitaan usempi yhtäaikainen
valinta, niin <select>-komento toimii kuten valintaruutu, muuten
se toimii kuten radiopainike. Jos valintaruudun alkiolle ei ole
määritelty erillistä arvoa value-attribuuttia
käyttäen, lähetetään palvelimelle alkion arvona
<option>-komennon sisältö.
Esimerkiksi seuraavan kaltaisesta lomakkeesta tehtäessä kuvan
mukaiset valinnat, olisi QUERY_STRINGin sisältönä:
Unix-palvelimissa suurin osa CGI-ohjelmien tarvitsemasta tiedosta on saatavana
ympäristömuuttujien kautta. CGI-ohjelmat hakevat tiedon
ympäristömuuttujista aivan kuten muutkin ohjelmat. Seuraavassa on
listattu yleisesti käytettävissä olevat
ympäristömuuttujat. Näiden lisäksi joillakin palvelimilla
(mm. Apache) on omia ympäristömuuttujiaan.
AUTH_TYPE sisältää käyttäjän
varmennustavan. Katso REMOTE_USER ja REMOTE_IDENT.
CONTENT_LENGTH sisältää STDIN-puskurissa olevan
tiedon pituuden tavuina. Tavujen määrä on sama kuin
merkkien määrä, koska yksi merkki esitetään
yhdellä tavulla.
CONTENT_TYPE sisältää kyselyn tiedon MIME-tyyppi, esim "text/html".
DOCUMENT_ROOT sisältää hakemiston, jonka alla WWW-dokumentit ovat palvelimessa.
GATEWAY_INTERFACE sisältää palvelimen käyttämän CGI:n versio muodossa CGI/versio.
HTTP_ACCEPT sisältää luettelon lukuohjelmalle kelpaavista MIME-tyypeistä. Eri tyypit esitellään toisistaan pilkulla eroteltuina.
HTTP_FROM sisältää kyselyn tekijän sähköpostiosoiteen.
HTTP_otsikkokenttä sisältää itse määritellyn otsikkokentän arvon.
HTTP_REFERER on sen dokumentin URL-osoite, josta CGI-ohjelmaan siirryttiin.
HTTP_USER_AGENT on kyselyn tehneen selainohjelman versio muodossa nimi/versiokirjasto/versio.
PATH_INFO on CGI-ohjelmalle välitetty
ylimääräinen hakemistopolku.
PATH_TRANSLATED on PATH_INFO muutettuna oikeaksi palvelimen hakemistopoluksi.
QUERY_STRING sisältää URL:ssä ohjelmalle annetut parametrit (kaikki ?-merkin jälkeiset merkit) merkkijonona. Lähetystapaa GET käytettäessä löytyy myös lomakkeen sisältö (nimi=arvo-parit) tästä ympäristömuuttujasta. Mahdolliset +-merkit ovat myös mukana.
REMOTE_ADDR on kyselyn tekijän IP-numero.
REMOTE_HOST on kyselyn tekijän IP-osoite nimenä.
REMOTE_IDENT sisältä kyselyn tekijän käyttäjätunnuksen., jos palvelin tukee RFC 931-tunnistusta. NCSA:n suosituksen mukaan käyttö pitäisi rajoittaa sisäänkirjoittautumiseen.
REMOTE_USER sisältää lukijan käyttäjätunnuksen, jos ohjelma on suojattu salasanalla. Ei ole välttämättä sama käyttäjätunnus kuin lukijan palvelinkoneessa oleva.
REQUEST_METHOD on tiedon pyyntötapa, yleisimmin GET, POST tai HEAD.
SCRIPT_NAME on suoritettavan CGI-ohjelman sijainti (esim. /cgi-bin/ohjelma.cgi).
SERVER_NAME on palvelimen nimi tai IP-osoite.
SERVER_PORT on palvelimen portin numero.
SERVER_PROTOCOL sisältää protokollan, jolla
ohjelmaa kutsuttiin muodossa protokolla/versio.
SERVER_SOFTWARE sisältää palvelinohjelmiston nimen ja version muodossa nimi/versio.
Esimerkiksi Jyväskylän yliopiston WWW-palvelin antoi
seuraavanlaisen tulostuksen kutsuttaessa yksinkertaista CGI-ohjelmaa, joka
tulostaa ympäristömuuttujien arvoja.
Click here for Picture
Server Side Includet (SSI) ovat HTML-dokumenttiin sijoitettavia komentoja,
joilla voidaan suorittaa ohjelmia tai tulostaa muuttujien arvoja. Vaikka SSI:t
eivät teknisesti ole CGI-ohjelmia, ne usein auttavat
välttämään CGI-ohjelmien kirjoittamisen, kun halutaan CGI:n
kaltaista tietoa tai tulostuksia. Aina ei ole järkevää generoida
uudestaan koko dokumenttia, vaan ainoastaan tietyt kohdat. SSI:t sijoittavat
dokumenttiin käskyjen tilalle niiden tulosteen. Kun selaimella katsotaan
SSI-käskyn sisältävän ohjelman lähdekoodia, ei
siinä näy alkuperäistä komentoa, vaan sen tuloste.
Kaikki palvelimet eivät kuitenkaan tue näitä käskyjä.
Erityisesti CERNin palvelin ei tunne SSI-käskyjä ilman
määritysten muuttamista. Komentojen käyttöön
ottamisessakin on erilaisia tapoja. Palvelimeen saattaa esimerkiksi olla
määritelty, että komentoja voidaan ajaa vain sivuilta, joiden
tarkennin on shtml.
Järjestelmällä on myös haittoja. Asiakkaan
pyytäessä dokumenttia SSI:tä kayttävältä
palvelimelta, käy palvelin läpi koko dokumentin etsien SSI-komentoja.
Dokumenttien tutkiminen ja komentojen suorittaminen kuormittavat palvelinta.
Lisäksi SSI:n käyttö antaa mahdollisuuksia
väärinkäytöksiin. Tietämätön
käyttäjä saattaa kutsua SSI:llä
järjestelmäkomentoja, jotka paljastavat luottamuksellista tietoa
palvelimesta ja sen käyttäjistä. Näin ollen SSI saattaa
olla kätevä, mutta sitä on käytettävä varovasti.
SSI:n peruskomentoja ei ole paljon, mutta ne saattavat
säästää yksinkertaisimpien CGI-ohjelmien kirjoittamiselta.
Kaikki SSI-komennot ovat muotoa:
echo var="ympäristömuuttuja"
flastmod [file="tiedosto"]
[virtual="osoite"]
DOCUMENT_NAME on dokumentin nimi.
DOCUMENT_URL on dokumentin URL-osoite.
QUERY_STRING_UNESCAPED sisältää dokumentille
välitetyt parametrit koodattuna, jossa erikoismerkkien edessä
"\"-merkki.
DATE_LOCAL sisältää päiväyksen ja
kellonajan palvelinkoneen kellosta.
DATE_GMT sisältää päiväyksen ja
kellonajan GMT:n mukaan.
LAST_MODIFIED sisältää tiedoston viimeisimmän muutospäivän ja ajan.
SSI-komentojen tulostaessa aikaa ja päivämääriä
voidaan tulostusformaattia muotoilla config-komennon timefmt-parametria
käyttämällä. Taulukossa 1 esitellään formaatin
määrittelyssä käytettävät koodit.
Koodi | Tarkoitus | Esimerkki |
%a | Viikonpäivän
lyhenne |
Sun |
%A | Viikonpäivä | Sunday |
%b | Kuukauden lyhenne (myös %h) |
Jan |
%B | Kuukausi | January |
%d | Päivä | 08 |
%D | Päiväys muodossa "%m/%d%y" | 08/11/97 |
%e | Päivä | 8 (ei 08) |
%H | Tunnit 0-23 | 14 |
%I | Tunnit 1-12 | 03 |
%j | Päivä vuodesta | 325 |
%m | Kuukausi numerona | 11 |
%M | Minuutit | 07 |
%p | AM/PM (aamupäivä/iltapäivä) | AM |
%r | Aika muodossa "%I:%M:%S %p" | 08.57.55 PM |
%S | Sekunnit | 55 |
%T | 24h aika muodossa "%H:%M:%S" | 14.24.09 |
%U | Viikon numero (myös %W) | 38 |
%w | Päivä viikosta (sunnuntai = 0) | 2 |
%y | Vuosi sadasta | 97 |
%Y | Vuosi | 1997 |
%Z | Aikavyöhyke | GMT |
Esimerkiksi lisättäessä HTML-koodiin
Netscape esitteli cookiet vähentämään palvelimella
tapahtuvaa käyttäjäkohtaisten tietojen varastointia.
Cookie-järjestelmän avulla sivukohtainen tieto varastoidaan
käyttäjän koneelle. Koska cookiet ovat asiakkaan
kovalevyllä, niin ne säilyvät vaikka selain välillä
suljettaisiinkin.
Cookien käyttö CGI-ohjelmalla tapahtuu seuraavasti:
Set-Cookie-otsikon syntaksi on seuraava:
CGI on käytöllinen rajapinta WWW-sovellusten tekemiseen. Yleensä ohjelmia kirjoitettaessa vastaan tulevat ongelmat liittyvätkin muihin tekijöihin kuin varsinaisen rajapinnan toimimattomuuteen. CGI:n käyttöä tulee varmasti vähentämään IntraBuilderin kaltaisten sovellusten lisääntyminen. Toisaalta verkottumisen ja etenkin verkon kautta tapahtuvan kaupankäynnin lisääntyminen pitävät CGI:n vielä pitkään yleisenä rajapintana WWW-sovellusten ohjelmoinnissa.
Spainbour Stephen, Quercia Valerie, "Webmaster -
Tehokäyttäjän opas", Suomen ATK-kustannus, 1997.
Niemi Juha, Kiuttu Petri, "Opeta itsellesi JavaScript", SuomenATK-kustannus, 1996.
MicroPC 11/97,
"CGI:llä vuorovaikutusta www-sivuille".
NCSA, "NCSA CGI Documentation",
"http://hoohoo.ncsa.uiuc.edu/cgi/", 1997.
Netscape, "HTTP Cookies",
"http://home.netscape.com/newsref/std/cookie_spec.html", 1997.
Introduction to the Common Gateway Interface,
http://www.virtualville.com/library/cgi.html
CGI Securirty Tutorial,
http://www.csclub.uwaterloo.ca/u/mlvanbie/cgisec/
The Web Developer's Virtual Library,
http://WWW.Stars.com/
The CGI Resource Index,
http://www.cgi-resources.com/
Perl,
www.perl.com
Delphi 2.0 and Standard CGI,
http://www.okcom.net/~mlovell/delphiCGI.html
Microbrew CGI Tutorial (Macintosh),
http://www.networkmultimedia.com/TutPage/CHAP101.htm
NCSA HTTPd Tutorial: Server Side Includes,
http://hoohoo.ncsa.uiuc.edu/docs/tutorials/includes.html