|
In listato 3 abbiamo la
subroutine più complicata di tutto il programma ma anche la
più indispensabile: quella che decodifica l'input. Il
meccanismo di invio di una form prevede che tutti i dati della form
vengano raccolti in una stringa compatibile con le regole degli URL
di Internet, e questo impone che certi caratteri possano essere
utilizzati e altri no.
1 ### UnCgi:
2 # input: $ENV{QUERY_STRING}
3 # output: %WWW, un array associativo;
5 # ritorna 0 if $ENV{QUERY_STRING} e' vuota, 1 altrimenti
6 sub UnCgi {
7 %WWW=();
8 local($lqs) = $ENV{'QUERY_STRING'};
9 return 0 unless $lqs;
10 (@localparms) = split(/&/,$lqs);
11 $nparms = scalar(@localparms);
12 foreach $p (@localparms) {
13 ($pname,$pvalue) = split(/=/, $p);
14 $pvalue =~ s/\+/ /g;
15 $pvalue =~ s/%([0-9a-fA-F][0-9a-fA-F])/sprintf("%c",hex($1))/eg;
16 $WWW{$pname} = $pvalue;
17 $pvalue =~ s/(['\\])/\\\1/g;
18 }
19 return 1;
20 }
Listato 3
Questo paragrafo è molto
tecnico ma può essere di infinito aiuto in molte occasioni. La
decodifica dell'input molto spesso è una cosa di cui non ci si
vuole preoccupare più di tanto, e quindi ci si affida a
routine di terze parti. In pratica spesso capita che occorra adattare
alle proprie esigenze routine come questa. Infatti si hanno casi
specifici (per esempio checkbox o selezioni) che vengono meglio
gestiti con una routine di decodifica dell'input ad hoc che non in
altri modi. Si invita il lettore non interessato a saltare il
paragrafo, (il che non pregiudica la lettura del resto) altrimenti a
leggerlo con molta attenzione.
Il formato di un tipico URL che
invoca uno script da una form è il seguente:
http://www.ditta.com/cgi-bin/prgcgi?a=hello&b=x
La parte fino al punto interrogativo
dovrebbe essere familiare a tutti. La parte che segue il punto
interrogativo sono i campi della form passati come parametri allo
script. Questa stringa viene passata così com'è allo
script tramite la variabile di ambiente QUERY_STRING.
In linea 8 cominciamo il
nostro lavoro leggendo la QUERY_STRING (attraverso l'array
associativo %ENV che contiene tutte le variabili di ambiente).
Ritorniamo subito se è vuota, perché vuol dire che lo
script è stato invocato senza parametri. Se invece abbiamo
proprio ottenuto i dati di una form allora dobbiamo tenere presente
questo:
i vari campi sono separati tra
di loro dal carattere &
ogni campo ha la forma
<nome>=<valore>
ogni carattere che non può
essere passato così com'è perché ha un
significato speciale (&, +, =, %)
viene passato col suo codice ascii, codificato come il carattere %
seguito da due cifre esadecimali corrispondenti al codice ascii del
carattere.
gli spazi sono codificati come
dei +: questo perché sono molto frequenti in pratica e
sarebbe inefficiente codificarli con la sequenza di tre caratteri
%20.
Queste semplici regolette guidano il
nostro programma di decodifica dell'input. In linea 10 separiamo
i campi in un array. In linea 11 contiamo il numero di
parametri. E' interessante il metodo con cui viene contato il numero
di elementi dell'array, che spieghiamo alla fine di questo stesso
paragrafo. Adesso possiamo ciclare sugli elementi dell'array, che
sono delle stringhe <nome>=<valore>; queste
vengono separate dalla split in linea 13, dopodichè si
procede a “pulire” i valori, restituendo i caratteri al
loro splendore originale. Prima vengono rigenerati gli spazi (linea
14) che hanno un trattamento particolare, infine tutti gli altri
caratteri codificati come numeri esadecimali. Prima assegniamo la
coppia nome/valore all' array associativo %WWW, poi il tocco
da maestro: assegniamo ad una variabile con il nome opportuno il
valore.
Adesso spieghiamo perché
l'espressione scalar(@localparms) ritorna il numero di
elementi dell'array. In Perl ci sono due contesti: scalare e array
(se vogliamo singolare e plurale), e la valutazione delle espressioni
cambia a seconda se il contesto è singolare o plurale. Il
contesto è dato dall'assegnamento ad una variabile oppure ad
un array: per esempio:
@a
= reverse("abc", "bc", "c");
$a
= reverse("abc", "bc", "c");
Il comando reverse se applicato ad
un contesto plurale, ritorna un array composto dagli argomenti in
ordine inverso. Quindi @a è ("c", "bc",
"abc"). Il comando reverse, applicato ad un contesto
singolare invece concatena tutti i valori passati come argomento in
una stringa e poi inverte la stringa carattere per carattere. Quindi
$a è "ccbcba".
Adesso possiamo chiarire la famosa
riga 10: un array valutato in un contesto plurale ritorna gli
elementi dell'array, mentre un array valutato in un contesto
singolare ritorna il numero di elementi dell'array. La keyword scalar
forza un contesto singolare. In realtà per avere il numero di
elementi di un array basta fare $nparms = @localparms, ma
scrivere esplicitamente scalar(@localparms) rende più
chiara l'intenzione. Ci sono casi comunque in cui è necessario
usare esplicitamente la scalar.
|