|
La subroutine GetParam implementa
una tecnica che consente di specificare i parametri sia dalla linea
di comando che dalla variabile di ambiente QUERY_STRING (che
contiene l’input specificato da una form quando il programma è
invocato come CGI). I parametri sulla linea di comando vengono
forniti utilizzando una sintassi <chiave>=<valore>,
volutamente simile (ma non uguale) al formato fornito dalle
QUERY_STRING di una CGI. La GetParam si occupa
appunto di colmare questo divario, uniformando l’input fornito
dalla CGI con l’input fornito dalla riga di comando.
Le differenze principali tra la
linea di comando e la QUERY_STRING stanno nel separatore dei
vari parametri, che nel primo caso è lo spazio mentre è
un & nel secondo, e in più alcuni caratteri sono
codificati in un formato particolare. Infatti dopo aver spezzato la
QUERY_STRING la GetParam si preoccupa appunto di
“pulire” l’input decodificando i caratteri
codificati. Il risultato è un array che ha la stessa forma sia
che provenga dalla linea di comando che dalla QUERY_STRING,
pronto per essere analizzato da ParseParam.
Occorre notare che viene impostata
la variabile $IsCgi, in modo da poter distinguere, dove serve,
il comportamento a linea di comando dal comportamento come CGI.
In pratica ci sono solo due casi in cui bisogna operare questa
distinzione: quando viene considerato il parametro file (che per
ragioni di sicurezza viene ignorato quando il programma è
invocato come CGI) e quando si stampano i risultati (un
programma invocato come CGI deve produrre un output che comincia con
una stringa come "Content-type: text/html").
La ParseParam scandisce
l’array in input che contiene i parametri. Come si vede
utilizza ampiamente le espressioni regolari, per esempio:
/^(url=!?|site=!?)(.+)/
Questa riga cerca i parametri url o site, negati o
meno, e raccoglie in $2 il valore del parametro. I parametri
url o site accettano dei pattern DOS-like, una sorta di
espressioni regolari semplificate, che implementeremo utilizzando le
espressioni regolari del Perl stesso. È possibile infatti
matchare utilizzando una espressione regolare contenuta in una
stringa.
Prima di analizzare il file di log,
ci costruiamo le espressioni regolari Perl corrispondenti ai pattern
forniti in input. Supponiamo che ci venga richiesto fornito un
pattern come *.?if (assumiamo che sia stato assegnato a $_).
I passi necessari per convertire un pattern in una espressione
regolare equivalente sono i seguenti:
(a) s/\W/\\$1/g;
(b) s/\\\?/\./g;
(c) s/\\\*/\.\*/g;
Innanzitutto dobbiamo risolvere il problema che certi caratteri hanno
un significato speciale nelle espressioni regolari che non hanno nei
pattern. Quindi in (a) “quotiamo” (togliamo il
significato speciale) a tutti i caratteri non alfanumerici
precedendoli con un backslash. Possiamo tranquillamente quotare
tutti i caratteri non alfanumerici invece di considerare solo quelli
che sappiamo avere un significato speciale: infatti i caratteri non
alfanumerici se vengono quotati NON assumono significato speciale (a
differenza dei caratteri alfanumerici). Adesso possiamo dare un
significato speciale a ? e *: l’equivalente del ?
nei pattern è il . nelle espressioni regolari, mentre
l’equivalente del * è .*. Infatti (b)
e (c) effettuano proprio la sostituzione delle sequenze \?
e \* con . e .*. Per capire (b) e (c)
non dobbiamo dimenticare che tutte i caratteri non alfanumerici erano
stati appena quotati in (a), e che nelle espressioni regolari
\, ? e * per essere specificati letteralmente
vanno a loro volta quotati. Il pattern risultante convertito è
perciò .*\..if Le varie espressioni regolari prodotte
via via vengono concatenate da un alternatore, in maniera da poter
risolvere ciascun caso (URL inclusi e URL esclusi, siti inclusi e
siti esclusi) con un solo matching.
|