Vai al menù, saltando i contenuti (access key "m")
Appunti sulla realizzazione di questo sito. Il guestbook
Il guestbook di questo sito è realizzato con due semplici script PHP. Uno si occupa di memorizzare i messaggi in un file di testo, l'altro di leggerli.
Lo script di lettura
La pagina web principale del mio guestbook contiene lo script di lettura e ha la seguente struttura
<h2>GuestBook</h2> <!-- IL FORM PER L'INVIO DEI DATI ALLO SCRIPT DI SCRITTURA TRAMITE IL METODO "POST" --> <!-- GESTIONI ERRORI CHE ARRIVANO DALLO SCRIPT DI SCRITTURA TRAMITE IL METODO "GET" --> <!-- LETTURA E STAMPA DEL "DATABASE" DEL GUESTBOOK -->
Vediamo prima di tutto il form per l'invio del messaggio
<form action="./send-message.php" method="post"> <p> Nome (max 24 caratteri):<br/> <input type="text" name="nome" size="24" maxlength="24"/><br/><br/> Messaggio (max 160 caratteri):<br/> <textarea name="messaggio" maxlength="160" rows="4" cols="40" id="messaggio"></textarea><br/><br/> <input type="submit" value="Invia"/> </p> </form> <br/>
Come si vede è un semplice form con due campi. Impostare il numero massimo dei caratteri per il nome è semplice, lo permette la casella di testo stessa. Invece per quanto riguarda la textarea non ho trovato opzioni analoghe e ho dovuto gestire il numero massimo di caratteri con il php.
Vediamo ora la gestione degli errori (che vengono passati alla pagina principale del guestbook con il metodo GET). Il codice non ha bisogno di spiegazioni particolari.
<? $error=$_GET['error']; if (!empty($error)) { switch ($error) { case 1: echo "<p><b>NON PUOI INSERIRE DUE MESSAGGI CONSECUTIVAMENTE!</b></p>\n"; break; case 2: echo "<p><b>HAI DIMENTICATO DI INSERIRE IL NOME O IL MESSAGGIO!</b></p>\n"; break; case 3: echo "<p><b>HAI SUPERATO LA LUNGHEZZA MASSIMA CONSENTITA PER IL MESSAGGIO (160 caratteri)!</b></p>\n"; break; case 4: echo "<p><b>HO COME L'IMPRESSIONE CHE TU STIA INSERENDO DELLO SPAM!</b></p>\n"; break; } } ?>
Prima di vedere il codice per stampare il contenuto del database del guestbook, vediamo come è fatto il database. Il database dove vengono memorizzati i vari messaggi del guestbook è un semplice file di testo con la seguente struttura:
DD Month YYYY HH:MM"nome"messaggio"IP
Come si vede i campi sono separati dal carattere "
Ora che abbiamo visto come è strutturato il database, possiamo vedere lo script per leggerlo e stampare il codice HTML (una table dove ogni riga è un messaggio):
<? $messaggi=file("./guestbook.txt"); $n=count($messaggi); echo "<table id=\"guestbook\">\n <col id=\"fst\"/><col id=\"snd\"/>\n"; for($i=0; $i<$n; $i++) { // Reading the lines backward $r=$n-($i+1); list($data, $utente, $messaggio, $IP) = split('"', $messaggi[$r]); echo "<tr><td>" . $data . "<br/>" . "<b>".$utente."</b>" . "</td><td>" . $messaggio . "</td></tr>\n"; }; echo "</table>\n"; ?>
Lo script di scrittura
Come è noto quando si clicca il pulsante di un form come quello
mostrato sopra, viene richiamata la pagina indicata nel codice,
nel nostro caso send-message.php
. Il codice di questa
nuova pagina potrà usare i dati inseriti nel form perché questi
sono contenuti nell'array $_POST.
La pagina send-message.php
ha la seguente struttura
<!-- definizione variabili --> <!-- pulizia del contenuto dei campi del form --> <!-- controllo errori e caricamento della pagina principale del guestbook passando il codice di errore con il metodo GET --> <!-- scrittura messaggio nel database-->
Vediamo la definizione e assegnazione di alcune variabili iniziali
setlocale(LC_TIME, "it_IT"); $error = 0; $db="./guestbook.txt"; $ip=$_SERVER['REMOTE_ADDR']; // Read the IP of the last message $file_ip=fopen("./last_IP","r"); $last_ip=fgets($file_ip); fclose($file_ip);
L'unica cosa da spiegare è la presenza del file last_IP
dove si trova l'indirizzo IP dell'ultimo messaggio scritto nel
guestbook. Questo IP verrà confrontato con quello del messaggio
attuale per vedere se è lo stesso o meno. Se è lo stesso, il messaggio
non verrà scritto.
Il passo successivo è recuperare il testo del messaggio e il nome dell'autore (che sono stati inviati tramite il metodo POST) e fare un escape dei comandi HTML e PHP eventualmente presenti.
// Escaping of HTML and PHP commands $messaggio=str_replace(array("\n","\r"),"",nl2br(htmlspecialchars($_POST['messaggio'],ENT_COMPAT,'UTF-8'))); $nome=str_replace(array("\n","\r"),"",nl2br(htmlspecialchars($_POST['nome'],ENT_COMPAT,'UTF-8')));
Tolgo i caratteri "pericolosi", poiché interpretabili,
usando la funzione htmlspecialchars(). L'opzione ENT_COMPAT
serve a indicare che verranno trasformati solo i caratteri ", &, < e > che diverranno rispettivamente
", &, < e >. UTF-8 è ovviamente la codifica da usare.
Come si vede, la stringa così ripulita, viene passata direttamente alla funzione nl2br
che aggiunge il tag <br />; prima di ogni ritorno a capo (\n\r
, \r\n
, \n
, \r
).
Infine la stringa risultante viene passata alla funzione str_replace
che rimpiazza
una sottostringa con un'altra. Nel nostro caso viene usata per eliminare i ritorni a capo, cioè
le sequenze \n
e \r
.
Questa operazione di sostituzione della forma degli a capo da php (\n, \r, ecc...) a HTML (<br />;) ci serve per poter fare in modo che nel database del guestbook, che è un semplice file di testo, ogni messaggio occupi una e una sola riga. Se non avessimo tolto gli a capo, il testo nel database avrebbe occupato più di una riga.
Poi c'è la gestione degli errori che si commenta da sé.
// Two consecutive message from the same IP are not allowed if ($last_ip == $_SERVER['REMOTE_ADDR']) { $error=1; header ("Location: http://biccari.altervista.org/c/guestbook/?error=1"); exit; }; // Empty message or empty name is not allowed if (empty($messaggio) or empty($nome)) { $error = 2; header ("Location: http://biccari.altervista.org/c/guestbook/?error=2"); exit; }; // message cannot be longer than 160 chars if (strlen($messaggio)>160) { $error = 3; header ("Location: http://biccari.altervista.org/c/guestbook/?error=3"); exit; }; // Inserting the http string is not allowed if (stripos($messaggio, 'http') !== false or strpos($nome, 'http') !== false) { $error = 4; header ("Location: http://biccari.altervista.org/c/guestbook/?error=4"); exit; };
Infine, se non ci sono stati errori, scrivo il nuovo messaggio nel database
guestbook.txt
e l'IP dell'autore nel file last_IP
.
if ($error == 0) { $file=fopen($db,"a+"); $stringa=ucwords(strftime("%d %B %Y %H:%M")) . '"' . $nome . '"' . $messaggio . '"' . $_SERVER['REMOTE_ADDR'] . "\n"; fwrite($file,$stringa); fclose($file); // Write the IP of the message $file_ip=fopen("./last_IP","w"); fwrite($file_ip,$_SERVER['REMOTE_ADDR']); fclose($file_ip); header ("Location: http://biccari.altervista.org/c/guestbook"); exit; };
Da notare che i campi nel file di testo (data, autore, messaggio, IP) sono separati con un carattere non inseribile da un visitatore, cioè i doppi apici. In realtà un autore può inserire i doppi apici nel suo messaggio ma questi verranno trasformati, come visto sopra, nella sequenza di caratteri ".