Php: Controllo dei dati provenienti dai form

  •  Alcuni accorgimenti da prendere e controlli da fare quando si acquisiscono dati e informazioni dai form: maschere molto comuni usate dai siti Web su Internet per interagire con i visitatori e rendere interattivo il sito. del
  • , aggiornata al
  • , di
  • in

Quando si programmano applicazioni per il Web capita spesso di dover interagire con gli utenti. Per farlo si usano i form: maschere dove si possono inserire testi per soddisfare le esigenze di interattività del sito. Si pensi ai forum, alle bacheche elettroniche, ai form mail, ecc. In questi casi occorre trattare e filtrare opportunamente il testo inserito dall'utente prima di poterlo utilizzare nel programma. Se non lo si fa, si rischia di andare incontro a seri problemi di funzionamento e sicurezza dell'applicazione.

Ad esempio se si chiede di inserire una data, una mail, un dato di tipo numerico, prima di prendere per buono ciò che l'utente inserisce occorre fare dei controlli per verificare che ciò che è stato inserito corrisponda al tipo di dato che ci aspettiamo e stia dentro il campo di valori prefissato.

Occorre inoltre fare anche dei controlli sui dati inseriti: la verifica che i dati non contengano elementi pericolosi per l'applicazione. Vediamo quali sono le funzioni che PHP mette a disposizione per facilitarci in questo compito.

I primi controlli

Supponiamo di avere nella variabile $messaggio il dato inserito da un utente in un modulo o in un form e che lo vogliamo memorizzare in una pagina Web del nostro sito in modo da renderlo visibile a tutti i visitatori oppure lo vogliamo usare per farci un ulteriore elaborazione e presentare un risultato.

Per prima cosa si deve controllare che la variabile $messaggio non sia vuota, ma contenga qualcosa. Per fare questo possiamo usare la funzione PHP empy() in questo modo:

If (!empty($messaggio)) { continua nel controllo }
else { print $errore; } // Se $messaggio non è vuoto, continua nel controllo altrimenti visualizza un errore.

Una ulteriore verifica sarebbe bene farla anche sulla dimensione della variabile al fine di evitare che un testo troppo lungo occupi troppo spazio rallentando il caricamento della pagina.

Per fare ciò possiamo usare la funzione PHP strlen()
if ( strlen ( $messaggio ) < $dimensione_massima ) { continua nel controllo }

Un controllo, in certi casi, è bene farlo anche sul tipo di dato. Se per esempio ci aspettiamo un dato numerico per fare un certo calcolo, dobbiamo controllare che effettivamente ci arrivi un numero. Per fare questo possiamo usare la funzione PHP (v.4) is_numeric() (eventualmente insieme ad altre funzioni simili come: is_integer(), is_real(), is_string() is_bool(), ecc per altri tipi di dati) in questo modo:

If (is_numeric($messaggio)) { continua nel controllo }

Ma non basta, nel caso di input numerici occorre controllare anche il "range" di validità del numero per evitare numeri troppo grossi o troppo piccoli che potrebbero fare andare in overflow il programma Quindi attenzione agli zeri! Una divisione per zero genera un errore.

Alcune precauzioni

Molto importante, a mio avviso, è filtrare il contenuto di $messaggio in modo da impedire che TAG HTML (inseriti involontariamente o maliziosamente) possano finire nella nostra pagina modificandone la formattazione. Si pensi a cosa accadrebbe se una persona inserisse maliziosamente nella maschera del nostro forum il seguente testo: <img src=//www.altrosito.com/immagine.jpg>. Il file immagine.jpg verrebbe caricato dal sito www.altrosito.com e l'immagine visualizzata sulla pagina del nostro sito, oppure si pensi se inserisse un testo del tipo <?php (istruzioni php) ?>.

Per evitare queste situazioni potenzialmente pericolose PHP mette a disposizione due funzioni: HtmlSpecialChar() e HtmlEntities().

HTMLSpecialChar() trasforma tutti i caratteri < > & " (doppi apici) rispettivamente nell'equivalente simbolico html: &lt; &gt; &amp; &quot; In questo modo si dà il corretto significato ai caratteri "<", ">" e si impedisce che il browser li interpreti come tag html.

Occorre quindi inserire nel programma di controllo una istruzione:
$messaggio = HTMLSpecialChar($messaggio); per filtrare il contenuto della variabile $messaggio ed eliminare i tag html.

Si può anche usare la funzione HTMLEntities() nello stesso modo:
$messaggio = htmlentities($messaggio);

La differenza è che HtmlEntities() trasforma nell'equivalente simbolico html un più ampio spettro di caratteri come ad esempio le lettere accentate à è ì ò ù che diventano &agrave; &egrave; &igrave; &ograve; eccetera.

Esiste una terza funzione: Strip_Tags() che invece elimina tutto il contenuto della variabile compreso tra i caratteri < e >. Quale di queste funzioni usare dipende dai vari casi e da cosa si vuole fare ed è compito del programmatore scegliere quella che più si adatta alle proprie esigenze.

La formattazione e MySQL

Un altro problema che sorge quando si tratta l'input di un form di tipo testo è la gestione del ritorno a capo. Si vuole che il testo inserito nel form rispetti la formattazione data dall'utente anche nella pagina Web che visualizzeremo.

Per fare questo PHP mette a disposizione la funzione nl2br() che inserisce, dopo ogni ritorno a capo contenuto nel testo, la stringa html <br>.

Altro aspetto a cui prestare attenzione è l'eliminazione dei ritorni a capo o degli spazi che, inseriti involontariamente dall'utente, possono dare fastidio ai fini di una corretta formattazione della pagina Web. Per questo PHP mette a disposizione un set di funzioni: rtrim(), ltrim(), trim() per eliminare gli spazi vuoti, i ritorni a capo, le tabulazioni, rispettivamente alla fine, all'inizio e da entrambi le parti.

Un altro elemento a cui fare molta attenzione è la variabile di configurazione del PHP: magic_quotes_gpc. Per conoscere il suo valore occorre usare la funzione PHP phpinfo() che visualizza molte informazioni su come è configurato l'interprete PHP sul server che stiamo usando.

Quando la variabile magic_quotes_gpc è impostata su on, tutti i caratteri ' (apice singolo), " (doppio apice), \ (barra contraria) verranno preceduti da una barra contraria \ o escape in modo automatico quando si acquisiscono da un form. Così se per esempio scrivo: \Roberto Benigni "la vita e' bella"\, nella variabile $messaggio mi trovo la stringa: \\Roberto Benigni \"lavita e\' bella\"\\.
Questa impostazione serve per facilitare gli inserimenti dei dati in un database MySQL.

Tuttavia se il nostro scopo è soltanto quello di visualizzare la stringa in una pagina Web oppure spedirla via posta elettronica, occorre eliminare le barre contrarie "\" di troppo.
Per risolvere velocemente il problema, PHP mette a disposizione la funzione stripslashes() da usarsi in questo modo:
$messaggio = stripslashes($messaggio);

Se invece magic_quotes_gpc è impostata su off e si prevede di inserire i dati della variabile $messaggio in un database MySQL occorre far precedere ogni carattere "\" (barra contraria), ' (apice), " (doppio apice), dal carattere di escape o barra contraria "\" . Questo al fine di evitare confusioni con la sintassi delle query SQL che potrebbero non funzionare correttamente e generare errori.
Per fare questo PHP mette a disposizione la funzione addslashes() da usarsi in questo modo:
$messaggio = addslashes($messaggio).

Conclusioni

Abbiamo visto alcuni aspetti a cui prestare attenzione quando si acquisiscono dati da un form e abbiamo abbozzato alcune soluzioni sfruttando la potenza delle funzioni PHP.

Concludo con un problema a mio avviso abbastanza fastidioso. E' quello che si verifica quando un utente fa il copia/incolla da documenti Word e simili nella maschera del form. Capita a volte di vedere nella pagina Web dei codici di caratteri tipo: &#8216; &#8217; &#61528; ecc. Si tratta dei codici estesi di metacaratteri html, nascosti nel copia/incolla e che diventano visibili una volta inviati alla nostra pagina Web. Infatti la codifica dei metacaratteri in Html prevede la seguente forma &#[codice esteso];. Se copiamo un carattere simbolico come questo "" in un form e lo filtriamo con la funzione Htmlspecialchar() o HtmlEntities(), può succedere di vedere comparire &#61529; nella nostra pagina Web se si usa MSIE 5.5, se invece usiamo Netscape Composer 4.76, non succede e compare un "Y".

Per risolvere questo problema possiamo controllare, attraverso una espressione regolare per esempio, se la variabile $messaggio contiene codifiche di caratteri estesi e in caso positivo togliere la codifica "amp" all'ampersand in questo modo:

if (ereg("&amp;#[0-9]{4,5};",$messaggio)) { $messaggio = str_replace("&amp;#","&#",$messaggio); }

Si tratta di una soluzione molto pedestre. Una soluzione più elegante e impegnativa potrebbe consistere in una tabella di conversione a cui far corrispondere ad ogni codifica numerica, la corrispondente codifica estesa del metacarattere HTML: Utilizziamo quindi la tabella in un array associativo attraverso la funzione PHP srttr() in questo modo:

if (ereg("&amp;#[0-9]{4,5};",$messaggio))
{ $tabella_di_conversione=array


    (
    "&amp;#8216;" => "&#8216;",
    "&amp;#8217;" => "&#8217;",
    "&amp;#8220;" => "&#8220;",
    "&amp;#8221;" => "&#8221;",
    . . . . .
    );

$messaggio = strtr($messaggio, $tabella_di_conversione);
}

Per un elenco dei metacaratteri HTML consiglio una visita a questa pagina:
//www.netstrider.com/tutorials/HTMLRef/ASCII/index.html.

Articolo scritto per Programmazione.it il 6 luglio 2002.

Riportato su www.webmasterpoint.org