Manuale CGI

Transcript

Manuale CGI
Manuale CGI
CGI significa "Common Gateway Interface" , ed è il metodo con cui un server agisce con database,
documenti, e altri programmi inviando o ricevendo dati; questi dati saranno poi visualizzati sul web. In
pratica, saper scrivere CGI significa programmare il web per il web. Il linguaggio "principe" per scrivere i
CGI è il Perl, anche se è possibile utilizzare altri linguaggi (C su tutti).
Vediamo più da vicino il funzionamento dei CGI e dei rapporti client-server: di solito, quando nel nostro
browser indichiamo un URL (Uniform Resource Locator), succede a grandi linee questo:
per prima cosa il nostro computer contatta il server HTTP basandosi sull'url da noi indicata;
il server HTTP cerca il nome del file che abbiamo richiesto dal nostro computer e, una volta trovato, ci
manda indietro il file;
come ultima cosa il nostro computer, una volta ricevuto il file, lo esamina, lo elabora e ce lo mostra a
video, nove volte su dieci come una normale pagina web (ovvero nel formato HTML).
E' comunque possibile, in determinati casi, configurare il server HTTP in modo che questo, ogni volta che
viene richiesto un file in una determinata directory, non mandi direttamente indietro tale file: questo file
viene eseguito come un vero e proprio programma dal server, e solo l'output di tale programma viene
inviato al nostro computer perchè lo visualizzi: un esempio lampante può essere il counter: il computer di
chi entra nel sito dove risiede il counter non fa assolutamente niente tranne visualizzare la gif preparata
dal server (sempre che si tratti di un counter grafico), che svolge tutto il lavoro, dall'intercettare il visitatore
al preparare un'immagine con il numero di accessi. E' appunto questa funzione che viene chiamata
Common Gateway Interface. E questi programmi sono chiamati script CGI.
Prepariamoci alle lezioni vere e proprie, facendo un rapido resoconto su cosa ci serve per iniziare;
intanto, un web server funzionante: non conviene (per chi ha questa fortuna) testare i frutti del lavoro su
un vero web server in rete. Vedremo nei prossimi capitoli come installare e configurare un server web
sulla nostra macchina, senza bisogno di reti di pc e modem sempre accesi. Servirà poi conoscere il Perl
ed avere l'interprete sulla propria macchina: non è necessaria una conoscenza da 'guru' di questo
linguaggio, ma più ne sapete meglio è. Come dice Larry Wall, autore di questo linguaggio, il Perl è come
una vera e propria lingua: c'è chi la studia in tutti i suoi risvolti, c'è chi se ne serve solo per i discorsi di
ogni giorno; tutti questi, comunque, sanno parlare; così il Perl può essere conosciuto a diversi gradi di
profondità, ma non è necessario conoscerne tutte le sfaccettature per scrivere i vostri script. Servirà poi
tanta pazienza, voglia di imparare e sperimentare. Tutto qui.
Come già anticipato, ci occuperemo dell'installazione e dell'approntamento del web server Apache su un
sistema Linux; perchè Linux? Sia perchè è un sistema completamente 'free' sia perchè le sue prestazioni
a livello di rete e di server sono davvero molto buone. Ovviamente, se state utilizzando un sistema
differente, potrete sempre leggere la documentazione presente: credetemi, non è un'impresa ardua,
soprattutto se si deve configurare un web server in locale. Addirittura in queste pagine parleremo
dell'installazione del server su un pc stand-alone: questo significa una sola macchina, niente schede di
rete, hub e simili, niente domini virtuali e via dicendo. Chi possiede un pc che funziona da server non avrà
proprio bisogno di leggere questo capitolo, ed è per questo che si è optato per l'installazione su un
singolo pc.
Iniziamo dai pacchetti precompilati: gli .rpm ed i .deb.
Vediamo per primi i pacchetti rpm, installabili su RedHat, Suse e Mandrake: come saprete, questi
pacchetti sono pronti all'uso, quindi basterà semplicemente installarli con il semplice comando rpm -i
Apache-xx.rpm. Le due x sono la versione di Apache: potete scegliere quella che volete, a patto che sia
abbastanza recente. Fatto questo, Apache sarà installato ma non è ancora tutto: da un terminale scrivete
setup e vi apparirà una schermata che vi permetterà di impostare alcune configurazioni del sistema;
andate nella parte relativa ai demoni e verificate che il demone httpd sia avviato al boot del sistema:
senza di questo Apache non andrà mai in esecuzione. Una volta che vi siete assicurati che sia tutto a
posto, lanciate il browser e inserite come indirizzo localhost: quella che vedrete è la schermata di
'benvenuto' di Apache: se la vedete (cosa assai probabile, se avete fatto quanto sopra descritto), vuol
dire che Apache è regolarmente in esecuzione sul sistema. Per la configurazione dello stesso, ne
parleremo più avanti, ricordatevi solo che con RedHat è distribuito anche un piccolo tool di
configurazione, chiamato Comanche.
Ecco qui la schermata di benvenuto di Apache installato su RedHat. Notate l'indirizzo sulla barra
del titolo e il tool comanche sulla destra.
Passiamo ai .deb, utilizzato sulla distribuzione Debian.
Anche qui le cose sono abbastanza semplici: installate il pacchetto con dpkg -i Apache-xx.deb e, se
tutto è andato a buon fine, dopo aver settato il pacchetto, partirà automaticamente lo script apacheconf:
questo vi guiderà passo-passo alla configurazione del server, ed in linea di massima questo sarà già
funzionante a perfezione. Anche in questo caso approfondiremo in seguito la configurazione 'manuale'.
Testate il tutto inserendo 'localhost' nella finestra dell'indirizzo del browser e verificate. La pagina sarà
differente da quella di RedHat: ma questo non ci importa perchè presto il file /var/www/index.html sarà
cambiato. Tale file, infatti, è il file di "apertura" di Apache, una sorta di home page: e chi, per la propria
pagina (anche se in localo) lascerebbe la schermata di Apache, per quanto possa essere bella?
Come ultimo vediamo i tgz, ovvero i sorgenti: qui il lavoro sarà leggermente più difficoltoso, ma non
impossibile: bisognerà infatti compilare tutto a mano.
Vediamo innanzitutto dove procurarsi i sorgenti: al sito www.apache.org si trova tutto quello che stiamo
cercando, compresi i vari porting per sistemi diversi. Quindi cerchiamo quelli per Linux e scarichiamoli sul
nostro HD. Una volta che il download è terminato, spostiamo il grosso archivio in una directory a
piacimento: qui si supporrà che tale directory sia /usr/local.
Lanciamo poi
$ gunzip Apache-xx.tar.gz
e successivamente
$ tar xvf Apache-xx.tar
A questo punto sarà comparsa la directory Apache-xx, ed è in questa directory che si dovrà lavorare.
Quindi diamo un bel
$ cd Apache-xx
e leggiamoci per bene i file REDME ed INSTALL: non leggere questi file significa fare le cose a casaccio,
poichè in fase di compilazione e preparazione potrebbe rendersi necessario lanciare qualche comando
senza il quale il lavoro risulterebbe vano.
Iniziamo quindi a lavorare.
Probabilmente avrete per la mani una versione 1.3 di Apache, per il quale ci sono due possibilità di
installazione: il nuovo processo, detto APACI, è più veloce e comodo, poichè utilizza tutte le modalità
'standard' di installazione dei pacchetti sotto Linux; il processo più vecchio è invece quello manuale, lungo
e noioso. Abbiamo optato qui per il primo: vediamo come si svolge il tutto:
•
intanto dobbiamo assicurarci di alcune cose: dobbiamo avere circa 12 Mb di spazio temporaneo
su disco e 3 Mb necessari all'installazione; serve poi il compilatore, che presumibilmente avrete
già installato: è vivamente consigliato GCC 2.7.2 o superiore. Vengono poi citati come opzionali
l'interprete perl5 (che comunque dovrete avere, altrimenti i CGI saranno impossibili da eseguire)
ed il supporto DSO (Dynamic Shared Object, che in due parole servono per alcune chiamate di
sistema per il caricamento dei moduli);
•
lanciamo lo script ./configure, per preparare la compilazione dei sorgenti; tale script accetta varie
opzioni:
-E' la directory nella quale volete installare Apache (ovviamente PREFIX dovrà
prefix=PRE
essere cambiato con il nome della directory): consigliata /usr/local
FIX
--addServe per copiare il sorgente di un modulo nell'albero dei sorgenti di Apache;
module=FIL ovviamente al posto di FILE dovrete inserire il path per il sorgente del modulo
E
--activatemodule=FIL Aggiunge al volo un'entry per un modulo al file di configurazione di Apache
E
--enableServe per fare in modo di abilitare (o disabilitare, utilizzando --disable-module) un
module=NA
modulo particolare
ME
--withServe per impostare l'interprete perl utilizzato da Apache (anche se di solito
perl=FILE Apache cerca da solo l'interprete)
Ovviamente la opzioni da passare a ./configure non sono tutte qui: si è pensato di presentarvi
solamente le più utili (soprattutto al nostro scopo). Per conoscere tutte le opzioni, lanciate
'./configure --help'
•
Iniziamo la compilazione lanciando 'make'. Sui computer moderni non ci vorrà molto, ma dovete
ad ogni modo attendere qualche minuto prima che l'operazione termini;
•
Ora installiamo il tutto: lanciamo 'make install' e lasciamo che il tutto si concluda.
•
A questo punto Apache è installato ma non ancora attivo: lanciamo 'PREFIX/sbin/apachectl start'
e dovremmo poter richiedere ad Apache il primo URL, che sarà http://localhost. Se volete fermare
Apache, lanciate 'PREFIX/sbin/apachectl stop'.
E questo è tutto per quanto riguarda l'installazione partendo dai sorgenti.
Veniamo ora alla parte più importante: la configurazione: il file principale è /etc/apache/httpd.conf , ma voi
potrete averlo da qualche altra parte, soprattutto se siete partiti dai sorgenti. In ogni caso, fate una ricerca
e rintracciate tale file.
Vediamo com'è strutturato tale file: intanto, ogni voce è ampiamente commentata, così da farvi capire
cosa state facendo e a cosa serve quello che state facendo. Ovviamente, un minimo di conoscenza del
linguaggio tecnico è necessaria per poter configurare al meglio.
Le voci più significative sono:
ServerType
Port
HostnameLookups
ServerAdmin
ServerRoot
LoadModule
ErrorLog
ServerName
Impostatelo su 'standalone', dovrebbe bastare.
Default è 80, non conviene cambiarla
Logga i nomi dei client (on) o solamente il loro numero IP (off);
lasciatelo pure su off
E' abbastanza inutile su un server locale, ma se volete impostate il
vostro indirizzo e-mail così, per ogni errore, potrete vantarvi di
essere visto da Apache come l'amministratore.
La directory dove Apache conserva i log, gli errori e i file di
configurazione; solitamente è la directory dove è presente il file
httpd.conf
Importante: indica ad Apache quali moduli caricare; se volete
andare veramente sul sicuro, caricateli tutti (anche se l'avvio di
Apache sarà più lento, ma si parla solo di qulche secondo).
Indispensabili ai nostri scopi sono tutti i moduli per i CGI, per il Perl
e i mime
Il file dove Apache scrive gli errori. /var/log/apache/error.log può
andare benissimo.
Il nome del vostro server. Se non l'avete mai impostato, sarà
localhost.localdomain ma, siccome è assai scomodo, lanciate (da
root) hostname e cambiate il nome al vostro host
Un altro importante file è srm.conf, che dovrebbe essere nella stessa directory di httpd.conf. Vediamolo
più da vicino:
DocumentRoot
La directory nella quale mettere i file html per la pagina locale.
Solitamente /var/www : quindi se in tale directory mettete un vostro
index.html, indicando 'localhost' come indirizzo del browser, vedrete
proprio questa pagina. E da questa partiranno le altre pagine
Il nome della pagina che verrà visualizzata come indice; solitamente
DirectoryIndex
index.html
Ed eccoci arrivati ai CGI: conviene impostare tale voce come :
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ . Cosa significa? semplicemente, che
ScriptAlias
voi potrete inserire i vostri CGI in /usr/lib/cgi-bin/, ma questi saranno
chiamati tramite http://localhost/cgi-bin/nome_cgi.cgi
Siamo quindi giunti alla fine, e dovreste avere un server locale perfettamente funzionante. Se qualcosa
fosse andato storto, leggete la documentazione inclusa nell'archivio che avete scaricato ed
eventualmente cercate la cartella /usr/doc/apache:, entrateci e leggete tutto quello che vi può essere di
aiuto.
Apriamo in questo capitolo una piccola parentesi: preferiamo illustrarvi adesso la teoria sui form poichè
nei prossimi capitoli si farà continuo riferimento ad essi. Crediamo che tutti o quasi sappiano cos'è un
form ma, per evitare equivoci, sappiate che un form è qualcosa di simile a
il cui codice sorgente è:
Ma partiamo dall'inizio.
La forma elementare di un form è la seguente:
<FORM> inizio del modulo
<INPUT>
..............
..............
Qui ci possono essere tutti i campi input che volete, pensate ad esempio ad un form per la registrazione
dei dati di un utente
<INPUT>
</FORM> fine del modulo
Vedremo in seguito come riempire quei campi 'INPUT', per il momento vediamo il primo form funzionante,
che non ha bisogno di CGI o altri strumenti.
<FORM METHOD=POST ACTION="mailto:[email protected]" ENCTYPE="application/x-www-formurlencoded"> </FORM>
(Noterete che quanto scritto sopra non funziona esattamente come sperato. Manca infatti lo spazio per
digitare l'input. Vedremo tra poche righe come sistemare il tutto). L'unica cosa che dovrete cambiare in
questo form sono le 'x', alla quale sostituirete il vostro indirizzo e-mail. Sfortunatamente, però, i dati
arriveranno in formato quasi illeggibile, ossia:
FORMNAME=Nuovo&NAME=Mario+Rossi&ADDRESS=
Via+Milano&CITY=Roma&STATE=IT
Ci sono 2 metodi per ovviare a questo inconveniente: utilizzare programmi che formattano il testo da soli,
senza che voi capiate niente oppure utilizzare un CGI: ovviamente scarteremo la prima ipotesi per la
seconda, anche se per adesso non andremo oltre; capirete più in là come manipolare questa stringa. Per
il momento non vi preoccupate se non riuscite a capire come ed in che modo arriveranno i dati: state
sicuri che arriveranno, e noi faremo in modo che arrivino anche in maniera leggibile.
Passiamo ora alla creazione dei nostri primi forms, quindi apriamo i tags <INPUT> e inseriamo altre
istruzioni: la più elementare è inserire la tipologia dell'immissione dei dati: la più comune è
<INPUT TYPE=TEXT>
Ogni input, inoltre, ha bisogno di un nome: ad esempio possiamo definire qualcosa come NAME="email"
in modo che, quando l'utente riempirà il form a noi arriverà una stringa tipo
'[email protected]'. Notate che 'email' è un nome scelto arbitrariamente, potrebbe essere
anche l'indirizzo, la pizza preferita o qualsiasi altra cosa. Sarà quindi utile inserire del testo che indichi
come riempire lo spazio del form che segue, onde evitare disastrosi disguidi. Inoltre, il nostro form può
essere ancora modificato aggiungendo il tag SIZE, ovvero la lunghezza del form: di default è SIZE=20,
ma potete mettere il valore che preferite; se però volete che il testo inserito non superi i TOT caratteri,
inserite il tag <MAXLENGTH>
Quindi il codice completo del form sarà:
Adesso, se provate tale form, il risultato è assicurato: se andate a vedere nella vostra posta in uscita,
noterete un messaggio in cui il mittente siete voi stessi, così come il destinatario, ed il testo di tale mail
sarà qualcosa del tipo: email=quello+che+avete+digitato. Un ultima cosa prima di concludere: potete
cambiare il tag <TYPE> da <TEXT> a <PASSWORD>, in modo che non vengano utilizzati i caratteri ma
degli asterischi.
Vediamo come può risultare un form di questo tipo (provate ad inserire più di 6 caratteri):
Restiamo sull'argomento ma cambiamo tipo di pulsanti: vediamo i cosiddetti 'radio buttons'. Il codice è:
I tag <BR> e <P> non sono strettamente necessari, ma ci permettono di avere un layout migliore:
Scelta uno
Scelta due
Scelta tre
Cosa restituirà un form di tal tipo? Beh, se scegliete "Scelta uno" restituirà "nome1=valore1", se scegliete
"Scelta due" restituirà "nome2=valore2" e via dicendo.
Se avete notato, i radio buttons ci permettono di scegliere una sola delle opportunità: se avete la
necessità che il visitatore possa scegliere più di un'alternativa, potrete sostituire i radio buttons con le
'checkboxes', il cui codice è in tutto e per tutto identico ai radio buttons; eccone un esempio:
ed il rispettivo layout:
Scelta uno
Scelta due
Scelta tre
Anche per le checkbox vediamo i dati restituiti: saranno identici a quelli dei radio buttons ma, siccome
potete operare scelte multiple, potreste avere (supponendo di selezionare "Scelta uno" e
"Sceltadue"):"name1=valore1&nome2=valore2".
Facciamo un ulteriore passo avanti: probabilmente questo form vi sarà molto familiare:
Il rispettivo codice è il seguente:
Di default, questo tipo di form visualizza il primo valore della lista, ma se volete, ad esempio, che sia
visualizzato il terzo (Valore3) potrete cambiare il codice contrassegnato dai due asteischi come:
<OPTION VALUE= "Valore3"SELECTED>Valore3
Volete trasformare questo form in una lista scorrevole? Niente di più semplice, basterà aggiungere un
semplice tag alla riga contrassegnata con l'asterisco: questo tag è <SIZE>.
<SELECT NAME="NOME" SIZE=3>
Attenzione che se <SIZE> è maggiore del numero di elementi del form, l'effetto non sarà proprio quello
sperato. Verificate il tutto inserendo prima 3 poi 5 come size del form. Anche con le liste è possibile
includere il tag SELECTED per preselezionare un elemento, e si fa esattamente come si è fatto in
precedenza.
Vediamo l'ultimo tipo di form la:
ovvero un area di testo il cui codice è
ovvero un area di testo il cui codice è:
Anche questo è modificabile: ad esempio si possono decidere le dimensioni, inserendo dopo name
<ROWS= XX> e <COLS=XX>, dove le due X sono il numero di righe e colonne. Quindi una textarea con
dimensioni arbitrarie potrebbe essere del tipo:
Chiudiamo la carrellata con i famosi pulsanti:
e
!
"
#
$
Il codice è semplice, per submit sarà:
Mentre per reset:
Sarà facile cambiare il testo di default per ogni pulsante introdicendo VALUE, ad esempio:
E questo è tutto per quanto riguarda i form.
Se avete già letto il tutorial gratuito sul Perl pubblicato su queste pagine, molte delle nozioni sotto
riportate non vi saranno nuove, e faticherete molto meno a capirne il funzionamento; ovviamente alcune
cose vi risulteranno del tutto nuove, ma verranno puntualmente spiegate facendo ricorso anche a degli
esempi, ove possibile e necessario.
Iniziamo ora a vedere i veri e propri script.
La prima cosa da sapere è che gli script, solitamente, vanno a generare delle pagine web, quindi
bisognerà inserire alcune istruzioni in modo che questo sia effettivamente quello che succede. La prima è
sicuramente:
print "Content-type:text/html\n\n";
Questa non è che un'istruzione che istruisce il browser sul tipo di dati che riceverà: in questo caso, il
browser saprà che si tratta di un documento html e lo formatterà di conseguenza; se al posto di questa
istruzione avessimo inserito:
print "Content-type:text/plain\n\n";
il CGI avrebbe inviato al nostro computer un documento "plain text". Ancora, se volessimo inviare
samples sonori o immagini, dobbiamo indicare il content-type appropriato; ad esempio, si potrebbe
indicare "image/gif" o "image/jpeg" o ancora "video/mpeg".
Nel caso ci si dimentichi di aggiungere questa linea, o si scriva qualcosa prima di essa, si riceverà un
messaggio di errore (solitamente "Internal Server Error"). Insomma, non dimenticatevi del Content-type:
un consiglio può essere quello di inserirlo appena sotto la riga #!/usr/bin/perl : così una volta inserite
queste prime due righe, non ci pensate più.
Fatto questo appunto, proviamo a scrivere il nostro primo script in perl, che chiameremo hello.pl: lo script
l'avrete già visto chissà quanti milioni di volte:
#!/usr/bin/perl
print "Ciao a tutti!\n";
Ok, lo script è fatto (semplice, no??), adesso basta salvarlo e renderlo eseguibile. Lanciando lo script,
verrà visualizzata la riga "Ciao a tutti", ma quello che noi ci prefiggiamo di fare è mandare l'output di
questo script ad un browser che creerà, in base ai dati ricevuti, una pagina web.
La prima cosa da fare è rinominare script.pl in script.cgi , perchè il server lo interpreti (non è strettamente
necessario, ma voi fatelo lo stesso); poi bisogna aggiungere i tags che verranno visualizzati nella nostra
nuova pagina: quindi lo script dovrà essere modificato come segue:
1) #!/usr/bin/perl
2) print "Content-type:text/html\n\n";
3) print "<html><head><title>Prima paginadiprova</title></head>\n";
4) print"<body>\n";
5) print "<h2>Ciao atutti!</h2>\n";
6) print"</body></html>\n";
Ok, lo script è pronto e tra l'altro assai semplice: forse vi stupirete della lunghezza del CGI rispetto allo
script iniziale, ma questo è normale: con questo script viene visualizzata una pagina in formato HTML, e
quello che abbiamo aggiunto sono solamente i tag principali per, appunto, realizzare questa pagina;
immaginate di avere fuso insieme il codice di una pagina HTML con uno script.
Analizziamo più da vicino questo semplice script, nel quale i numeri di riga sono stati inseriti solo per
comodità ... voi nei vostri script non sognatevi nemmeno di inserirli, a meno che vogliate vedere
un'interminabile serie di errori.
La prima è l'intestazione: indica dove risiede l'interprete Perl che eseguirà lo script: come già detto in
precedenza, l'interprete deve risiedere sul server, poichè è questo che esegue lo script, inviandovi
solamente il risultato. Ripetiamo, anche perchè non fa mai male, che /usr/bin/perl è una locazione
abbastanza 'standard', ma nel vostro sistema l'interprete potrebbe non essere lì: per questo e per tutti gli
altri script che seguiranno, dovrete sempre indicare la locazione dell'interprete nel vostro sistema.
La seconda è l'header MIME, sul quale si è già discusso in precedenza, ed indica il tipo di pagina da
creare: in questo caso si tratterà di una pagina html. Notate però una cosa importantissima: sopra 'html' ci
sono due ritorni a capo ( \n\n ); questi servono a separare l'header dalla pagina vera e propria: deve
sempre esserci una riga vuota tra l'uno e l'altro, altrimenti il server vi dirà che il vostro script ha un "bad
header".
La terza è importantissima: in pratica fa in modo che la pagina creata abbia alcuni dei tags fondamentali
del linguaggio html: <html>, <head> e<title>; notate anche che, tra i tags <title> e </title> viene inserito il
titolo della pagina, com'era ovvio aspettarsi.
La quarta linea introduce il tag <body>, ovvero il corpo della pagina, nella quale, come si vede dalla riga
5, viene introdotta la frase "Ciao a tutti" formattata con il tag<h2>.
La sesta riga chiude la pagina: definisce la fine del tag <body>e <html>, ovvero </body> e</html>.
Facciamo qui notare una cosa: nello script visto in precedenza, ci sono quattro istruzioni print() per creare
la pagina: in un caso del genere (ovvero davanti ad uno script così semplice), avremmo potuto anche fare
ricorso ad una sola riga di print() come segue:
print "<html><head><title>Prima pagina
diprova</title></head><body><h2>Ciaoatutti!</h2></body></html>\n";
Lo svantaggio è minimo ma c'è: intanto, il sorgente della pagina sarà più difficile da leggere, specialmente
se si generano pagine più complesse: infatti tutto il codice HTML è compreso in una sola riga. Inoltre sarà
ben difficile inserire altri comandi che l'interprete dovrà eseguire, ad esempio la funzione split() che
vedremo più avanti.
Insomma, lo script com'è stato presentato è scritto in maniera abbastanza 'standard' (anche se c'è chi
scrive'print"</body>\n</html>"' o in altri modi) e comoda per le successive operazioni che compiremo su
questo stesso codice; cercate anche che i vostri seguano a grandi linee questo canone.
Ora salvate lo script, spostatelo nella directory cgi-bin ed eseguitelo, ovviamente richiamandolo con un
link: vedrete il vostro primo script all'opera! Se cercate di aprirlo tramite browser, cioè senza che il server
lo interpreti, non succederà niente, tranne la mera visualizzazione del codice dello script.
Nel caso voi eseguiate questo script ma il risultato non sia quello sperato, potrebbe essere successa una
di queste cose:
• avete sbagliato a scrivere lo script, e l'interprete Perl non riesce ad eseguirlo correttamente;
•
avete inserito la locazione sbagliata del CGI: questo è un errore che si presenta spesso. Se nel
vostro sistema i CGI si trovano in /usr/lib/cgi-bin e, nella pagina nella quale richiamate lo script, il
link punta direttamente a tale directory, il server non lo interpreterà, ma si limiterà a visualizzarne
il codice. Questo perchè il server è impostato con un importante parametro, ScriptAlias (già visto
in precedenza): in pratica, tramite questo parametro, il server sa che gli script sono in /usr/lib/perl,
ma li interpreterà solo se il link punta alla directory indicata nel parametro ScriptAlias: quindi il link
dovrà puntare a http://vostrohost/cgi-bin/nome_dello_script.cgi.
•
se leggete semplicemente il codice dello script, potrebbe essere che:
3a) il file script.pl non è stato rinominato in script.gci
3b) il vostro server non è configurato per eseguire CGI: mano alla documentazione, cercate di
risolvere il problema)
Vediamo ora come verrà visualizzata la pagina: se andate a vederne il sorgente, leggerete esattamente:
<html><head><title>Prima pagina diprova</title></head>
<body>
<h2>Ciao a tutti!</h2>
</body></html>
La pagina risultante, invece, sarà proprio come ce la aspettavamo:
La prima schermata è la pagina risultante interpretata da Netscape, la seconda il sorgente della pagina,
la terza il sorgente dell script CGI; come vedete, non c'è trucco e non c'è inganno.
Invece il vostro browser visualizzerà una normale pagina html, il cui titolo sarà "prima pagina di prova" e
che conterrà il testo formattato "Ciao a tutti!". Nell'ovvio caso in cui dovrete creare pagine più comlpesse,
basterà inserire altri statement "print" seguiti dai normali tags html e dal testo.
Come con ogni linguaggio di programmazione, anche con i CGI si possono utilizzare alcune variabili
d'ambiente, 'contenute' nella hash %ENV; vediamone innanzitutto una lista (ordinata alfabeticamente, ed
estratta tramite web server Apache installato sul pc utilizzato per la stesura di questo articolo):
Nome
Descrizione - Valore
DOCUME
NT_ROO La root directory del server - /var/www
T
GATEWA
Y_INTER L'interfaccia gateway utilizzata - CGI/1.1
FACE
HTTP_A I tipi MIME accettati dal client - image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
CCEPT image/png, */*
HTTP_A
CCEPT_
Il charset ( = set di caratteri) accettato - iso-8859-1,*,utf-8
CHARSE
T
HTTP_A
CCEPT_
Il linguaggio accettato - en
LANGUA
GE
HTTP_H
Il nome dell'host del server - scatolinux.it
OST
In pratica, cosa si è inserito come indirizzo per giungere alla pagina del server HTTP_R
http://scatolinux.it ma, essendo questo un server locale e non remoto, si sarebbe anche potuto
EFERER
inserire "localhost" oppure "http://localhost"
HTTP_U
Il software (browser) utilizzato dal visitatore - Emacs-W3/4.0pre.14 URL/p4.0pre.14 (i386SER_AG
debian-linux; X11)
ENT
PATH
Il path di sistema del server - /bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin
Ovvero la stringa ricercata; in questo caso il valore è nullo poichè non è stata indicata alcuna
QUERY_
stringa, in quanto lo script non è interattivo. Solitamente la sintassi per la ricerca è "nome-delSTRING
cgi?stringa"
REMOTE
L'indirizzo IP del visitatore - in questo caso è 127.0.0.1 poichè tutto si è svolto in locale
_ADDR
REMOTE
La porta tramite la quale il visitatore è connesso al server - 1240
_PORT
REQUES
T_METH Può essere basilarmente GET o POST (verranno analizzati più avanti) - GET
OD
REQUES L'URL richiesta dal visitatore - /cgi-bin/getinfo.cgi (infatti getinfo.cgi è lo script con il quale sono
T_URI
state ottenute tutte le informazioni)
SCRIPT_
FILENAM Il nome e la locazione locale dello script - /usr/lib/cgi-bin/getinfo.cgi
E
SCRIPT_
Il nome e la locazione remota dello script - /cgi-bin/getinfo.cgi
NAME
SERVER
Il nome dell'amministratore del server - [email protected], lascio a voi scoprire chi sia.
_ADMIN
SERVER
Il nome del server - scatolinux.it [1]
_NAME
SERVER
La porta nella quale il server è in ascolto - 80
_PORT
SERVER
_PROTO Il protocollo del server - HTTP/1.0
COL
SERVER
Il software e gli eventuali moduli in esecuzione sul server - Apache/1.3.3 (Unix) Debian/GNU
_SOFTW
PHP/3.0.5 mod_perl/1.16
ARE
CONTEN
Variabile riservata alla query, può essere HTTP POST o PUT
T_TYPE
CONTEN
T_LENG La lunghezza del contenuto della query di cui si parlava qui sopra
HT
Le ultime due variabili sono state separate dalle altre per un semplice motivo: con un CGI che riporta le
variabili di %ENV in condizioni normali, queste due variabili non appaiono, poichè sono riservate alle
query. Se avessimo scritto un CGI con una query, allora anche queste sarebbero apparse.
Ovviamente, questa vuole essere una lista parziale delle variabili, ogni server ha le proprie: ad esempio,
se si utilizza Apache 1.3 si potranno avere anche le variabili 'keepalive', 'downgrade-1.0' (sempre se
impostate nei file di configurazione) e via dicendo; per avere ulteriori informazioni su queste variabili, si
legga la documentazione del proprio server. Notiamo anche un'altra cosa: alcune di queste variabili
danno informazioni riguardo al server, e di conseguenza non cambieranno a seconda del CGI (tra
queste, SERVER_NAME, SERVER_ADMIN ecc.), altre servono a tracciare informazioni sul visitatore
(HTTP_USER_AGENT, REMOTE_ADDR, REMOTE_HOST ecc.), altre sono riferite alla query in
questione, altre ancora sulla macchina in cui è installato il server.
Tutte queste variabili sono contenute nell'hash %ENV, e sono settate automaticamente per ogni CGI:
basta solamente richiamarle. Questo speciale array è una variabile speciale del Perl che contiene le
variabili d'ambiente: ad esempio, con un semplice script Perl si può vedere la home directory dell'utente
che ha eseguito lo script, indicando $ENV{HOME}.
Mettiamo ora in pratica le nozioni appena introdotte: volendo scoprire che software è in esecuzione sul
server e relativi moduli installati, si potrebbe scrivere uno script come il seguente:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print "<html><head><title>Rilevazionedelsotware</title></head>\n";
print"<body>\n";
print "Server utilizzato: $ENV{'SERVER_SOFTWARE'}\n";
print"</body></html>";
Se le vostre nozioni di Perl non vi tradiscono, dovreste ricordare cosa significa la penultima riga; in caso
contrario, vi ricordiamo che dopo i due punti viene preso l'elemento SERVER_SOFTWARE dall'hash
%ENV, che viene visualizzato dopo 'Server utilizzato'. Ora salvate questo script, spostatelo dove di
dovere ed eseguitelo: il risultato sarà esattamente quello che ci si aspettava. E se avete più browser nel
vostro sistema, divertitevi a provarli tutti.
Volendo, potete divertirvi a creare tanti piccoli script che eseguono rilevazioni simili, creando diverse
pagine per ognuna di queste. Noi preferiamo però darvi uno strumento più completo, ovvero uno script
che analizzi tutte le variabili di %ENV e le restituisca a video con una pagina HTML; eccolo qui di seguito:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print "<html><head><title>Variabili CGI del nostroserverweb</title></head>\n";
print"<body>\n";
print "Content-type: text/plain", "\n\n";
foreach $key (sort keys %ENV) {
print $key, " = ", $ENV{$key}, "\n";
}
Il risultato lo lasciamo vedere a voi, anche se è altamente probabile che già sappiate quale sarà.
La variabile QUERY_STRING ha a che fare con la ricerca di determinate stringhe nei documenti,
database o simili; può contenere una sola stringa senza spazi, ma certo, così com'è, la sua utilità non è
granchè elevata, a meno che si stia facendo una ricerca molto semplice. Per ricerche più complesse,
sarebbe meglio che questa potesse contenere più informazioni; ad esempio quando cerchiamo qualcosa
in un database in rete, solitamente non passiamo a tale variabile solo una stringa, ma anche altre
informazioni quali: che tipo di campo deve essere ricercato, se la stringa deve essere case-sensitive o
meno e così via; inoltre, spesso inseriamo anche degli spazi, per cercare più di una parola. Ovviamente,
tutto ciò è possibile con i dovuti accorgimenti; supponiamo di voler mandare al nostro CGI alcune
informazioni del tipo:
Nome = Marco
Età = 25
Città = Roma
Occupazione = impiegato comunale
in modo che questo cerchi nel database l'individuo (o individui) che soddisfano il nostro criterio di ricerca.
Se noi potessimo indicare a QUERY_STRING solo una chiave, ad esempio 'Marco', la ricerca avrebbe
certamente successo, ma si dovrebbe scartabellare tra molti (troppi!) risultati. L'accorgimento di cui si
parlava sopra, è quello di inserire tra ogni variabile il simbolo & e di sostituire gli spazi con il simbolo +
come segue:
QUERY_STRING="Nome=Marco&Età=25&Città=
Roma&Occupazione=impiegato+comunale"
Bene, così avete capito per sommi capi come lavorano i motori di ricerca.
Immaginiamo di avere un form scritto come:
<form action="http://vostroserver.it/cgi-bin/invia.cgi" method="GET">
Inserisci qui il testo: <input type= "text" name= "testo_di_esempio"size=30><p>
</form>
che, interpretato dal browser, risulterà come
Inserisci qui il testo:
Notate che in questo esempio non c'è il bottone 'Invia' o 'Click me' (in realtà il nome non ha importanza,
possiamo deciderlo noi a nostro piacimento; solo che se mettiamo "Antonio" difficilmente la gente capirà),
solo una finestrella dove inserire il testo. Ebbene, tramite GET con la sola pressione del tasto Invio le
informazioni vengono inviate al CGI che procederà ad interpretarle; quindi, senza inserire altri form,
basterà, in fase di costruzione della pagina, inserire del semplice testo che indichi di premere invio per
spedire i dati. Solitamente gli argomenti di GET sono passati al CGI come
http://vostroserver.it/cgi-bin/script.cgi?argomento
I dati risultanti da questo CGI saranno del tipo testo_di_esempio=argomento.
Ora torniamo per un attimo al puro Perl per vedere come rendere la stringa umanamente leggibile, senza
'=' e '&' (che per adesso non c'è ancora) con spaziature e ritorni a capo,al fine di avere due distinti campi
di dati: utilizziamo quindi la funzione Perl "spilt()":
@campi = split(/\&/,$ENV{'QUERY_STRING'});
foreach $valore (@campi) {
($nome_variabile, $dato) = split(/=/,$valore);
print "$nome_variabile = $dato\n";
}
Questo semplice script quindi dividerà i due campi, dando come risultato:
nome = mario
cognome = rossi
Molto più umano come formato, no?
Poi, volendo, si può implementare questo script in un CGI, in modo da creare una pagina HTML; ormai
dovreste aver imparato la tecnica per fare ciò, quindi non ripetiamo il procedimento.
Prima di concludere con GET, una nota importante:
GET non è un metodo totalmente sicuro di invio di dati poichè, essendo i dati passati come parte degli
URL, questi restano nei log del sistema, e sono teoricamente leggibili da chiunque abbia accesso al
sistema. Quindi NON utilizzate mai GET per inviare o ricevere (la ricezione tramite GET è un pericolo per
un potenziale vostro cliente/acquirente, che notoriamente e giustamente, pretende che i dati passati al
server siano protetti) password, numeri di carte di credito e simili. Per questo tipo di dati, utilizzate POST.
Ricordatevene quando ce ne sarà bisogno. Soprattutto, giusto per non far sembrare il metodo GET
inutile, aggiungiamo che questo è utilizzato basilarmente per ricerche sui database.
Uno script di esempio, collegato allo script di cui abbiamo parlato sopra, che interpreta le informazioni
passate da GET potrebbe essere qualcosa del tipo:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print "<html><head><title>Restituzionedeltesto</title></head>\n";
print"<body>\n";
print "$ENV{'QUERY_STRING'}\n";
print"</body></html>";
Se ad esempio avete inserito "Ciao a tutti" il CGI vi restituirà: 'testo_di_esempio=Ciao+a+tutti', ossia
metterà sulla sinistra il nome del form, sulla destra il testo da voi digitato.
Chiamate lo script invia.cgi e verificate voi stessi.
Oltre alla possibilità di mandare una sola stringa tramite GET, si possono utilizzare anche due o più
stringhe, come si può vedere nel codice del prossimo form:
<form action="http://vostroserver.it/cgi-bin/invia.cgi" method="GET">
Nome: <input type= "text" name= "nome"size=30><p>
Cognome: <input type= "text" name= "cognome"size=30><p>
</form>
La risultante stringa QUERY_STRING sarà dunque:
$ENV{'QUERY_STRING'} = nome=mario&cognome=rossi
supponendo che abbiate inserito 'mario rossi' nel form. Quindi apparirà il simbolo "&". Ma a questo punto
saprete anche come toglierlo.
Come si è già potuto capire, il metodo POST è più affidabile di GET poichè non utilizza il carattere ? per
passare le informazioni, ma le manda nella forma dello standard input (quello che in Perl è <STDIN> );
ovviamente c'è anche un rovescio della medaglia: le informazioni ricevute tramite POST sono più difficili
da decodificare poichè alcuni caratteri sono codificati come un % seguito dal codice ASCII del carattere:
ad esempio, uno spazio non sarà visto come siamo soliti vedere lo spazio, ma come %20.
Fortunatamente, ci sono degli standard; vediamone alcuni:
Carattere
Stringa codificata
spazio
%20
/
%2F
~
%7E
:
%3A
;
%3B
@
%40
&
%26
invio
%0A
:
%3A
|
%7C
\
%5C
<
%3C
>
%3E
Per decodificare questi dati, dobbiamo ancora una volta far ricorso al Perl, e più specificamente ai
comandi substitute e translate: visto che questo linguaggio ha grandi capacità per quanto riguarda il
pattern matching ed il pattern substitution, coadiuvato dallo espressioni regolari, non sarà difficile
eseguire un'operazione del genere. Vediamo innanzitutto un comando generale per il pattern substitution:
$stringa =~ s/pattern/sostituzione/;
che sostituisce pattern con sostituzione nella variabile scalare $stringa. Vediamo velocemente come
funziona:
$stringa = "Oggi è il 20 settembre";
$stringa =~ s/settembre/ottobre/;
print $stringa
che visualizzerà "Oggi è il 20 ottobre"
Per quanto riguarda il translate, un comando generale è:
$stringa =~ tr/searchlist/replacement-list/;
Questo comando eseguirà il translate di tutti i caratteri in searchlist con quelli in replacement-list.
Ad esempio,
$stringa = "Ciao, oggi è il 20 OTTOBRE";
$stringa =~ tr/[A,Z]/[a,z]/;
print $stringa;
analizzerà $stringa e renderà minuscoli tutti i caratteri maiuscoli che trova, restituendo "ciao, oggi è il 20
ottobre".
Ora torniamo al POST: ci serviremo di queste due istanze:
$stringa =~ tr/+/ /;
$stringa =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
La prima è semplice: sostituisce il segno + con uno spazio.
La seconda è più complicata, e apparentemente incomprensibile: tramite le espressioni regolari, ci sarà la
sostituzione di tutti i % seguiti da 2 caratteri (%7E, %40 ecc.) [2] nel lorocorrispondente ASCII, utilizzando
la funzione del Perl pack(). La funzione pack() è piuttosto complicata, per chi volesse saperne di più si
rimanda qui alla documentazione (perlfunc); intanto sappiate che, così com'è, funziona alla perfezione in
quest'ambito.
Vediamo ora uno script funzionante:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@coppie = split(/&/, $buffer);
foreach $pair (@coppie) {
($nome, $valore) = split(/=/, $coppia);
$valore =~ tr/+/ /;
$valore =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$HASH{$nome} = $valore;
}
print "<html><head><title>Form Output</title></head><body>";print "<h2>Risultati
delform</h2>\n";
foreach $key (keys(%HASH)) {
print "$key = $HASH{$key}<br>";
}
print "</body></html>";
Cosa fa questo script? Vediamolo punto per punto:
il CGI legge lo stream STDIN (standard input, che altro non sono che i campi del form) depositandolo
nello scalare $buffer, poi esegue la funzione split() sul detto buffer, agendo sulle coppie
"variabile=valore". Il blocco foreach, poi, esegue un ulteriore split sulle coppie appena ottenute,
rendendole puro testo (cioè sostituendo i caratteri %XX) e depositandole in un hash da noi chiamato
%HASH. Le chiavi di %HASH sono gli input passati al form. Così, per esempio, se avete un form con tre
campi (nome, cognome, indirizzo), questi saranno, nello script, $HASH{'nome'}, $HASH{'cognome'} e
$HASH{'indirizzo'}. Alla fine, lo script visualizzerà le varie chiavi, un po' come faceva lo script per le
variabili CGI.
Ora che abbiamo capito l'utilità dei tale complicatissimo script (se si possiedono solide basi di
programmazione in Perl non risulta poi tanto comlpicato, credeteci!), passiamo alle belle notizie: con
questo script si può maneggiare qualsiasi tipo di dato, dai più semplici ai più complicati. Quindi tenetelo
sempre presente.
Fatta questa doverosa premessa (che più che altro era una piccola scusa), vediamone una variante:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@coppie = split(/&/, $buffer);
foreach $coppia (@coppie) {
($nome, $valore) = split(/=/, $coppia);
$valore =~ tr/+/ /;
$valore =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$HASH{$nome} = $valore;
}
$mail = '/usr/sbin/sendmail';
$destinatario = '[email protected]';
open (MAIL, "|$mail -t") or die("Non trovo $mail!\n");
print MAIL "To: $destinatario\n";
print MAIL "Reply-to: $HASH{'email'} ($HASH{'nome'})\n";
# è necessario che nel form abbiate inserito un campo 'email' ed un campo 'nome', altrimenti
perderete il nome e l'indirizzo del visitatore
print MAIL "Subject: Form di prova\n\n";
foreach $key (keys(%HASH)) {
print MAIL "$key = $HASH{$key}\n";
}
close(MAIL);
print "<html><head><title>Formresultsent</title></head>\n";
print "<body><h2>Grazie per aver completatoilform</h2></body>\n";
print "Tornaall'<ahref=\"index.html\">indice</a>.
print"</body></html>\n";
Cosa cambia dallo script di prima? Sicuramente avrete notato una parte di codice in più, e se l'avete letto
probabilmente avrete capito a cosa serve. In pratica abbiamo inserito un bel po' di automatizzazione:
infatti il risultato dello script non è più visualizzato come una pagina web, bensì viene spedito
direttamente a $destinatario (dovrete riempire tale campo con i vostri dati) tramite sendmail, il cui path è
stato scritto come /usr/sbin/sendmail, e se nel vostro server la locazione fosse diversa, basterà
specificarlo in $mail. E il visitatore? Beh, lui vedrà una nuova pagina che lo ringrazierà per avere
completato il form, con un link che lo riporterà all'indice.
Avrete quindi capito che anche per i CGI si possono utilizzare degli standard, lasciando alla propria
fantasia e necessità l'eleborazione di script ancora più funzionali.
Adesso testiamo il tutto: salviamo lo script appena presentato ( o quello ancora precedente, se non volete
l'invio di mail, nel caso non stesse utilizzando sendmail o per qualche altro motivo) con il nome post.cgi,
rendiamolo eseguibile nella directory cgi-bin e scrivete una pagina con un form come il seguente, che vi
presenterà quattro campi dati da completare con nome, cognome, email ed indirizzo:
<form action="http://vostroserver.it/cgi-bin/post.cgi" method="POST">
nome: <input type="text" name="nome">
email: <input type="text" name="email">
età: <input type="text" name="età">
indirizzo: <input type="text" name="colore_preferito">
<input type="submit" value="Invia">
<input type="reset" value="Resetta">
</form>
Inserite qualche dato e fate le vostre prove, magari inserendo le vostre varianti. Dovrebbe risultarvi tutto
più semplice di quanto sembri.
Ormai dovreste avere tutti gli strumenti necessari per iniziare a scrivere i vostri script. Prima però di
concludere la nostra trattazione sui CGI, vediamo come fare in modo che questi producano delle pagine
complesse, utilizzando come base lo script di cui ci siamo serviti in precedenza per estrarre le variabili del
nostro server. Utilizzeremo ancora tale script, ma faremo in modo che questo sia leggermente più
complesso e vada a generare delle pagine web più 'accattivanti' del cupo sfondo grigio come abbiamo
visto succedere in precedenza.
Questo aspetto può sembrare inutile, ed ai fini prettamente pratici lo è. Solo che, una volta che
integrerete il vostro sito con degli script, sarà meglio che la pagina prodotta sia in linea con lo stile delle
altre pagine.
Vediamo ora come arrivare ad un simile risultato.
#!/usr/bin/perl
print "Content-type:text/html\n\n";
# Titolo della pagina
print "<html><head><title>VariabiliCGI</title></head>";
# Impostazioni (colori) della pagina
print"<body text=\"#000000\" bgcolor=\"#FFFFFF\" link=
\"#0000EE\"vlink=\"#551A8B\"alink=\"#FF0000\"><p>\n";
# Tabella blu introduttiva
print"<center><table COLS=1 WIDTH=\"90%\" BGCOLOR=\"#000099\" NOSAVE >\n";
print"<tr>\n";
print"<td>\n";
print"<center>\n";
print "<br><b><fontcolor= \"#FFFFFF\"><fontsize= +2>VariabilidelserverwebApache1.3.3</font></font></b></center>\n";
print "<br><fontsize=+2></font>&nbsp;</td>\n";
print"</tr>\n";
print"</table></center>\n";
print"<p>\n";
# Immagine, cambiatene l'origine (dopo il tag src)
print"<center><img src=\"immagine.jpg\" alt= \"Qui c'è lo spazio per un'immagine, mettetecela
purevoi!!\"height=40width=80%></center>\n";
# Tabella delle variabili
print"<br><center><table border= 2width=\"90%\">\n";
foreach $key (sort keys %ENV) {
print"<tr><td>$key</td>\n";
print"<td>$ENV{$key}</td></tr>\n";
}
print"</table>\n";
# Scritta in fondo alla pagina
print"<center><p>\n";
print "<br><b><fontcolor= \"#000099\"><fontsize= +1>I valori delle variabili sono stati
ricavatitramiteloscriptgetinfo.cgi</font></font></b></center>\n";
# Altra scritta a fondo pagina: notate che abbiamo dovuto inserire il simbolo '\' prima delle slash (
/ ) e delle virgolette. Se avete un po' di basi di programmazione in perl, dovreste benissimo
sapere perchè!
print "<p>Back to<ahref=\"http:\/\/vostrosito.it\/main.html\">main</a>\n";
# E con questo is chiude la pagina!
print "</body></html>";
Notate una cosa, per quanto riguarda la creazione della tabella con i nostri dati: non è assolutamente
utile inserire manualmente i nomi delle variabili a sinistra e lasciare che lo script estrapoli i valori e li
inserisca a destra, definendo in precedenza il numero delle tabelle: inserendo dopo l'istruzione 'foreach' i
tags per la creazione delle varie celle della tabella, lo script provvederà da sè a mettere nomi e valori al
posto giusto, chiudendo la tabella quando non ha più valori da inserire. Quindi, questo script andrà
benissimo sia che dobbiate inserire tre variabili sia che ne abbiate una lista lunghissima: si arrangerà a
creare la tabella, e non aggiungerà una riga in eccesso.
Non vi mettiamo lo screenshot della pagina per far verificare a voi stessi il risultato di questo lavoro.
Visto quanto è semplice generare pagine più belle e complesse delle cupe pagine grigie? A voi
sperimentare nuove soluzioni.
Finora, abbiamo sempre e solo utilizzato il Perl per la creazione dei nostri script ma, come già detto in
precedenza, i linguaggi per fare ciò sono molteplici: ovviamente, il server deve supportare il linguaggio da
noi scelto perchè il CGI sia corretamente interpretato ed eseguito; per quanto riguarda il Perl, si può
andare sul sicuro, praticamente ogni server lo supporta; se però scriviamo uno script in Applescript, non
possiamo pretendere che questo giri su un server qualunque, dobbiamo prima informarci.
Visto comunque che la maggioranza dei server gira su sistemi o dialetti Unix, vediamo un linguaggio
semplice e abbastanza completo per la generazione dei CGI: gli script di bash.
Intanto, cos'è la bash? La bash (Bourne again shell) è un interprete di linguaggio di comandi compatibili
con la shell 'sh', che esegue i comandi provenienti dallo standard input (la tastiera) o da un file. In linea di
massima, questa shell si può definire la più utilizzata nel mondo unix, sia per la sua potenza che per la
versatilità. E sono proprio questi due aspetti che andremo ad utilizzare.
Ricordate comunque che lo shell scipting non è il linguaggio ideale per la creazione dei CGI: lo si
presenta qui solo per completezza.
Vediamo subito un primo esempio:
#!/bin/sh
echo "Content-type: text/html"
echo
echo "<html><head><title>Pagina di prova ricavata tramite uno scriptdibash</title></head>"
echo "<body><H2>Ciao atutti!<H2></body></html>"
Come certamente capirete, questo script non fa altro che creare una pagina con il suo bel titolo e la frase
"Ciao a tutti!" nel corpo.
Vediamo più in dettaglio lo script:
• la prima riga "cerca" l'interprete: una riga simile era presente in tutti gli script in Perl.
•
la seconda è introdotta da un comando, "echo" che, in un certo senso, è simile al "print" del perl;
si legge infatti dalla pagina di manuale della bash quanto segue:" (echo) emette gli args, separati
da spazii.". Cosa vuol dire? Semplice, che qualsiasi cosa scritta dopo il comando echo verrà
(normalmente) mostrata a video. Dopo il comando echo è presente il content-type della pagina
che vogliamo generare: niente di nuovo.
•
la terza crea una linea vuota per separare il content-type dal contenuto vero e proprio; se ciò non
avvenisse, il server uscirebbe con un messaggio di errore lamentandosi di un "bad header".
Ricordiamoci di inserirla.
•
la quarta apre itags <html><head> e<title>, inserisce il titolo e chiude gli ultimi due tags.
• la quinta apre i tags <body> e<h2>, inserisce il corpo e chiude tutti i tags rimasti aperti.
Non è difficile scrivere gli script con il linguaggio della shell, che però non può fornire, da sola, la
completezza di funzionalità offerte dal perl.
Se vi interessa l'argomento dello shell scripting, non solo per quanto riguarda i CGI, leggetevi per benino
la documentazione della/e vostre shell e state sicuri che avrete per le mani un altro potentissimo
strumento.
Abbiamo visto finora un metodo di scrivere il codice dei CGI: se vi state chiedendo se ne esistono altri,
ebbene, la risposta è sì.
Prendete ad esempio lo script presentato qui sopra, ed esattamente le righe:
print"<body text=\"#000000\" bgcolor=\"#FFFFFF\" link=
\"#0000EE\"vlink=\"#551A8B\"alink=\"#FF0000\"><p>\n";
e
print "<p>Back to <a href=\"http:\/\/vostrosito.it\/main.html\">main</a>\n";
Come avrete quasi sicuramente notato, entrambe sono zeppe di caratteri ' \ ' : la teoria del Perl ci dice
che tale carattere serve a fare in modo che il carattere successivo sia interpretato 'testualmente', ovvero
senza dare ad esso il significato che normalmente, in Perl, questo ha; per chi parla inglese, si dice che
caratteri come " o / "must be escaped". E' lo stesso discorso fatto solo con tre parole.
Detto questo, vediamo come si possono scrivere i CGI con una sintassi alternativa, che ci semplificherà
non poco le cose. Prendiamo ad esempio questo script:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print "<html><head><title>Titolo</title></head>";
print"<body text=\"#000000\" bgcolor=\"#FFFFFF\" link=
\"#0000EE\"vlink=\"#551A8B\"alink=\"#FF0000\"><p>\n";
print "Torna alla <ahref=\"http:\/\/vostrosito.it\/home.html\">home page</a>
print"</body></html>\n";
Lo script di per sè è semplice, produce una pagina con sfondo bianco dove è presente un link all'indice
del vostro sito, ma non è questo quello che ci interessa: la parte più importante dello script sono la
penultima e la terzultima riga: in queste, infatti, abbondano i caratteri " e / . Come già visto, tali caratteri
vanno introdotti con il carattere \ solo che, nove volte su dieci, ci si dimentica, e ci si danna per ore a
capire perchè lo script non funzioni.
Beh, non c'è altro da fare che rimediare. Vediamo come:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print <<EOF;
<html><head><title>Titolo</title></head>
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink=
"#551A8B"alink="#FF0000"><p>
Torna alla <ahref="http://vostrosito.it/home.html">home page</a>
EOF
;
print "</body></html>\n";
Con questo metodo, evitate di dover inserire continuamente gli statement "print" e, soprattutto, potrete
dire addio ai caratteri \ che, prima o poi, dimenticherete.
Provate per credere e, soprattutto, scegliete come preferite scrivere i vostri script: non vi è alcuna
differenza tra l'uno e l'altro metodo, il risultato generato è esattamente lo stesso.
Come già anticipato in precedenza, lo script deve essere eseguibile: per chi non sapesse cosa questo
significihi, si tenga presente che i permessi sui file rappresentano la possibilità di leggere (r), scrivere (w)
ed eseguire il file (x). Solitamente i permessi sono così indicati (in notazione semplificata):
-rwxr-x--x proprietario nome del file
Il primo simbolo indica che il file è un file normale; se fosse stato, ad esempio, una directory, sarebbe
stato 'd'. Poi bisogna considerare i simboli a gruppi di tre: il primo (rwx) indica che il proprietario di tale file
ha i permessi di lettura, scrittura ed esecuzione sui file; il secondo (r-x) indica che gli utenti del gruppo del
proprietario hanno i permessi di lettura, esecuzione ma non di scrittura (infatti la 'w' è sostituita da un '-'); il
terzo si riferisce genericamente agli altri utenti: in questo caso, hanno solamente i diritti di esecuzione sul
file. Solitamente, i CGI hanno permessi -rwxr-xr-x.
Per scrivere diverse pagine a seconda del browser utilizzato dai visitatori del nostro sito, possiamo
avvalerci anche qui di un CGI:
$browser = $ENV{'HTTP_USER_AGENT'};
if ($browser =~ /Mozilla/) {
....... # Codice per netscape
} else {
....... # Codice per gli altri browser
}
Con questo script, succederà qualcosa (dovete decidere voi cosa sarà questo 'qualcosa' inserendo il
codice appropriato al posto dei puntini!) se il browser utilizzato risulta Netscape, qualcos'altro per gli altri
browser.
Ovvero come debuggare o testare un CGI in assenza di un web server.
Il debugging di un CGI non è cosa semplicissima da realizzare: innanzitutto, comunque, assicuratevi di
avere il codice Perl scritto in maniera corretta: utilizzate la chiamata al Perl con l'opzione -w e inserite nel
codice, dopo la riga #!/usr/bin/perl 'use strict;' . L'opzione -w vi darà dettagliate (per quanto possibile)
informazioni sugli errori presenti nel vostro codice, 'use strict;' impedirà invece che, nel vostro codice, ci
siano operazioni considerate potenzialmente dannose o pericolose.
Fatto questo, potete emulare l'esecuzione del CGI come segue:
Settate la variabile di ambiente manualmente:
export HTTP_USER_AGENT = "Mozilla/2.0b6"
(solo per shell bash, per csh utilizzate setenv). In seguito bisognerà, una volta scritto lo script, fare in
modo che tale script prenda da qualche parte i dati solitamente passati da un form: per fare questo,
scrivete un normale file di testo con i dati ed eseguite lo script utilizzando un pipe del file di testo sullo
script:
cat file | script.pl
... e vedete cosa succede.
Comunque, la cosa migliore da fare è testare gli script in locale.
La situazione è questa: un amico vi passa l'ultima versione del suo contatore-di-accessi-che-visualizzatutte-le-statistiche-del-sito-oltre-a-quelle-del-visitatore-e-che-fa-pure-il-caffè!! Oppure trovate il CGI che vi
mancava completamente gratuito in un sito.
Bene, non accettate le caramelle dagli sconosciuti. Non potete mai sapere se lo script è sicuro.
Verificatelo andando a leggerne il codice (sempre che il CGI non sia stato fatto con un linguaggio tipo C e
compilato), se non capite qualcosa chiedete a qualcuno (non all'autore, questo è certo).
Specialmente se lo script è di dimensioni considerevoli, o se apre e legge file di sistema o se va a
lanciare programmi, è probabile che non sia sicuro. Per questo, diffidate dei CGI scritti in C e
precompilati: esigetene il codice sorgente.
Molti grandi script sono soggetti a cose di questo tipo, come quelli utilizzati (ora non più!!) da hotmail,
excite e purtroppo molto altri.
Molte volte capita di sentire la domanda: ma è più sicuro scrivere un CGI in Perl, in C o in chissà quale
altro linguaggio?'. Beh, non preoccupatevi: la sicurezza è data da come è scritto il CGI, non dal
linguaggio utilizzato, sebbene alcuni possano essere più 'sicuri' di altri.
State sempre attenti a non esporre MAI il CGI all'interazione con la shell: potrebbero esserci dei buchi
della sicurezza. Ad esempio,
open (COMMAND, "/usr/bin/finger $utente_del_form");
o
system ("/usr/ucb/finger $utente_del_form");
o ancora
@data = `usr/bin/finger $utente_del_form`;
L'utente del form potrebbe essere talmente smaliziato (o fare qualcosa inavvertitamente) da crearvi seri
problemi. Piuttosto, se vi serve un finger sull'utente del form, utilizzate il secondo costrutto nella forma
system ("/usr/ucb/finger", $form_user);
ovvero passando gli argomenti come una lista invece che come una stringa.
Fate in modo che gli utenti del sito non interagiscano MAI in prima persona con l'interprete Perl: se
qualcuno passasse all'interprete perl qualche linea (dopo il '?') 'maliziosa', rischierete di trovarvi il disco
vuoto o di vedere dati privati in mano altrui.
Sembra una stupidata, ma è sempre meglio aggiungerlo.
Spesso capita che il server si rifiuti di eseguire qualcosa uscendo con determinati errori o messaggi
richiamati da alcuni codici numerici. I codici 2xx indicano successo, i codici 4xx e 5xx indicano errore, i
codici 3xx indicano redirezione. Vediamo i più frequenti:
• OK 200 - Tutto è andato a buon fine.
•
CREATED 201 - In risposta ad un POST, indica successo;
•
No Response 204 - Indica successo nel senso che la domanda è stata inoltrata al server, ma che
niente è ritornato al client. Questo permette l'esecuzione di script senza che, ad avvenuto invio
dei dati, il client si sposti dalla pagina corrente;
•
Bad request 400 - Errore di sintassi o richiesta impossibile da soddisfare;
•
Unauthorized 401 - Il client non è autorizzato a determinate operazioni;
•
Forbidden 403 - Lo script ha qualche errore nei permessi
•
Not found 404 - Lo odiate vero? Quindi non specifico il suo significato.
•
Internal Error 500 - Errore del server. Questa volta non è colpa nostra.
•
Not implemented 501 - Il server non supporta quello da noi richiesto.
•
Service temporarily overloaded 502 - Il server è sovraccarico di richieste, e non può accontentare
la nostra.
Innanzitutto, per quanto riguarda il server web, fate un salto a www.apache.org, il sito ufficiale di questo
software.
Per quanto riguarda il Perl, i siti www.perl.com e www.perl.org sono due ottimi punti di riferimento,
insieme a www.activestate.com, dove potrete trovare l'interprete perl per diversi sistemi (tutta la famiglia
windows in primis).
Non dimenticatevi poi usenet: il consiglio è di andare a discutere dell'argomento, magari esponendo
anche i vostri problemi, su it.comp.www.cgi (in italiano); c'e n'è uno anche in tedesco ma forse è meglio
non citarlo.
Se cercate guide su argomenti più specifici ed approfonditi, la rete vi mette a disposizine centinaia di
documenti ben fatti: basta solo cercare. Ricordatevi comunque che l'esperienza si acquisisce soprattutto
sul campo.