[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]


202. Indicizzazione dei dati con freeWAIS

freeWAIS è la versione libera di WAIS (Wide Area Information Service), un servizio ideato per consentire l'indicizzazione dei dati e conseguentemente la ricerca in base a stringhe di interrogazione opportune. Il servizio si estende attraverso la rete, per mezzo del protocollo Z39.50 (oppure WAIS, a seconda delle preferenze), che normalmente fa uso della porta 120 con il trasporto TCP. Attualmente, per evitare confusione tra le varie derivazioni di questo sistema, si fa riferimento normalmente a freeWAIS-sf, dove l'aggiunta «sf» rappresenta la caratteristica più importante di questa derivazione, costituita da un'estensione rispetto alla gestione degli indici. freeWAIS-sf è software libero, al contrario di altro software per l'indicizzazione dei file, e può essere utilizzato perfettamente anche senza fare caso alle sue caratteristiche legate alla gestione della rete.

Il problema di freeWAIS-sf sta nel fatto che si trova difficilmente nelle distribuzioni GNU/Linux, probabilmente perché è stato dimenticato. In tal caso, si è costretti a procurarsi i sorgenti, e provvedere da soli alla loro compilazione. In questo capitolo verrà mostrato un uso molto semplice di questo sistema, utilizzando caratteristiche essenziali e solo alcuni dei programmi che lo compongono, anche in considerazione del fatto che mancando un pacchetto predisposto appositamente per la propria distribuzione GNU/Linux si incontrano già molte difficoltà.

202.1 Installazione di freeWAIS-sf e gestione del servente WAIS

Se non si dispone di un pacchetto già pronto per la propria distribuzione GNU/Linux, oppure se quello che si ha è il risultato di una conversione, occorre prendersi cura di controllare e sistemare l'avvio del servizio. Per cominciare, dovrebbe essere previsto questo tipo di servizio almeno nel file `/etc/services', con le righe seguenti:

z3950		210/tcp		wais		# NISO Z39.50 database
z3950		210/udp		wais

Successivamente occorre predisporre uno script adatto da inserire nella procedura di inizializzazione del sistema. Una versione molto semplice di questo, senza controlli, potrebbe essere simile all'esempio seguente, e si potrebbe trattare del file `/etc/init.d/waisserver'. Naturalmente, se per questo script si segue la politica della propria distribuzione, è meglio; inoltre, è bene verificare le opzioni passate a `waisserver'.

#! /bin/sh
#
# /etc/init.d/waisserver
#

NOME=waisserver
DEMONE=/usr/bin/waisserver

# Verifica la presenza del file binario, e in mancanza esce.
test -f $DEMONE || exit 0

case "$1" in
  start)
    echo -n "Avvio del servizio WAIS: $NOME"
    $DEMONE -p -u nobody -l 10 -e /var/log/wais.log -d /var/lib/wais &
    sleep 5
    echo "."
    ;;
  stop)
    echo -n "Chiusura del servizio WAIS: $NOME"
    killall $NOME
    echo "."
    ;;
  reload)
	$0 stop
	$0 start
	;;
  restart)
	$0 stop
	$0 start
	;;
  force-reload)
	$0 stop
	$0 start
	;;
  *)
    echo "Utilizzo: /etc/init.d/$NOME {start|stop|reload|force-reload|restart}"
    exit 1
    ;;
esac

exit 0

In alternativa, è possibile controllare `waisserver' attraverso il demone `inetd'; in tal caso non si usa l'opzione `-p', si fa riferimento al'alias `waisserver.d', e si inserisce la riga seguente nel file `/etc/inetd.conf' (appare spezzata in due parti per motivi tipografici):

z3950	stream	tcp	nowait	nobody	/usr/sbin/tcpd
    /usr/bin/waisserver.d -e /var/log/wais.log -d /var/lib/wais

Ci può essere la necessità di sistemare anche alcuni piccoli dettagli. In particolare, è probabile che freeWAIS-sf cerchi di utilizzare il programma `gzcat', inteso come un `cat' in grado di intervenire direttamente sui file compressi con `gzip'. È probabile che tale programma non esista, e che al suo posto ci sia piuttosto un collegamento simbolico denominato `zcat', che punta al solito `gzip' con il quale si ottiene lo stesso risultato. Se ciò accade, si può risolvere il problema con lo script che viene mostrato di seguito:

#!/bin/sh
# /bin/gzcat
cat "$@" | gzip -d

Se `waisserver' viene avviato con i privilegi di un utente comune, come `nobody', bisogna provvedere in qualche modo al file utilizzato per la registrazione degli eventi. In pratica, se si pretende che `waisserver' funzioni con l'identità `nobody', occorre fare in modo che possa creare il suo file. La soluzione a questo problema potrebbe essere quella di creare una sottodirectory all'interno di `/var/log/', cambiandole l'utente proprietario, in modo che al suo interno possa essere creato il file delle registrazioni.

202.1.1 # waisserver

waisserver [<opzioni>]

waisserver.d [<opzioni>]

`waisserver' e `waisserver.d' sono due nomi che fanno capo allo stesso eseguibile; di solito, uno dei due è un collegamento simbolico all'altro. La distinzione dei nomi serve a definirne il contesto: `waisserver' si utilizza per il funzionamento autonomo, mentre `waisserver.d' si usa quando deve essere sottoposto al controllo del demone `inetd'.

Nella descrizione delle opzioni, si osservi in particolare il caso di `-d', che serve a definire una directory come posizione predefinita per i file degli indici da utilizzare per le ricerche.

Alcune opzioni

-p [<porta>]

L'opzione richiede esplicitamente di stare in ascolto di una porta, e se non viene indicato l'argomento, si tratta di quella predefinita. In questo modo, si vuole che il demone funzioni in modo indipendente da `inetd'.

-s

Si tratta dell'opposto dell'opzione `-p', in quanto richiede espressamente di utilizzare standard input e standard output, e questo serve per l'utilizzo sotto il controllo di `inetd'. Quando il demone viene avviato utilizzando il nome `waisserver.d', questa opzione è predefinita.

-d <directory-indici>

Definisce la directory predefinita per la ricerca degli indici, quando questi vengono indicati senza un percorso. È probabile che non sia possibile raggiungere indici collocati in posizioni precedenti a tale punto di riferimento, ma conviene verificarlo, in modo da sapere se questa caratteristica può essere sfruttata come misura di sicurezza.

-e [<file>]

Definisce il file da utilizzare per annotare i messaggi di errore. Se non viene specificata questa opzione, viene usato il file `/dev/null'; se invece viene usata, ma senza l'argomento, il risultato viene emesso attraverso lo standard error, a meno che sia stata selezionata l'opzione `-s' (o comunque che non stia funzionando in qualità di `waisserver.d'), perché in tal caso non può essere usato, e quindi si ripiega ancora per `/dev/null'.

-l <n-livello-diagnostico>

Questa opzione permette di definire il livello di dettaglio delle informazioni che si vogliono ottenere attraverso il file generato con l'opzione `-e'. Il valore zero rappresenta l'annullamento di questi messaggi, mentre valori superiori, fino a 10, aumentano il dettaglio.

-u <utente>

Se l'eseguibile viene avviato con i privilegi dell'utente `root', è possibile richiedergli di funzionare assumendo l'identità di un altro utente. In generale, per ragioni di sicurezza, è bene sfruttare questa possibilità.

Esempi

In precedenza sono stati mostrati alcuni esempi che adesso è il momento di descrivere. Nel caso dell'avvio di `waisserver' in modo indipendente dal demone `inetd', è stato mostrato il comando seguente:

waisserver -p -u nobody -l 10 -e /var/log/wais.log -d /var/lib/wais &

Per sicurezza è stata usata l'opzione `-p', in modo da rendere esplicito il fatto che si deve mettere in ascolto delle richieste attraverso la rete; viene utilizzata l'opzione `-u' in modo da limitare i privilegi a quelli dell'utente `nobody'; viene richiesto un livello diagnostico massimo, attraverso il file `/var/log/wais.log'; infine, la directory iniziale per la ricerca degli indici è `/var/lib/wais/'.

È importante osservare che in questo modo, `waisserver' deve essere messo esplicitamente in funzione sullo sfondo.

Per quanto riguarda la gestione del servizio attraverso il demone `inetd', è stato mostrato il caso seguente, che nella realtà deve apparire su una sola riga:

z3950	stream	tcp	nowait	nobody	/usr/sbin/tcpd
    /usr/bin/waisserver.d -e /var/log/wais.log -d /var/lib/wais

Viene usato il nome `waisserver.d', per richiedere implicitamente l'utilizzo dei flussi di dati standard, invece di lasciare che si occupi da solo dell'ascolto delle richieste dalla rete, e in tal modo, non è stata usata nemmeno l'opzione `-s', che comunque non sarebbe stata sbagliata. Si può osservare quindi che l'opzione `-p' è assente, necessariamente, mentre non è stata usata l'opzione `-u', dal momento che il programma viene già avviato con i privilegi dell'utente `nobody'. In questo caso, si è preferito lasciare il livello diagnostico al valore predefinito.

202.2 Indici

freeWAIS-sf permette di effettuare delle ricerche solo se prima sono stati costruiti gli indici dei dati a cui si vuole fare riferimento. Questi indici riguardano esclusivamente dei file di testo, o comunque file il cui contenuto sia leggibile come lo può essere un file di testo normale. Nella fase di creazione degli indici è possibile specificare delle particolarità che qui non vengono descritte, e possono essere apprese leggendo la documentazione originale.

Una volta realizzati gli indici, le richieste per effettuare le ricerche devono comprendere l'indicazione dell'indice a cui si vuole fare riferimento, oppure si ricade nell'indice predefinito che è `INFO', e deve essere collocato nella directory predefinita, stabilita all'avvio del servente.

Ogni indice è composto da molti file, accomunati dalla stessa radice, corrispondente al nome che si attribuisce all'indice. In pratica, volendo fare riferimento all'indice `prova', verranno generati una serie di file, corrispondenti al modello `prova.*'.

A titolo di esempio introduttivo, l'indice `prova' collocato nella directory `/var/lib/wais/', generato in base al contenuto delle pagine di manuale, potrebbe essere generato con il comando seguente, che mostra sullo schermo una serie di informazioni simili a quelle che si possono vedere sotto.

waisindex -d /var/lib/wais/prova -r /usr/man[Invio]

718: 0: Sep 27 15:33:43 1999: 6: Starting to build database /var/lib/wais/prova
718: 1: Sep 27 15:33:43 1999: -2: Warning: couldn't open /var/lib/wais/prova.syn
					   synonym translation disabled
718: 2: Sep 27 15:33:43 1999: 6: File: /usr/man/man5/adduser.conf.5.gz
718: 3: Sep 27 15:33:43 1999: 6: File: /usr/man/man5/sources.list.5.gz
718: 4: Sep 27 15:33:44 1999: 6: File: /usr/man/man5/locatedb.5.gz
718: 5: Sep 27 15:33:44 1999: 6: File: /usr/man/man5/keymaps.5.gz
718: 6: Sep 27 15:33:44 1999: 6: File: /usr/man/man5/porttime.5.gz
718: 7: Sep 27 15:33:44 1999: 6: File: /usr/man/man5/faillog.5.gz
...
718: 1444: Sep 27 15:36:21 1999: 6: adding word 'fr' into the stoplist
				    /var/lib/wais/prova.stop since it has
				    21941 occurences (limit 20000).
...
718: 2577: Sep 27 15:38:40 1999: 100: Total word count for dictionary is: 1822254
718: 2578: Sep 27 15:38:42 1999: 6: Finished build

A seconda delle politica che si vuole attuare, questa operazione potrebbe essere fatta anche utilizzando privilegi inferiori a quelli dell'utente `root', e in tal caso andrebbero predisposti opportunamente i permessi relativi alla directory `/var/lib/wais/'.

Per quanto riguarda l'accesso alle informazioni generate, è sufficiente che siano disponibili i permessi di lettura, dal momento che è previsto un solo procedimento di scrittura, precisamente nel momento della creazione dell'indice.

L'accesso locale agli indici dovrebbe essere consentito anche senza utilizzare la rete (dipende da come sono stati compilati i programmi), e si utilizza `waissearch', per esempio nel modo seguente, dove si cercano tutte le corrispondenze con la parola «crypt». Si osservi anche il modo attraverso il quale si esce dal programma.

waissearch -d /var/lib/wais/prova crypt[Invio]

 Search Response:
  NumberOfRecordsReturned: 13
   1: Score:  473, lines: 122 'crypt.3   /usr/man/man3/'
   2: Score:  427, lines:  90 'create_user.7l   /usr/man/man7/'
   3: Score:  422, lines: 115 'pg_hba.conf.5   /usr/man/man5/'
   4: Score:  354, lines:  86 'getpass.3   /usr/man/man3/'
   5: Score:  332, lines: 166 'wavelan_cs.4   /usr/man/man4/'
   6: Score:  323, lines: 153 'wavelan.4   /usr/man/man4/'
   7: Score:  289, lines: 251 'undocumented.3   /usr/man/man3/'
   8: Score:  221, lines: 563 'login.defs.5   /usr/man/man5/'
   9: Score:  175, lines: 754 'Opcode.3pm   /usr/man/man3/'
  10: Score:  160, lines:1147 'pppd.8   /usr/man/man8/'
  11: Score:  114, lines:3161 'perldiag.1p   /usr/man/man1/'
  12: Score:  100, lines:4606 'perlfunc.1p   /usr/man/man1/'
  13: Score:   91, lines:6223 'perltoc.1p   /usr/man/man1/'

View document number [type 0 or q to quit]: q[Invio]

Search for new words [type q to quit]: q[Invio]

Se invece è necessario accedere a un servente presso un nodo di rete remoto, si può aggiungere l'indicazione del suo nome o del suo indirizzo:

waissearch -h dinkel.brot.dg -d /var/lib/wais/prova crypt

Eventualmente potrebbe non essere necessario specificare il percorso per l'indice. Per la precisione, questo vale nel caso si acceda utilizzando il protocollo di rete, e quindi indicando il nodo, quando l'indice deve essere cercato nella directory predefinita secondo quanto stabilito nella riga di comando di avvio del servente. In tal caso:

waissearch -h dinkel.brot.dg -d prova crypt

Una volta ottenuto l'elenco dei file che corrispondono alla stringa di ricerca, si può ottenerne il contenuto, specificando il numero progressivo. Nel caso del primo esempio, se invece di uscire con il comando `q' fosse stato selezionato il numero uno, ecco quello che avrebbe potuto essere il risultato (ridotto in più punti):

Headline: crypt.3   /usr/man/man3/
.\" Michael Haardt (michael@cantor.informatik.rwth.aachen.de)
.\" Sat Sep  3 22:00:30 MET DST 1994
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
    ...
.\" "
.TH CRYPT 3 "September 3, 1994" "" "Library functions"
.SH NAME
crypt \- password and data encryption
.SH SYNOPSIS
.B #define _XOPEN_SOURCE
.br
.B #include <unistd.h>
.sp
.BI "char *crypt(const char *" key ", const char *" salt );
.SH DESCRIPTION
.B crypt
    ...
.SH "CONFORMING TO"
SVID, X/OPEN, BSD 4.3
.SH "SEE ALSO"
.BR login "(1), " passwd "(1), " encrypt "(3), " getpass "(3), " passwd (5)

Evidentemente, il file viene ottenuto così come si trova, con l'aggiunta di un'intestazione con l'informazione di cosa si tratta. Probabilmente, la cosa più importante è sapere dove si trova il file, e questo era già stato determinato prima.

È proprio in situazioni come questa che è necessario predisporre lo script `gzcat', perché i file delle pagine di manuale potrebbero essere stati compressi per risparmiare spazio.

202.2.1 $ waisindex

waisindex [<opzioni>] <file-o-directory>...

`waisindex' crea un indice delle parole contenute nei file indicati, o in quelli delle directory indicate, in maniera che poi si possa fare una ricerca rapida per queste parole, determinando quali siano i file che le contengono. In generale, lo spazio utilizzato dai file che costituiscono l'indice è quasi lo stesso di quello dei file che vengono scanditi.

La creazione di un indice è un'operazione a senso unico; è consentita l'aggiunta in riferimento ad altri file, ma non l'aggiornamento di dati già analizzati. In generale, deve essere ripetuta l'operazione ogni volta che si vuole aggiornare un indice in base ai cambiamenti dei dati originali.

Alcune opzioni

-d <indice>

L'uso di questa opzioni è praticamente obbligatorio, dal momento che serve a stabilire il nome (e il percorso) dell'indice che si vuole creare. In pratica, il nome dell'indice corrisponde a quello di un file, tenendo conto che poi vengono creati diversi file, tutti con la stessa radice, ma con un'estensione differente.

-a

Si richiede di aggiungere dati. Questa opzione non consente di aggiornare dati già accumulati, ma solo di aggiungere informazioni nuove. Sotto questo aspetto, potrebbe essere di scarsa utilità.

-r

Fa in modo di scandire ricorsivamente anche le sottodirectory.

-export

Fa in modo di aggiungere le informazioni sul nodo di rete e sulla porta TCP, per facilitare la lettura del risultato della scansione quando questa serve a chi accede dall'esterno.

-e [<file>]

Questa opzione permette di ridirigere i messaggi di errore in un file, che se non è specificato è `/dev/null'. Ciò può servire quando si utilizza `waisindex' all'interno di uno script che non dovrebbe emettere messaggi.

Esempi

Negli esempi seguenti si suppone di utilizzare i privilegi di un utente diverso da `root', che però abbia la possibilità di creare gli indici nelle directory relative, e che possa accedere in lettura ai dati da scandire.

waisindex -d /var/lib/wais/man -r /usr/man

Genera i file degli indici `/var/lib/wais/man.*', in base ai dati contenuti a partire dalla directory `/usr/man/'.

waisindex -a -d /var/lib/wais/man -r /usr/local/man

Aggiunge agli indici creati nell'esempio precedente le informazioni sui file che si trovano a partire dalla directory `/usr/local/man/'.

waisindex -d /var/lib/wais/INFO -r /usr/man

Crea l'indice `INFO', nella directory `/var/lib/wais/'. Convenzionalmente, l'indice `INFO' è quello predefinito.

202.2.2 $ waissearch

waissearch [<opzioni>] <file-o-directory>...

`waissearch' accede a un indice, leggendolo direttamente dal filesystem, o utilizzando un servente per mezzo della rete, mostrando il risultato della ricerca, e restituendo eventualmente il contenuto di uno o più file corrispondenti. `waissearch' è pensato per essere usato in modo interattivo, ma potrebbe essere anche inserito in uno script, utilizzando qualche piccolo accorgimento.

Alcune opzioni

-h <host>

Permette di accedere a un servente attraverso il protocollo di rete.

-p <porta>

In caso di necessità, permette di specificare il numero della porta TCP da contattare.

-d <indice>

Permette di indicare l'indice all'interno del quale svolgere la ricerca. Se si fa una ricerca locale, senza l'indicazione di un nodo di rete da contattare, è necessario indicare il percorso per raggiungere i file dell'indice, dove la parte finale corrisponde al nome dell'indice stesso; se si esegue una ricerca remota, il percorso assoluto serve solo nel caso in cui il servizio remoto sia stato configurato male, per cui gli indici non si trovano nella directory predefinita.

-m <n-massimo-corrispondenze>

Se si vuole evitare di fare una ricerca completa, si può utilizzare questa opzione per indicare il numero massimo di corrispondenze che si vogliono vedere.

Esempi

waissearch -d /var/lib/wais/man crypt

Cerca nell'indice `/var/lib/wais/man' la corrispondenza per la parola «crypt».

waissearch -h dinkel.brot.dg -d /var/lib/wais/man crypt

Come nell'esempio precedente, ma utilizzando il servizio del nodo `dinkel.brot.dg'.

waissearch -h dinkel.brot.dg -d man crypt

Come nell'esempio precedente, contando sul fatto il servizio remoto sia configurato correttamente, per ciò che riguarda la directory degli indici.

waissearch -h dinkel.brot.dg crypt

Cerca nell'indice predefinito del nodo `dinkel.brot.dg' le corrispondenze per la parola «crypt». In generale, l'indice predefinito corrisponde al nome `INFO'.

#!/bin/sh
echo -n | waissearch "$@"
echo

L'esempio rappresenta uno script molto banale, in grado di richiamare `waissearch', con gli stessi argomenti passati allo script, facendo in modo che termini immediatamente di funzionare dopo aver mostrato l'elenco delle corrispondenze. Lo stesso esempio permette di capire come incorporare `waissearch' in uno script di altro genere.

202.3 Sintassi per l'interrogazione attraverso freeWAIS-sf

Per utilizzare al meglio questo sistema di ricerca, occorre conoscere la sintassi per le interrogazioni. Le possibilità effettive possono dipendere dal modo in cui sono compilati i sorgenti. In generale, dovrebbero essere valide le regole che vengono descritte qui.

Per prima cosa, un elenco di parole spaziate rappresenta la ricerca di tutti i file che contengono almeno una di quelle parole, mentre una frase delimitata, che viene passata come un solo argomento, rappresenta la corrispondenza esatta con quella frase. Inoltre, si possono usare gli operatori booleani `and' e `or' e le parentesi tonde. Evidentemente, tali parole non possono essere usate come obiettivi di una ricerca; inoltre, è evidente che l'operatore `or' è predefinito.

Vale la pena di soffermarsi sull'operatore `not', che va inteso come un «AND NOT» normale, per cui va usato come operatore binario (e non unario come sarebbe nella normalità). In pratica, l'interrogazione seguente non è valida:

not tizio

Per individuare tutti i file che non contengono una cerca parola, occorre indicare prima cosa devono contenere. In pratica, l'esempio va corretto nel modo seguente:

"" not tizio

Infine, si possono indicare delle parole incomplete utilizzando il carattere jolly `*', che ha lo stesso significato intuitivo che si conosce per le shell. Non sono previsti altri caratteri del genere.

Interrogazione Corrispondenza
<parola> File che contengono la parola indicata.
<parola> <parola> File che contengono almeno una delle parole.
<parola> or <parola> File che contengono almeno una delle parole.
<radice>* File che contengono una parola con la radice indicata.
"<frase>" File che contengono la frase esatta.
<parola> and <parola> File che contengono entrambe le parole.
<parola> not <parola> File che contengono la prima, ma non la seconda parola.
(<interrogazione>) Le parentesi precisano l'ordine di interpretazione.

Tabella 202.1: Riassunto della sintassi di interrogazione.

202.4 Descrizione di un sistema molto semplice di indicizzazione del proprio sito HTTP

Senza ricorrere al protocollo usato da freeWAIS-sf, è possibile predisporre un sistema CGI molto semplice che si avvalga localmente di `waissearch' per generare un indice dei documenti HTML che corrispondono a un certo modello di ricerca.

Supponendo di gestire un sito HTTP, che localmente si articola a partire dalla directory `/home/httpd/html/', si comincia con la costruzione di un indice:

waisindex -d /var/lib/wais/http -r /home/httpd/html[Invio]

Così si crea l'indice `http' nella directory `/var/lib/wais/', in base al contenuto della directory `/home/httpd/html/'. Quello che serve adesso è un programma CGI da usare nello stesso elaboratore che offre il servizio HTTP, in modo da poter interrogare l'indice appena creato.

#!/usr/bin/perl
#======================================================================
# cerca.pl
#======================================================================

#----------------------------------------------------------------------
# Incorpora la libreria di decodifica dei dati.
#----------------------------------------------------------------------
require ('mini-lib.pl');

#======================================================================
# &Metodo_non_gestibile ()
#----------------------------------------------------------------------
sub Metodo_non_gestibile {
    print "Content-type: text/html\n";
    print "\n";
    print "<HTML>\n";
    print "<HEAD>\n";
    print "<TITLE>Errore</TITLE>\n";
    print "</HEAD>\n";
    print "<BODY>\n";
    print "<H1>Metodo $ENV{REQUEST_METHOD} non gestibile.</H1>\n";
    print "</BODY>\n";
    print "</HTML>\n";
};

#======================================================================
# &Modulo_iniziale ()
#----------------------------------------------------------------------
sub Modulo_iniziale {
    print "Content-type: text/html\n";
    print "\n";
    print "<HTML>\n";
    print "<HEAD>\n";
    print "<TITLE>Ricerca all'interno del sito</TITLE>\n";
    print "</HEAD>\n";
    print "<BODY>\n";
    print "<H1>Ricerca all'interno del sito</H1>\n";
    print "<P>\n";
    print "<FORM ACTION=\"/cgi-bin/cerca.pl\" METHOD=\"GET\">\n";
    print "<P>\n";
    print "Stringa di ricerca:\n";
    print "<INPUT NAME=\"richiesta\" SIZE=60>\n";
    print "<INPUT TYPE=submit VALUE=\"Cerca\"></P>\n";
    print "</FORM>\n";
    print "</BODY>\n";
    print "</HTML>\n";
};

#=======================================================================
# &Elabora_riga ()
#-----------------------------------------------------------------------
sub Elabora_riga {
    local( $riga ) = @_[0];
    local( $punteggio ) = 0;
    local( $file_percorso ) = "";
    local( $nome_file ) = "";
    local( $percorso ) = "";

    #-------------------------------------------------------------------
    # Scompone la riga in modo da estrarre il nome del file e il
    # percorso relativo al sito HTTP.
    #-------------------------------------------------------------------
    if ( $riga =~ m|^.*Score:\s+([0-9]*),.*?'(.*?)'.*$|i ) {
	$punteggio = $1;
	$file_percorso = $2;

	#---------------------------------------------------------------
	# È meglio scomporre l'analisi attraverso le espressioni
	# regolari, altrimenti si fa troppa confusione.
	#---------------------------------------------------------------
	$file_percorso =~ m|^(.*)\s+/home/httpd/html/(.*?)/?$|i;
	$nome_file = $1;
	$percorso = $2;

	#---------------------------------------------------------------
	# Se questa variabile è vuota, non si può mettere la barra
	# iniziale.
	#---------------------------------------------------------------
	if ( $percorso eq "" ) {
	    ;
	} else {
	    $percorso = "/$percorso";
	}

	#---------------------------------------------------------------
	# Emette le righe utili come riferimenti ipertestuali.
	#---------------------------------------------------------------
	print "<P>Punteggio: $punteggio ";
	print "<A HREF=\"$percorso/$nome_file\">";
	print "$percorso/$nome_file</A></P>\n";
    }
}

#======================================================================
# &Elaborazione_richiesta ()
#----------------------------------------------------------------------
sub Elaborazione_richiesta {

    #------------------------------------------------------------------
    # Rinvia la richiesta a waissearch e ne restituisce l'esito.
    #------------------------------------------------------------------
    if ( open( WAIS,
	    "echo -n | waissearch -d /var/lib/wais/http \'$DATI{richiesta}\' |"
	 ) ) {

	print "Content-type: text/html\n";
	print "\n";
        print "<HTML>\n";
        print "<HEAD>\n";
	print "<TITLE>Risultato della ricerca in base al modello: ";
        print "$DATI{richiesta}</TITLE>\n";
	print "</HEAD>\n";
        print "<BODY>\n";
	print "<H1>Risultato della ricerca</H1>\n";
        print "<P><STRONG>$DATI{richiesta}</STRONG></p>\n";

        while ( $risposta = <WAIS> ) {
	    #-----------------------------------------------------------
	    # Legge le righe del testo restituito da waissearch, e
	    # se corrispondono al modello, la funzione seguente
	    # emette direttamente una riga adatta alla pagina che
	    # si sta costruendo.
	    #-----------------------------------------------------------
	    &Elabora_riga( $risposta );
	};

	print "</BODY>\n";
        print "</HTML>\n";

    } else {
	print "Content-type: text/html\n";
        print "\n";
	print "<HTML>\n";
        print "<HEAD>\n";
	print "<TITLE>Errore</TITLE>\n";
        print "</HEAD>\n";
	print "<BODY>\n";
        print "<H1>Errore</H1>\n";
	print "Si è manifestato un errore durante l'inoltro ";
        print "della richiesta.\n";
	print "</BODY>\n";
        print "</HTML>\n";
    }
}


#======================================================================
# Inizio del programma.
#======================================================================

local ( %DATI ) = ();
local ( $risposta ) = "";

#----------------------------------------------------------------------
# Decodifica i dati in funzione del tipo di metodo della richiesta.
#----------------------------------------------------------------------
if ( $ENV{REQUEST_METHOD} eq 'GET' ) {
    %DATI = &Decodifica_GET;
} elsif ( $ENV{REQUEST_METHOD} eq 'POST' ) {
    %DATI = &Decodifica_POST;
} else {
    &Metodo_non_gestibile;
};

#----------------------------------------------------------------------
# Controlla che sia stata indicata una stringa di ricerca, altrimenti
# mostra il modulo per iniziare.
#----------------------------------------------------------------------
if ( $DATI{richiesta} eq "" ) {
    &Modulo_iniziale();
} else {
    &Elaborazione_richiesta();
}

#======================================================================
1;
#======================================================================

Il programma mostrato fa uso della solita libreria `mini-lib.pl', descritta nel capitolo 199. Richiamando il programma attraverso un navigatore (dovrebbe trattarsi dell'URI http://localhost/cgi-bin/cerca.pl), si ottiene ciò che si vede nella figura 202.1.

176.jpg

Figura 202.1: La maschera iniziale generata dal programma CGI attraverso un navigatore grafico.

Provando a inserire una richiesta composta dalla stringa «apache httpd», che indica di individuare i file contenenti la parola «apache» o la parola «httpd», indifferentemente, si potrebbe ottenere un risultato simile a quello mostrato nella figura 202.2.

177.jpg

Figura 202.2: Risultato di un'interrogazione.

Naturalmente, il programma in questione può essere abbellito, soprattutto con una guida che mostri la sintassi che può essere utilizzata per le interrogazioni.

202.5 Riferimenti

---------------------------

Appunti Linux 2000.04.12 --- Copyright © 1997-2000 Daniele Giacomini --  daniele @ pluto.linux.it


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]