lunedì 31 marzo 2008

Joomla 1.5: Inserire video YouTube in un articolo

Il titolo spiega già il problema. Abbiamo inserito un nostro video su YouTube (o trovato il video di qualcun altro che ci piace) e vogliamo includerlo in un articolo del nostro sito realizzato con Joomla.

Non è una cosa difficle da fare, ma esistono più modi per farla.

Inserire il codice direttamente nell'editor

YouTube fornisce il codice html necessario per includere un video in una pagina web (riquadro Informazioni su questo video, nella pagina da cui il video viene riprodotto, vedi figura)

Il codice si può inserire in un articolo utilizzando il pulsante html dell'editor WYSIWYG standard di Joomla che consente di lavorare sul codice html grezzo del contenuto che si sta scrivendo.

L'inserimento di codice html con l'editor di Joomla non è un'operazione che riesce sempre in quanto alcuni editor filtrano determinati tag o attributi quando il contenuto viene salvato. Per cui bisogna sempre controllare se il video si visualizza correttamente. In caso contrario conviene aprire il sorgente html della pagina e verificare che il codice inserito sia stato salvato correttamente.

Dalle impostazioni dell'editor è di solito possibile disabilitare questo filtro (cosa però pericolosa per la sicurezza del sito se si consente l'inserimento di articoli agli utenti non amministratori) o aggiungere i tag che ci servono alla lista di quelli consentiti.

È difficile fare una casistica precisa dato il numero di editor esistenti e le diverse versioni di Joomla, ma per quello che ho potuto verificare, l'inserimento manuale del codice fornito da YouTube con il metodo spiegato sopra funziona di sicuro con TinyMCE e Joomla 1.5.

Problemi di validazione

C'è però un problema. Se una volta inserito il codice provate a validare la pagina contenente il video con il W3C validator, con ogni probabilità otterrete una serie di errori di validazione. Infatti il codice fornito da YouTube non è valido XHTML Transitional che è il DocType comunemente usato nei template di Joomla.

Ora a molti questa cosa potrà non fare nè caldo nè freddo, ma come si sa, il mondo è pieno di gente strana, e ci sono anche quelli che alla validità del codice sui propri siti ci tengono.

Quindi che si fa?

QTube

Per evitare operazioni di copia e incolla e correzioni a mano del codice mi sono scritto un plugin che rende molto semplice inserire un video YouTube in un qualsiasi contenuto Joomla.

Il plugin, oltre a risolvere il problema della validazione del codice, ovvia anche agli inconvenienti dovuti ad eventuali filtri dei tag html impostati nell'editor, è semplice da utilizzare e consente le stesse opzioni di personalizzazione del codice che sono disponibili sul sito di YouTube.

Plugin con questo tipo di funzionalità ne esistono già e alcuni consentono di inserire video da fonti diverse da YouTube. Se però tutti i video che vi interessa includere nel vostro sito sono su YouTube, questa può essere una soluzione più 'leggera' rispetto a plugin molto più complessi.

Il plugin è scritto per Joomla 1.5 (e versioni successive) in modalità nativa, quindi non serve attivare Legacy Mode. La licenza è open source e questo è il link da cui potete scaricare il pacchetto di installazione: QTube.

Il sito come potrete vedere non è il solito: mi sembrava strano continuare a parlare di Joomla senza avere un sito personale realizzato con questo cms, per cui l'ho fatto, o meglio iniziato, in quanto l'unica cosa che ci trovate per ora è il plugin in questione. Altro è in cantiere, non solo relativo a Joomla, ma si avrà modo di parlarne.

Se trovate errori o problemi d'uso lasciate un commento.

mercoledì 19 marzo 2008

AJAX: Validazione di un form

Vediamo un esempio di come utilizzare AJAX e PHP per realizare una funzione di validazione di un modulo (form) per l'inserimento di dati. L'uso di AJAX ci darà la possibilità di presentare all'utente un messaggio di errore non appena il campo contenente un valore non valido viene abbandonato per passare al campo successivo.

In questo modo l'interazione dell'utente con il modulo è molto più diretta e semplice rispetto a quanto avverrebbe se la validazione dei campi avvenisse solo al momento della pressione del pulsante Invia.

Il modulo di esempio è semplicissimo: è uno 'scheletro' di modulo per la registrazione di un utente contenente solo i campi nome utente ed indirizzo email. Tutto qui.

Le regole di validazione sono:

  • Il nome utente non deve essere già presente nel database.
  • L'indirizzo email deve essere valido.
  • Non si può utilizzare lo stesso indirizzo email per più di una registrazione.

Il sorgente è scaricabile dal sito (Form-Ajax). Il contenuto del pacchetto zip è il seguente

db.sql - Script SQL per creare la tabella users usata nell'esempio.

dbconfig.php - Costanti per l'accesso al database: server, nome db, utente e password. Da modificare con i dati relativi al proprio server e database.

user.php - definizione della classe User che incapsula i dati dell'utente ed i metodi per la validazione e il salvataggio degli stessi nel database.

index.php - Contiene il codice HTML per la visualizzazione del form e le istruzioni per processare l'invio dei dati.

main.css Regole di stile applicate al modulo e ai campi.

validate.js - Javascript che crea l'oggetto XMLHttpRequest, invia la richiesta e processa il risultato.

validate.php - Script che riceve le richieste inviate tramite l'oggetto XMLHttpRequest e provvede alla validazione di un campo.

Funzionamento

Scrivo solo qualche nota generale senza commentare tutto il codice.

Come detto all'inizio quello che vogliamo ottenere è una validazione dei dati in tempo reale non appena il focus si sposta da un campo a quello successivo.

Partiamo dall'esame del codice HTML di un campo del modulo (in index.php)

<input id="user_id" name="user_id" type="text"
onblur="validate(this.id, this.value)" ... />

L'evento onblur, che si attiva quando il campo perde il focus, chiama la funzione Javascript validate() (in validate.js) passandole l'attributo ID e il valore del campo.

La funzione svolge questi compiti

1) Crea l'oggetto XMLHttpRequest. Il codice è lo stesso visto nell'articolo AJAX: Liste di Selezione Dinamiche e quindi valgono le considerazioni fatte a suo tempo.

2) Invia una richiesta allo script validate.php con metodo POST in questo modo

var data = "fldid=" + fldId + "&fldval=" +
encodeURIComponent(fldVal);

xmlHttp.open("POST", 'validate.php', true);
xmlHttp.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");

xmlHttp.onreadystatechange = stateChanged;
xmlHttp.send(data);
waiting = true;

waiting è una variabile globale usata come semaforo per impedire di inviare una nuova richiesta quando la precedente è ancora in esecuzione.

La risposta ricevuta dallo script validate.php è gestita dalla funzione stateChanged(). Il formato della risposta è

fldid;messaggio

fldid (anche a intuito) è il valore dell'attributo ID del campo che viene validato, messaggio esiste solo in caso di errore di validazione.

Separate le due componenti della stringa di risposta, si utilizza ID per accedere al tag <span> destinato alla visualizzazione degli errori che si trova sotto ogni tag <input> e vi si inserisce il messaggio. Tutto questo è svolto dal seguente codice

var resp = xmlHttp.responseText;
var p = resp.indexOf(';',0);
if(p > 0) {
 var fld = resp.substr(0,p);
 var msg = resp.substr(p+1);
 var cont = document.getElementById(fld + '_msg');
 if(msg) {
   cont.className= 'error';
 }
 cont.innerHTML = msg;
}

Su validate.php non c'è molto da dire. Crea un oggetto user (istanziando la classe in user.php) e lo inizializza con i dati letti da $_POST (ID e valore del campo da validare). Ricevuto il risultato della validazione, (metodo validate() di user) compone ed invia la stringa di risposta.

Anche per quanto riguarda la classe User (in user.php) lascio da parte ogni dettaglio. Il costruttore della classe riceve come argomento (in un array associativo chiavi / valori) il nome e i valori dei campi da validare (metodo validate()) e salvare nel database (metodo store()).

In caso di errori il relativo messaggio è memorizzato nella proprietà errors accessibile con il metodo getErrors().

Da notare che ci sono errori relativi a singoli campi ed errori in un certo senso globali (ad esempio la impossibilità di connettersi al database): i primi vengono visualizzati sotto al campo i secondi nella parte alta del modulo. Guardatevi setError() nella classe User per capire come questa informazione viene inserita nella proprietà errors.

Per finire diciamo due parole su quanto succede quando si preme Invia. Il controllo passa a index.php che compie di nuovo la validazione di tutti i campi (metodo validate(), oggetto user). Questo passo è necessario perché la validazione AJAX potrebbe essere facilmente scavalcata disabilitando Javascript nel browser.

Se la validazione va a buon fine i dati sono salvati nel database (metodo store(), oggetto user) altrimenti vengono visualizzati gli opportuni messaggi di errore.

<span class="error" id="user_id_msg">
<?php if(isset($errors['user_id'])){echo $errors['user_id'];}?>&nbsp;
</span>

Per installare e provare l'esempio

  • scaricate form-ajax.zip
  • scompattate l'archivio in una cartella del vostro sito web o localmente se usate Xampp, Wamp EasyPHP o simili
  • create un database MySql di prova
  • con PhpMyAdmin o strumento equivalente lanciate lo script db.sql per creare la tabella users
  • modificate dbconfig.php con i valori per accedere al vostro database
  • visitate index.php con il vostro browser
Se qualcosa non è chiaro o trovate qualcosa che non va nel codice lasciate un commento. Alla prossima.

domenica 2 marzo 2008

PHP: Proteggere un form da spam con codice captcha

Un form di contatti è un modo semplice per ricevere messaggi o altre informazioni dai visitatori del proprio sito.

Questo tipo di form può però diventare un facile bersaglio per programmi (spambot) creati per inviare messaggi indesiderati in maniera completamente automatica anche a centinaia di form contemporaneamente (o quasi).

Un modo per proteggersi è l'utilizzo di un codice di verifica captcha. Anche se credo che tutti sappiano di che si tratta visto che sono usati dovunque, due parole si possono spendere. Innanzi tutto captcha è un acronimo che sta per "Completely Automated Public Turing test to tell Computers and Humans Apart". Lasciando da parte la spiegazione su cosa sia il test di Turing (per chi non lo sa è ed è interessato a saperlo hanno inventato apposta i motori di ricerca) si può tradurre più o meno liberamente: test pubblico e completamente automatico per distinguere gli esseri umani dai computer.

La forma di test captcha più comunemente usata in un form consiste nella visualizzazione di una sequenza di caratteri ruotati o distorti e su uno sfondo non uniforme. L'esatta sequenza deve essere riportata in un campo apposito del form, altrimenti l'invio dei dati viene rifiutato. Il riconoscimento di caratteri in queste condizioni è relativamente facile per un essere umano mentre scrivere un programma in grado di fare la stessa cosa è molto più complesso anche se non impossibile, come dimostra il fatto che molti tipi di captcha sono state decifrate con software appositi.

Comunque anche se non è un metodo del tutto infallibile l'uso di un test captcha può bloccare la gran parte dei programmi spambot riducendo drasticamente la quantità di spam ricevuta attraverso un form di contatti.

Classe php per generare immagini captcha

Scrivere uno script php che generi immagini adatte ad un test captcha non è proprio una cosa banale, però esistono classi già pronte liberamente utilizzabili. L'esempio che vedremo è basato su PHP Captcha ( http://www.ejeliot.com/pages/2 ).

Il sito è in inglese per cui ho pensato tornasse utile a molti una breve spiegazione con sorgente di esempio.

Per prima cosa suggerisco di scaricare il pacchetto dal sito (PHP-Captcha), scompattarlo in una directory del vostro sito o web server locale ed aprire index.php nel vostro browser per eseguire il semplice script dimostrativo.

La libreria richiede che sul server siano installate le librerie grafiche GD con il supporto per i font TrueType. Se quando lanciate lo script di esempio non vedete l'immagine, la mancanza delle librerie grafiche è la causa più probabile del problema. Dovrebbe comunque essere una situazione abbastanza rara in quanto quasi tutti gli host le includono.

Il contenuto del pacchetto è il seguente

  • php-captcha.inc.php: libreria PHP Captcha
  • captcha.php script per la generazione dell'immagine captcha.
  • index.php esempio di form con codice di validazione.
  • fonts/ cartella con i fonts TrueType usati per la generazione dell'immagine.

File captcha.php

<?php
  require('php-captcha.inc.php');

Include il file con la definizione della classe.

$fonts = array('fonts/VeraBd.ttf', 'fonts/VeraIt.ttf',
'fonts/Vera.ttf');
$captcha = new PhpCaptcha($fonts, 120, 60);

Il costruttore riceve tre argomenti

  • array con i percorsi dei font da utilizzare per la generazione dei caratteri
  • larghezza dell'immagine in pixel
  • altezza dell'immagine in pixel
$captcha->setNumChars(4);

Specifichiamo che la captcha sia formata da 4 caratteri casuali. Se impostate un codice più lungo ricordatevi di aggiustare la larghezza dell'immagine, perché questo non avviene automaticamente. Altrimenti rischiate che uno o più caratteri siano 'tagliati' e di conseguenza risulti sempre impossibile inserire il codice corretto.

$captcha->SetNumLines(80);

Impostiamo il numero delle righe di disturbo che vengono visualizzate sullo sfondo del codice. Se si omette questa riga il valore predefinito è 70.

$captcha->UseColour(true);

Sia le lettere che le linee di disturbo sono a colori. Se si omette questa riga l'immagine sarà generata in toni di grigio.

//$captcha->DisplayShadow(true);

Visualizza un'ombreggiatura per i caratteri del codice. Questa opzione è commentata nel sorgente perché a mio parere rende i caratteri troppo difficili da leggere. Fate qualche prova con e senza questa opzione e decidete se essere o meno d'accordo con me.

$captcha->SetMinFontSize(13);
$captcha->SetMaxFontSize(19);

Impostiamo la dimensione minima e massima del font per i caratteri del codice. Anche in questo caso bisogna fare attenzione a non specificare una dimensione font troppo grande per la misura dell'immagine. Se si omettono queste righe i valori predefiniti sono rispettivamente 16 e 25.

$captcha->SetCharSet('A-Z,1-9');

Specifichiamo quali caratteri devono essere utilizzati per il codice. Nell'esempio il codice potrà essere formato da caratteri alfabetici maiuscoli e numeri da 1 a 9 (perché lo zero si confonde facilmente con la lettera O). Si possono specificare più sequenze di caratteri separate da virgola. Potreste voler sperimentare con altre impostazioni come ad esempio

  • $captcha->SetCharSet('A-Z,a-z') Tutti i caratteri alfabetici maiuscoli e minuscoli
  • $captcha->SetCharSet('0-9') Solo numeri

Se si omette questa opzione il valore predefinito è A-Z: il codice sarà formato solo da caratteri maiuscoli, niente numeri.

$captcha->Create();
?>

A questo punto l'immagine captcha può essere generata.

Ci sono alcune altre opzioni di configurazione, ma quelle viste sono più che sufficienti per personalizzarvi la captcha come desiderate.

Ne cito solo un'altra non utilizzata nell'esempio, ma che può tornare utile.

$captcha->SetBackgroundImages(array_immagini);

Si passa come argomento un array con i percorsi di diversi file immagine. Una di queste immagini sarà scelta a caso ed usata come sfondo per il codice captcha al posto delle righe casuali.

File index.php

In gran parte contiene codice html per la creazione del form per cui non lo commento tutto. Richiamo la vostra attenzione su un paio di punti importanti.

<?php require('php-captcha.inc.php');?>

La libreria deve essere inclusa in testa al file prima di ogni tag html e ogni altro output. Fate anche attenzione a non lasciare righe vuote prima del tag di apertura php altrimenti avrete un errore.

if($_SERVER['REQUEST_METHOD'] == 'POST') {
 if (!PhpCaptcha::Validate($_POST['captcha'])) {
   echo 'Codice captcha errato!<hr />';
 } else {
   ...
 }
}

Questa è la parte che controlla che il codice inserito corrisponda a quello visualizzato nell'immagine. Non c'è molto da dire perché fa tutto la classe.

<img style="border:1px solid" src="captcha.php" alt="captcha" /><br />
<input name="captcha" type="text" size="6" /><br />

Visualizza l'immagine captcha e il campo per l'inserimento del codice. Lo script che genera dinamicamente l'immagine (captcha.php, esaminato in dettaglio sopra) deve essere inserito come valore dell'attributo src del tag <img>.

È tutto.

Va detto che utilizzare un test captcha per proteggere un form è una decisione da prendere con attenzione. Non è una soluzione infallibile a tutti i problemi di spam e può creare problemi di accessibilità al vostro sito. Se decidete di seguire questa strada spero che il codice proposto (PHP-Captcha) possa esservi utile.