paper.gifioProgrammo N°8, Ottobre 1997 ©Copyright DIEMME Editori

fire.gif

MENU DI LINK E CONTATORI
Lo scripting cgi, oltre che fornire un ponte interattivo tra la pagina web e l'utente finale, viene spesso usato per superare i limiti piuttosto ristretti dell'HTML. Un tipico esempio riguarda sia la creazione di un menu di link che consente di ottimizzare lo spazio disponibile sulla pagina e sia la generazione di statistiche
Il trucco consiste nell'interfacciare il tag SELECT con uno script perl che restituirà il documento html selezionato. In un primo tempo, quindi, svilupperemo un menu statico e poi scopriremo i segreti dei contatori dinamici.
linea.gif
UN MENU STATICO
Poiché il nostro menu dovrà essere sempre visibile, formatteremo la pagina html utilizzando i frame. Ecco il codice html di base: menu.html:

<HTML>
<HEAD>
<TITLE>Menu di Link</TITLE>
</HEAD>
<FRAMESET cols="150,*">
  <FRAME name="sx" src="sx.html" scrolling="no">
  <FRAMESET rows="100,*">
    <FRAME name="form"  src="form.html" scrolling="no">
    <FRAME name="central" src="central.html" scrolling="auto">
  </FRAMESET>
</FRAMESET>
</HTML>

sx.html, frame di sinistra:

<HTML>
<HEAD>
<TITLE>Menu di Link</TITLE>
</HEAD>
<BODY bgcolor="#000080">
</BODY>
</HTML>

form.html, frame del menu:

<HTML>
<HEAD>
<TITLE>Menu di Link</TITLE>
</HEAD>
<BODY bgcolor="#c0c0c0">
<CENTER>
<FORM METHOD="POST" ACTION="http://localhost/cgi-bin/menu.cgi" target=central>
<SELECT NAME="link">
<OPTION SELECTED>Link 1
<OPTION>Link 2
<OPTION>Link 3
<OPTION>Link 4
<OPTION>Link 5
</SELECT> 
<INPUT TYPE="submit" NAME="" VALUE="OK">
</FORM>
</CENTER>
</BODY>
</HTML>

central.html, frame centrale:

<HTML>
<HEAD>
<TITLE>Menu di Link</TITLE>
</HEAD>
<BODY bgcolor="#ffffff">
</BODY>
</HTML>

Ed ora passiamo allo script. Ci servirà innanzitutto un file (link.db) che conterrà tutti link. Una specie di piccolo database così formattato:

Descrizione link;url

Link 1;http://localhost/link1.html
Link 2;../link2.html

img_articolo Ogni riga sarà un record, costituito a sua volta da due campi separati da un puto e virgola ;. Nel capo 1 ci sarà la descrizione del link, uguale a quella del tag SELECT nel frame del menu; mentre nel campo 2 scriveremo l'URL assoluto o relativo. Salviamo il file link.db nella directory dei cgi del server http ed assicuriamoci che i diritti di lettura siano attivi con chmod 644 link.db. A questo punto scriviamo il codice perl.

Lo script deve leggere il file link.db e con la funzione split memorizzare i due campi nell'array @campo usando come separatore il punto e virgola. A questo punto basterà verificare se il contenuto della variabile link del tag SELECT, e passata al cgi, è uguale al primo campo del record. Se ciò è vero si restituirà la pagina individuata dall'URL del campo 2 con un print "Location:\n\n".


#!/usr/bin/perl
require "cgi-lib.pl";
$menudb = "./link.db";
&ReadParse(*CGI);
&CercaLink($menudb, $CGI{link});
sub CercaLink {
  local ($db, $cgi) = @_;
  open (DB, "<$db");
  while (<DB>) {
    @campo = split(/;/, $_);
    if ($campo[0] =~ /$cgi/i) { 
      close(DB);
      last;
    }
  }
  print "Location: $campo[1]\n\n";
  exit; 
}

linea.gif
SERVER SIDE INCLUDES
Prima di affrontare il tema dei contatori dinamici è necessario spendere qualche parola sulle direttive SSI. L'uso di un contatore in una pagina web, è reso possibile solo se sono state attivate speciali istruzioni nel file di configurazione srm.conf del server (apache o NCSA).
AddType text/x-server-parsed-html .shtml
Tale istruzione è note anche come direttiva di Server Side Includes, e fornisce un metodo per poter eseguire "al volo" programmi da un documento html. L'esecuzione dello script counter.cgi si può quindi ottenere con la seguente istruzione nel file index.shtml.
<!--#exec cgi="cgi-bin/counter.cgi"-->
linea.gif
UN CONTATORE DINAMICO
Forse parlare di contatori oggi farà sorridere. In Rete se ne trovano per tutti i gusti e con poche modifiche si possono adattare alle esigenze di ciascun utente. Tuttavia l'argomento contatori, solleva una questione piuttosto importante della programmazione CGI, ovvero l'accesso concorrente ai file. Ogni volta che si accede ad una pagina web dotata di counter, parte un programmino che visualizza e poi incrementa un numero contenuto in un file. Supponiamo che più client, sparsi per il mondo, accedano contemporaneamente a quella pagina. Ne consegue che quel piccolo file di log potrà subire dei danneggiamenti o addirittura cancellazioni a causa di operazioni di scrittura in contemporanea. Sorge quindi la necessità di bloccare in esclusiva la scrittura sul file per ogni singola richiesta. Basta utilizzare una chiamata alla funzione di sistema flock e al resto cui pensa il sistema operativo accodando tutte le altre richieste e garantendo una scrittura corretta.

#!/usr/bin/perl
open (COUNT, "+<./counter/counter.log") || die "cannot open counter.log";
flock(COUNT, 2) || die "cannot lock counter.log";
$count = <COUNT>;
if ($count =~ /\n$/) {
  chop $count;
}
@numero = split(//, $count);
@img = `ls ./counter/*.gif`;
if (@img) {
  print "Content-type: text/html\n\n";
  $num = length($count);
  $i=0;
  while ($i <= $num-1) {
    print "<img src=$numero[$i].gif>";
    $i++;
  } 
}
else {
  print "Content-type: text/plain\n\n";
  print "Benvenuto, sei il visitatore $count\n";
}
$count++;
seek(COUNT, 0, 0);
print COUNT "$count";
close(COUNT);

img_articolo Lo script è abbastanza semplice. Per comodità la directory del file di log (counter.log) e delle immagini per il contatore (0.gif, 1.gif, etc.) è una sottodirectory della cgi-bin (quella in cui sono contenuti i CGI del server). Il file di log, inoltre, non deve essere protetto in scrittura consentendo a chi si connette alla nostra home page di aggiornare il contatore. Il file counter.log deve esistere. Basta editarlo, scrivere il numero 1 (per i più furbi va bene anche 1000) e salvarlo.

A questo punto possiamo analizzare il programma. counter.cgi, è questo il nome dello script, inizia con una istruzione di apertura del file di log subito seguita dalla chiamata alla funzione flock. Con <COUNT> si legge il file e con split si crea l'array @numero i cui elementi serviranno per concatenare i tag IMG creando la sequenza corretta di immagini gif. Prima di chiudere il file di log, si incrementa il contatore con $count++, si esegue un rewind con la funzione seek (in pratica mi posiziono all'inizio del file) e poi scrivo il valore aggiornato con print COUNT "$count". Benone. Se abbiamo 10 immagini gif con i numeri da 0 a 9 possiamo provare il nostro contatore. Sarà un po' spartano ma rappresenta una buona base di partenza per fare esercizio. E se non abbiamo i numeri .gif? Niente paura. Lo scrpt stamperà il contenuto di counter.log come semplice testo anziché come sequenza di immagini: versatile no?
linea.gif
LE SPECIFICHE CGI
Nel momento in cui il server http esegue un cgi, vengono impostate numerose variabili d'ambiente. Ecco le più utili ed importanti, usate soprattutto per ottenere informazioni aggiuntive altrimenti irraggiungibili.

SERVER_SOFTWARE
Il nome e la versione del server http che risponde alla richiesta cgi
SERVER_NAME
Il nome del server http che può essere un alias di DNS o un indirizzo IP numerico
GATEWAY_INTERFACE
La versione delle specifiche CGI
SERVER_PROTOCOL
Il nome e la versione del protocollo di comunicazione (HTTP)
SERVER_PORT
Il numero di porta a cui è indirizzata la richiesta (di solito la porta 80)
REQUEST_METHOD
Il metodo usato per la richiesta (GET, POST, etc)
SCRIPT_NAME
Il path completo del programma cgi
QUERY_STRING
Contiene i dati passati dalle richieste GET, ISINDEX, ISMAP
REMOTE_HOST
Il nome dell'host che invia la richiesta
REMOTE_ADDR
L'indirizzo IP dell'host che invia la richiesta
AUTH_TYPE
Il metodo usato dal protocollo di autenticazione dell'utente. Questa variabile è settata solo se il server supporta tale protocollo e se il cgi è protetto.
REMOTE_USER
Il nome dell'utente autentificato. Questa variabile è settata solo se il server supporta il protocollo di autenticazione e se il cgi è protetto.
CONTENT_TYPE
Per le richieste POST e PUT questa variabile contiene il tipo MIME dei dati passati al cgi
CONTENT_LENGTH
La lunghezza dei dati passati con il metodo POST.
HTTP_ACCEPT
I tipi MIME accettati dal client
HTTP_USER_AGENT
Il nome e la versione del browser che ha inviato la richiesta
Per risalire al contenuto di tale enviroment si usa l'istruzione $ENV{"nome_variabile"}.

fire.gif

Data creazione HTML: Febbraio 1998
Autore: Francesco Munaretto
E-mail: NoSpam@thank.you
exclaim.gif