versione PDF - LinuxDidattica
Transcript
versione PDF - LinuxDidattica
Tecnologie Web Fulvio Ferroni [email protected] 2011.08.09 Copyright Fulvio Ferroni [email protected] Via Longarone, 6 - 31030 - Casier (TV) Le informazioni contenute in questa opera possono essere diffuse e riutilizzate in base alle condizioni poste dalla licenza GNU General Public License, come pubblicato dalla Free Software Foundation. In caso di modifica dell’opera e/o di riutilizzo parziale della stessa, secondo i termini della licenza, le annotazioni riferite a queste modifiche e i riferimenti all’origine di questa opera, devono risultare evidenti e apportate secondo modalità appropriate alle caratteristiche dell’opera stessa. In nessun caso è consentita la modifica di quanto, in modo evidente, esprime il pensiero, l’opinione o i sentimenti del suo autore. L’opera è priva di garanzie di qualunque tipo, come spiegato nella stessa licenza GNU General Public License. Queste condizioni e questo copyright si applicano all’opera nel suo complesso, salvo ove indicato espressamente in modo diverso. II Indice generale Premessa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . VIII L’autore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . VIII Parte i Nozioni preliminari sulla rete Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 La rete Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.1 Cenni storici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2 Protocolli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.3 Intranet e Extranet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.4 Il World Wide Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7 1.4.1 1.4.2 1.5 Ipertesti e ipermedia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Come funziona il Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Gli indirizzi delle risorse in Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.5.1 1.5.2 URL completi di percorso e nome di file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 URL con altri protocolli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 1.6 Collegarsi ad Internet da casa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Parte ii Il Web statico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2 Il linguaggio HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.1 Storia dell’HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.2 Contenuto di un file HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.3 Strumenti per la creazione di documenti HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.4 Uso dei validatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.5 Struttura di un documento HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.5.10 2.5.11 L’elemento ‘html’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 L’elemento ‘head’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 L’elemento ‘body’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Elementi di blocco e elementi di testo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Intestazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Paragrafi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 L’elemento ‘span’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Righello orizzontale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Centratura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Interruzione di linea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Grassetto, corsivo e sottolineato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.6 Nidificazione dei tag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.7 Insiemi di caratteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.7.1 2.7.2 2.7.3 2.8 Entità per caratteri speciali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Entità per caratteri riservati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Lo spazio unificatore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Altri elementi di uso frequente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 III 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.9 Commenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Uso dei colori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Elemento ‘font’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Elemento ‘address’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Elemento ‘div’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Elemento ‘pre’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Elementi ‘subscript’ e ‘superscript’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Elementi ‘emphasis’ e ‘strong’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Elenchi o liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.9.1 2.9.2 2.9.3 2.10 Collegamenti ipertestuali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 2.10.1 2.10.2 2.10.3 2.10.4 2.10.5 2.11 Collegamenti esterni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Collegamenti a etichette in un documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Usare i collegamenti insieme ad altri elementi . . . . . . . . . . . . . . . . . . . . . . . . . 42 Collegamenti interni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Collegamenti ad altre parti dello stesso documento . . . . . . . . . . . . . . . . . . . . 44 Immagini nei documenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.11.1 2.11.2 2.11.3 2.11.4 2.12 Liste numerate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Liste puntate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Liste a glossario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Inserimento di immagini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Posizionamento delle immagini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Dimensionamento delle immagini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Collegamenti con immagini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 L’attributo ‘title’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3 HTML: nozioni avanzate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.1 Informazioni supplementari nell’intestazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.1.1 3.1.2 3.1.3 3.2 Uso delle tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3 Uso dei riquadri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Riquadri in linea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Oggetti multimediali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 3.4.1 3.5 Esempi di tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Attributi dell’elemento ‘table’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Attributi del titolo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Attributi delle righe e delle celle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Creazione di celle vuote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Tabelle nidificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Riquadri e riquadri in linea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 3.3.1 3.3.2 3.4 L’elemento ‘meta’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 L’elemento ‘link’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Gli elementi ‘base’, ‘script’, ‘style’, ‘isindex’ . . . . . . . . . . . . . . . . . . . . 51 Attributi degli oggetti multimediali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Immagini mappate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 IV 4 I fogli di stile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.1 Caratteristiche dei fogli di stile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.2 Struttura delle regole di stile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.2.1 4.2.2 4.3 Definizione dei selettori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Dichiarazione di regole di stile per la formattazione . . . . . . . . . . . . . . . . . . . . . 74 Tipi di fogli di stile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 Fogli di stile in linea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Fogli di stile incorporati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Fogli di stile collegati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Organizzazione a cascata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Fogli di stile alternativi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 4.4 Posizionamento con i fogli di stile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 4.5 Fogli di stile per la stampa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 4.5.1 4.5.2 Parte iii Fogli di stile per media diversi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Impostazione di un foglio di stile per la stampa . . . . . . . . . . . . . . . . . . . . . . . . . 93 Il Web dinamico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 5 Introduzione al Web dinamico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6 Moduli e programmi CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 6.1 Creazione di moduli HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.2 Controlli dei moduli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 6.2.1 6.2.2 6.2.3 6.2.4 Elemento ‘input’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 L’elemento ‘select’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 L’elemento ‘textarea’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Raggruppamento e ordinamento dei controlli di un modulo . . . . . . . . . . . . . 106 6.3 L’attributo ‘accesskey’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 6.4 Prerequisiti per l’uso di CGI (cenni alla configurazione di ‘Apache’) . . . . . . . . . 107 6.4.1 6.4.2 6.4.3 6.5 Configurazione di ‘Apache’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Gestione dei «siti-utente» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Permessi su file e directory di un sito Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Approfondimenti sul protocollo HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 6.5.1 6.5.2 6.5.3 La richiesta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 La risposta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 Simulazione di una connessione HTTP da linea di comando . . . . . . . . . . . . 117 6.6 Creazione della pagina di risposta da parte del CGI . . . . . . . . . . . . . . . . . . . . . . . . . 118 6.7 Variabili di ambiente per i CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 6.8 Passaggio dei dati del modulo al programma CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 6.9 Decodifica dei dati di input del CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 6.9.1 6.9.2 6.10 Esempio di decodifica dati in Perl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Altri strumenti per la decodifica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Esempio completo di esecuzione di un CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 V 6.11 Considerazioni finali sui CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 7 Web, basi di dati e linguaggio PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 7.1 Architetture ‘three-tier’ e pattern ‘MVC’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 7.2 Strumenti necessari per la gestione di basi di dati via Web . . . . . . . . . . . . . . . . . . . 133 7.3 Basi di dati con MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 7.3.1 7.3.2 7.3.3 7.3.4 7.4 Attivazione del servente MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Dialogo con il servente MySQL con ‘mysql’ . . . . . . . . . . . . . . . . . . . . . . . . . 136 Comandi utili per usare MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Creazione di una tabella in MySQL per le prove . . . . . . . . . . . . . . . . . . . . . . . 139 Basi di dati con PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 7.4.1 7.4.2 7.4.3 7.4.4 Attivazione del servente PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Dialogo con il servente PostgreSQL con ‘psql’ . . . . . . . . . . . . . . . . . . . . . . . 142 Comandi utili per usare PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Creazione di una tabella in PostgreSQL per le prove . . . . . . . . . . . . . . . . . . . 145 7.5 Introduzione al linguaggio PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 7.6 Cenni alla sintassi del linguaggio PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 7.7 Validazione dell’input con PHP (cenno alle espressioni regolari) . . . . . . . . . . . . . . 153 7.8 Le sessioni in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 7.8.1 7.8.2 7.8.3 Il concetto di stato di un applicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Mantenere lo stato nelle applicazioni con PHP . . . . . . . . . . . . . . . . . . . . . . . . 157 Sessioni native in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 7.9 Pagine PHP che richiamano se stesse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 7.10 Gestione degli errori in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 7.11 Inclusione di codice e scrittura di funzioni in PHP . . . . . . . . . . . . . . . . . . . . . . . . . 168 7.12 La funzione ‘header()’ di PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 7.13 Gestione di basi di dati MySQL e PostgreSQL con PHP . . . . . . . . . . . . . . . . . . . . 171 8 Script attivi, DHTML, applet, servlet (cenni) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 8.1 JavaScript e Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 8.2 Script attivi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 8.2.1 8.2.2 Attributi di evento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Limiti di JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 8.3 DHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 8.4 Applet Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 8.4.1 8.4.2 8.5 Caratteristiche del linguaggio Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Creazione ed esecuzione delle applet Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Servlet Java e JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Parte iv Nuovi sviluppi del Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 9 Da HTML a XML (cenni) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 9.1 Limiti dell’HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 VI 9.2 Genesi e natura dell’XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 9.3 Documenti XML ben formati e validi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 9.4 Parser ed applicazioni XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 10 Programmazione distribuita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 11 Introduzione ai Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 11.1 Componenti dei Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 12 Web 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 12.1 Web 2.0: punto di vista «sociale» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .206 12.2 Web 2.0: punto di vista tecnologico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 12.3 Generalità su Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 12.4 L’oggetto XMLHttpRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 12.4.1 12.4.2 12.4.3 12.4.4 Chiamate di tipo get . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Chiamate di tipo post . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 Chiamate sincrone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 Esempio di gestione di un modulo con Ajax . . . . . . . . . . . . . . . . . . . . . . . . . 216 13 Bibliografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 13.1 Testi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 13.2 Siti Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 13.3 Altre fonti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 VII « Premessa Queste dispense sono scritte allo scopo di fornire una panoramica sugli strumenti utili alla creazione di applicazioni Web; sono basate sui precedenti lavori dello stesso autore, «Corso HTML» e (dalla versione 2010.08.31) «Creazione di pagine Web» e li sostituiscono completamente. Nella prima parte viene fatta una breve storia di Internet e del Web e vengono date le nozioni fondamentali per comprenderne il funzionamento. Si passano poi, nella seconda parte, ad esaminare gli strumenti per la creazione di pagine Web statiche: HTML e CSS. Riguardo invece alla terza parte sul Web dinamico, data la vastità del tema, vengono approfonditi solo i CGI e, in parte, l’uso del PHP e l’interfacciamento con le basi di dati; altri strumenti come JavaScript, le servlet Java, JSP, vengono esaminati in modo più superficiale. La quarta parte (da completare), infine, è dedicata ad un breve esame di XML e dei Web Services e agli ultimi sviluppi che hanno portato all’avvento del Web 2.0. Gli strumenti cui si fa riferimento nelle dispense sono quasi esclusivamente appartenenti alla categoria del software libero o Open Source; non vengono prese in esame tecnologie o piattaforme proprietarie. L’autore « Fulvio Ferroni via Longarone,6 31030 Casier (TV) [email protected] Laureato in matematica, insegnante di informatica dal 1992 dopo una precedente esperienza di sistemista presso la Unisys Italia. Usa GNU/Linux dal 1997 quando installò con successo una Slackware su un 386 usando 50 dischetti. F | ulvio Ferroni ... nel 1961, quando era ancora carino. VIII Parte i Nozioni preliminari sulla rete Internet « 1 2 3 Capitolo 1 La rete Internet « In questo capitolo vengono date alcune informazioni sulla genesi ed il funzionamento della rete Internet e del WWW (World Wide Web) (denominato più brevemente Web). 1.1 Cenni storici « Internet è una rete internazionale formata dall’interconnessione di molte migliaia di reti di computer. La sua storia inizia alla fine degli anni cinquanta e precisamente nel 1958 quando negli Stati Uniti viene creata, nell’ambito del Dipartimento della Difesa, un’agenzia di nome DARPA ( Defence Advanced Research Projects Agency). Il suo scopo fondamentale era quello di riacquisire il primato tecnologico nei confronti dell’Unione Sovietica che nel 1957 aveva lanciato il primo satellite artificiale della storia, lo Sputnik e qualche anno dopo inviato anche il primo uomo, Yuri Gagarin, in orbita. Siccome il programma spaziale venne poi assegnato alla NASA, DARPA si dedicò alla ricerca informatica di base. Stante il clima di ostilità esistente in quel periodo tra le due superpotenze, la cosiddetta «guerra fredda», DARPA doveva in particolare progettare un sistema di telecomunicazioni in grado di funzionare in caso di un attacco bellico particolarmente distruttivo, anche di tipo nucleare. I primi studi portarono alla definizione della rete ‘Arpanet’ cioè di quella che può essere considerata l’antenata di Internet: essa non aveva nessuna autorità centrale, i nodi che ne facevano parte erano autonomi ed in grado di operare in una situazione di forte instabilità in modo che la rete potesse sopportare anche la distruzione di uno o più dei nodi stessi. Il 30 agosto 1969 venne installato il primo nodo presso l’Università della California a Los Angeles dotata di un computer «Processore di messaggi di interfaccia Honeywell numero 1»; la sua attivazione avvenne il 2 settembre 1969 e questa può essere a tutti gli effetti considerata la «data di nascita» di Internet. Nel giro di 3 mesi i nodi divennero quattro: Stanford Research Institute, Università della California a Santa Barbara, Università dello Utah. Nel corso degli anni ’70 molte istituzioni collegarono le loro reti o i loro computer ad Arpanet e gli utenti iniziarono ad usare la rete principalmente per scambiarsi a distanza messaggi sotto forma di posta elettronica o per inviare e ricevere file contenenti dati o programmi. All’inizio degli anni ’80, la rete cominciò ad espandersi in modo massiccio e divenne a tutti gli effetti una «rete di reti» utilizzando ancora Arpanet come dorsale (rete ad alta velocità che unisce tra loro altre reti locali). Nel 1981 i computer collegati erano 213. Rimanevano però esclusi gli atenei e i centri di ricerca che non avevano rapporti con il Dipartimento della Difesa degli Stati Uniti. Per potere estendere l’accesso a tutti gli interessati fu necessario il disimpegno dei militari che nel 1983 crearono una loro rete (‘Milnet’) mentre Arpanet assunse il nome di ‘Internet’ e passò all’utilizzo del protocollo di rete TCP/IP (Transmission Control Protocol al posto del precedente NCP (Network Control Protocol). Nel 1985 si collegavano a Internet 100 reti diverse, divenute 500 nel 1989, saturando completamente la capacità della dorsale Arpanet. Fu a questo punto che la NSF (National Science Foundation), istituita dal governo degli Stati Uniti con lo scopo di favorire la crescita di sistemi di comunicazione tra le università, decise di creare la nuova dorsale ‘Nfsnet’ al fine di sostituire Arpanet che fu infatti definitivamente smantellata nel 1990. Adesso esistono molte altre dorsali affiancate a Nfsnet ed è quindi possibile il collegamento ad Internet di migliaia di reti (oltre 50.000 nel 1995) e milioni di singoli computer o ‘host’ (5 nel La rete Internet 4 1994, saliti a 110 nel 2000 e a 320 a fine 2004); tale collegamento può avvenire con vari mezzi trasmissivi come: cavi in fibra ottica, cavi coassiali, cavi telefonici, satelliti, onde radio. Nella tabella seguente viene mostrato il numero di utenti di Internet nel Mondo, negli USA e in Italia negli ultimi anni (i dati sono espressi in milioni): Anno 1995 1997 2000 2005 Mondo (% su ab.) 14 (0,4%) 90 (2%) 260 (4,5%) 900 (15%) USA (% su ab.) 10 (4%) 40 (15%) 105 (35%) 200 (68%) Italia (% su ab.) 0,45 (0,7%) 2,3 (4%) 10 (16%) 28 (49%) Come si vede da queste cifre in Italia il numero di utenti è stato a lungo molto basso rispetto al totale ma ultimamente sta crescendo con grande rapidità. Anche nel nostro paese Internet si sta affermando come fondamentale mezzo di comunicazione ed efficace strumento di lavoro nonché come sbocco commerciale di notevole importanza; molte aziende infatti stanno spostando del tutto o in parte la loro attività sulla rete dando impulso al cosiddetto «Commercio Elettronico». La caratteristica più interessante di Internet è che nessuno ne è «proprietario»; tutti gli enti che sono collegati alla rete ne gestiscono una parte e sono responsabili di una frazione dell’immensa mole di informazioni in essa contenute. In ultima analisi anche un utente finale (cioè chiunque di noi) che crea e pubblica delle pagine e le diffonde in rete diviene «comproprietario» di Internet. Siamo dunque in presenza di un mezzo di comunicazione moderno, in continua espansione, diffuso in tutto il Mondo e soprattutto libero. La differenza con le televisioni, i giornali, le case editrici, discografiche e cinematografiche è infatti evidente: esse sono sempre o quasi di proprietà di qualcuno che, volendo, può manipolarle a piacimento in modo da influenzare le opinioni, i gusti e le scelte degli «utenti» per i propri scopi più o meno leciti (ogni riferimento all’attuale situazione italiana è puramente «voluto»). Inoltre con tali mezzi difficilmente si riesce ad avere un ruolo attivo nel processo di comunicazione, come invece è spesso possibile in Internet. Grazie al computer e alle reti è nato dunque questo mezzo di comunicazione e di condivisione delle informazioni totalmente libero con ciò smentendo le paure di molte persone (espresse anche in tanti libri o film) che temevano che il calcolatore potesse divenire una sorta di «Grande Fratello» in grado di controllare e condizionare la vita di tutti i cittadini limitandone in modo inaccettabile la libertà. Almeno per ora queste macchine così bistrattate sono servite esattamente al contrario: sono infatti uno strumento di libertà di cui praticamente tutti possono usufruire (almeno nei paesi economicamente avanzati). Credo infine sia da sottolineare il fatto che Internet è uno strumento e come di tutti gli strumenti se ne può fare un uso buono o uno cattivo. Sono quindi profondamente sbagliate le campagne giornalistiche, per fortuna ora meno frequenti, che, basandosi sulla sostanziale ignoranza del fenomeno, sia da parte del grande pubblico sia, cosa molto più grave, da parte dei giornalisti che le conducono, tendono a criminalizzare Internet dipingendola come la fonte delle peggiori nefandezze ed arrivando ad affermare che darebbe addirittura assuefazione come la droga. Questo modo di dipingere la situazione non fa altro che favorire chi, a vari livelli, vorrebbe introdurre vincoli, controlli, limitazioni, censure, all’interno della rete e riguardo al suo utilizzo. La rete Internet 5 1.2 Protocolli « Il funzionamento di Internet è basato su tutta una serie di ‘protocolli’. Per protocollo si intendono la procedura e le regole da seguire nel trasmettere e ricevere dati su una rete, oppure su una linea di comunicazione, in modo che gli utenti possano usare macchine elettroniche per scambiare informazioni in modo ordinato, così da riprodurre fedelmente al punto di ricezione quello che è stato inviato dal punto di trasmissione. Il protocollo specifica il formato dei dati, la temporizzazione dei segnali, la sequenza d’invio e i sistemi per verificare la presenza di eventuali errori di trasmissione. Prima di parlare dei protocolli di Internet è opportuno introdurre un concetto molto importante su cui essi sono basati, quello della differenza tra ‘clienti’ e ‘serventi’. Un servente è un computer (con apposito software) che fornisce informazioni o servizi; un cliente è uno strumento o programma, di solito su un computer diverso, che usufruisce delle informazioni o dei servizi. La caratteristica fondamentale di tutti i protocolli di Internet è il loro essere gratuiti e «aperti» cioè in grado di funzionare con la quasi totalità delle reti fisiche e in maniera indipendente dall’hardware di un particolare produttore. Il protocollo più importante è senza dubbio il TCP/IP basato sulla tecnologia a «commutazione di pacchetto»: i dati da inviare vengono suddivisi nel nodo (computer) di partenza in diverse parti o ‘pacchetti’) il cui cammino attraverso la rete può seguire differenti percorsi; nel nodo di arrivo vengono poi ricomposti controllandone anche l’integrità. Un primo vantaggio di tale metodo consiste nel fatto che non è necessario né definire né conoscere il cammino da seguire; è compito di appositi dispositivi, i ‘router’, instradare i dati evitando le eventuali interruzioni e scegliendo, comunque, il percorso più veloce. Un altro vantaggio è che vengono sfruttati al meglio i canali trasmissivi che non sono mai interamente occupati da un’unica trasmissione come avviene ad esempio nelle comunicazioni telefoniche nelle quali la linea tra il chiamante ed il ricevente è occupata per tutta la durata della telefonata (in tal caso si parla di «commutazione di circuito»). Osserviamo la figura 1.2 e consideriamo che il computer A invii dati al computer B, senza che le due macchine siano collegate in modo diretto in quanto sono presenti altri nodi intermedi (i succitati router, qui indicati con dei cerchi) attraverso i quali vengono smistati i pacchetti; a tale scopo questi ultimi contengono al loro interno l’indirizzo del nodo di destinazione, oltre che di quello di origine. F | igura 1.2. La rete Internet 6 Se supponiamo che il messaggio inviato da A a B sia suddiviso in tre pacchetti possiamo ipotizzare i seguenti percorsi (fra quelli possibili): • pacchetto 1: A - R1 - R2 - R3 - R6 - R7 - B • pacchetto 2: A - R1 - R2 - R5 - R9 - R10 - R7 - B • pacchetto 3: A - R1 - R4 - R8 - R10 - R7 - B Approfondimenti sul protocollo TCP/IP e sulle reti di computer in generale esulano dagli scopi di questo corso, si consiglia la consultazione di testi specifici. Altri protocolli e servizi importanti in Internet sono: • TELNET per collegarsi a distanza ad un computer e SSH (Secure Shell) per farlo in modalità sicura; • SMTP (Simple Message Transfer Protocol) e POP3 (Post Office Protocol 3) rispettivamente per invio e ricezione della posta elettronica; • FTP (File Transfer Protocol) per lo scambio di file; • NNTP (Network News Transport Protocol) per la distribuzione di messaggi nei ‘newsgroup’ (bacheche elettroniche); • HTTP (HyperText Transfer Protocol) per il trasferimento di documenti ipertestuali («pagine Web»); 1.3 Intranet e Extranet « Una Intranet è una rete invariabilmente imperniata sul protocollo TCP/IP e che spesso utilizza ‘serventi Web’ (di cui parliamo in seguito) come punto di centralizzazione e pubblicazione delle informazioni. Viene realizzata entro i confini di una azienda o di una qualunque organizzazione ed è invisibile o solo parzialmente visibile dall’esterno o perché non è collegata con Internet o perché è collegata tramite un dispositivo firewall che ha il compito di proteggere i dati dalle intrusioni esterne non desiderate. Viene utilizzata come struttura per convogliare informazioni utili alle attività interne e per facilitarne l’uso da parte degli utenti. In una Intranet si usano infatti gli stessi strumenti di Internet, come ad esempio i programmi di navigazione grafici, molto «amichevoli» e facili da usare e i programmi per la gestione della posta elettronica. Una Extranet è invece l’opposto di Internet, nel senso che è ancora una rete geografica di ampia portata imperniata sul protocollo TCP/IP che però viene utilizzata unicamente per scopi privati e alla quale possono accedere solamente le persone autorizzate da una determinata azienda che ne è gestore oltre che proprietaria. Con essa si ha l’esportazione all’esterno dei confini aziendali delle informazioni che sono reperibili sulla Intranet aziendale. La Extranet comprende le aziende e le persone che si trovano all’esterno del firewall con le quali l’azienda desidera comunque mantenere uno scambio di informazioni. Un esempio tipico è quello di una grossa azienda che crea una Extranet con le aziende sue fornitrici e/o clienti. La rete Internet 7 1.4 Il World Wide Web « Il World Wide Web rappresenta uno spazio definito all’interno di Internet. Si usa la parola «spazio» perché è difficile descriverlo in altro modo. Infatti non si tratta di un oggetto fisico e nemmeno di un’entità riconducibile a confini geografici, bensì è un sistema di presentazione e soprattutto d’interconnessione tra le informazioni, concepito in modo da favorire il passaggio automatico da un documento all’altro e consentire la «navigazione» in un grande mare informativo, basandosi esclusivamente su ciò che appare sullo schermo del computer. Il World Wide Web fa parte di Internet ma comprende solo una parte delle risorse disponibili in essa, ecco perché lo definiamo come uno degli spazi contenuti all’interno del grande universo Internet. Il progetto del Web è nato nel 1991 presso i1 CERN (Consiglio Europeo per la Ricerca Nucleare) di Ginevra, quale sistema per semplificare lo scambio di informazioni tra ricercatori scientifici che già utilizzavano Internet per far circolare i loro articoli e pubblicazioni. Il metodo che veniva usato era infatti basato sul protocollo FTP e presupponeva la conoscenza esatta della dislocazione fisica delle informazioni da scaricare dalla rete . Era inoltre essenziale possedere i programmi adatti ad «aprire» i documenti scaricati che potevano essere scritti con gli strumenti più diversi. Infine non era previsto nessun meccanismo di collegamento automatico tra le varie informazioni, cosa invece possibile con gli ‘ipertesti’. Il 13 marzo del 1989, Tim Berners Lee, un ricercatore del CERN che può essere considerato il «padre» del Web, scrisse un documento dal titolo «Information Management: a Proposal" in cui si chiedeva di creare un sistema che rendesse più agevole la condivisione di informazioni, a livello mondiale, tra scienziati e ricercatori, risolvendo i tre problemi prima evidenziati. La proposta prevedeva tre componenti essenziali: • un’interfaccia utente comune per tutti (indipendente quindi dal tipo di computer utilizzato); • la capacità di incorporare nel sistema i tipi più diversi di documento e le tecnologie più varie; • l’accessibilità universale a tutte le informazioni contenute in questo ambito. Il nome stesso del progetto, «Ragnatela estesa quanto il Mondo», sottolinea l’interconnessione tra informazioni; in sostanza si trattava di trasformare l’enorme capacità informativa disponibile su Internet in qualcosa che chiunque potesse usare e consultare con facilità. Per questo fu necessario definire: • un nuovo linguaggio universale per la creazione di documenti con caratteristiche ipertestuali, il linguaggio HTML (HyperText Markup Language); • una notazione universale di localizzazione degli stessi, gli URL (Uniform Resource Locator) o URI (Uniform Resource Identifier); • un nuovo protocollo ottimizzato per il trasferimento di ipertesti, l’HTTP. L’architettura risultante è di tipo ‘cliente/servente’. Il Web infatti funziona grazie a dei computer, dotati di apposito software, chiamati Web server su cui sono depositati documenti il cui formato e sistema di visualizzazione è conforme alle specifiche definite dal CERN; gli utenti possono usufruire di queste informazioni grazie a dei programmi clienti chiamati browser o ‘navigatori’. La rete Internet 8 Le idee di Berners Lee furono considerate interessanti e meritevoli di approfondimento da parte del CERN; così nel giro di due anni, con il contributo del collega Robert Cailliau, si arrivò alla definizione delle basi del Web e fu attivato il primo servente su un computer NeXT. Fondamentale fu comunque la creazione dei primi strumenti utili alla fruizione delle informazioni: il primo browser che si chiamava ‘www’ e aveva una interfaccia a caratteri, iniziò a essere utilizzato su scala ridotta nel marzo del 1991. Un’altra tappa determinante fu l’installazione di WAIS (Wide Area Information Servers) per consentire dal Web la ricerca di documenti su scala mondiale usando come parole chiave i termini contenuti nel testo dei documenti stessi. Verso la fine del 1991, il CERN, annunciando l’esistenza del progetto a tutti gli scienziati impegnati nella ricerche sulla fisica nucleare per le alte energie, e rinunciando ad ogni diritto d’autore sul progetto stesso, diede il battesimo ufficiale al World Wide Web. Nel gennaio del 1993 erano operativi 50 serventi Web, alla fine dello stesso anno erano diventati 623. La progressione negli anni seguenti è stata impressionante: Periodo gennaio 1993 dicembre 1993 giugno 1994 dicembre 1994 giugno 1995 gennaio 1996 gennaio 1999 gennaio 2000 gennaio 2001 gennaio 2002 gennaio 2003 gennaio 2004 gennaio 2005 gennaio 2008 Numero di serventi Web 50 623 2.738 10.022 23.500 90.000 4.000.000 10.000.000 27.500.000 37.000.000 35.000.000 46.000.000 58.000.000 180.000.000 (1.500.000 Italiani) Un ruolo fondamentale in questa crescita è stato assunto dai browser grafici il primo dei quali si chiamava ‘Viola’ e funzionava su terminali X-Window cioè su terminali grafici collegati in rete locale ad a un minicomputer dotato del sistema operativo Unix. Nel 1993 l’NCSA ( National Center for Supercomputing Applications) diffuse la prima versione di ‘Mosaic’ per X-Window sviluppata da Marc Andreesen. Per molto tempo Mosaic è stato il principale browser per il Web ed il suo impiego si è esteso alle piattaforme più diverse, tra cui anche Windows; dal suo ceppo sono nati molti dei programmi di navigazione successivi. Nel 1994 nacquero le prime società di software specializzate nella produzione di prodotti per il Web e per Internet. Una delle più importanti fu la ‘Mosaic Communication Corporation’ fondata in California dallo stesso Marc Andreesen che alla fine del 1994 rilasciò un navigatore per Windows, Macintosh e X Window che si chiamava ‘Netscape Navigator’. Il prodotto divenne talmente popolare da trasferire il proprio nome anche all’azienda medesima, che divenne ‘Netscape Communications’. Nel luglio del 1994 il CERN iniziò a trasferire il progetto Web a un altro ente, il W3C ( World La rete Internet 9 Wide Web Consortium), al quale partecipano vari soggetti come il MIT (Massachusetts Institute of Technology) e, per l’Europa, l’INRIA (Institut National de Recherche en Informatique et en Automatique - Istituto nazionale della ricerca sull’informatica e sull’automazione). Tale ente, libero e senza fini di lucro, è attualmente impegnato in attività finalizzate all’evoluzione delle tecnologie e nella definizione degli standard del Web ed è presieduto da Tim Berners Lee. Nel frattempo ‘Microsoft’, che in un primo momento aveva sottovalutato l’importanza commerciale di Internet, lanciò sul mercato il proprio browser ‘Internet Explorer’, scatenando quella che fu denominata «guerra dei browser» contro il programma della Netscape. La battaglia venne vinta nettamente e velocemente da Internet Explorer grazie al fatto che, a partire da Windows 98, il programma di navigazione veniva incorporato nel sistema operativo. Questo avvenne malgrado il programma concorrente non fosse inferiore dal punto di vista tecnologico e anzi avesse il vantaggio di essere multi-piattaforma (era disponibile per macchine Unix o GNU/Linux). Netscape Navigator, che nel 1997 era il navigatore nettamente più diffuso, nel 2000 era ridotto ad un ruolo del tutto marginale; inoltre l’azienda Netscape non esisteva più essendo stata acquistata nel 1998 da AOL (American On Line) (a sua volta assorbita nel 2000 in ‘Time Warner’). Per fortuna nel 1998, con una mossa che fece scalpore, Netscape non solo aveva reso gratuito il suo programma (scelta ormai obbligata dato che il programma concorrente era gratuito) ma aveva anche deciso di rilasciare il codice sorgente. Questo permise la nascita del progetto ‘Mozilla’, interamente Open Source, dell’omonimo browser e di tanti altri basati sullo stesso motore di rendering denominato ‘Gecko’: ‘Epiphany, Galeon, Firefox, Netscape’ (rinato a nuova vita grazie al codice del progetto Mozilla). Questi oggi sono i programmi di navigazione di riferimento fuori dalla piattaforma Microsoft (in GNU/Linux soprattutto) e, grazie alle loro ottime qualità, si stanno ritagliando uno spazio significativo anche fra gli utenti Windows (come nel caso dell’ottimo ‘Firefox’ utilizzato, nel 2008, da circa il 20% dei «navigatori»). In queste dispense non vengono approfonditi i temi relativi al software libero, all’open source, a GNU/Linux per i quali si rimanda alla vastissima documentazione presente in rete; ciò non toglie che l’autore privilegi nettamente l’uso di tali strumenti come evidenziato in seguito, ad esempio nel paragrafo sul Web e le basi di dati (paragrafo 7). 1.4.1 Ipertesti e ipermedia « La proposta originariamente avanzata da Tim Berners Lee descriveva in dettaglio l’utilità di avere un sistema che fosse facile da consultare su qualsiasi tipo di computer o terminale, nel quale fosse possibile eseguire ricerche e che creasse una connessione il più fitta possibile tra documenti pubblici e privati, al fine di facilitare e incoraggiare la navigazione tra questi ultimi. L’attuale struttura del Web rispecchia queste specifiche iniziali ed è basata su tre componenti essenziali: • la rete Internet; • gli ipertesti; • la multimedialità Con il termine «multimedialità» si intende l’uso di una pluralità di mezzi di comunicazione (media) per la trasmissione di messaggi e informazioni; i più importanti tra tali mezzi sono: testo scritto, suoni, immagini, filmati. La rete Internet 10 L’efficacia della trasmissione di un messaggio è notoriamente legata alla ridondanza dei mezzi elementari con cui essa è effettuata. Pensiamo ad esempio alla narrazione, nella Bibbia, della consegna dei comandamenti a Mosè in mezzo a bufere, lampi, tuoni e forti sensazioni fisiche, oppure alla differenza che corre tra leggere il testo di una commedia o vederla rappresentata, o ancora alla molteplicità di stimoli con cui vengono bombardati i giovani di oggi nelle discoteche. Recenti studi dimostrano che nella mente umana il ricordo di una comunicazione persiste tanto più quanto maggiore è il numero dei mezzi impiegati per trasmetterla e tale persistenza è massima se c’è interazione tra le parti coinvolte nella comunicazione, come emerge dalla figura 1.4. F | igura 1.4. Dal punto di vista informatico la multimedialità consiste in un insieme di tecnologie, basate su un personal computer, con le quali vengono combinati testo, immagini, suoni, filmati, per formare un unico messaggio ricco di informazioni ed efficace dal punto di vista della comunicazione. Più precisamente può essere chiamato «sistema interattivo multimediale» un sistema di elaborazione in grado di utilizzare contemporaneamente almeno tre dei seguenti media: testo, grafici, animazioni grafiche, segnali audio, suoni musicali, voce, immagini, filmati. La tecnologia oggi disponibile è comunque già in grado di assicurare l’integrazione di tutti questi mezzi su una stessa macchina; tutti i personal computer sul mercato sono infatti equipaggiati con scheda audio, casse acustiche, scheda video in grado di gestire filmati, microfono, lettore di DVD-ROM. Fra le applicazioni multimediali meritano un’attenzione particolare gli «Ipermedia» che sono estensioni degli «Ipertesti». Gli ‘Ipertesti’ nascono da un’idea di Ted Nelson che nel 1965 ipotizzò un sistema software in grado di memorizzare articoli, annotazioni, relazioni ed altre informazioni testuali nel quale l’utente poteva navigare liberamente. Alla base dell’idea di Nelson c’era l’osservazione che l’uomo parla in modo sequenziale perché è dotato di un solo tratto vocale, legge e scrive sequenzialmente perché in tal modo sono organizzati i testi, ma ha una capacità di pensiero molto più sofisticata. Infatti la nostra mente opera spesso per associazione di idee ed è in grado di costruire una vera e propria «rete» di conoscenze molto complessa in cui molti elementi sono in relazione non lineare tra loro. Gran parte dei sistemi informatici forniscono strumenti, anche sofisticati, in grado di gestire e manipolare dati ed informazioni in modo solo sequenziale e senza alcuna visione integrata. Gli La rete Internet 11 ipertesti invece permettono di stabilire collegamenti e rimandi all’interno dei documenti o fra documenti diversi creando una organizzazione non lineare del testo che non può essere resa su una singola pagina; si aggiunge in pratica una «terza dimensione» al testo in modo da «entrare dentro» di esso. Pensiamo ad esempio di avere un testo riguardante Foscolo e leggiamo che in un certo periodo della sua vita egli fu ammiratore di Napoleone; se vogliamo maggiori informazioni su quest’ultimo dobbiamo cambiare testo e passare ad uno che lo riguardi. Con un ipertesto invece si può passare con un semplice comando (un «click» del mouse sul nome Napoleone) alle informazioni che ci interessano. Inoltre possiamo continuare la nostra «navigazione» nel documento in modo molto libero sfruttando i collegamenti in esso presenti ed arrivando ad esempio alla Napoli dei primi anni dell’800 passando per Gioacchino Murat, cognato di Napoleone, che fu re nella città in quel periodo. Tecnicamente gli ipertesti si basano su grafi (reti) di nodi (concetti, idee, documenti) tra loro collegati e vengono creati con appositi programmi e con tecniche di cui comunque l’utilizzatore non deve preoccuparsi. I collegamenti tra i vari documenti avvengono grazie a dei ‘riferimenti’. Il riferimento (detto ‘iperlink’ o ‘collegamento ipertestuale’) deve essere evidenziato in qualche modo rispetto al resto del testo, ad esempio con un colore diverso o con la sottolineatura. Si parla poi di «Ipermedia» quando in un ipertesto vengono integrati suoni, immagini, filmati ed altro ancora. Nell’esempio precedente si potrebbe pensare di avere a disposizione, nello stesso documento, anche l’immagine digitalizzata di un quadro raffigurante Napoleone oppure un paesaggio della Napoli di inizio ’800 o, ancora, l’attacco della Terza Sinfonia di Beethoven che era stata inizialmente dedicata al Bonaparte. 1.4.2 Come funziona il Web « Come abbiamo visto gli ipertesti e la multimedialità (e quindi gli ipermedia) sono componenti essenziali del Web che, non a caso, viene anche definito «iperspazio». In essi l’elemento fondamentale è l’iperlink attraverso il quale si può passare ad un’altra sezione dello stesso documento, ad un altro documento che può trovarsi sul nostro computer, sul servente a cui siamo collegati o addirittura su un altro servente situato in qualunque parte del mondo purché collegato ad Internet. Se il sistema ipertestuale è ben fatto il documento a cui ci si collega contiene un link a quello di provenienza così che sia sempre possibile ritornare sui propri passi. Siccome questo non sempre avviene, i browser sono in grado di tenere traccia del percorso e permettono in qualsiasi momento di muoversi a ritroso (tasto [ Indietro ]). L’elemento cardine per il funzionamento del Web è il protocollo HTTP che è basato sul modello cliente/ servente e si appoggia sul TCP/IP. Si tratta di un protocollo per lo scambio di documenti ipertestuali molto semplice che regola l’interazione tra il nostro navigatore e il servente con cui quest’ultimo di volta in volta si connette a seguito di una nostra richiesta diretta oppure seguendo un collegamento ipertestuale. Il dialogo tra queste due entità si svolge in quattro fasi: • connessione; • richiesta documento; La rete Internet 12 • risposta; • disconnessione. Le prime tre fasi sono di solito segnalate nella finestra del browser con scritte che ci spiegano cosa sta succedendo. Nella richiesta il programma di navigazione deve specificare al servente quale protocollo deve essere utilizzato (HTTP oppure FTP o altro ancora) in quanto lo stesso browser può essere utilizzato per collegarsi anche con serventi che non fanno parte del Web e che offrono servizi Internet più tradizionali, come appunto lo scaricamento di file attraverso il protocollo FTP. Dopo che la pagina è giunta sulla nostra macchina la connessione col servente s’interrompe e viene ripresa quando si chiede di passare a una seconda pagina sul medesimo o su un altro servente. Questo talvolta vale anche per il percorso a ritroso, dove si chiede di visualizzare una seconda volta una pagina che avevamo già visto. L’eventuale presenza di grafica rende il procedimento abbastanza lento poiché i file corrispondenti agli elementi grafici (spesso molto voluminosi in termini di occupazione di memoria) devono essere scaricati autonomamente rispetto alla pagina in cui sono contenuti. Una soluzione pratica per eliminare questo inconveniente consiste nel creare una cache o memoria di transito sul disco della nostra macchina oppure sul servente che fa da ‘proxy’, cioè da porta di accesso verso Internet, nella nostra rete privata. Così, ogni volta che chiediamo una pagina già vista, questa viene caricata dal disco locale oppure dal disco del servente locale anziché essere ritrasferita da Internet. Un sistema per non dover scaricare continuamente la stessa pagina consiste nel salvarla sulla propria macchina come file autonomo e nel richiamarla dall’interno del browser come si richiamerebbe un qualsiasi documento dall’interno di un word processor (tra l’altro, alcuni programmi di elaborazione dei testi permettono di visualizzare e modificare queste pagine scaricate in locale senza dover ricorrere a programmi di navigazione specializzati). Maggiori dettagli sul funzionamento del protocollo HTTP vengono forniti nell’ambito del capitolo riguardante il Web dinamico (paragrafo 6.5). 1.5 Gli indirizzi delle risorse in Internet « Abbiamo visto come, con il protocollo HTTP, si possa accedere alle informazioni presenti in Internet; questo però è possibile solo se si conosce l’‘indirizzo’ della risorsa (pagina Web o altro) a cui si vuole fare riferimento e cioè il suo ‘URL’ o ‘URI’. Ogni URL della rete identifica una certa risorsa e non possono esistere due risorse diverse con stesso indirizzo. Spesso si dice anche che un URL identifica un ‘sito Internet’ dove con il termine ‘sito’ si intende la sezione del disco di un particolare computer nella quale risiedono dei documenti Web; il significato viene però solitamente esteso fino a comprendere anche la macchina nel suo complesso e l’organizzazione che la usa per pubblicare le proprie informazioni in Internet. Un URL è una stringa che inizia con il nome del protocollo da utilizzare per reperire la risorsa (esempio ‘http://’). Per illustrare correttamente la sua struttura occorre però fare prima riferimento al modo in cui i computer sono identificati in Internet (o in qualsiasi rete basata su protocollo TCP/IP): ogni computer è individuato univocamente da un ‘indirizzo IP’ o ‘ IP-address’ che nella versione La rete Internet 13 IP V 4 (Internet Protocol version 4) è composto da quattro ottetti di bit (cioè da quattro gruppi di 8 cifre binarie). Ad esempio il servente Web del Ministero della Pubblica Istruzione è su un computer che ha indirizzo «11000001.11001110.00001111.11001001». Come si vede l’IP-address è espresso con quattro numeri binari (separati da un punto); ciò si giustifica in quanto sappiamo benissimo che il linguaggio dei computer è il sistema binario costituito dai soli simboli 0 e 1. Per comodità però gli indirizzi IP vengono sempre indicati «tradotti» in decimale e così il precedente diventa «193.206.15.201». Gli indirizzi IP sono suddivisi in classi e ne esistono alcuni che sono riservati per usi speciali (ad esempio quelli che iniziano con 10 oppure da 172.16 a 172.31, o con 192.168 e che sono usati per le reti private). L’argomento dell’indirizzamento IP richiederebbe comunque una trattazione ben più ampia di questi brevi cenni ma questo va al di là degli scopi di queste dispense. Per maggiore completezza si deve aggiungere che, per usufruire di un certo servizio in Internet, l’indirizzo della macchina che lo fornisce è solo una parte dell’informazione che il cliente deve conoscere; è infatti necessario indicare anche la «porta», cioè un numero intero compreso tra 0 e 65.535 che identifica il programma attivo sul servente e adibito a fornire quel servizio. Il dialogo in rete tra cliente e servente avviene infatti grazie alla creazione di una coppia di socket, uno per ognuna dei due nodi di rete coinvolti, costituiti dall’indirizzo IP e dalla porta da essi utilizzati. La sintassi con cui si indicano i socket è: «IP:Porta», ad esempio 193.206.15.201:80. Nell’ambito del TCP/IP esistono una serie di porte dette «porte ben note» (quelle comprese tra 0 e 1.023) che sono associate ai servizi di rete più diffusi e importanti; ad esempio: porta 20 e 21 per FTP, 22 per SSH, 23 per TELNET, 25 per SMTP, 80 per HTTP, 110 per POP3. Si noti che la conoscenza della porta utilizzata da un certo servizio è importante solo relativamente al servente in quanto solitamente il socket del cliente viene creato (dal programma cliente) prendendo il proprio indirizzo IP e un numero di porta scelto casualmente e maggiore di 10.000. Quindi se consideriamo ad esempio una connessione HTTP tra i due nodi 193.206.15.201 (servente) e 88.82.114.44, i socket coinvolti possono essere: 193.206.15.201:80 e 88.82.114.44:15543. Il fatto che il servente offra il servizio sulla porta 80 non è scontato, ma, siccome tale porta è quella convenzionalmente associata al servizio HTTP, praticamente tutti i serventi Web sono configurati per rispondere alle richieste indirizzate su di essa. Per lo stesso motivo non è necessario, quando si naviga con un browser, indicare, oltre l’indirizzo del servente, anche la porta cui collegarsi in quanto viene impostata automaticamente a 80 dal programma di navigazione. I socket di rete e la loro programmazione richiederebbero approfondimenti che esulano dagli obiettivi di queste dispense; chi fosse interessato può consultare il documento, dello stesso autore, «Programmazione dei socket di rete in GNU/Linux» reperibile all’indirizzo hhttp:// www.linuxdidattica.org/docs/altre_scuole/planck/ i. L’assegnazione degli indirizzi di rete (e delle porte ben note) viene curata da una organizzazione senza fini di lucro, l’ICANN (Internet Corporation for Assigned Names and Numbers, 14 La rete Internet www.icann.org), la quale a sua volta delega ad enti nazionali la gestione degli indirizzi di rete nei vari paesi. In Italia tale gestione è stata curata fino al 1998 dal GARR (Gruppo Armonizzazione delle Reti di Ricerca) e adesso dalla RA (Registration Authority) italiana, che fa capo al CNR (Consiglio Nazionale delle Ricerche), in base alle indicazioni fornite dalla ‘Naming Authority’ italiana (che opera in stretto rapporto con il Ministero delle poste e delle telecomunicazioni). Maggiori dettagli sull’assegnazione degli indirizzi IP si possono trovare all’indirizzo hhttp://www.nic.it i. Un difetto del complesso, ma efficiente, metodo di indirizzamento degli host di Internet è che gli indirizzi sono limitati e con gli attuali ritmi di crescita della rete si corre seriamente il rischio di esaurire entro poco tempo tutti gli indirizzi disponibili. Per questa ragione è stata sviluppata recentemente una versione evoluta del protocollo IP, denominata ‘IP Next Generation’ o IP V 6 (Internet Protocol version 6), basata su un sistema di indirizzamento a 128 bit che assicurerà un massiccio incremento nella disponibilità di indirizzi di rete. L’indirizzo numerico comunque non è utilizzabile comodamente e non è facile da ricordare; molto meglio poter individuare i vari computer con un nome. Questo è possibile grazie all’introduzione nella rete del DNS (Domain Name Service). Il DNS è il meccanismo con cui si riesce a indirizzare le risorse su Internet utilizzando una notazione mnemonica, allettante anche dal punto di vista commerciale, garantendo al tempo stesso una individuazione univoca della risorsa sulla rete. Attraverso il DNS ogni host di Internet può essere dotato di un nome composto da stringhe di caratteri. Tali stringhe, a differenza che nell’indirizzo numerico, possono essere di lunghezza illimitata. L’indirizzo del servente del Ministero della Pubblica Istruzione diviene www.istruzione.it che è senz’altro più comodo da utilizzare e da ricordare. quindi Come si può vedere, anche i nomi mnemonici sono sequenze di simboli separati da punti e questo rispecchia la struttura gerarchica del DNS. Esso infatti suddivide l’intera rete in settori, denominati ‘domini’, a loro volta divisi in ‘sottodomini’, e così via per vari livelli; ogni sottodominio fa parte del dominio gerarchicamente superiore: all’ultimo livello della gerarchia ci sono i singoli computer. L’identificativo di un host riassume le varie gerarchie di domini a cui appartiene; illustriamo il concetto servendoci di un altro esempio di nome mnemonico: www.progaut.itis.biella.it; in realtà il nome del computer è solo ‘www’, il resto della stringa serve ad indicare chi ha la responsabilità di tale computer e del suo nome. Scorrendo la stringa da destra a sinistra troviamo ‘it’ che è il ‘dominio di primo livello’ e sta ad indicare che il computer si trova in una gerarchia facente capo ad una autorità nazionale italiana (‘it’ per Italy). Successivamente abbiamo ‘biella’ che è un ‘sottodominio di primo livello’ e indica che l’autorità facente capo alla città di Biella ha ricevuto il permesso da quella immediatamente superiore (in questo da quella del dominio ‘it’) di poter a sua volta concedere sottodomini ad altre autorità sottostanti o nomi ai propri computer. Continuando troviamo ‘itis’ che è un ‘sottodominio di secondo livello’ che viene gestito da una autorità per questo delegata da quella di livello superiore (in questo caso ‘biella’). Ancora più a sinistra troviamo ‘prog-aut’ che è un ‘sottodominio di terzo livello’ gestito da una autorità gerarchicamente sottostante a quella che gestisce il sottodominio ‘itis’. La rete Internet 15 Questa autorità ha deciso di chiamare ‘www’ il computer che contiene la pagina iniziale (e presumibilmente anche le altre pagine) del sito in questione. Naturalmente non tutti gli identificativi sono così articolati; ad esempio in www.linux.it, abbiamo solo il sottodominio di primo livello ‘linux’, e l’autorità che lo gestisce ha deciso di chiamare ‘www’ il computer che ospita la home page del sito. Il numero e le sigle dei domini di primo livello, o ‘domini principali’, sono fissati a livello internazionale e vengono gestiti da appositi organismi. Nell’ambito di ognuno di tali domini possono essere creati un numero qualsiasi di sottodomini rispettando però le regole stabilite da ogni autorità nazionale di gestione del DNS. Quando il DNS è stato sviluppato, Internet era diffusa, salvo rare eccezioni, solo negli Stati Uniti e la rete venne suddivisa in sei domini principali o G T LD (general Top level domain), tuttora esistenti, le cui sigle caratterizzano il tipo di ente o organizzazione che possiede un certo sito: • ‘com’ per le organizzazioni commerciali; • ‘edu’ per gli enti di ricerca e università; • ‘gov’ per gli enti governativi; • ‘int’ per le organizzazioni sorte a seguito di trattati internazionali; • ‘mil’ per gli enti militari; • ‘net’ per gli enti di gestione della rete; • ‘org’ per gli enti diversi (volontariato, associazioni senza fini di lucro). Quando la rete ha cominciato a diffondersi a livello internazionale sono stati creati altri domini, chiamati regionali o CC T LD (country code Tld), uno per ogni nazione, ad esempio: • ‘it’ per l’Italia • ‘uk’ per l’Inghilterra • ‘fr’ per la Francia • ‘de’ per la Germania Talvolta anche negli Stati Uniti si usano suffissi geografici. A partire dal 2000 l’ICANN ha aumentato il numero dei gTld introducendo anche: • ‘aero’ aeronautica; • ‘biz’ affari; • ‘coop’ cooperative; • ‘info’ informazione; • ‘jobs’ risorse umane; • ‘museum’ musei; • ‘name’ pagine personali; • ‘pro’ professionisti; La rete Internet 16 • ‘travel’ società di viaggi. Vediamo altri esempi di URL completi: http://www.tin.it è l’indirizzo del sito della Telecom Italia Net; http://www.deejay.it è l’indirizzo del sito di Radio Deejay; http://www.cambridge.edu è l’indirizzo del sito dell’università di Cambridge negli USA; http://www.fbi.gov è l’indirizzo del sito dell’FBI; http://www.ci.berkeley.ca.us è l’indirizzo della rete civica della città di Berkeley in California. Dal punto di vista tecnico il DNS è costituito da un sistema di archivi distribuiti nella rete e collegati tra loro chiamati ‘name server’. Essi svolgono la funzione di tradurre i nomi in indirizzi numerici (tecnicamente si parla di «risoluzione dei nomi») per conto degli host o di altri ‘name server’. Infatti la comunicazione effettiva tra i computer della rete avviene sempre e solo attraverso gli indirizzi IP numerici. Quando un computer deve collegarsi ad un altro, con nome ad esempio www.linux.it, esso interroga il proprio ‘name server’ locale per risolvere il nome in questione (è per questo che quando ci abboniamo con un fornitore di servizio, o «provider» per navigare in Internet, fra i parametri che ci vengono forniti per impostare il browser c’è anche l’indirizzo IP di un servente DNS). Nel caso il ‘name server’ non sia in grado di risolvere il nome richiesto, chiede «aiuto» ad un altro servente, detto ‘‘name server’ di primo livello’ la cui scelta è determinata dal dominio principale dell’indirizzo in questione. Questo servente, a sua volta, può non essere in grado di rispondere e ricorre quindi ad altri ‘name server’ (di livello inferiore). Il procedimento continua fino al reperimento dell’indirizzo del computer cercato, se esiste. Nello svolgere questo compito il ‘name server’ memorizza gli indirizzi che ha conosciuto in modo da rispondere più velocemente a successive richieste. Grazie a questo meccanismo il DNS è sempre aggiornato in modo automatico e non è necessaria alcuna autorità centrale che memorizzi nomi ed indirizzi dei milioni di computer collegati ad Internet. Come avviene per gli indirizzi IP, la gestione del DNS in un dominio di primo livello viene affidata a degli enti specifici. Questi enti hanno il compito di assegnare i nomi di sottodominio, controllando che non ci siano omonimie, e di gestire l’archivio principale del dominio di cui sono responsabili. In Italia l’ente che si occupa dell’assegnazione dei nomi di dominio e della gestione dei registri e del ‘name server’ primario per il ccTld ‘it’ è ancora la Registration authority sotto il controllo della Naming Authority che ne stabilisce procedure operative e regolamento. Negli Stati Uniti la gestione dei nomi è affidata a delle compagnie private sotto il controllo della già citata ICANN. La rete Internet 17 I servizi forniti dalla RA sono rivolti ai provider, cioè a quelle organizzazioni che registrano domini per conto terzi (ad esempio http://www.register.it o http://www.cyb.it) e ai «mantainer», cioè a quelle persone o organizzazioni che gestiscono autonomamente il proprio sito senza rivolgersi ad un provider esterno. Per concludere notiamo che, quando navighiamo, possiamo tralasciare la scrittura del protocollo prima dell’URL (oltre che, come notato in precedenza, quella della porta dopo di esso) in quanto viene assegnato automaticamente dal programma come ‘http://’; inoltre nessuno vieta l’uso di indirizzi numerici per fare riferimento ad un certo sito anche se è molto più difficile ricordarli; ad esempio per collegarsi al sito di Radio Deejay si potrebbe anche digitare l’URL: http:// 213.92.17.218. 1.5.1 URL completi di percorso e nome di file « Gli esempi visti sinora si riferiscono sempre all’indirizzo della home page dei siti considerati; se si vuole visualizzare una pagina particolare, contenuta in una certa directory del servente, dovremo aggiungere all’URL il percorso completo delle directory ed il nome del file che contiene la pagina desiderata. Ad esempio: http://www.linux.it/GNU/articoli/index.shtml fa riferimento alla pagina contenuta nel file ‘index.shtml’ nella directory ‘/GNU/articoli/’ del sito www.linux.it. Si noti come nell’indicazione del percorso si usa il simbolo «/» per indicare le sottodirectory, anziché il simbolo «\» come si fa, ad esempio, in ambiente Windows. L’importante comunque è conoscere l’URL della pagina iniziale di un sito in quanto da essa, seguendo i vari collegamenti, sarà possibile rintracciare le altre pagine che fanno parte del sito stesso. A questo proposito è importante notare che non è quasi mai necessario conoscere il nome esatto di tale pagina in quanto è quasi sempre «index.html», o «default.html», o simile e i serventi Web sono predisposti per cercare automaticamente pagine con questi nomi. Ad esempio se digitiamo l’indirizzo www.linuxdidattica.org oppure www.linuxdidattica.org/index.html otteniamo in risposta lo stesso documento. 1.5.2 URL con altri protocolli « Gli URL permettono di individuare risorse Internet generiche e non solo siti Web come negli esempi visti sinora; è infatti possibile inserire altri protocolli al posto di ‘http://’ come ad esempio ‘ftp://’. Questo è il protocollo usato per il trasferimento di file da un computer ad un altro. Di solito i siti FTP si trovano su macchine che si chiamano ftp (e non www) e allora i loro URL saranno simili a ftp://ftp.unipd.it che è il sito ftp dell’Università di Padova. Altri protocolli come ‘gopher://’, ‘mailto:’, ‘news:’ sono molto meno usati. Importante è invece la stringa ‘file://’ (usata al posto del protocollo anche se non è un protocollo). Con essa si fa riferimento a dei file contenuti sul computer locale, cioè quello che stiamo usando per navigare in Internet. Ad esempio l’URL file://esempi/indice.htm fa riferimento alla pagina contenuta nel file ‘indice.htm’, che è nella directory ‘esempi’ del nostro computer. 18 La rete Internet 1.6 Collegarsi ad Internet da casa « Per collegarsi a Internet sono necessari (oltre naturalmente ad un computer) un modem o adattatore ed un abbonamento ad un ISP (Internet Service Provider ). Un ISP è una azienda che fornisce a pagamento o, per i collegamenti più lenti, anche gratis, la possibilità di collegarsi alla rete, di avere una o più caselle di posta elettronica e, talvolta, anche un po’ di spazio sul proprio servente per pubblicare pagine in Internet. In Italia possiamo citare tra i provider più noti TIN (Telecom Italia Net ), Libero, Tiscali. Si deve inoltre avere il protocollo TCP/IP sul proprio computer ed anche il protocollo PPP (Point to Point Protocol). Questo non è un problema visto che questi protocolli sono forniti a corredo di tutti i sistemi operativi più diffusi per personal computer. Il protocollo PPP consente di usare i protocolli Internet (IP), normalmente utilizzati su connessioni ‘Ethernet’, cioè in reti locali, su linee seriali e quindi per i collegamenti via modem attraverso la porta seriale RS-232 o la porta USB del personal computer. Il MODEM (MODulatore DEModulatore), è una periferica che permette il collegamento tra computer fisicamente distanti usando le normali linee telefoniche in quanto trasforma (in un modo che qui non approfondiamo) i segnali digitali (bit), propri degli elaboratori, in segnali analogici adatti a essere trasportati su tali linee (originariamente progettate per la comunicazione vocale). Se due computer distanti (chiamiamoli C1 e C2) si devono scambiare informazioni saranno necessari due modem (rispettivamente M1 e M2), uno per ogni elaboratore, collegati alla linea telefonica; se il computer C1 invia un messaggio questo sarà convertito (modulato) in analogico da M1 e instradato sulla linea; all’arrivo presso C2 il messaggio viene riconvertito (demodulato) in digitale da M2. Se è C2 a inviare un messaggio i ruoli dei dispositivi sono naturalmente invertiti. I modem si classificano secondo la loro velocità, misurata in base ai bit al secondo (bps) che riescono ad inviare o ricevere; gli apparecchi di ultima generazione arrivano a 55.600 bps ed i loro prezzi sono ormai molto bassi (poche decine di euro). Da qualche tempo è possibile collegarsi al provider anche con l’ADSL (Asymmetric Digital Subscriber Line), che sfrutta, nelle zone raggiunte dal servizio, le normali linee telefoniche. In tal caso si possono raggiungere velocità tra i 2 Mbps e i 20 Mbps (teorici) in ‘download’ (trasferimento dei dati dal provider al nostro computer) e tra i 128 Kbps e i 512 Kbps (sempre teorici) in ‘upload’ (trasferimento inverso); ovviamente gli abbonamenti ADSL sono tutti a pagamento. Anche per l’ADSL è necessario un dispositivo aggiuntivo che può essere un modem ADSL USB oppure un ‘router’ADSL a cui ci si collega con un cavo di rete; la seconda alternativa è migliore perché spesso il router ADSL ha anche funzioni di switch (con almeno quattro porte) e talvolta pure di Access Point WiFi, a costi sempre abbastanza contenuti. Nel caso del modem ADSL, usare il termine «modem» è comunque scorretto in quanto si tratta solo di un adattatore; infatti non è necessaria alcuna modulazione o demodulazione data la natura digitale dei segnali ADSL. Parte ii Il Web statico « 19 20 21 Capitolo 2 Il linguaggio HTML « I documenti presenti nel Web hanno un formato particolare che comprende dei codici speciali grazie ai quali un browser è in grado di visualizzare in modo appropriato tali documenti. Il linguaggio utilizzato è l’HTML (HyperText Markup Language - linguaggio per la codifica degli ipertesti attraverso marcatori) che costituisce una versione semplificata dell’SGML (Standard Generalized Markup Language - linguaggio di codifica standard e generalizzato). L’SGML è stato sviluppato dall’organizzazione internazionale per gli standard nel 1986 per definire linguaggi markup progettati per vari scopi. Ogni linguaggio della famiglia SGML deve rispettare certi requisiti fra i quali quello che tutti i simboli siano definiti e descritti usando un DTD (Document Type Definition); il DTD per l’HTML definisce i marcatori disponibili e il modo di usarli. L’HTML non è un linguaggio di programmazione e un documento scritto in HTML non è assolutamente un programma cioè una serie di istruzioni che l’elaboratore deve eseguire su dei dati; piuttosto il documento HTML è esso stesso un dato ed il linguaggio definisce le regole per l’inserimento di particolari ‘tag’ (o marcatori) che indicano ai programmi di navigazione quale struttura avrà la pagina da visualizzare. La funzione principale dell’HTML è quella di classificare le varie parti che compongono un documento: si può indicare quale parte rappresenta il titolo, in quali posizioni inserire delle immagini, quali parti enfatizzare e così via. Sono presenti anche alcuni comandi per la formattazione e la definizione del layout e questo ha portato ad una «contaminazione» del linguaggio alla quale si è cercato di porre rimedio proponendo l’uso dei «fogli di stile» o CSS (Cascading Style Sheet). Di questo si occupa più diffusamente il capitolo 4 riguardante i CSS. Un aspetto importantissimo dell’HTML è che è indipendente da qualsiasi piattaforma hardware e software: in altre parole una volta scritto un documento con gli elementi standard di HTML, si può essere sicuri che la pagina verrà visualizzata nello stesso modo con qualsiasi browser su qualsiasi computer. Inoltre il suo utilizzo è libero, non ci sono licenze né aggiornamenti da comprare e non si dipende da nessuna azienda produttrice di software. 2.1 Storia dell’HTML « L’HTML si sta evolvendo rapidamente e ne sono state già rilasciate varie versioni. E’ stato ideato nel 1989 insieme al Web da Tim Berners Lee. Attualmente la definizione degli standard dell’HTML (oltre che di quelli dell’HTTP e di altre tecnologie Web) è sotto la responsabilità del consorzio W3C. La prima versione dell’HTML si chiamava ‘HTML’ (senza numero di versione) e non ha avuto una grande diffusione perché quando è apparsa esistevano pochissimi serventi Web; è comunque servita da base per le successive versioni che hanno sempre conservato la compatibilità all’indietro (i documenti scritti con la prima versione possono essere tranquillamente usati con le versioni più recenti). Nel 1993 Dave Ragget ha sviluppato una versione aggiornata di HTML, chiamata ‘HTML+’ che non è mai diventato uno standard ufficiale ma le cui innovazioni sono state incorporate nella versione ‘2.0’. Alla fine del 1994 è stato approvato lo standard ‘HTML 2.0’, più affidabile e un po’ più semplice delle versioni precedenti; esso ha conosciuto una grande diffusione anche se è stato criticato dagli Il linguaggio HTML 22 sviluppatori di siti Web perché permetteva l’utilizzo di un numero troppo esiguo di comandi di formattazione del documento. Per questo motivo, e anche per la lentezza con la quale il W3C approvava i nuovi standard, le società produttrici di programmi di navigazione (principalmente Netscape e Microsoft) hanno iniziato a supportare tag non standard e non approvati dal W3C, conosciuti come «estensioni» per l’HTML. Naturalmente ogni browser gestiva le proprie estensioni e i programmi rimasti «fedeli» agli standard non erano in grado di interpretare i nuovi tag. Nel 1995 è stato redatto lo standard ‘HTML 3.0’ che però prevedeva troppi cambiamenti rispetto alla versione precedente e quindi non è stato preso in considerazione dagli sviluppatori. Migliore fortuna ha avuto la versione ‘HTML 3.2’ del 1996 che era maggiormente compatibile con la versione ‘2.0’ e comprendeva anche le estensioni usate dai browser più diffusi (‘Netscape Navigator’ e ‘Internet Explorer’). La versione più recente di HTML è la ‘4.0’ del 1997 (revisionata con la ‘4.01’) che rispetto alla precedente incorpora alcune funzioni che fino a quel momento erano estensioni, gestisce un insieme di caratteri (Unicode) più esteso del precedente (Latin-1) ed anche un nuovo marcatore per gli oggetti multimediali. Occorre comunque osservare che la versione di HTML supportata sicuramente anche dai browser meno moderni e di minore diffusione è la ‘3.2’. 2.2 Contenuto di un file HTML « Le pagine scritte in HTML sono costituite da puro testo, non contengono informazioni specifiche di una certa piattaforma o di un certo programma e possono essere scritte o modificate con qualsiasi editor di testo (ad esempio ‘Edit’ di MS-Dos, ‘Blocco note’ di MS-Windows, o ‘vi’ di GNU/Linux). Tali pagine sono chiamate anche «sorgenti HTML» e contengono al loro interno due tipi di oggetti: • il testo del documento; • i marcatori HTML. Un marcatore (o tag, o elemento) HTML è una stringa di simboli con un significato speciale: inizia con il simbolo di minore «<», continua con una «parola riservata» e termina con il segno di maggiore «>». I seguenti sono esempi di tag: ‘<html>’, ‘</B>’, ‘<BODY>’, ‘<P>’. Nei tag non si ha distinzione tra lettere maiuscole e minuscole, quindi ‘<BODY>’, ‘<body>’, ‘<Body>’ rappresentano lo stesso elemento. In questo testo gli elementi del linguaggio HTML sono quasi sempre indicati in minuscolo in quanto questo diviene obbligatorio in XHTML che è l’evoluzione dell’HTML e del quale si occupa brevemente il capitolo 9. Esistono due tipi di tag: quelli di inizio con i quali si attivano certe opzioni o funzioni, e quelli di fine con i quali si disattivano le stesse opzioni e funzioni. Il linguaggio HTML 23 Il testo inserito tra il tag di inizio e quello di fine viene visualizzato dai programmi di navigazione in modo appropriato secondo le specifiche dei marcatori utilizzati. I marcatori di fine si scrivono nello stesso modo di quelli di inizio eccetto per il fatto che dopo il simbolo di minore (<) si ha sempre il simbolo della barra «/»; se ad esempio scriviamo nel documento HTML: |<b>Questo testo sarà in grassetto</b> il testo compreso tra i due tag, (cioè il contenuto di quell’elemento) sarà visualizzato in grassetto (‘b’ sta per bold). Esistono anche degli elementi per cui la stringa di fine non è obbligatoria, come ‘<p>’, che indica l’inizio dell’elemento paragrafo ed il cui contenuto è il testo del paragrafo stesso. Ci sono poi dei tag senza neanche il contenuto come ‘<hr>’, che serve ad inserire nel documento una righello orizzontale. Alcuni marcatori prevedono degli «attributi», (indicati esclusivamente al momento dell’apertura del tag prima del simbolo «>») che specificano determinate proprietà dei marcatori e possono avere un valore. La sintassi da utilizzare prevede che ogni attributo sia separato dal precedente o dalla stringa di apertura del tag da uno spazio; l’eventuale valore deve essere preceduto dal simbolo «=» e racchiuso tra virgolette ("). La cosa più importante da capire riguardo ai tag è che essi non vengono mai visualizzati dal browser, piuttosto viene visualizzato il loro «effetto» sul testo della pagina Web. Questo avviene grazie all’operazione di ‘rendering’ effettuata da un apposito «motore» incorporato in ogni browser. I motori di rendering più importanti sono: • ‘Gecko’, per Firefox, Galeon, Epiphany e altri; • ‘KHTML’, per Konqueror; • ‘Presto’, per Opera; • ‘Trident’, per Internet Explorer; • ‘Webkit’, per Chrome e Safari. I migliori sono: Presto e Gecko riguardo alla velocità, KHTML riguardo all’aderenza agli standard. Se qualche tag è scritto male, contiene errori di sintassi o non è riconosciuto per qualsiasi altro motivo, viene semplicemente ignorato dal browser che non da nessuna segnalazione di errore al riguardo. Molte volte inoltre il programma di navigazione riesce a interpretare correttamente e quindi a presentare in modo accettabile anche pagine Web contenenti errori e imperfezioni nell’uso dei marcatori. Questo non significa che si possa prestare poca attenzione nella realizzazione di pagine Web con la scusa che poi i browser «digeriscono» tutto, anche in vista dell’uso del molto meno permissivo XHTML. Il linguaggio HTML 24 2.3 Strumenti per la creazione di documenti HTML « Per scrivere un documento in linguaggio HTML, come detto, si può usare un comunissimo e semplicissimo editor di testo; esistono però anche altri strumenti più sofisticati che si suddividono fondamentalmente in due categorie: • editor «dedicati» cioè studiati appositamente per la scrittura di codice HTML ma sempre a formattazione differita (il risultato della formattazione del documento è visibile solo successivamente usando un programma di navigazione); • editor a formattazione immediata (il risultato finale della formattazione del documento è visibile immediatamente) che creano automaticamente il codice HTML. Nel primo caso si tratta di editor con delle funzioni aggiuntive per la scrittura degli elementi HTML, per il controllo ortografico, per l’ordinamento del testo ed altre ancora. Nel secondo caso si tratta di strumenti come ‘Macromedia Dreamweaver’, ‘Microsoft Frontpage’ o come il programma libero ‘Kompozer’, che permettono di comporre la pagina partendo dal suo aspetto e generano automaticamente il sorgente non richiedendo quindi alcuna conoscenza del linguaggio HTML. Questi programmi sono detti anche editor WYSIWYG (What You See Is What You Get, ciò che vedi è ciò che ottieni) ed il loro uso può apparire conveniente fino a far ritenere superfluo un corso di HTML. I sostenitori dell’uso di tali strumenti affermano tra l’altro che con essi i creatori di pagine Web sono sollevati dalla necessità di imparare comandi molto complicati e che la produttività e la qualità del lavoro sono migliori. Esistono però motivi molto importanti che invece ne sconsigliano l’utilizzo: • il linguaggio HTML è molto semplice e non dovrebbero essere necessari molti «aiuti» per usarlo correttamente; • se si conosce il linguaggio si hanno maggiori possibilità di correggere errori e risolvere problemi sfruttando a pieno le sue potenzialità e si può intervenire sui propri documenti da qualsiasi computer e con qualunque editor; • il codice HTML creato automaticamente è solitamente di cattiva qualità, non efficiente, male organizzato e può contenere elementi incompatibili con gli standard ufficiali del linguaggio. Quindi è utile conoscere l’HTML e per la creazione di documenti non è consigliabile l’uso di programmi troppo sofisticati; al massimo si consiglia l’uso di editor dedicati. 2.4 Uso dei validatori « Per essere sicuri di avere realizzato un documento HTML aderente agli standard si può ricorrere ai «validatori» che sono programmi che ispezionano un sorgente HTML individuando gli errori nell’uso dei tag oppure l’uso di elementi considerati «deprecati» o proposti da qualche azienda ma non riconosciuti ufficialmente dal W3C come facenti parte dell’HTML standard. Molti di questi strumenti sono disponibili direttamente in rete; un esempio è il validatore del consorzio W3C all’indirizzo hhttp://validator.w3.org i al quale si possono sottoporre documenti già presenti in rete, fornendo il relativo indirizzo, oppure file da caricare al momento per la validazione. Il linguaggio HTML 25 2.5 Struttura di un documento HTML « La struttura generale di un documento HTML viene definita con i seguenti elementi fondamentali: • html • head • title • body Questi elementi anche se mancanti vengono considerati presenti da quasi tutti i programmi di navigazione; è comunque buona norma includere tutti e quattro questi elementi in qualsiasi documento HTML. All’inizio del sorgente HTML si deve inoltre inserire una riga che specifichi quale è la versione di HTML utilizzata. Per fare questo si usa la dichiarazione <!DOCTYPE> che non è un tag HTML ma una entità SGML. Molti browser gestiscono anche documenti Web mancanti di tale elemento; è comunque opportuno inserirlo per evitare incompatibilità e per poter usare senza problemi gli strumenti di validazione del sorgente HTML. Per la versione HTML 4.01 la linea da scrivere è una delle seguenti: |<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" | "http://www.w3.org/TR/html4/strict.dtd"> |<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | "http://www.w3.org/TR/html4/loose.dtd"> |<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" | "http://www.w3.org/TR/html4/frameset.dtd"> Nel primo caso si intende utilizzare la variante «strict» dell’HTML, cioè una versione in cui non è ammesso l’utilizzo di una serie di elementi considerati «deprecati» come i riquadri (frame) o i tag ‘<center>’ e ‘<b>’. Nel secondo caso invece si intende usare la variante «Transitional» in modo da poter inserire anche i marcatori deprecati. Nel terzo caso infine si intende usare la variante «Frameset» in modo da avere a disposizione i marcatori deprecati e poter utilizzare anche i riquadri. La suddivisione in varianti è stata proposta dal W3C con la versione ‘4.01’ dell’HTML (e ‘1.0’ dell’XHTML), nel gennaio del 2000, per i seguenti scopi: • imporre regole più rigide nell’uso del linguaggio grazie alla variante strict eliminando tutta una serie di marcatori non riguardanti la struttura del documento ma il suo aspetto; • incoraggiare l’uso dei CSS per la definizione del layout delle pagine; Il linguaggio HTML 26 • favorire la transizione dall’HTML all’XHTML; • permettere comunque un passaggio morbido alla nuova versione senza provocare un rifiuto da parte degli sviluppatori Web grazie alle più permissive varianti Transitional e Frameset. Un elenco dei tag deprecati si può trovare all’indirizzo hhttp://www.w3.org/TR/REC-html40/appendix/ changes.html#h-A.3.1.2 i. Il presente documento fa riferimento alla variante Frameset dell’HTML che è tutt’ora la più utilizzata per la creazione di pagine Web. 2.5.1 L’elemento ‘html’ « Lo scopo di questo elemento è quello di indicare che il file che si sta scrivendo è realizzato in linguaggio HTML. Tutto il testo, comprensivo degli altri tag, dovrà essere racchiuso tra i suoi tag di inizio e fine: |<html> |.... |.... contenuto del documento |.... |</html> Un documento HTML deve sempre contenere due sezioni o parti: • la sezione intestazione (head) che contiene elementi che non influenzano la visualizzazione da parte dei programmi di navigazione ma specificano proprietà comunque importanti del documento; • la sezione corpo (body) in cui è presente il contenuto da visualizzare. 2.5.2 L’elemento ‘head’ « La sezione intestazione inizia con il tag ‘<head>’ e termina con ‘</head>’ e contiene almeno il titolo del documento racchiuso tra i tag ‘<title>’ e ‘</title>’; può contenere altre informazioni come i dati sull’autore e sul programma che ha generato il documento, o anche degli script cioè insiemi di comandi scritti in un qualche linguaggio di programmazione e che possono svolgere varie attività interagendo con il browser. Il titolo deve essere una descrizione del documento breve, perché viene visualizzato dai programmi di navigazione nella barra del titolo della finestra, e significativa, perché viene utilizzato dai programmi che catalogano i documenti di Internet per creare indici di ricerca. Il linguaggio HTML 27 2.5.3 L’elemento ‘body’ « La sezione corpo è racchiusa tra i tag ‘<body>’ e ‘</body>’ e contiene la parte del documento che viene visualizzata dai browser quando si apre la pagina. Il seguente è un semplicissimo esempio che riassume la struttura generale di una pagina Web con l’uso dei tag sinora illustrati: |<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" | "http://www.w3.org/TR/html4/frameset.dtd"> |<html> |<head> |<title>Istituto Max Planck Esempio in HTML</title> |</head> |<body> |Testo che viene visualizzato |</body> |</html> In figura 2.7 si vede l’aspetto di questa pagina una volta aperta con un browser. F | igura 2.7. 2.5.4 Elementi di blocco e elementi di testo « I marcatori che possono essere presenti nel corpo di un documento si possono suddividere in due tipologie: • elementi di testo o in linea (inline); • elementi di blocco (block-level). I primi si usano per inserire immagini, creare collegamenti, modificare l’aspetto del testo, i secondi per definire gruppi di testo con uno scopo specifico, come intestazioni, sezioni, tabelle. La differenza principale tra i due tipi di elementi è che quelli di blocco provocano interruzioni di paragrafo e quelli di testo invece no. Il linguaggio HTML 28 2.5.5 Intestazioni « I titoli o intestazioni sono elementi di blocco disponibili in sei livelli diversi; al crescere del livello diminuisce il grado di evidenza del testo contenuto. L’uso dei titoli non è obbligatorio ma sicuramente utile per organizzare in modo razionale le pagine. Ogni intestazione inizia con ‘<hn>’ e termina con ‘</hn>’ dove n è il numero corrispondente al livello desiderato; sono previsti i seguenti attributi: • align="left"; • align="right"; • align="center"; • align="justify". Il loro effetto è quello di allineare le intestazioni rispettivamente a sinistra, destra, centro e ad entrambi i margini. 2.5.6 Paragrafi « In HTML l’inizio di un paragrafo è indicato con il tag ‘<p>’ mentre non è obbligatorio il tag di fine ‘</p>’. In vista del passaggio a XHTML è comunque consigliabile abituarsi a «chiudere» tutti i tag, anche quelli che non lo richiedono esplicitamente in HTML. Nel caso dei tag vuoti si può anche utilizzare la forma abbreviata di chiusura che consiste nel posporre al tag di apertura la barra obliqua; ad esempio invece di scrivere: |<hr></hr> si può scrivere: |<hr/> Si noti che la presenza di spazi o righe vuote nel sorgente HTML viene ignorata dai browser (gli spazi vengono compattati) e quindi l’unico modo per separare correttamente i paragrafi è, appunto, l’uso del tag ‘<p>’. A tale proposito consideriamo le seguenti porzioni di codice HTML: |<h1>Semplice esempio</h1> |<p> Questo è un semplice esempio con due righe di testo.</p> |<p>Questa è la seconda riga.</p> oppure: Il linguaggio HTML 29 |<h1> |Semplice esempio |</h1> |<p> Questo è un semplice esempio con due righe di testo.</p> | |<p>Questa è la seconda riga.</p> oppure: |<h1>Semplice esempio |</h1> |<p> Questo è un semplice |esempio con due righe di testo.</p> |<p>Questa è la seconda riga.</p> Questi tre esempi produrranno esattamente lo stesso effetto al momento della visualizzazione con il browser, quello mostrato in figura 2.13. F | igura 2.13. A proposito dei paragrafi si deve anche ricordare che non è opportuno cercare di inserire righe vuote con una sequenza di ‘<p>’ consecutivi perché molti programmi di navigazione in questo caso li riducono ad un solo ‘<p>’ annullando lo sforzo compiuto dall’autore del sorgente HTML. All’interno dell’elemento paragrafo si possono utilizzare gli attributi di allineamento visti per le intestazioni. Naturalmente il tag ‘<p>’ è un elemento di blocco. 30 Il linguaggio HTML 2.5.7 L’elemento ‘span’ « Con il tag ‘<span>’ si può definire un contenitore generico di testo, cioè un qualcosa di molto simile ad un paragrafo, tenendo però presente che in questo caso si tratta di un elemento in linea e non di blocco. 2.5.8 Righello orizzontale « Con il tag ‘<hr>’ si inserisce nel documento una riga orizzontale, oltre a separare il testo in due paragrafi. Questo elemento è di blocco e ha vari attributi, il più interessante dei quali è ‘size’ che permette di impostare lo spessore della linea in pixel. 2.5.9 Centratura « Il tag ‘<center>’, che è di blocco, viene usato per centrare tutto ciò che è contenuto tra tale elemento e la rispettiva chiusura ‘</center>’. 2.5.10 Interruzione di linea « Per interrompere una linea e «andare a capo» senza definire un nuovo paragrafo, si usa il tag ‘<br>’. Questo elemento è di testo e si differenzia da ‘<p>’ perché quest’ultimo, oltre a terminare la linea, termina anche il paragrafo iniziandone uno nuovo. Il problema citato in precedenza, relativo all’inserimento di più righe vuote tra due porzioni di testo, può essere risolto utilizzando una sequenza di tag ‘<br>’ invece che tag ‘<p>’. 2.5.11 Grassetto, corsivo e sottolineato « Con gli elementi ‘<b>’ e ‘</b>’ si enfatizza il testo tra essi contenuto, con ‘<i>’ e ‘</i>’ si visualizza in corsivo, con ‘<u>’ e ‘</u>’ si sottolinea; questi sono tutti elementi di testo. 2.6 Nidificazione dei tag « In un documento HTML i tag sono sempre nidificati (cioè inseriti uno nel contenuto di uno precedente); abbiamo infatti visto come l’elemento ‘<body>’ sia contenuto all’interno dell’elemento ‘<html>’. Consideriamo ora la seguente porzione di codice HTML: |<p> |<b>Esempio con tag <i>nidificati</i></b> |</p> Il marcatore per il corsivo è all’interno di quello per il grassetto che, a sua volta è all’interno di quello per la separazione dei paragrafi; l’effetto di è quello di visualizzare il testo in grassetto e la parola nidificati anche in corsivo. Il linguaggio HTML 31 Riguardo alla nidificazione ci sono alcune regole da ricordare: • gli elementi devono essere completamente nidificati e non chiusi nell’ordine sbagliato; • gli elementi di testo possono essere nidificati in elementi di blocco o in altri di testo; • gli elementi di blocco possono essere nidificati solo in altri elementi di blocco. Quindi i seguenti esempi risultano errati: |<b><i> | Esempio di nidificazione errata a causa dei tag di chiusura |</b></i> | |<b>Esempio sbagliato con tag di <p>blocco</p> interno a uno di testo</b> Alcuni programmi di navigazione riescono ugualmente ad interpretare sorgenti HTML contenenti errori simili a questi ma, come detto più volte in precedenza, è sempre bene rispettare le regole data la minore permissività di strumenti più moderni come l’XHTML. 2.7 Insiemi di caratteri « Le prime versioni di HTML, fino alla ‘3.2’, utilizzano un insieme di caratteri chiamato Latin-1 o ISO 8859-1. L’ISO (International Organization for Standardization) ha il compito di definire gli standard in vari ambiti a livello mondiale; l’acronimo dovrebbe essere IOS ma è stato preferito ISO che in lingua greca indica «uguaglianza». Questo insieme di caratteri comprende tutti i simboli stampabili del codice ASCII (American Standard Code for Information Interchange), cioè quelli di valore decimale da 32 a 126, e altri caratteri numerati da 160 a 255 che includono simboli speciali e lettere straniere. Con l’‘HTML 4.0’ viene introdotto l’uso del set di caratteri Unicode o UCS (Universal Character Set) o ISO-10646 che comprende 38.885 caratteri, appartenenti alle lingue di tutto il Mondo, e che può essere codificato in molti modi diversi (UCS-2 UTF-8 (Unicode Transformation Format 8) e altri ancora. Essendo questo standard ancora abbastanza nuovo può capitare che un programma di navigazione non gestisca i caratteri UCS; inoltre non è detto che il computer che utilizziamo contenga il font di caratteri in grado di visualizzare determinati simboli UCS. 2.7.1 Entità per caratteri speciali « Torniamo quindi all’insieme di caratteri Latin-1, e vediamo come si possono utilizzare i simboli speciali cioè quelli che non hanno codice ASCII compreso tra 32 e 126 (in decimale). A tale scopo si ricorre alle entità per caratteri speciali che sono oggetti HTML scritti con una sintassi particolare: iniziano con il simbolo «&», terminano con «;» e prevedono l’indicazione di un codice con un nome o in forma numerica. Ad esempio la lettera "à" corrisponde all’entità à oppure à. Di seguito sono elencati alcuni dei caratteri speciali più usati (almeno in Italia) con i rispettivi codici: Il linguaggio HTML 32 Carattere à è é ì ò ù È £ e Nome à è é ì ò ù È £ € Numero à è é ì ò ù È £ € 2.7.2 Entità per caratteri riservati « In modo simile viene risolto anche il problema dell’uso di caratteri «normali» ma che per HTML hanno un significato particolare, come i simboli di maggiore e minore, la «&» e altri. In questo caso si usano le entità per caratteri riservati da scrivere con le stesse regole di sintassi: Carattere " < > & Nome " < > & Numero " < > & 2.7.3 Lo spazio unificatore « Tra i caratteri speciali ce n’è uno molto importante: lo spazio unificatore con il quale si inserisce uno spazio tra due parole facendo in modo però che esse rimangano sempre nella stessa riga. Per inserire tale elemento si usano le entità oppure  . Con lo spazio unificatore si riesce anche a ottenere il rientro della prima riga di un paragrafo, cosa impossibile da realizzare con gli spazi «normali» o i tabulatori, visto che questi verrebbero compattati dal browser in fase di visualizzazione. Questo effetto (insieme a molti altri) si ottiene comunque in modo molto più elegante, efficace e aderente agli standard, utilizzando gli strumenti messi a disposizione dai CSS. Questa osservazione deve essere ritenuta valida, e non viene quindi ripetuta, per tutti gli elementi o attributi che definiscono caratteristiche di formattazione e aspetto del testo (colori, allineamento, sfondi ecc.). 2.8 Altri elementi di uso frequente « Vediamo adesso una rapida carrellata di marcatori usati abbastanza frequentemente. Il linguaggio HTML 33 2.8.1 Commenti « In un documento HTML si possono inserire commenti e annotazioni che non verranno visualizzate ma che possono essere utili per chi esamina il codice sorgente. I commenti devono essere racchiusi tra «<!--» e «-->». 2.8.2 Uso dei colori « In un documento HTML si possono gestire i colori dello sfondo e del testo e si può definire un’immagine come sfondo usando alcuni attributi del tag body. Come prerequisito occorre però conoscere il sistema additivo dei colori che è alla base della grafica dello schermo: ogni colore viene ottenuto «sommando» una certa quantità di rosso, di verde e di blu che sono i colori fondamentali; sommando il massimo di ognuno dei tre colori si ottiene il bianco. Per stabilire la quantità dei colori fondamentali da usare si deve indicare un insieme di 3 coppie di cifre esadecimali precedute dal simbolo «#»: la prima relativa al rosso, la seconda al verde, la terza al blu. Ad esempio il valore "#000000" rappresenta il nero mentre "#00FF00" è il verde e "#F0F0F0" un grigio chiaro. C’è anche la possibilità di indicare i colori con il loro nome (in inglese) che però deve essere conosciuto e che non è disponibile per tutte le sfumature possibili (256*256*256 = 24061070). Gli attributi del tag body da usare sono ‘bgcolor’ per il colore dello sfondo e text per il colore del testo; inoltre, anche se non riguarda i colori, è importante l’attributo ‘background’ per usare un’immagine come sfondo del documento. Nel seguente esempio viene definito un documento con sfondo nero e testo bianco: |<html> |<head> |<title>Esempio con i colori</title> |</head> |<body bgcolor="#000000" text="#FFFFFF"> |<b>Testo</b> |</body> |</html> Se si vuole usare come sfondo l’immagine contenuta nel file ‘clouds.jpg’ presente nella stessa directory dove risiede il sorgente HTML, si scrive invece: |<body background="clouds.jpg"> Se gli attributi di body non vengono specificati la visualizzazione del documento avviene secondo lo standard del programma di navigazione, di solito testo nero su sfondo bianco. 34 Il linguaggio HTML 2.8.3 Elemento ‘font’ « Si tratta di un elemento di testo che consente di cambiare il colore, la dimensione ed il tipo dei caratteri utilizzando rispettivamente gli attributi ‘color’, ‘size’ e ‘face’. Per i colori si usano i codici esadecimali visti in precedenza, per il tipo carattere si usa il suo nome, per la dimensione ci sono sette possibilità numerate da 1, la più piccola, a 7, la più grande. Si può però anche indicare una dimensione relativa rispetto alla dimensione normale del testo; ecco alcuni esempi: |<font size="5">Esempio con dimensione 5</font> |<font size="-1">Esempio con dimensione minore di uno di quella normale</font> |<font size="+1">Esempio con dimensione maggiore di uno di quella normale</font> Gli ultimi due esempi equivalgono ai seguenti in cui si usano i tag small e big: |<small>Esempio con dimensione minore di uno di quella normale</small> |<big>Esempio con dimensione maggiore di uno di quella normale</big> Naturalmente i tre attributi possono essere combinati come nel seguente esempio: |<font color="#00FF00" size="2" |face="Arial">Esempio con colore verde, grandezza 2 e tipo Arial</font> L’elemento font può essere utilizzato anche per modificare colore e dimensione delle intestazioni se viene nidificato all’interno dei tag ‘<h1>’, ‘<h2>’ ecc. 2.8.4 Elemento ‘address’ « Questo elemento di blocco viene usato per inserire informazioni che riguardano l’autore del documento tra i tag ‘<address>’ e ‘</address>’. 2.8.5 Elemento ‘div’ « L’elemento di blocco div suddivide il documento in sezioni ed è delimitato dai tag ‘<div>’ e ‘</div>’. Ogni sezione può essere definita con un particolare allineamento del testo grazie all’uso degli stessi attributi visti per paragrafi e intestazioni; se ad esempio si vuole centrare una porzione di testo composta da molti paragrafi, invece di centrarli uno ad uno si può ricorrere al tag div nel seguente modo: |<div align="center"> |testo da centrare |</div> Il linguaggio HTML 35 2.8.6 Elemento ‘pre’ « Si tratta di un elemento di blocco che permette di visualizzare del testo nel modo in cui viene scritto nel file sorgente, senza che gli spazi siano compattati dal programma di navigazione; tutto il testo contenuto fra i tag ‘<pre>’ e ‘</pre>’ viene visualizzato così come è scritto usando un carattere monospaziato (generalmente il Courier). 2.8.7 Elementi ‘subscript’ e ‘superscript’ « Sono elementi di testo che servono a scrivere caratteri rispettivamente nelle posizioni di «pedice» e «apice». I tag da usare sono ‘<sub>’ e ‘<sup>’ come mostrato nel seguente esempio: |<html> |<head> |<title>Esempio con sup e sub</title> |</head> |<body> |Equazione di secondo grado: a*x<sup>2</sup> + b*x + c = 0 |<p/> |Formula chimica dell’acqua: H<sub>2</sub>O |</body> |</html> che viene visualizzato come mostrato in figura 2.25. F | igura 2.25. Il linguaggio HTML 36 2.8.8 Elementi ‘emphasis’ e ‘strong’ « Sono elementi di testo che servono rispettivamente a enfatizzare e a enfatizzare molto, quanto viene racchiuso tra i rispettivi tag ‘<em>’ e ‘</em>’, ‘<strong>’ e ‘</strong>’. In qualche caso questi elementi hanno lo stesso effetto dei tag ‘<i>’ e ‘<b>’. 2.9 Elenchi o liste « Gli elenchi o liste sono elementi di blocco molto usati e sono definiti in cinque tipologie: • liste numerate e ordinate; • liste puntate con richiamo grafico; • liste a glossario o di definizione; • liste a menu; • liste a directory. Gli ultimi due tipi sono usati molto raramente e sono anzi sconsigliati; esaminiamo quindi solo le altre tre tipologie di elenchi. 2.9.1 Liste numerate « I tag di inizio e fine di una lista numerata sono ‘<ol>’ e ‘</ol>’; ciascuna voce dell’elenco deve essere poi preceduta dal marcatore ‘<li>’ e seguita (non obbligatoriamente) da ‘</li>’. C’è la possibilità di stabilire il tipo di numerazione desiderata con l’attributo ‘type’ del tag ‘<ol>’: • type="1" per i numeri arabi; • type="a" per i caratteri minuscoli; • type="A" per i caratteri maiuscoli; • type="i" per i numeri romani minuscoli; • type="I" per i numeri romani maiuscoli. Si può anche stabilire il punto di partenza della numerazione con l’attributo ‘start’. Le impostazioni per difetto sono: numerazione araba e partenza dal valore «1». Anche il tag ‘<li>’ prevede un attributo, ‘value’ per assegnare ad una certa voce un valore specifico e alterare quindi la normale sequenza di numerazione della lista. Il seguente codice: |<html> |<head><title>Esempio lista numerata</title></head> |<body> |<ol type="1" start="1"> |<li>Penne</li> Il linguaggio HTML 37 |<li>Matite</li> |<li>Quaderni</li> |<li value="5">Libri</li> |<li>Zaini</li> |</ol> |</body> |</html> viene visualizzato come mostrato in figura 2.27. F | igura 2.27. In questo esempio la lista contiene solo testo non formattato; è comunque possibile inserire qualsiasi elemento di blocco o di testo come voce dell’elenco. 2.9.2 Liste puntate « I tag di inizio e fine di una lista puntata (o non numerata) sono ‘<ul>’ e ‘</ul>’; anche in questo caso serve poi ‘<li>’ per ogni voce dell’elenco. Si può stabilire il tipo di carattere di richiamo delle voci listate con l’attributo type: • type="circle" per usare un cerchio vuoto; • type="disc" per usare un cerchio pieno; • type="square" per usare un quadrato. Le liste (anche quelle numerate) possono essere nidificate in modo da creare delle sottoliste. I caratteri standard di richiamo dovrebbero essere il disco per le liste principali, il cerchio per le sottoliste di primo livello e il quadrato per le altre, ma questa cosa dipende molto dal browser usato. Vediamo un esempio: 38 Il linguaggio HTML |<html> |<head><title>Esempio lista puntata</title></head> |<body> |<h1>Lista materiali</h1> |<ul> | <li>Hardware | <ul> | <li>Unità centrale | <ul> | <li>CPU</li> | <li>Memoria centrale</li> | <li>Clock</li> | </ul> | </li> | <li>Periferiche | <ul> | <li>Memorie di massa | <ul> | <li>Nastro</li> | <li>Floppy Disk</li> | <li>Hard Disk</li> | <li>CD-ROM</li> | </ul> | </li> | <li>Stampante</li> | <li>Tastiera</li> | <li>Mouse</li> | <li>Schermo</li> | </ul> | </li> | </ul> | </li> | <li>Software | <ul> | <li>Software di base</li> | <li>Software applicativo</li> | </ul> | </li> |</ul> |</body> |</html> In questo esempio l’indentatura serve solo ad aumentare la leggibilità del sorgente in quanto, come più volte detto, gli spazi sono ignorati dal browser. Il risultato è visibile in figura 2.29. Il linguaggio HTML 39 F | igura 2.29. 2.9.3 Liste a glossario « Le liste a glossario sono delimitate dai tag ‘<dl>’ e ‘</dl>’; le voci dell’elenco sono contrassegnate dal marcatore ‘<dt>’ mentre ‘<dd>’ viene usato per fornirne la definizione. Ecco un esempio: |<html> |<head><title>Esempio lista a glossario</title></head> |<body> |<dl> |<dt>Hardware</dt> |<dd>Insieme degli elementi del computer che hanno una |consistenza fisica</dd> |<dt>Software</dt> |<dd>Insieme dei programmi</dd> |</dl> |</body> |</html> che viene visualizzato come in figura 2.31. Il linguaggio HTML 40 F | igura 2.31. Alcune osservazioni: • un elemento ‘<dd>’, come anche ‘<li>’, può contenere sia elementi di blocco che di testo; in ‘<dt>’ invece possono esserci solo elementi di testo; • ad una voce ‘<dt>’ possono essere associate più definizioni ‘<dd>’ ma è vero anche il viceversa: una definizione associata a più voci. 2.10 Collegamenti ipertestuali « La possibilità di definire collegamenti ipertestuali o link tra documenti diversi è senz’altro uno dei motivi del successo del Web in quanto permette di passare facilmente da una pagina ad un’altra senza preoccuparsi delle rispettive collocazioni fisiche. I documenti collegati possono infatti risiedere nella stessa macchina o su macchine diverse, distanti anche migliaia di chilometri, purché collegate ad Internet; inoltre è possibile definire dei link anche ad altre parti di una stessa pagina. L’entità HTML da usare per definire i collegamenti è chiamata «ancora», è un elemento di testo e corrisponde ai tag ‘<a>’ e ‘</a>’ accompagnati da vari attributi tra i quali i più usati sono ‘name’ e ‘href’. Il testo che si trova tra i marcatori di apertura e chiusura è quello che il programma di navigazione evidenzia in qualche modo per attirare l’attenzione sulla presenza del collegamento e viene denominato «zona sensibile» o «zona attiva» del documento (si parla di «zona» e non di «testo sensibile» perché un collegamento può essere definito anche su elementi diversi, come le immagini). Ogni browser mette in risalto i link in modo diverso: vengono differenziati quelli già visitati, da quelli da visitare e da quelli attivi (un link è attivo per il breve tempo in cui viene selezionato dall’utente); di solito i colori standard usati sono rispettivamente: blu (#0000FF), violetto (#800080) e rosso (#FF0000). Si possono comunque personalizzare i colori del testo dei collegamenti ricorrendo a degli attributi del tag ‘<body>’ e precisamente: ‘link’ per il colore dei collegamenti, ‘vlink’ per il colore dei collegamenti già visitati, ‘alink’ per il colore dei collegamenti attivi. Per esempio per avere rispettivamente verde, marrone, fucsia: Il linguaggio HTML 41 |<body link="#00FF00" vlink="#800000" alink="#FF00FF"> 2.10.1 Collegamenti esterni « Per collegamenti esterni si intendono quelli che puntano a documenti memorizzati su macchine diverse da quella che ospita la pagina che stiamo definendo. Per definire questo tipo di collegamenti è necessario usare l’attributo ‘href’ (che sta per hypertext reference) seguito dall’URL della pagina alla quale ci si vuole collegare. Ad esempio: |<a href="http://www.istruzione.it">Ministero della Pubblica Istruzione</a> La scritta «Ministero della Pubblica Istruzione» viene evidenziata dal navigatore; la selezione di tale voce, con il mouse o con la tastiera, attiva il collegamento con il sito del Ministero ed il browser visualizza la pagina iniziale di tale sito (di solito è la pagina contenuta nel file ‘index.html’ che viene aperta per difetto se, come nell’esempio in questione, non è indicato espressamente un nome di file). Altro esempio: |<a href="http://www.linuxdidattica.org/docs/filosofia/manifesto-gnu-it.html"> |Manifesto GNU di R. Stallmann</a> In questo modo si definisce un collegamento con un documento contenente il «Manifesto GNU» di R, Stallman» memorizzato presso il sito hhttp://www.linuxdidattica.org i sul percorso ‘docs/ filosofia/’ con nome ‘manifesto-gnu-it.html’. Altro esempio: |<a href="mailto:[email protected]">Invia messaggio a pippo</a> In questo modo si definisce un collegamento attivando il quale si accede alla definizione di un messaggio di posta elettronica da inviare a [email protected]. 2.10.2 Collegamenti a etichette in un documento « L’attributo ‘name’ del tag ‘<a>’ permette di inserire delle etichette (o label) che fanno riferimento a diverse sezioni di un documento. La presenza di queste etichette può essere sfruttata definendo, in un’altra pagina HTML, dei collegamenti che puntano al documento non più in modo generico ma indicando una sezione specifica associata ad una di tali etichette. Se ad esempio definiamo una pagina di nome ‘esempio.html’ sulla macchina pc01.max.planck in modo che contenga etichette: | | | |<a .... .... (testo del documento) .... name="E1">Esempio di etichetta numero 1</a> Il linguaggio HTML 42 | | | |<a | | | .... .... (testo del documento) .... name="E2">Esempio di etichetta numero 2</a> .... .... (testo del documento) .... diviene possibile collegarsi ad essa da un altro documento in vari modi come mostrato di seguito: |Da <a href="http://pc01.max.planck/esempio.html"> |qui </a> ci si collega all’inizio della pagina esempio | |Da <a href="http://pc01.max.planck/esempio.html#E1"> |qui </a> ci si collega alla pagina esempio all’etichetta 1 | |Da <a href="http://pc01.max.planck/esempio.html#E2"> |qui </a> ci si collega alla pagina esempio all’etichetta 2 Quindi per collegarsi ad una certa etichetta di un documento basta aggiungere all’indirizzo di quest’ultimo il simbolo "#" seguito dal nome dell’etichetta a cui vogliamo fare riferimento. 2.10.3 Usare i collegamenti insieme ad altri elementi « L’elemento ‘<a>’ può essere utilizzato insieme ad altri marcatori HTML ma si deve ricordare che è proibito nidificarlo in altri elementi ‘<a>’. Vediamo alcuni esempi: • collegamento all’interno di una intestazione: |<h3><a href="http://pc01.max.planck/"> |Esempio di intestazione con link</a></h3> si noti che ‘<a>’ che è un elemento di testo deve essere interno al tag di intestazione che è un elemento di blocco; • collegamento in corsivo: |<i><a href="http://pc01.max.planck/"> |Esempio di collegamento in corsivo</a></i> oppure: |<a href="http://pc01.max.planck/"> |<i>Esempio di collegamento in corsivo</i></a> • lista di collegamenti: |<p>I seguenti sono i serventi |a cui ci possiamo collegare:</p> Il linguaggio HTML |<ul> |<li><a |<li><a |<li><a |<li><a |</ul> 43 href="http://serlinux1.max.planck/">serlinux1</a></li> href="http://serlinux3.max.planck/">serlinux3</a></li> href="http://serlinux5.max.planck/">serlinux5</a></li> href="http://serlinux7.max.planck/">serlinux7</a></li> Sarebbe anche possibile cambiare il colore del testo dei collegamenti, nidificando il marcatore ‘<font>’ all’interno del marcatore «ancora»; questa però è un’operazione sconsigliata in quanto si verrebbero a perdere le impostazioni preimpostate relative ai colori dei collegamenti con la distinzione tra quelli visitati, non visitati e attivi e si potrebbe quindi creare disorientamento nell’utente. 2.10.4 Collegamenti interni « I collegamenti interni sono quelli che fanno riferimento a file residenti sul proprio sito Web; si definiscono nello stesso modo di quelli esterni eccetto per il fatto che è possibile fare riferimento anche a indirizzi «relativi». Se ad esempio stiamo scrivendo una pagina HTML residente su pc01.max.planck/ classi/4d/pippo/ e vogliamo fare riferimento al documento ‘esempio2.html’ presente sulla stessa macchina e stessa directory, basta scrivere: |<a href="esempio2.html">Link alla pagina esempio2</a> Se invece vogliamo collegarci ad un documento, presente sulla stessa macchina ma in una directory differente, dovremo specificare il percorso per raggiungerlo ricorrendo, se necessario, alla notazione «..» che indica la directory «madre» della directory corrente. Vediamo alcuni esempi: |<a href="pluto/esempio2.html">Link alla pagina esempio2</a> in questo caso ci colleghiamo al file ‘esempio2.html’ che è in pc01.max.planck/ classi/4d/pippo/pluto/; |<a href="../paperino/esempio2.html">Link alla pagina esempio2</a> in questo caso ci colleghiamo al file ‘esempio2.html’ che è in pc01.max.planck/ classi/4d/paperino/. Per i collegamenti interni è sempre consigliato l’uso di indirizzi relativi in modo che tutto continui a funzionare senza modifiche (o quasi) anche in caso si spostino tutti i documenti del nostro sito in un’altra posizione del disco o addirittura su un’altra macchina. Se si usano indirizzi assoluti questo naturalmente non è possibile e si devono modificare i vari collegamenti in caso di spostamento dei documenti. 44 Il linguaggio HTML 2.10.5 Collegamenti ad altre parti dello stesso documento « Grazie all’uso delle etichette è possibile definire collegamenti ad altre parti dello stessa pagina in modo da poter «saltare» immediatamente ad esse. Questo può servire in caso di pagine molto lunghe oppure per creare degli indici del contenuto di un documento HTML. Ad esempio se si definisce in un documento una etichetta: |<a name="sezione1">Sezione 1</a> poi si può stabilire il link ad essa scrivendo: |<a href="#sezione1">Link alla sezione 1</a> Nel caso si voglia definire l’indice di un documento (di nome ‘esempio.html’) è opportuno inserire delle etichette ad ogni intestazione del documento stesso: |<h1><a name="cap1">CAPITOLO 1</a></h1> | .... | .... |<h1><a name="cap2">CAPITOLO 2</a></h1> | .... | ecc. ecc. L’indice può risiedere nel documento stesso (di solito all’inizio) oppure in un altro; nel primo caso viene definito così: |<a href="#cap1">Capitolo 1. Il sistema di elaborazione</a> |<a href="#cap2">Capitolo 2. I sistemi operativi</a> | .... | ecc. ecc. Nel secondo caso invece (supponendo che l’indice sia in un altro documento ma nella stessa macchina e directory): |<a href="esempio.html#cap1">Capitolo 1. Il sistema di elaborazione</a> |<a href="esempio.html#cap2">Capitolo 2. I sistemi operativi</a> | .... | ecc. ecc. 2.11 Immagini nei documenti « Nei documenti HTML è possibile inserire immagini ed i formati più comunemente utilizzati sono GIF (Graphic Interchange Format) e JPEG (Joint Photographic Experts Group); i file corrispondenti hanno rispettivamente le estensioni «.gif» e «.jpg» o «.jpeg». Il formato GIF è stato sviluppato da Compuserve alla fine degli anni ’80 ed è particolarmente adatto per linee, icone, immagini generate dal computer e con colori netti, non sfumati; inoltre, Il linguaggio HTML 45 grazie a specifici software, le immagini GIF possono anche essere rese trasparenti e animate (qui però non approfondiamo queste possibilità). Il formato JPEG si è diffuso dal 1993 ed è progettato per le fotografie e per altre immagini con colori sfumati. Tra i due il formato GIF è senz’altro il più diffuso per il fatto che le immagini GIF sono solitamente poco «pesanti» e quindi si trasferiscono in tempi brevi. Si deve infatti notare che, quando viene richiesta ad un servente Web una pagina contenente immagini, quest’ultimo invia in risposta il file HTML corrispondente alla pagina e, separatamente, i file dove sono memorizzate le immagini; se questi ultimi sono molto grandi (e in presenza di collegamenti lenti alla rete) avremo dei tempi di attesa abbastanza lunghi per il completamento a video della pagina richiesta. A vantaggio delle immagini JPEG c’è la maggiore qualità (sono "a 24 bit" cioè possono avere 16 milioni di colori contro gli "8 bit" e 256 colori delle GIF) e la compattezza: la stessa immagine in formato JPEG occupa circa un quarto dello spazio in byte del formato GIF. Di solito comunque le immagini JPEG hanno un maggiore occupazione di memoria perché create con apparecchi fotografici, mediante acquisizione dallo scanner o da altre fonti ad alta qualità e definizione. Nel 1995 il W3C ha definito un nuovo formato di immagini per la rete, il PNG (Portable Network Graphics) che, almeno nelle intenzioni, avrebbe dovuto sostituire gli altri formati; infatti PNG prevede il supporto da 256 colori (con PNG-8 che può essere considerato il sostituto di GIF) fino a 16,7 milioni di colori (con PNG-24 che dovrebbe sostituire JPEG). Nella realtà il formato PNG, pur utilizzato, non ha mai sostituito del tutto gli altri formati. In conclusione possiamo dire che la scelta tra i formati dipende fortemente dalle caratteristiche delle immagini che si vogliono utilizzare; di solito in un documento Web si trovano immagini di tutti i formati citati. 2.11.1 Inserimento di immagini « L’elemento che si utilizza per l’inserimento di immagini è ‘<img>’; è un elemento di testo, prevede l’attributo ‘src’ per specificare il file contenente l’immagine e l’attributo ‘alt’ per indicare un testo alternativo nel caso quest’ultima non possa essere visualizzata. Esempio: |<img src="topolino.gif" alt="Topolino"/> In questo modo si inserisce l’immagine contenuta nel file di nome ‘topolino.gif’ residente nella directory corrente; il testo alternativo è Topolino. I motivi per cui può essere necessario il testo alternativo sono i seguenti: • il browser non supporta la grafica; • il browser è programmato per pronunciare testo al posto di immagini (per utenti non vedenti); • il browser è stato configurato solo per il testo in modo da velocizzare il caricamento dei documenti Web; Il linguaggio HTML 46 • dare la possibilità al browser di visualizzare il testo alternativo mentre l’immagine viene caricata; • l’immagine da visualizzare non viene trovata dal servente Web. 2.11.2 Posizionamento delle immagini « Le immagini possono essere posizionate con l’attributo ‘align’ del tag ‘<img>’; i valori possibili sono "top", "bottom" e "middle" per l’allineamento verticale e "left" e "right" per l’allineamento orizzontale. Il valore per difetto è "top" grazie al quale il bordo superiore dell’immagine è allineato con la riga di testo di cui essa fa parte (si ricordi che l’elemento ‘<img>’ è di testo). Invece con "bottom" è il bordo inferiore dell’immagine ad essere allineato con la riga di testo, mentre con "middle" quest’ultimo viene allineato con la parte centrale dell’immagine. Con le scelte "right" e "left" l’immagine viene posizionata rispettivamente al margine destro o sinistro della pagina ed il testo che segue l’elemento ‘<img>’ viene visualizzato affiancato all’immagine stessa. Se si vuole interrompere la visualizzazione del testo affiancato e far posizionare gli elementi successivi sotto l’immagine si deve usare l’interruzione di linea con attributo ‘clear’ nel seguente modo: |<br clear="left/"> |<!-- oppure --> |<br clear="right/"> |<!-- oppure --> |<br clear="all/"> rispettivamente nel caso che l’immagine sia sul bordo sinistro o sul bordo destro o ci siano immagini su entrambi i lati. L’esempio seguente mostra l’uso di alcuni degli attributi appena illustrati: |<html> |<head><title>Esempio posizionamento immagini</title></head> |<body> |<h1>Esempio posizionamento immagini</h1> |Prima immagine a destra e top con testo non affiancato |<img src="tux.jpg" align="right"/> |<br clear="right/"> |Altra immagine allineata bottom |<img src="tux.jpg" align="bottom"/> |<p><br/> |<img src="tux.jpg" align="left"/> |Immagine a sinistra con<br/> testo affiancato</p> |</body> |</html> Nella figura 2.53 viene mostrato l’aspetto della pagina aperta con un browser. Il linguaggio HTML 47 F | igura 2.53. 2.11.3 Dimensionamento delle immagini « Attraverso l’uso di altri attributi del tag ‘<img>’ si possono dimensionare le immagini, impostare lo spessore del bordo e stabilire quanto spazio vuoto lasciare tra esse e il testo che le circonda. Gli attributi ‘width’ e ‘height’ permettono di specificare rispettivamente la larghezza e l’altezza di un’immagine espressa in pixel. Esempio: |<img src="topolino.gif" width="100" height="200" alt="Topolino"/> L’attributo ‘border’ permette di specificare un bordo di un certo spessore espresso in pixel; il valore di difetto è zero che significa nessun bordo. Esempio: |<img src="topolino.gif" width="100" height="200" border="10" alt="Topolino"/> Si noti che in questo caso l’immagine avrà una larghezza totale di 120 pixel e un’altezza totale di 220 pixel. Con gli attributi ‘hspace’ e ‘vspace’ si indica infine lo spazio vuoto, sempre espresso in pixel, da lasciare a sinistra o destra (con ‘hspace’) e sopra e sotto (con ‘vspace’) all’immagine. Il linguaggio HTML 48 2.11.4 Collegamenti con immagini « E’ possibile usare immagini al posto del testo o anche insieme al testo come «ancore» per i collegamenti. Esempi: |<a href="http://pc01.max.planck/"><img src="topolino.gif"/></a> |<a href="http://pc01.max.planck/">Link a pc01<img src="topolino.gif"/></a> Nel primo caso il collegamento è definito sull’immagine, nel secondo è definito sia sull’immagine che sul testo. Occorre ricordare che alcuni navigatori aggiungono automaticamente un bordo blu intorno ad una immagine collegamento per evidenziare la presenza di quest’ultimo, quindi non è opportuno definire bordi personalizzati per tali immagini. 2.12 L’attributo ‘title’ « Questo attributo, che può essere usato praticamente con tutti i marcatori, permette di inserire una etichetta di testo che viene visualizzata come tooltip dal programma di navigazione quando l’utente si posiziona con il puntatore del mouse sull’elemento cui l’attributo è associato. Occorre prestare attenzione al fatto che qualche browser visualizza come tooltip per le immagini il testo alternativo ad esse associato (se presente); nel caso venga inserita qualche immagine che ha sia l’attributo ‘alt’ che l’attributo ‘title’, è quest’ultimo che viene preso in considerazione. Nell’esempio seguente viene usato l’attributo ‘title’ associato ad una immagine e in figura 2.58 viene mostrato l’effetto ottenuto. |<html> |<head><title>Esempio di attributo title su immagine</title></head> |<body> |<h1>Esempio attributo title su immagine</h1> |Posizionare il puntatore del mouse sull’immagine per ottenere la didascalia |<p/> |<img src="tux.jpg" alt="Immagine di Tux" title="Tux la mascotte di GNU/Linux"/> |</body> |</html> F | igura 2.58. 49 Capitolo 3 HTML: nozioni avanzate « In questo capitolo vengono esaminati alcuni aspetti del linguaggio HTML che possiamo definire «avanzati»: i tag ulteriori da usare nell’intestazione, le tabelle, i riquadri, gli oggetti multimediali, le immagini mappate. 3.1 Informazioni supplementari nell’intestazione « La sezione intestazione di un documento HTML può contenere altre informazioni oltre al titolo del documento che, come abbiamo visto nel capitolo precedente, viene assegnato tramite il tag ‘<title>’. Esistono infatti i seguenti elementi che possono essere inseriti al suo interno: ‘<meta>’, ‘<link>’, ‘<base>’, ‘<style>’, ‘<script>’, ‘<isindex>’. 3.1.1 L’elemento ‘meta’ « E’ un elemento usato per descrivere alcune proprietà del documento ed è solitamente accompagnato dall’attributo ‘name’ o da ‘http-equiv’ che a loro volta necessitano dell’attributo ‘content’. Vediamo alcuni esempi di uso del marcatore ‘<meta>’ con attributo ‘name’: |<meta name="Author" content="Paolino Paperino"/> |<meta name="Copyright" content="Walt Disney Italia"/> In questo modo si informa il programma di navigazione su chi è l’autore del documento e si danno informazioni sul copyright. |<meta name="generator" content="Mozilla/4.04 [en] (Win95; I) [Netscape]"/> Qui invece si indica il programma usato per creare il documento HTML; quando si usano editor HTML una linea simile a questa viene automaticamente inserita nella sezione di intestazione. Nell’esempio l’editor usato è la versione ‘4.04’ in inglese di ‘Netscape Navigator’ (conosciuta con il "soprannome" di ‘Mozilla’). Altri esempi: |<meta name="description" content="Breve descrizione del documento"/> |<meta name="keywords" content="Qui, Quo, Qua, 313, Paperopoli, Paperina"/> In questi esempi si danno informazioni utili per i ‘motori di ricerca’ (programmi in grado di indicizzare i siti Web per poi permettere agli utenti di Internet ricerche basate sui criteri più vari); qui si forniscono una piccola descrizione della pagina Web ed una serie di parole chiave riguardanti il suo contenuto, inserendo rispettivamente description e keywords nell’attributo ‘name’ e i valori corrispondenti in ‘content’. L’attributo ‘http-equiv’ è usato per vari scopi, ad esempio: • per causare il refresh automatico della pagina dopo un certo tempo (nell’esempio 15 secondi): HTML: nozioni avanzate 50 |<meta http-equiv="refresh" content="15"/> • per richiamare automaticamente un’altra pagina trascorso un certo tempo: |<meta http-equiv="refresh" content="10;url=http://www.aaa.it/altrapagina.html"/> • per evitare che il documento venga memorizzato nella cache e quindi il navigatore richieda sempre una nuova copia dello stesso: |<meta http-equiv="expires" content="0"/> Inoltre può essere usato per indicare la data di scadenza della pagina in modo che i navigatori prelevino la versione aggiornata al momento opportuno: |<meta http-equiv="expires" content="Sat, 4 Nov 2000 12:00:00 GMT"/> Metodi alternativi per evitare la memorizzazione del documento nella cache sono i seguenti: |<meta http-equiv="Pragma" content="no-cache"/> |<meta http-equiv="Cache-Control" content="no-cache, must revalidate"/> L’attributo ‘http-equiv’ può essere utilizzato anche per classificare il contenuto del documento in modo che possano essere attivati meccanismi di protezione per i minori da parte dei programmi di navigazione; tali aspetti non vengono comunque approfonditi in questa sede. 3.1.2 L’elemento ‘link’ « Con questo elemento si possono definire delle relazioni tra il documento ed altre pagine Web. Attenzione a non confondere questo tag con un collegamento («link» in inglese) che, come abbiamo visto, si realizza con il tag ‘<a>’. Sono previsti i due attributi ‘rel’ e ‘rev’, con il primo si stabilisce una relazione tra il nostro documento ed un’altra pagina Web, con il secondo invece si indica che un’altra pagina è in relazione con la nostra. Se ad esempio abbiamo una pagina chiamata ‘pagina1.html’ che fa parte di un sito il cui indice è memorizzato (come avviene di solito) in ‘index.html’, può essere opportuno indicare nella testata di ‘pagina1.html’: |<link rel="index" href="index.html"> in tal modo i navigatori e i motori di ricerca saranno informati della relazione esistente tra i due documenti e lo saranno ancora meglio se nella testata di ‘index.html’ si inserisce: |<link rev="index" href="pagina1.html"> Queste informazioni potrebbero anche essere sfruttate da browser avanzati che includano tra i pulsanti di navigazione un tasto «Index» che permetta di saltare immediatamente all’indice del HTML: nozioni avanzate 51 sito in cui è contenuta la pagina visualizzata. 3.1.3 Gli elementi ‘base’, ‘script’, ‘style’, ‘isindex’ « Gli elementi ‘<base>’ (con il quale si può indicare la URL in cui risiede il documento) e ‘<isindex>’ (indica che la pagina è in effetti un programma che effettua operazioni di ricerca) sono poco importanti ed usati molto raramente. Invece i marcatori ‘<style>’ e ‘<script>’ sono molto importanti in quanto servono per utilizzare «fogli di stile» e istruzioni di certi linguaggi di «scripting» all’interno delle pagine Web; tali argomenti vengono approfonditi più avanti in queste dispense (capitolo 4 e paragrafo 8). 3.2 Uso delle tabelle « Le tabelle sono elementi molto usati per la realizzazione di documenti in HTML in quanto permettono di organizzare i dati in strutture formate da righe e colonne ma soprattutto perché con esse si può impostare l’aspetto di una pagina disponendo i paragrafi in colonne, oppure creando dei margini, o ancora distribuendo testo ed immagini in modo più vario. Questo modo di usare le tabelle, pur ancora molto frequente, è da considerare deprecato a vantaggio del posizionamento ottenuto attraverso i fogli di stile. Nelle tabelle di un documento HTML, come in qualsiasi tabella si identificano i seguenti componenti: • il titolo, opzionale, della tabella; • le celle, cioè le intersezioni tra righe e colonne, che contengono i dati; • le intestazioni delle righe o colonne, cioè delle celle contenenti le etichette che identificano i tipi di dati delle righe o colonne corrispondenti. La tabella più piccola che si può creare contiene una sola cella, cioè una riga e una colonna; non ci sono invece restrizioni teoriche sul numero massimo di celle definibili; esiste però un limite dettato da ragioni pratiche in quanto è opportuno che la tabella entri per larghezza nella finestra del browser onde evitare il ricorso, scomodo e spesso sgradito, alla barra di scorrimento orizzontale di quest’ultimo. Le tabelle sono supportate da tutti i programmi di navigazione e ne esistono due diversi modelli: quello dell’‘HTML 3.2’ contenente una serie molto semplice di elementi e quello dell’‘HTML 4.0’ che ha introdotto nuovi attributi conservando però la compatibilità con il precedente. Nella maggior parte dei casi è sufficiente conoscere il modello di tabelle più semplice che è quindi quello trattato in questa sede; le funzioni più complesse dell’‘HTML 4.0’ sono necessarie solo per lavori abbastanza sofisticati. HTML: nozioni avanzate 52 3.2.1 Esempi di tabelle « Introduciamo gli elementi per la definizione delle tabelle con un semplice esempio: |<html> |<head> |<title>Esempio 1 con tabelle</title> |</head> |<body> |<p> |<table border> |<caption>Tabella di prova</caption> |<tr> |<th>Alunno</th> |<th>Voto orale</th> |<th>Voto scritto</th> |<th>Media</th> |</tr> |<tr> |<td>Pippo</td> |<td>5</td> |<td>7</td> |<td>6</td> |</tr> |<tr> |<td>Pluto</td> |<td>6</td> |<td>8</td> |<td>7</td> |</tr> |</table> |</p> |</body> |</html> L’elemento da usare per la creazione di una tabella è ‘<table>’; è un elemento di blocco e richiede il tag ‘</table>’ alla fine della definizione della tabella stessa. Con ‘<caption>’ e ‘</caption>’ si può inserire il titolo della tabella. Il tag ‘<tr>’ definisce le varie righe, suddivise in celle il cui contenuto è definito con ‘<td>’ per le celle normali, o con ‘<th>’ per le intestazioni. I tag ‘</tr>’, ‘</td>’, ‘</th>’ non sono obbligatori. L’esempio precedente viene visualizzato nel modo mostrato nella figura 3.12. F | igura 3.12. HTML: nozioni avanzate 53 Vediamo anche un esempio di tabella in cui le intestazioni sono per riga invece che per colonna: |<html> |<head> |<title>Esempio 2 con tabelle</title> |</head> |<body> |<p> |<table border cellpadding="9"> |<caption>Tabella 2</caption> |<tr> |<th>Matematica</th> |<td>Prof. Pippo</td> |<td>Ore: 5</td> |</tr> |<tr> |<th>Storia</th> |<td>Prof. Pluto</td> |<td>Ore: 3</td> |</tr> |</table> |</p> |</body> |</html> Il risultato in questo caso è quello di figura 3.14. F | igura 3.14. 54 HTML: nozioni avanzate Nel seguente, ulteriore esempio si ha invece una tabella con le intestazioni sia nelle righe che nelle colonne: |<html> |<head> |<title>Esempio 3 con tabelle</title> |</head> |<body> |<p> |<table align="center" border="15"> |<caption>Terza tabella</caption> |<tr> |<th>Alunni/Materie</th> |<th>Italiano</th> |<th>Storia</th> |<th>Matematica</th> |<th>Diritto</th> |</tr> |<tr> |<th>Pippo</th> |<td>5</td> |<td>7</td> |<td>6</td> |<td>6</td> |</tr> |<tr> |<th>Pluto</th> |<td>6</td> |<td>8</td> |<td>7</td> |<td>7</td> |</tr> |<tr> |<th>Paperino</th> |<td>6</td> |<td>6</td> |<td>7</td> |<td>7</td> HTML: nozioni avanzate 55 |</tr> |</table> |</p> |</body> |</html> In questo caso si ottiene quanto mostrato in figura 3.16. F | igura 3.16. 3.2.2 Attributi dell’elemento ‘table’ « Gli attributi degli elementi per la definizione delle tabelle sono tutti opzionali; se non se ne specifica alcuno si ottiene una tabella allineata a sinistra e senza bordi. Iniziamo a considerare gli attributi del marcatore ‘<table>’ che sono: ‘align’, ‘border’, ‘cellspacing’, ‘cellpadding’, ‘bgcolor’, ‘width’. Con l’attributo ‘align’, usato nel terzo degli esempi precedenti, si specifica l’allineamento della tabella; i valori possono essere "left" (valore per difetto), "center" e "right". Attraverso ‘bgcolor’ si specifica il colore dello sfondo della tabella usando i codici dei colori visti in precedenza. L’attributo ‘border’ permette di aggiungere i bordi a tutte le celle della tabella; se si specifica anche un valore in pixel, come nel terzo esempio, si ottiene il dimensionamento dei bordi, ma solo di quelli esterni. Con ‘cellspacing’ e ‘cellpadding’ si può specificare di quanti pixel distanziare rispettivamente una cella da un’altra cella e il bordo delle celle dal loro contenuto (come è stato fatto nel secondo esempio). Con ‘width’ si imposta la grandezza della tabella, in percentuale rispetto alla larghezza della finestra del browser, oppure in base a un valore espresso in pixel. Ad esempio: 56 HTML: nozioni avanzate |<table width="50%"> oppure: |<table width="300"> Se questo attributo non viene usato, la tabella è dimensionata in base al contenuto della sue celle; a questo proposito è opportuno sottolineare, come emerge anche dagli esempi, che la larghezza di una colonna di una tabella è determinata dalla larghezza della cella più grande appartenente alla colonna stessa; allo stesso modo l’altezza di una riga si adegua all’altezza della cella più grande presente in essa. 3.2.3 Attributi del titolo « All’interno del titolo, cioè tra ‘<caption>’ e ‘</caption>’ si possono inserire solo elementi di testo. Con l’attributo ‘align’ si può decidere se il titolo sta sopra (impostazione per difetto) o sotto la tabella: |<caption align="top">Titolo sopra</caption> oppure: |<caption align="bottom">Titolo sotto</caption> 3.2.4 Attributi delle righe e delle celle « I tag ‘<tr>’, ‘<th>’, ‘<td>’ prevedono gli attributi ‘align’, ‘valign’, ‘bgcolor’; esistono inoltre gli attributi ‘rowspan’, ‘colspan’, ‘width’ che si applicano solo a ‘<th>’ e ‘<td>’. Con ‘align’ si imposta l’allineamento orizzontale dei dati in una cella o in tutte le celle di una riga a seconda che tale attributo sia abbinato a ‘<td>’ e ‘<th>’ oppure a ‘<tr>’; il valore per difetto è "left" e gli altri possibili sono "center" e "right". Con ‘valign’ invece si imposta l’allineamento verticale dei dati; i valori possibili sono: "top", "middle" (valore per difetto), "bottom", "baseline". Il valore "baseline" è simile a "top" e imposta quindi un posizionamento in alto nella cella; la differenza è nel fatto che con "baseline" la parte inferiore della prima riga di testo di ogni cella è sempre allineata qualunque sia la dimensione dei caratteri usati nelle varie celle. L’attributo ‘bgcolor’ permette di specificare il colore di sfondo di una riga o di una cella e questa impostazione prevale sull’impostazione dell’intera tabella; se ad esempio abbiamo: |<table bgcolor="#FF0000"> |<tr> |<td>Cella 1</td> |<td>Cella 2</td> |</tr> |<tr bgcolor="#00FF00"> HTML: nozioni avanzate 57 |<td>Cella 3</td> |<td bgcolor="#0000FF">Cella 4</td> |</tr> |</table> La tabella ha lo sfondo rosso ma la seconda riga lo ha verde e la cella 4, che fa parte della seconda riga, ha lo sfondo blu. Gli attributi ‘colspan’ e ‘rowspan’ servono ad unire orizzontalmente e verticalmente più celle di una tabella; vediamone il funzionamento con un esempio in cui si usa ‘rowspan’ (l’utilizzo di ‘colspan’ è analogo): |<html> |<head> |<title>Esempio 4 con tabelle</title> |</head> |<body> |<p> |<table border> |<caption>Tabella n. 4</caption> |<tr> |<th rowspan="2">Milano</th> |<td>Minima</td> |<td>-2</td> |</tr> |<tr> |<td>Massima</td> |<td>10</td> |</tr> |<tr> |<th rowspan="2">Roma</th> |<td>Minima</td> |<td>4</td> |</tr> |<tr> |<td>Massima</td> |<td>13</td> |</tr> |</table> |</p> |</body> |</html> Il risultato che si ottiene è quello mostrato in figura 3.23. HTML: nozioni avanzate 58 F | igura 3.23. Infine l’attributo ‘width’ permette di specificare la larghezza in pixel di una cella indipendentemente dal suo contenuto; ad esempio: |<td width="20"></td> Si ricordi comunque che le celle di una colonna assumono sempre una larghezza pari a quella della cella più larga della colonna stessa. In una cella si può inserire praticamente tutto ciò che può essere definito nella sezione ‘body’ di un documento: • testo; • elementi di blocco (paragrafi, elenchi, altre tabelle, ecc.) • elementi di testo (font, collegamenti, immagini, ecc.) Grazie a questo, come detto in precedenza, le tabelle vengono anche usate per definire la disposizione degli elementi all’interno della pagina; ovviamente in questo caso si evita di definire i bordi, le celle di intestazione, il titolo e tutto quello che può rendere «visibile» la tabella stessa. Il documento HTML dell’esempio seguente è appunto «impaginato» usando una tabella che qui serve a posizionare con precisione tre piccole immagini allineate orizzontalmente e le relative didascalie sotto di esse: |<html> |<head><title>Esempio di posizionamento usando tabella</title> |</head> |<body> |<h1 align="center">Prova di posizionamento attraverso tabella</h1> |<p>Le seguenti immagini, con relative didascalie, sono |posizionate grazie all’uso di una tabella: le immagini sono |inserite nelle tre celle della prima riga, le stringhe nelle |tre celle della seconda riga.</p> |<p/><br/><p/> HTML: nozioni avanzate 59 |<table cellpadding="10"> |<tr> |<td width="200" align="center"><img src="tux.jpg" width="100" height="120"/></td> |<td width="200" align="center"><img src="tux_univ.jpg" width="100"←,→height="120"/></td> |<td width="200" align="center"><img src="Family_linux.png" width="160"←,→height="120"/></td> |</tr> |<tr> |<td align="center">Tux</td> |<td align="center">Tux studente</td> |<td align="center">Tux ... e famiglia</td> |</tr> |</table> |</body> |</html> Nella figura 3.26 vediamo come viene visualizzata la pagina. F | igura 3.26. Il risultato che si ottiene inserendo i vari elementi come contenuto delle celle di una grossa tabella è solitamente accettabile, ma è utile ribadire che lo stesso risultato (se non migliore) si ottiene in modo più appropriato ed «elegante» con i fogli di stile. 3.2.5 Creazione di celle vuote « Per creare una cella vuota è sufficiente digitare il tag ‘<td>’ seguito immediatamente da ‘</td>’; può però accadere che qualche browser non visualizzi i bordi di una cella vuota. Per essere sicuri che i bordi siano visibili è possibile inserire nella cella vuota uno spazio unificatore: |<td> </td> HTML: nozioni avanzate 60 3.2.6 Tabelle nidificate « Una tabella è nidificata quando viene inserita in una cella di un’altra tabella. L’uso di tabelle nidificate è anche un modo per ottenere due tabelle affiancate; basta infatti inserire le due tabelle da affiancare in due celle di una tabella «madre» definita senza bordo: |<html> |<head> |<title>Esempio 5 con tabelle</title> |</head> |<body> |<p> |<table align="center"> |<caption>Tabella n. 5</caption> |<tr> |<td> | <table border="10"> | <caption>I Quadrimestre</caption> | <tr><td></td><th>Orale </th><th>Scritto</th> | <th>Pratico </th></tr> | <tr><td>Pippo </td><td>6 </td><td>7 </td><td>7</td></tr> | <tr><td>Pluto </td><td>7 </td><td>8 </td><td>8</td></tr> | </table> |</td> |<td> | <table border="10"> | <caption>II Quadrimestre</caption> | <tr><td></td><th>Voto finale </th></tr> | <tr><td>Pippo </td><td>7 </td></tr> | <tr><td>Pluto </td><td>8 </td></tr> | </table> |</td> |</tr> |</table> |</p> |</body> |</html> Il risultato che si ottiene è quello mostrato in figura 3.29. F | igura 3.29. HTML: nozioni avanzate 61 3.3 Riquadri e riquadri in linea « In questo paragrafo vengono illustrati i riquadri (frame) e i riquadri in linea (inline frame). Si ricorda che l’uso di questi elementi è deprecato a meno che non si faccia riferimento alla variante «Frameset» dell’HTML; qui vengono trattati perché permettono in modo semplice di gestire più documenti HTML in una singola pagina. 3.3.1 Uso dei riquadri « I riquadri sono delle suddivisioni della finestra del browser in cui possono essere visualizzati documenti HTML diversi. Un esempio in cui possono essere utili è se si hanno siti Web con molti livelli di pagine: in tal caso si potrebbe pensare di usare un riquadro per visualizzare un indice del sito in modo permanente ed un altro per contenere le varie pagine che si richiamano durante la navigazione. Per definire una pagina che deve contenere riquadri si usa un documento HTML particolare chiamato ‘frameset’ che si differenzia da quelli visti finora in quanto contiene l’elemento ‘<frameset>’ al posto di ‘<body>’. Vediamo un esempio: |<html> |<head> |<title>Esempio con riquadri</title> |</head> |<frameset cols="35%,65%" bordercolor="#00FF00"> |<frame src="doc1.html"/> |<frame src="doc2.html" name="frame2"/> |<noframes> |<body> |Se vedete questo messaggio il vostro browser non gestisce i frame. |Per visualizzare i documenti cliccare sui link: |<a href="doc1.html">Primo documento</a> |<a href="doc2.html">Secondo documento</a> |</body> HTML: nozioni avanzate 62 |</noframes> |</frameset> |</html> Il bordo dei riquadri viene impostato di colore verde con l’attributo ‘bordercolor’ (per difetto il colore assegnato è il grigio); grazie all’attributo ‘cols’ con valore "35%,65%" si ha una suddivisione in due colonne contenenti rispettivamente i documenti ‘doc1.html’ e ‘doc2.html’. La parte del documento compresa tra i marcatori ‘<noframes>’ e ‘</noframes>’ serve a rendere fruibile la pagina anche ai programmi di navigazione che non gestiscono i riquadri; essa è alternativa al ‘frameset’ e contiene una sezione ‘body’ come i «normali» documenti HTML. L’aspetto del documento viene mostrato nella figura 3.31; i messaggi di file non trovato dipendono dal fatto che i due documenti ‘doc1.html’ e ‘doc2.html’ non sono stati creati. F | igura 3.31. Volendo ottenere una suddivisione in riquadri orizzontali si deve usare l’attributo ‘rows’ al posto di ‘cols’; è anche possibile usare entrambi gli attributi per definire delle "griglie" di riquadri come nel seguente esempio: |<frameset cols="300,*" rows="25%,50%,25%"> La grandezza dei riquadri può essere specificata anche in pixel: nell’esempio la prima colonna è grande 300 pixel, mentre il carattere «*» significa che la seconda colonna occupa lo spazio restante nella finestra. Esiste anche la possibilità di usare riquadri nidificati continuando a dividerli in più parti fino ad un massimo di nove riquadri presenti nella finestra. Si deve però tenere presente che l’uso contemporaneo di più di due o tre riquadri in una finestra può favorire errori nella realizzazione del documento e può creare disorientamento nell’utente che lo visualizza. Quando si usano i riquadri nidificati, il primo ‘frameset’ si chiama «‘frameset’ di appartenenza» e gli altri «‘frameset’ dipendenti». HTML: nozioni avanzate 63 Vediamo un esempio con riquadri nidificati: |<html> |<head> |<title>Esempio con riquadri nidificati</title> |</head> |<frameset cols="250,*"> | <frame src="doc1.html"/> | <frameset rows="50%,50%"> | <frame src="doc2.html" name="frame2"/> | <frame src="doc3.html" name="frame3"/> | </frameset> |</frameset> |</html> In questo modo si ottiene una finestra suddivisa in due colonne, una larga 250 pixel, l’altra la restante parte dello spazio, a sua volta suddivisa in due righe di uguale grandezza. L’attributo ‘name’ del tag ‘<frame>’ serve ad assegnargli un nome; questo è utile nel caso si voglia fare in modo che i collegamenti attivati su un riquadro abbiano "effetto" su un altro. Ad esempio possiamo avere in ‘doc1.html’ il collegamento seguente in cui si fa uso dell’ulteriore attributo ‘target’: |<a href="doc4.html" target="frame2">Cliccare per vedere documento 4</a> Se viene attivato questo collegamento, il riquadro che lo contiene non si altera mentre in quello chiamato "frame2" si ha la visualizzazione della pagina ‘doc4.html’, come mostrato nella figura 3.35. F | igura 3.35. Nel caso in un documento ci siano molti collegamenti tutti con stesso ‘target’ si può evitare di scrivere l’attributo per ognuno di essi ricorrendo all’elemento ‘<base>’ da inserire nella sezione ‘head’ nel seguente modo: HTML: nozioni avanzate 64 |<head> |<title>Titolo</title> |<base target="nome_frame"> |</head> Esistono quattro nomi di destinazioni "speciali" che è possibile assegnare all’attributo ‘target’ e precisamente: • "_blank": indica di caricare il documento aprendo una nuova finestra del navigatore; • "_parent": fa riferimento al ‘frameset’ di appartenenza (può essere utile se si usano riquadri nidificati); • "_self": indica di caricare il documento nel riquadro corrente (questa è l’impostazione per difetto e quindi ha senso usarla solo nel caso si voglia cambiare la destinazione stabilita con un ‘base target’ precedente); • "_top" è forse l’opzione più utile e permette di rimuovere tutti i riquadri presenti nella finestra. Altri attributi del tag ‘<frame>’ sono: • ‘frameborder’, con valori "0" oppure "1" (per difetto è "1"): con "0" si elimina il bordo di separazione tra un riquadro e quello adiacente; si possono usare anche i valori "no" per avere un bordo normale e "yes" per averlo tridimensionale e si può anche impostare lo spessore del bordo con l’attributo ‘border’ del tag ‘<frameset>’; questi attributi comunque sono estensioni HTML fuori dallo standard; • ‘borderwidth, borderheight’, si possono usare per stabilire quanto spazio in pixel deve essere inserito tra i bordi del riquadro (rispettivamente i bordi destro e sinistro oppure superiore e inferiore) ed il suo contenuto; • ‘noresize’, permette di impedire il ridimensionamento del riquadro da parte dell’utente; • ‘scrolling’, con valori "yes" oppure "no" oppure "auto"; il valore per difetto è "auto" ed indica che le barre di scorrimento vengono aggiunte al riquadro automaticamente quando necessario; il valore "yes" le fa inserire sempre ed il valore "no" mai (sconsigliato). 3.3.2 Riquadri in linea « I riquadri in linea sono elementi di testo che permettono di visualizzare un documento separato come parte di una pagina; i marcatori da usare sono ‘<iframe>’ e ‘</iframe>’ con gli stessi attributi del tag ‘<frame>’ ed in più ‘width’, ‘height’ e ‘align>’, con ovvio significato. Un riquadro in linea dovrebbe sempre contenere anche del testo alternativo da visualizzare se il browser non supporta tale elemento. Vediamo un esempio: |<html> |<head> |<title>Esempio con gli iframe</title> |</head> HTML: nozioni avanzate 65 |<body> |<i>Dopo questo testo abbiamo un elemento iframe contenente un altro |documento HTML.</i> |<p/> |<div align="center"> |<iframe src="doc2.html" name="riquadro"/> |<p>Testo alternativo: il browser non supporta i riquadri in linea.</p> |<p><a href="doc1.html">Cliccare qui per il documento</a></p> |</iframe> |</div> |</body> |</html> Nella figura 3.38 vediamo l’aspetto del documento. F | igura 3.38. Anche ai riquadri in linea può essere assegnato un nome, esattamente allo stesso scopo visto per i riquadri: riferendosi all’esempio, è possibile definire in un altra pagina un collegamento che, grazie all’attributo ‘target’ con valore "riquadro", fa aprire un documento all’interno del riquadro in linea. 3.4 Oggetti multimediali « Per inserire oggetti multimediali (suoni e filmati) in un documento HTML si usa principalmente l’elemento di testo ‘<object>’. Grazie alla tecnica dello streaming è anche possibile ascoltare suoni e vedere filmati in tempo reale (cioè durante il trasferimento, senza dover attendere che il file relativo all’oggetto multimediale sia stato completamente scaricato dalla rete) ma sono necessari appositi programmi come ‘RealPlayer’. Si deve comunque tenere conto che in assenza di connessioni veloci alla rete la riproduzione di filmati e brani musicali scaricati da Internet avviene con una qualità praticamente inaccettabile. I formati più comuni dei file audio sono: • .au: Unix audio; • .wav: Microsoft Wave; HTML: nozioni avanzate 66 • .aif: Macintosh audio; • .ra o .ram: RealAudio; • .mid o .midi: MIDI (Music Instrument Digital Interface); • .mp3: standard MPEG-1 audio layer III. I primi quattro contengono suoni digitalizzati con una qualità non eccezionale e una richiesta di memoria notevole per pochi secondi di registrazione. I file MIDI invece contengono "istruzioni musicali" che vengono interpretate ed eseguite dalla scheda audio del computer che così può riprodurre il brano; sono file molto piccoli e offrono suoni di elevata qualità. I file mp3 sono sicuramente i più "famosi" e stanno cambiando la maniera di acquisire, ascoltare, archiviare musica. L’mp3 è uno standard di compressione di musica digitalizzata che permette di memorizzare brani con qualità pari a quella dei CD musicali occupando circa un decimo dello spazio che sarebbe necessario senza la compressione (una canzone di tre minuti occupa circa 3 MB di memoria). Diventa quindi possibile scaricare i brani da Internet anche con una normale connessione casalinga, ascoltarli con opportuni lettori software, conservarli sulle proprie memorie di massa o copiarli su lettori mp3. Passando ai formati video possiamo citare: • .mpg o .mpeg: MPEG (Moving Pictures Expert Group); • .avi: Microsoft AVI (Audio Video Interleave); • .mov o .qt: QuickTime. Tutti i tipi di file video supportano anche l’audio associato ma occupano una grande quantità di memoria (almeno 1 Mb per 30 secondi di filmato). I migliori sono i filmati MPEG che offrono anche una buona qualità di riproduzione. 3.4.1 Attributi degli oggetti multimediali « L’elemento ‘<object>’ prevede gli attributi ‘data’, ‘type’ e molti degli attributi già visti per le immagini (per definire larghezza, altezza, allineamento, bordo, ecc.). Non è invece previsto l’attributo ‘alt’ in quanto il testo alternativo si inserisce semplicemente tra i tag ‘<object>’ e ‘</object>’. Esempi: |<object data="symphony.mid" type="audio/midi"> |Sinfonia in formato midi</object> |<object data="meteo.mov" type="video/quicktime" align="left"←,→width="200" height="150"> |Filmato da satellite meteo</object> L’attributo ‘type’ può essere tralasciato a patto che il browser sia in grado di identificare il tipo di oggetto multimediale solo dall’estensione del suo nome. In certi casi è possibile specificare altri tag: ad esempio, nel caso di file midi, per far partire HTML: nozioni avanzate 67 automaticamente la riproduzione del brano: |<object data="symphony.mid" type="audio/midi"> |<param name="autostart" value="true"/> |Sinfonia in formato midi con autostart |</object> 3.5 Immagini mappate « Abbiamo visto in precedenza come sia possibile inserire in un documento un collegamento ancorato su una immagine; solitamente l’effetto dell’attivazione del collegamento è sempre lo stesso in qualsiasi punto dell’immagine si agisca. Con le immagini mappate è invece possibile definire collegamenti diversificati per le varie zone di una immagine. Gli elementi da utilizzare per includere delle immagini a mappa in un documento sono ‘<map>’, ‘<area>’ e l’attributo ‘usemap’ di ‘img’ nel seguente modo: |<map name="nomemappa"> |<area shape="rect" coords="x1,y1,x2,y2" href="doc1.html" /> |<area shape="rect" coords="x3,y3,x4,y4" href="doc2.html" /> |</map> |<img src="nome_immagine.jpg" usemap="#nomemappa"/> In questo modo viene definita una immagine di mappa con nome nomemappa e due aree definite come rettangoli con vertici (x1,y1), (x2,y2) e (x3,y3), (x4,y4) che puntano rispettivamente a ‘doc1.html’ e ‘doc2.html’. I valori possibili di ‘shape’ sono: • "rect", permette di definire un’area rettangolare specificando con ‘coords’ le coordinate dei vertici alto a sinistra e basso a destra; • "circle", in tal caso l’area è un cerchio e con ‘coords’ si specificano x,y,r cioè le coordinate del centro e il raggio; • "poly", in questo modo si definisce un poligono e con ‘coords’ si indicano le coordinate dei suoi vertici. Per usare la mappa così definita si deve poi ricorrere al tag ‘img’ con l’attributo ‘usemap’ come mostrato nell’esempio precedente. Si deve notare che il riferimento all’immagine con ‘img’ non deve necessariamente essere inserito subito dopo la definizione della mappa fatta con ‘<map>’, ma può essere in qualsiasi punto del documento; si noti inoltre che il valore si ‘usemap’ è un indirizzo URL: nell’esempio si fa riferimento ad una mappa definita nello stesso documento in cui è inserito l’elemento ‘<img>’, ma si potrebbe usare una mappa definita in un altro file o addirittura in un altro sito Web. 68 HTML: nozioni avanzate 69 Capitolo 4 I fogli di stile « In questo capitolo vengono esaminati gli aspetti fondamentali della natura e dell’uso dei «fogli di stile a cascata» o CSS (Cascading Style Sheet) della cui importanza si è già accennato precedentemente. 4.1 Caratteristiche dei fogli di stile « I CSS sono raccolte di regole riguardanti la presentazione di un documento HTML e che non influiscono sulla sua struttura interna. Questo è un primo motivo per cui essi si fanno preferire rispetto ai tag HTML utilizzabili per variare l’aspetto del documento. Altri vantaggi sono: la maggiore varietà di «interventi» realizzabili, grazie ai CSS, sull’aspetto della pagina; la possibilità di creare facilmente un’unica definizione delle caratteristiche di un certo sito esternamente alle sue pagine, cosa che porta un duplice ulteriore beneficio: • l’aspetto di tutte le pagine risulta uniforme; • le modifiche riguardanti l’esteriorità delle varie pagine non devono essere fatte in ognuna di esse ma solo una volta nel file contenente le definizioni del foglio di stile. Occorre comunque segnalare che, a fronte di questi vantaggi, i fogli di stile presentano anche un inconveniente dovuto al mancato rispetto degli standard CSS da parte di qualche programma di navigazione; può infatti accadere che le stessa pagina, costruita con determinate regole di stile, venga visualizzata in modo diverso da browser diversi. Al momento gli standard riguardanti i fogli di stile, rilasciati dal W3C, sono CSS1, CSS2 e CSS3; la sintassi non prevede distinzione fra maiuscole e minuscole ma in queste dispense si preferisce l’uso delle minuscole in coerenza con la scelta fatta riguardo ai sorgenti HTML. 4.2 Struttura delle regole di stile « Un foglio di stile è costituito da varie regole ognuna delle quali formata da un «selettore» e da un «blocco di dichiarazioni»; ogni dichiarazione consiste poi nell’associazione tra una «proprietà» e il relativo «valore». L’insieme delle dichiarazioni deve essere racchiuso tra i simboli «{» e «}»; ogni dichiarazione deve essere conclusa con «;» e fra proprietà e rispettivo valore deve essere inserito un «:». Il selettore determina, nell’ambito del documento HTML che fa uso di quella regola di stile, a quale elemento o a quali elementi si applicano le formattazioni specificate con le successive dichiarazioni. Dei modi con cui le regole di stile possono essere associate a un documento HTML si occupa il prossimo paragrafo (4.3). Come primo esempio di regola di stile si consideri la seguente: |h1 {color: red; font-style: italic;} Anche senza conoscere ulteriori dettagli sulla definizione delle regole di stile è abbastanza semplice capire che la regola in questione permette di ottenere intestazioni di primo livello (selettore I fogli di stile 70 ‘h1’) con testo di colore rosso e in corsivo. 4.2.1 Definizione dei selettori « Un selettore può definire gli elementi da formattare nei seguenti modi: • in base al nome dell’elemento; • in base a raggruppamenti di elementi in classi e in ID; • in base al fatto che gli elementi abbiano certi attributi e valori; • in base al contesto cui l’elemento appartiene; • in base a pseudo-classi e a pseudo-elementi. La definizione può anche avvenire combinando uno o più dei succitati criteri. Inoltre è possibile applicare le stesse dichiarazioni a più selettori semplicemente elencandoli separati da una «,». 4.2.1.1 Selettori basati sul nome di elementi « Questa categoria di selettori è molto semplice in quanto gli elementi cui si vogliono applicare le regole si identificano con il nome che hanno nel linguaggio HTML. Nell’esempio precedente si è visto un selettore di questo tipo, identificato con ‘h1’, che permette di applicare le regole specificate nelle successive dichiarazioni a tutti i marcatori ‘<h1>’. Vediamo un altro esempio con il quale facciamo in modo che tutti i paragrafi e le intestazioni di livello tre abbiano testo di colore verde e giustificato: |p,h3 {color: green; text-align: justify;} 4.2.1.2 Selettori di classe e selettori ID « Attraverso le classi e gli ID si possono specificare regole da applicare in modo indipendente dai marcatori HTML. Una classe si definisce utilizzando il simbolo «.» seguito dal nome della classe e preceduto (non obbligatoriamente) dal nome di un marcatore. Vediamo un esempio: |p.classe1 {color: red; text-align: left;} |.classe2 {font-weight: bold;} In questo modo vengono definita una classe classe1 relativa al marcatore ‘<p>’ e una classe classe2 relativa a qualsiasi marcatore. Nel codice HTML si può fare riferimento a queste regole usando l’attributo ‘class’ per i tag cui si vogliono applicare; ad esempio: I fogli di stile 71 |<h1 class="classe2">Titolo di classe2</h1> |<p class="classe1"> |Testo di colore rosso e allineato a sinistra</p> |<p> |Paragrafo normale</p> |<p class="classe2"> |Paragrafo con caratteri in grassetto</p> Come si vede la classe classe2 si può associare a qualsiasi tag, mentre la classe classe1 solo a marcatori ‘<p>’. Un ID si definisce utilizzando il simbolo «#» seguito dal nome della classe e preceduto (non obbligatoriamente) dal nome di un marcatore. Vediamo un esempio: |#ident1 {color: green; font-style: italic;} Nel codice HTML si può fare riferimento a questa regola usando l’attributo ‘id’ per il tag cui si vuole applicare tali formattazioni, ad esempio nel modo seguente: |<h1 id="ident1">Titolo con ID ident1</h1> |<p> |Paragrafo normale</p> La differenza fondamentale tra i selettori di classe e i selettori ID è che i primi si possono usare in associazione a quanti si vuole elementi, i secondi invece una sola volta all’interno di un documento HTML. Quindi le regole da utilizzare per molteplici elementi del documento si definiranno per selettori di classe, mentre quelle uniche per selettori di ID. Gli ID hanno il vantaggio che possono funzionare da segnaposti individuabili dai programmi di navigazione; se abbiamo un indirizzo come http://www.dominio.it#id1, il browser cerca di localizzare l’elemento con ID id1 e se lo trova si posiziona in quel punto della pagina. Notiamo comunque che un tag può tranquillamente essere associato contemporaneamente ad una classe e ad un ID in modo da avere delle peculiarità comuni anche ad altri elementi e contemporaneamente altre uniche, oltre che essere essere individuabile facilmente dal programma di navigazione. 4.2.1.3 Selettori in base a attributi e valori « La selezione di marcatori può avvenire anche in base alla presenza di un attributo oppure di un attributo con un dato valore (anche parziale); l’indicazione dell’attributo, semplice o valorizzato deve avvenire tra i simboli «[» e «]». L’esempio seguente mostra nell’ordine l’uso di un selettore di attributo semplice, di un selettore di attributo esatto e di un selettore di attributo parziale (si noti in questo caso l’uso dell’operatore «~=»): |[align] {font-style: italic;} |a[href="www.google.com"] {font-weight: bold;} |a[href~="google"] {font-weight: bold;} I fogli di stile 72 4.2.1.4 Selettori in base al contesto « I selettori basati sul contesto tengono conto della struttura del documento HTML e permettono di fare riferimento a marcatori che sono «discendenti», «figli», «adiacenti» di altri marcatori. Un marcatore è discendente di un altro (che viene detto «antenato») quando è annidato in esso a un qualunque livello di profondità; è invece figlio di un marcatore (che viene detto «genitore») se è un discendente diretto; infine due marcatori si dicono adiacenti se hanno lo stesso genitore. Si tenga presente che in documento HTML il tag ‘<html>’ è l’antenato di qualsiasi altro marcatore e per questo viene detto «elemento radice». Nel prossimo esempio viene mostrata una porzione di codice HTML in cui abbiamo due tag ‘<h1>’ e ‘<p>’ adiacenti e figli di ‘<body>’, e i tag ‘<em>’ e ‘<b>’ figli rispettivamente di ‘<h1>’ e ‘<p>’ (oltre che, ovviamente, discendenti di ‘<body>’). |<body> |<h1>Esempio per mostrare <em>struttura</em></h1> |<p> |Testo normale, <b>testo in grassetto</b></p> |</body> La selezione in base alla struttura avviene con la sintassi mostrata nell’esempio seguente: |h1 em {color: yellow;} |p > b {font-style: italic;} |h1 + p {text-align: justify;} I tre selettori dell’esempio si interpretano nel seguente modo: • seleziona i tag ‘<em>’ che siano discendenti di un ‘<h1>’; • seleziona i tag ‘<b>’ che siano figli di un ‘<p>’; • seleziona i tag ‘<p>’ che siano adiacenti di un ‘<h1>’; 4.2.1.5 Selettori basati su pseudo-classi e pseudo-elementi « Questo tipo di selettori è particolarmente importante perché permette di assegnare stili non in base alla struttura del documento o alla presenza di certi elementi con determinati attributi e valori, ma in base allo «stato» in cui si trovano determinati oggetti in un certo momento. In particolare con le pseudo-classi è possibile selezionare, in base allo stato in cui si trovano, certi tag che vengono utilizzati per l’interazione con l’utente. Al momento l’unico esempio che abbiamo incontrato di tale tipo di marcatori è quello per i collegamenti ‘<a>’ e quindi vediamo l’uso dei selettori di pseudo-classi solo relativamente ad esso; quanto mostrato può poi essere facilmente applicato anche ad altri tipi di tag «interattivi», quelli relativi ai moduli, presentati più avanti (paragrafo 6). Nell’esempio seguente viene mostrato l’uso di selettori di pseudo-classi: |a:link {color: magenta;} |a:visited {color: red;} |a:hover {color: yellow;} |a:active {color: brown;} I fogli di stile 73 • Con ‘:link’ si selezionano tutti i collegamenti che sono davvero tali (si ricordi che il tag ‘<a>’ viene anche usato per inserire le etichette con l’attributo ‘name’); • ‘:visited’ permette di selezionare i collegamenti già visitati; • ‘:hover’ si riferisce a elementi sui quali è posizionato il puntatore del mouse; • ‘:active’ si riferisce a elementi attivati da operazioni dell’utente (ad esempio un collegamento nel momento in cui lo si attiva con il pulsante del mouse. Le prime due sono pseudo-classi per i collegamenti; le altre due insieme a ‘:focus’ (seleziona qualsiasi elemento che è attivo cioè che sta ricevendo l’input dell’utente) sono dette «dinamiche» e possono essere applicate a qualsiasi tag (come detto, il loro uso è importante relativamente ai moduli HTML). Esiste anche la possibilità di combinare le pseudo-classi come mostrato di seguito: |a:link:hover {color: magenta;} |a:visited:hover {color: red;} |a:link:visited {color: black;} Nel primo caso si vogliono selezionare i collegamenti non visitati su cui è posizionato il puntatore del mouse; nel secondo caso stessa cosa per i collegamenti visitati; il terzo caso è assurdo (un collegamento non può essere allo stesso tempo visitato e non visitato) e viene solitamente ignorato dai browser. Concludiamo il paragrafo con gli pseudo-elementi grazie ai quali è possibile selezionare, e applicare gli stili, alla prima lettera o alla prima riga o anche prima e dopo un certo elemento. Riguardo alla prima lettera e alla prima riga la sintassi è molto semplice e intuitiva, come dimostrato dal prossimo esempio: |p:first-letter {color: green;} |p:first-line {color: red;} Molto interessanti sono gli pseudo-elementi ‘:before’ e ‘:after’ che usati congiuntamente alla regola ‘content’ permettono di inserire un contenuto (chiamato «contenuto generato») nel documento HTML prima o dopo un certo marcatore; un esempio può chiarire facilmente le potenzialità di questi selettori: |h1:before {content: "Nuovo capitolo"; display: block; color: green;} |body:after {content: "Fine del documento"; font-style: oblique;} L’effetto è quello di inserire la stringa «Nuovo capitolo» di colore verde prima di ogni intestazione di livello 1 e la stringa «Fine del documento», obliqua, alla fine del testo visualizzato. Interessante è anche l’uso della proprietà ‘display’ che nell’esempio serve a inserire il testo generato come elemento di blocco e quindi a fare proseguire il testo contenuto nel tag ‘<h1>’ su un nuovo paragrafo; tale proprietà può assumere vari altri valori, che qui non consideriamo, tra cui "inline" che è il valore per difetto. Le possibilità offerte dalla proprietà ‘content’ e da altre riguardanti tipi speciali di contenuto generato (virgolette generate, contatori) sono molto maggiori di quelle appena mostrate ma non vengono approfondite in questa sede. I fogli di stile 74 4.2.2 Dichiarazione di regole di stile per la formattazione « Una volta visto come è possibile selezionare le parti del documento cui applicare gli stili passiamo ad elencare alcuni di quelli relativi alla formattazione del testo. Alcune proprietà possono essere «ereditate»; ciò significa che gli stili vengono applicati a un marcatore e anche a tutti i suoi discendenti. L’elenco non è completo e viene fornito in modo molto sintetico con una tabella contenente le proprietà, il loro significato, i valori (almeno i più importanti) che esse possono assumere e se sono «ereditate» oppure no; in caso di necessità, queste informazioni possono essere integrate consultando testi e manuali riguardanti i CSS. Altri tipi di regole di stile, stavolta relative al posizionamento degli oggetti nel documento, vengono invece illustrate nel paragrafo 4.4. Quando si fa riferimento a grandezze (misura di caratteri, interlinea ecc.) si possono utilizzare varie unità di misura; alcune sono assolute: • pixel (px); • punti (pt); • millimetri (mm); • centimetri (cm); • pollici (in); • picas (pc, pari a 12 pt). Altre unità di misura sono relative, come: • em-height (em), altezza media dell’insieme di caratteri usato; • ex-height (ex), altezza del carattere «x» dell’insieme di caratteri usato. Esiste poi la possibilità di esprimere grandezze in percentuale, calcolata di solito in base alle dimensioni del tag genitore di quello considerato. Proprietà font-family: Significato Famiglia di caratteri Valori Arial, "Helvetica Bold" .... Ereditata Commento Si Si applica a qualsiasi elemento; nomi multipli devono essere racchiusi tra virgolette; è possibile inserire più valori di famiglie di caratteri separati da «,» per avere una gerarchia di scelta; il valore per difetto dipende dal browser. I fogli di stile Proprietà 75 Ereditata Significato Valori font-size: Grandezza carattere xx-small, x-small, small, medium, large, x-large, xx-large, smaller, larger, dimensione esatta in una delle unità di misura elencate in precedenza, dimensione in percentuale (nn%) Si font-style: Stile del carattere normal, italic, oblique Si font-variant Maiuscoletto normal, small-caps Si font-weight: Peso del carattere normal, bold, bolder, lighter Si del line-height: Interlinea backgroundcolor: Colore di sfondo backgroundimage: Immagine sfondo backgroundposition: backgroundrepeat: backgroundattachment: di Posizione di partenza dell’immagine di sfondo Modo di ripetizione dell’immagine di sfondo Per far scorrere l’immagine di sfondo insieme all’elemento di cui è sfondo normal, valore intero da moltiplicare per la dimensione del carattere, valore in percentuale (nn%) sulla dimensione del carattere, valore esatto espresso con una delle unità di misura previste. transparent, colore espresso in esadecimale (preceduto da «#») o con codice mnemonico (red, green,...) Commento Si applica a qualsiasi elemento; il valore per difetto è medium; nel caso di valore in percentuale, o di valore «em», o di indicazione smaller o larger, viene presa come base la dimensione del carattere dell’elemento genitore; esempi: 15px, 20pt, 75%, 0.75em. Si applica a qualsiasi elemento; il valore per difetto è normal. Si applica a qualsiasi elemento; il valore per difetto è normal. Si applica a qualsiasi elemento; il valore per difetto è normal. Si Si applica a qualsiasi elemento; il valore per difetto è normal. No Si applica a qualsiasi elemento; il valore per difetto è transparent. none, URI dell’immagine No Si applica a qualsiasi elemento; il valore per difetto è none. center, left, right, top, bottom top left, top right, bottom left, bottom right, valori delle coordinate assolute o in percentuale rispetto all’angolo superiore sinistro No Si applica a elementi di blocco; il valore per difetto è 0% 0%. no-repeat, repeat, repeat-x, repeat-y No Si applica a qualsiasi elemento; il valore per difetto è no-repeat. scroll, fixed No Si applica a qualsiasi elemento; il valore per difetto è scroll. I fogli di stile 76 Significato Valori Ereditata Commento color: Colore del testo colore espresso in esadecimale (preceduto da «#») o con codice mnemonico (red, green,...) Si Si applica a qualsiasi elemento; il valore per difetto dipende dal browser. text-align: Allineamento del testo left, center, justify textdecoration: Effetti «speciali» sul testo none, underline, overline, line-through, blink No text-indent: Indentazione della prima riga valore o percentuale specificati come per i valori in ‘font-size’ Si texttransform: Capitalizzazione del testo none, uppercase, lowercase, capitalize Si white-space: Trattamento degli spazi vuoti normal, nowrap, pre No word-spacing: Controllo del tracking (spazio tra le parole) letter-spacing: Controllo del kerning (spazio tra le lettere) Proprietà right, normal, valore espresso con una delle unità di misura citate in precedenza normal, valore espresso con una delle unità di misura citate in precedenza Si Si applica a elementi di blocco; il valore per difetto dipende dal browser, di solito è left. Si applica a qualsiasi elemento; il valore per difetto è none. Si applica a elementi di blocco; il valore per difetto è 0; il valore in percentuale viene calcolato in base alla larghezza dell’elemento di blocco che contiene l’elemento considerato; si possono inserire anche valori negativi che permettono di avere rientri a sinistra del testo. Si applica a qualsiasi elemento; il valore per difetto è none; con capitalize si fa in modo che la prima lettera di ogni parola sia maiuscola. Si applica a elementi di blocco; il valore per difetto è normal; con nowrap si evita che gli spazi facciano spezzare una riga; con pre si fa in modo che gli spazi e le righe vuote vengano mantenute e non compattate; con normal si ha il comportamento consueto del programma di navigazione relativamente agli spazi e righe vuote. Si Si applica a qualsiasi elemento; il valore per difetto è normal. Si Si applica a qualsiasi elemento; il valore per difetto è normal. I fogli di stile Proprietà vertical-align: 77 Significato Allineamento verticale del testo Valori baseline, sub, super Ereditata Commento No Si applica a elementi in linea; il valore per difetto è baseline; si noti che con sub e super si ottiene la trasformazione del testo in pedice e apice ma senza riduzione della dimensione dei caratteri, per la quale occorre intervenire con la proprietà ‘font-size’. Una osservazione importante riguarda la proprietà ‘font-family’: è possibile che si imposti un tipo di carattere non disponibile presso l’elaboratore dell’utente; in tal caso si può includere il carattere nella pagina nel modo illustrato sotto: |@font-face {font-family: pippo; src: url(pippo.eot);} |h1 {font-family: pippo;} Nell’esempio ‘pippo.eot’ è il file che contiene la definizione del carattere e che deve ovviamente essere presente nel servente Web. Infine è importante segnalare che esistono anche proprietà a sintassi abbreviata, come ad esempio ‘font:’ o ‘background:’, con le quali si possono assegnare, scrivendoli separati da spazi, i valori elencati in precedenza e relativi rispettivamente ai font e allo sfondo. 4.3 Tipi di fogli di stile « I fogli di stile contengono delle definizioni di proprietà da applicare a documenti HTML o a parti di essi e per questo devono essere «associati» al codice HTML; tale associazione può avvenire in varie maniere e questo differenzia in modo abbastanza netto i tipi di CSS. 4.3.1 Fogli di stile in linea « In questo caso gli stili vengono assegnati direttamente agli elementi HTML a cui si vogliono applicare grazie all’attributo ‘style’; ad esempio: |<p style="font-size: 12px; color: #FF0000"> |Testo contenuto nel paragrafo |</p> I fogli di stile 78 4.3.2 Fogli di stile incorporati « In questo caso i fogli di stile sono definiti all’interno della pagina con l’uso del tag ‘<style>’; esempio: |<html> |<head> |<title>Esempio con foglio di stile |</title> |<style type="text/css"> |h1, h2 { text-transform: capitalize; | text-align: center; } |body { color: #10AA10; background-color: #C0C0C0; } |p.pippo { font-size: larger; | font-weight: bolder; | text-align: center; } |</style> |</head> |<body> |<h1> titolo di tipo h1 </h1> |<p> |Questo documento è realizzato con un foglio di stile |incorporato.</p> |<p class="pippo"> Questo paragrafo è |definito nel CSS come paragrafo di classe "pippo".</p> |<hr/> |<p> |Questo invece è un paragrafo normale.</p> |</body> |</html> Il risultato che si ottiene con il sorgente dell’esempio è mostrato in figura 4.18. F | igura 4.18. I fogli di stile 79 4.3.3 Fogli di stile collegati « Il modo migliore per associare un foglio di stile ad una pagina HTML è quello di definirlo esternamente alla pagina stessa (come detto in precedenza questo permette di definire uno stile standard anche per un intero sito Web e di concentrare le modifiche solo sul foglio di stile e non su tutte le pagine). Per il collegamento al foglio esterno si usa il tag ‘<link>’ nella sezione di intestazione, con gli attributi ‘href’, ‘rel’ e ‘type’; vediamo un esempio: |<html> |<head> |<title>Esempio con foglio di stile esterno</title> |<link href="foglio1.css" rel="stylesheet" type="text/css"/> |</head> L’attributo ‘rel’ può avere anche il valore "alternate stylesheet" per definire un foglio di stile alternativo; inoltre si può aggiungere l’attributo ‘title’ per indicare il nome del foglio (questo è utile nel caso i programmi di navigazione siano in grado di mostrare all’utente la lista dei fogli di stile associati ad un documento permettendo di scegliere il preferito). Il foglio di stile a cui si riferisce l’esempio si chiama ‘foglio1.css’ e potrebbe avere il seguente contenuto (definito con un normale editor di testo): |/* Esempio di foglio di stile | da collegare */ |@import url(http://www.maxplanck.it/libcss/foglio2.css) |h1, h2 { text-transform: capitalize; | text-align: center; } |body { color: #10AA10; background-color: #C0C0C0; } |p.pippo { font-size: larger; | font-weight: bolder; | text-align: center; } Le righe racchiuse tra «/*» e «*/» sono un commento; il costrutto ‘@import’ serve ad importare all’interno del foglio di stile ulteriori definizioni contenute nel foglio a cui fa riferimento l’indirizzo specificato (in questo caso ‘foglio2.css’ nella directory ‘libcss’ del servente Web www.maxplanck.it; le altre definizioni sono le stesse utilizzate nell’esempio con il CSS incorporato. Se, per qualche motivo, si avessero problemi con il collegamento dei fogli di stile si può ricorrere all’importazione; a tale scopo basta usare il costrutto ‘@import’, in modo simile all’esempio precedente, inserito però direttamente nel documento HTML, racchiuso tra un tag ‘<style>’ e un ‘</style>’. A proposito del costrutto ‘@import’ è importante osservare che esso fa parte, insieme a ‘@media’, ‘@charset’, ‘@font-face’, delle cosiddette «@-rules» con le quali si possono fare alcune operazioni particolari. Fra queste, ‘@media’, riveste una notevole importanza per i CSS per la stampa, come mostrato nel paragrafo 4.5. I fogli di stile 80 4.3.4 Organizzazione a cascata « L’organizzazione a cascata dei fogli di stile consiste semplicemenite nel fatto che c’è un ordine di priorità tra regole di stile definite con tipi di CSS diversi; in altre parole se abbiamo un documento HTML in cui si utilizzano regole di stile definite in un foglio collegato, altre regole incorporate ed altre ancora in linea, in caso di conflitto sono queste ultime ad essere applicate. Quindi le regole di stile in linea prevalgono su quelle incorporate (e importate) e queste a loro volta su quelle collegate. Questo fatto può essere sfruttata quando, nella definizione degli stili delle pagine di un sito, si vogliono definire delle regole generali ma si vogliono avere delle «eccezioni» per alcune pagine; in tal caso si definiscono le regole globali in fogli collegati da usare in tutte le pagine, ma nelle pagine «particolari» si inseriscono delle regole di stile incorporate o in linea che sovrascrivono le altre. 4.3.5 Fogli di stile alternativi « In precedenza si è visto come impostando l’attributo ‘rel’ del tag ‘<link>’ con il valore "alternate stylesheet" sia possibile definire un foglio di stile alternativo da collegare a un certo documento HTML. Per maggiore completezza occorre chiarire che ad un documento HTML si possono collegare: • un foglio di stile chiamato «persistente», o di base, che viene applicato indipendentemente dalle preferenze degli utenti; tale foglio di stile viene collegato impostando il valore "stylesheet" nell’attributo ‘rel’ e senza attributo ‘title’; • un foglio di stile chiamato «automatico» che viene applicato se l’utente non fa alcuna scelta; tale foglio di stile viene collegato impostando il valore "stylesheet" nell’attributo ‘rel’ e un nome nell’attributo ‘title’; • uno o più fogli di stile alternativi che vengono collegati impostando per ognuno il valore "alternate stylesheet" nell’attributo ‘rel’ e un nome univoco nell’attributo ‘title’; l’utente può scegliere tra uno di questi e il foglio di stile automatico agendo su apposite voci di menu disponibili nei programmi di navigazione. Nel prossimo esempio abbiamo una pagina HTML cui sono collegati un foglio persistente, uno automatico e due fogli alternativi; nella figura 4.22 viene mostrato il menu di scelta degli stili disponibili al momento della visualizzazione di tale documento con il browser ‘Firefox’. |<html> |<head><title>Esempio per collegamento fogli di stile</title> |<link rel="stylesheet" href="foglio_pers.css" type="text/css"/> |<link rel="stylesheet" href="foglio_auto.css" type="text/css"←,→title="Stile di default"/> |<link rel="alternate stylesheet" href="foglio1.css" type="text/css"←,→title="Stile alternativo 1"/> |<link rel="alternate stylesheet" href="foglio2.css" type="text/css"←,→title="Stile alternativo 2"/> |</head> |<body> |<h1>Prova fogli di stile alternativi</h1> |Selezionare uno degli stili disponibile attraverso |l’apposito menu nel programma di navigazione. I fogli di stile 81 |<p></p> |</body> |</html> F | igura 4.22. 4.4 Posizionamento con i fogli di stile « Per parlare di posizionamento con i fogli di stile occorre prima di tutto chiarire come questi ultimi considerano e gestiscono gli elementi presenti in una pagina; ogni elemento genera un riquadro rettangolare (o box) non visibile comprendente: • l’area del contenuto dell’elemento; • lo spazio tra il contenuto dell’elemento e i bordi dell’area (padding); • i bordi esterni dell’area (border); • lo spazio intorno ai bordi (margin). L’unica parte sempre presente è l’area del contenuto, le altre possono essere impostate ad ampiezza nulla. Vediamo (o ricordiamo) anche altri concetti molto importanti riguardanti gli elementi di una pagina HTML. I riquadri degli elementi possono essere di blocco o in linea, con le conseguenze che questo comporta e che sono già state chiarite in precedenza (paragrafo 2.5.4). Gli elementi possono essere «non rimpiazzati» o «rimpiazzati»; nel primo caso il contenuto si trova all’interno del riquadro, nel secondo il tag è solo un segnaposto per un altro oggetto (l’esempio più banale di questo tipo di elemento è ‘<img>’). Ogni elemento è contenuto in un «blocco contenitore», ad esempio: |<body> |<div> |<h1>Titolo</h1> |<p>Testo</p> I fogli di stile 82 |</div> |</body> |</html> qui i tag ‘<h1>’ e ‘<p>’ hanno ‘<div>’ come blocco contenitore ed esso, a sua volta è contenuto in ‘<body>’. Il «flusso» di visualizzazione di un documento HTML è da sinistra a destra e dall’alto verso il basso, questo è il comportamento normale di tutti i browser almeno per le lingue occidentali; un elemento può essere estrapolato dal flusso normale solo posizionandolo oppure rendendolo fluttuante con la proprietà ‘float’. Nel resto del paragrafo vediamo appunto le proprietà dei CSS da utilizzare per il posizionamento oltre a quelle riguardanti le varie caratteristiche dei box degli elementi. Il posizionamento può essere: • statico, è quello applicato per difetto; l’elemento rimane nel flusso normale del testo; • relativo; l’elemento risulta spostato rispetto a quella che sarebbe stata la sua posizione «naturale»; • assoluto; l’elemento è rimosso dal flusso e posizionato specificando le coordinate rispetto al suo blocco contenitore, cioè all’antenato più prossimo posizionato non staticamente (in assenza viene considerato come contenitore il documento); • fisso; come per assoluto ma considerando come blocco contenitore la finestra del browser. In caso alcuni riquadri si sovrappongano, è anche possibile ordinarli in base all’asse perpendicolare all’area di visualizzazione, immaginando che il documento sia costituito da livelli sovrapposti. Esiste infine la possibilità di rendere l’elemento fluttuante, cioè di spostarlo dal normale flusso, ma facendo in modo che esso influisca ancora sul resto del testo (che solitamente gli viene fatto scorrere intorno). In ogni caso con i CSS si ottiene un tipo di posizionamento che viene detto «liquido» in quanto tiene conto automaticamente del variare delle dimensione dell’area di visualizzazione della pagina (finestra del browser dell’utente). Come abbiamo fatto nel paragrafo 4.2.2 relativamente agli stili per la formattazione del testo, ricorriamo anche qui ad una tabella per elencare le proprietà riguardanti il posizionamento dei riquadri e le loro caratteristiche. Proprietà Ereditata Significato Valori width: Larghezza di un elemento auto, valore espresso con una delle unità di misura consentite o in percentuale No height: Altezza di un elemento auto, valore espresso con una delle unità di misura consentite No Commento Si applica a elementi di blocco e rimpiazzati; il valore per difetto è auto; il valore in percentuale è calcolato in base all’elemento contenitore. Si applica a elementi di blocco e rimpiazzati; il valore per difetto è auto; I fogli di stile Proprietà 83 Significato Valori Ereditata visibility: Visibilità di un elemento visible, hidden No border-color: Colore dei bordi di un riquadro transparent, codice colore in esadecimale o mnemonico No Commento Si applica a qualsiasi elemento; il valore per difetto è visible; un elemento nascosto risulta comunque presente (cioè influenza comunque il comportamento degli elementi vicini). Si applica a qualsiasi elemento; il valore per difetto è il colore dell’elemento contenuto; se si inserisce un solo colore esso vale per tutti e quattro i bordi, altrimenti si possono inserire quattro colori separati da spazi relativi nell’ordine a: bordo alto, bordo destro, bordo basso, bordo sinistro (oppure si possono usare le proprietà specifiche ‘border-top-color’, ‘border-right-color’ ‘border-bottom-color’ ‘border-left-color’). border-style: Stile dei bordi di un riquadro none, dotted, dashed, solid, double, groove, ridge, inset, outset No Si applica a qualsiasi elemento; il valore per difetto è none; se si inserisce un solo stile esso vale per tutti e quattro i bordi, altrimenti si possono inserire quattro stili separati da spazi relativi nell’ordine a: bordo alto, bordo destro, bordo basso, bordo sinistro (oppure si possono usare le proprietà specifiche ‘border-top-style’, ‘border-right-style’ ‘border-bottom-style’ ‘border-left-style’). I fogli di stile 84 Proprietà border-width: Significato Spessore dei bordi di un riquadro Valori thin, medium, thick, valore espresso con una delle unità di misura consentite Ereditata No Commento Si applica a qualsiasi elemento; il valore per difetto è medium; se si inserisce un solo valore o codice esso vale per tutti e quattro i bordi, altrimenti si possono inserire quattro valori o codici separati da spazi relativi nell’ordine a: bordo alto, bordo destro, bordo basso, bordo sinistro (oppure si possono usare le proprietà specifiche ‘border-top-width’, ‘border-right-width’ ‘border-bottomwidth’ ‘border-left-width’). margin: Ampiezza dei margini di un riquadro auto, valore espresso con una delle unità di misura consentite o in percentuale No Si applica a qualsiasi elemento; il valore per difetto è 0; valori in percentuale vengono calcolati in base alla larghezza dell’elemento genitore; se si inserisce un solo valore esso vale per tutti e quattro i margini, altrimenti si possono inserire quattro valori separati da spazi relativi nell’ordine a: margine alto, destro, basso, sinistro (oppure si possono usare le proprietà specifiche ‘margin-top’, ‘margin-right’ ‘margin-bottom’ ‘margin-left’). I fogli di stile Proprietà padding: 85 Significato Ampiezza del padding di un riquadro Valori valore espresso con una delle unità di misura consentite o in percentuale Ereditata No Commento Si applica a qualsiasi elemento; il valore per difetto è 0; valori in percentuale vengono calcolati in base alla larghezza dell’elemento genitore; se si inserisce un solo valore esso vale per tutti e quattro i lati, altrimenti si possono inserire quattro valori separati da spazi relativi nell’ordine a: padding alto, destro, basso, sinistro (oppure si possono usare le proprietà specifiche ‘padding-top’, ‘padding-right’ ‘padding-bottom’ ‘padding-left’). position: posizionamento di un riquadro static, relative, absolute, fixed No bottom: Scostamento in basso di un riquadro posizionato auto, valore espresso con una delle unità di misura consentite o in percentuale No left: Scostamento a sinistra di un riquadro posizionato auto, valore espresso con una delle unità di misura consentite o in percentuale No right: Scostamento a destra di un riquadro posizionato auto, valore espresso con una delle unità di misura consentite o in percentuale No top: Scostamento in alto di un riquadro posizionato auto, valore espresso con una delle unità di misura consentite o in percentuale No z-index: Posizionamento sull’asse perpendicolare all’area di visualizzazione auto, numero intero No float: Direzione di spostamento di un elemento fluttuante none, left, right No Si applica a qualsiasi elemento; il valore per difetto è static. Si applica a qualsiasi elemento posizionato (con valore di ‘position’ diverso da static); il valore per difetto è auto. Si applica a qualsiasi elemento posizionato (con valore di ‘position’ diverso da static); il valore per difetto è auto. Si applica a qualsiasi elemento posizionato (con valore di ‘position’ diverso da static); il valore per difetto è auto. Si applica a qualsiasi elemento posizionato (con valore di ‘position’ diverso da static); il valore per difetto è auto. Si applica a qualsiasi elemento posizionato (con valore di ‘position’ diverso da static); il valore per difetto è auto; i riquadri con valori di ‘z-index’ alti sono più «vicini» all’utente di quelli con valori bassi. Si applica a qualsiasi elemento; il valore per difetto è none. I fogli di stile 86 Proprietà Significato Valori Ereditata clear: Controllo scorrimento elementi fluttuanti none, left, right, both No overflow: Modalità di gestione del traboccamento del testo visible, hidden, scroll, auto No clip: Definizione di un’area di taglio auto, rect(valore_su, valore_dx, valore_giu, valore_sx) No Commento Si applica a elementi di blocco; il valore per difetto è none; si usa per impedire che elementi fluttuanti compaiano a sinistra, a destra o da entrambi i lati dell’elemento cui si assegna questa proprietà (tale elemento si posizionerà quindi dopo eventuali elementi fluttuanti e non accanto ad essi). Si applica a elementi di blocco e rimpiazzati; il valore per difetto è visible; con visible il contenuto che eccede le dimensioni del contenitore viene reso comunque visibile adattando queste ultime, con hidden invece è nascosto, con scroll e auto vengono aggiunte delle barre di scorrimento sul riquadro, nel primo caso sempre, nell’altro solo se necessario. Si applica a elementi posizionati in modo assoluto; il valore per difetto è auto; si usa per definire un’area rettangolare in cui è reso visibile il contenuto del riquadro; il contenuto eccedente viene trattato in base a quanto stabilito con la proprietà ‘overflow’. Prima di concludere osserviamo che per utilizzare proficuamente i fogli di stile per il posizionamento degli elementi di un documento HTML è opportuno usare abbondantemente il tag ‘<div>’ in modo da definire le sezioni della pagina cui applicare le necessarie regole di stile. Questa non deve essere però una forzatura: una buona suddivisione del documento in sezioni, che tenga conto correttamente della sua struttura logica, sarà quasi sicuramente idonea anche all’uso per l’assegnazione degli stili di formattazione e di posizionamento. Infine vediamo due esempi molto simili di pagine contenenti un riquadro di testo con gestione del traboccamento dello stesso, tre immagini con relative didascalie posizionate con precisione e una immagine fluttuante contornata da testo sulla sua destra o sulla sua sinistra. Il tutto è realizzato con regole di stile di un foglio incorporato, nel primo caso usando il posizionamento relativo nell’altro il posizionamento assoluto. La scelta del CSS di tipo incorporato è dettata solo da ragioni di praticità: in questo modo infatti, per ognuno dei due esempi, è sufficiente mostrare il sorgente HTML e non più file separati. I fogli di stile Vediamo il primo esempio: |<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" | "http://www.w3.org/TR/html4/strict.dtd"> |<html> |<head> |<title>Posizionamento relativo con CSS |</title> |<style type="text/css"> |body { font-family: "DejaVu Sans"; font-size: 14px; } |h1.titolo { color: green; | font-style: italic; | text-align: center; } |.box_immagini { position: relative; | top: 0px; | left: 50px; } |.box_fluttua { width: 350px; | height: 100px; } |.fluttua { float: left; | margin-top: 5px; | margin-right: 15px; | width: 140px; | height: 120px; } |.riga11 { position: relative; | top: 0%; | left: 0%; | width: 120px; | height: 135px; } |.riga12 { position: relative; | top: 0%; | left: 20%; | width: 120px; | height: 135px; } |.riga13 { position: relative; | top: 0%; | left: 40%; | width: 180px; | height: 135px; } |.riga21 { position: relative; | top: 0%; | left: 0%; | margin-top: 10px; | width: 120px; | height: 15px; | text-align: center; } |.riga22 { position: relative; | top: -2em; | left: 33%; | margin-top: 10px; | width: 120px; | height: 15px; | text-align: center; } |.riga23 { position: relative; | top: -4em; | left: 66%; 87 I fogli di stile 88 | margin-top: 10px; | width: 180px; | height: 15px; | text-align: center; } |p.testo { width: 300px; | height: 100px; | overflow: auto; } |</style> |</head> |<body> |<h1 class="titolo">Prova di posizionamento relativo con CSS</h1> |<p class="testo"> |Le tre immagini seguenti con le relative didascalie sono |posizionate con la proprietà position dei CSS e posizionamento |relativo. L’immagine successiva è fluttuante a sinistra ed è |inserita dopo la parola "fluttuante".</p> |<div class="box_immagini"> | <img class="riga11" src="tux.jpg"/> | <img class="riga12" src="tux_univ.jpg"/> | <img class="riga13" src="Family_linux.png"/> |</div> |<p/> |<p class="riga21"> | Tux</p> |<!-- Le ultime due didascalie sono posizionate correttamente in |verticale ricorrendo a un posizionamento relativo negativo rispettivamente |di -2 e -4 em cioè 2 volte e 4 volte l’ampiezza media del carattere |usato; questo le fa allineare alla prima didascalia. --> | <p class="riga22"> | Tux laureato</p> | <p class="riga23"> | Tux family</p> |<div class="box_fluttua"> | <p>Questa immagine è fluttuante, | <img class="fluttua" src="Linux-Inside-small.gif"/> | a sinistra; quindi il testo si affianca alla sua destra.</p> |</div> |</body> |</html> Il risultato che si ottiene è mostrato nella figura 4.26. F | igura 4.26. I fogli di stile Ecco invece il sorgente del secondo esempio: |<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" | "http://www.w3.org/TR/html4/strict.dtd"> |<html> |<head> |<title>Posizionamento assoluto con CSS |</title> |<style type="text/css"> |h1.titolo { color: blue; | font-style: italic; | text-align: center; } |.box_immagini { position: relative; | top: 1px; | left: 15px; | width: 66%; | height: 50%; } |.box_fluttua { position: relative; | top: 180px; | left: 50px; | width: 350px; } |.fluttua { float: right; | margin-top: 5px; | margin-right: 15px; | width: 140px; | height: 120px; } |img.dim1 { width: 120px; | height: 135px; } |img.dim2 { width: 180px; | height: 135px; } |.riga11 { position: absolute; | top: 0%; | left: 0%; } |.riga12 { position: absolute; | top: 0%; | left: 33%; } |.riga13 { position: absolute; | top: 0%; 89 90 I fogli di stile | left: 66%; } |.riga21 { position: absolute; | top: 135px; | left: 0%; | margin-top: 5px; } |.riga22 { position: absolute; | top: 135px; | left: 33%; | margin-top: 5px; } |.riga23 { position: absolute; | top: 135px; | left: 66%; | margin-top: 5px; } |p.testo { width: 300px; | height: 100px; | overflow: auto; } |</style> |</head> |<body> |<h1 class="titolo">Prova di posizionamento assoluto con CSS</h1> |<p class="testo"> |Le tre immagini seguenti con le relative didascalie sono |posizionate con la proprietà position dei CSS e posizionamento |assoluto. L’immagine successiva è fluttuante a destra |ed è inserita dopo la parola "fluttuante".</p> |<div class="box_immagini"> |<!-- le immagini e le didascalie sono ognuna in una sezione |figlia della sezione box_immagini che non è posizionata |staticamente (position:relative) e quindi ha effetto il posizionamento |assoluto rispetto a questa ultima. --> | <div class="riga11"> | <img class="dim1" src="tux.jpg"/> | </div> | <div class="riga12"> | <img class="dim1" src="tux_univ.jpg"/> | </div> | <div class="riga13"> | <img class="dim2" src="Family_linux.png"/> | </div> | <div class="riga21"> | <p>Tux</p> | </div> | <div class="riga22"> | <p>Tux universitario</p> | </div> | <div class="riga23"> | <p>Tux family</p> | </div> |</div> |<div class="box_fluttua"> |<!-- La sezione box_fluttua è posizionata relativamente con |uno scostamento verticale tale da "scavalcare" immagini e didascalie --> |<p>Questa immagine è fluttuante, |<img class="fluttua" src="Linux-Inside-small.gif"/> I fogli di stile 91 |a destra; quindi il testo si affianca alla sua sinistra.</p> |</div> |</body> |</html> Il risultato che si ottiene è mostrato nella figura 4.28. F | igura 4.28. Si possono confrontare i risultati di questi due esempi con la pagina, simile, presentata nel paragrafo 3.2.4 ottenuta posizionando gli elementi tramite una tabella. 4.5 Fogli di stile per la stampa « Una delle caratteristiche più interessanti dei CSS è la loro capacità di definire stili diversi per mezzi di comunicazione diversi; è possibile infatti associare allo stesso documento HTML un foglio di stile dedicato alla visualizzazione a video, uno per la stampa su carta, uno per dispositivi portatili (palmari), uno per alfabeto braille ed altri ancora. In queste dispense si prende in esame solo il caso della stampa su carta che riveste sicuramente una notevole importanza viste le difficoltà che di solito si incontrano quando si stampano documenti visualizzati con un programma di navigazione. Le pagine Web, infatti, sono quasi sempre concepite e realizzate per essere visualizzate a video e quindi contengono tutta una serie di oggetti e di formattazioni che al momento della stampa sono inutili se non addirittura dannosi; pensiamo ad esempio a barre di scorrimento, barre contenenti menu, immagini di sfondo, sfondi colorati. C’è poi il caso, abbastanza comune, di pagine impostate con larghezza fissa maggiore di quella dei fogli A4 e che quindi risultano «tagliate» a destra quando trasferite su carta. A questi inconvenienti è possibile dare una soluzione anche senza l’uso dei CSS; basta infatti predisporre versioni diverse della stessa pagina: una per il video e una per la stampa, premunendosi di inserire nella prima un collegamento alla seconda a disposizione dell’utente e da utilizzare al momento di effettuare la stampa. I fogli di stile 92 In questo modo abbiamo però un notevole aggravio di lavoro per la scrittura di una doppia versione delle pagine del sito, senza contare poi che l’utente potrebbe non «notare» il collegamento alla versione da stampare e continuare quindi a usare la versione «sbagliata». Meglio quindi ricorrere ai CSS tanto più che l’idea di base è la stessa: una pagina (o meglio, un foglio di stile) per il video e una per la carta, solo che stavolta la scelta viene fatta in automatico dal programma di navigazione al momento che si decide di mandare in stampa il documento. 4.5.1 Fogli di stile per media diversi « La specifica del mezzo di comunicazione cui è rivolto un foglio di stile avviene nel seguente modo: • per i fogli collegati con l’attributo ‘media’ del tag ‘<link>’; ad esempio: |<link rel="stylesheet" type="text/css" href="stile_video.css" media="screen"> |<link rel="stylesheet" type="text/css" href="stile_carta.css" media="print"> • per i fogli incorporati con il costrutto ‘@media’; ad esempio: |<style type="text/css"> |@media screen { | /* regole di stile per il video */ |} |@media print { | /* regole di stile per la stampa su carta */ |} |</style> • per i fogli importati: |<style type="text/css"> |@import url(stile_video.css) screen; |@import url(stile_carta.css) print; |</style> Oltre ai media video e stampa sono previste altre possibilità che però sono molto meno usate e anche meno supportate dai vari browser; il pieno supporto si ha per screen, print e all che è il valore assegnato per difetto e significa che quel foglio di stile si applica a qualsiasi mezzo di comunicazione. L’elenco completo dei media utilizzabili è il seguente: • all; • aural: dispositivi di sintesi vocale; • braille; • embossed: stampanti braille; • handheld: palmari; • print; I fogli di stile 93 • projection: proiezioni a tutto schermo; • screen; • tty: terminali a caratteri; • tv: web tv. Quando si definiscono i fogli di stile per il video e la stampa occorre fare in modo che non risultino collegati al documento HTML anche fogli di stile per qualsiasi media perché le impostazioni presenti in essi avrebbero effetto anche sul documento stampato, con effetti potenzialmente deleteri. 4.5.2 Impostazione di un foglio di stile per la stampa « Prima di tutto occorre osservare che per poter definire proficuamente un foglio di stile per la stampa occorre che il documento HTML contenga solo tag relativi alla sua struttura e non alla formattazione e presentazione; infatti, solo se queste ultime sono completamente demandate a regole di stile, è possibile alterare l’aspetto della pagina semplicemente cambiando il CSS collegato. Nel foglio di stile per la stampa occorre eliminare gli elementi che non hanno senso per questo tipo di output associando ad essi la proprietà ‘display’ con valore none; si possono poi ridimensionare e riposizionare gli altre elementi per sfruttare lo spazio «guadagnato». Sicuramente è utile anche eliminare colori e immagini di sfondo, definendo il documento con caratteri neri su fondo bianco e togliere eventuali impostazioni della dimensione della pagina lasciando che il browser possa sfruttare tutta la dimensione del foglio in stampa. Anche la scelta del tipo di carattere è importante: sullo schermo si preferiscono di solito caratteri «senza grazie» (sans-serif ) come Arial e Verdana; per la stampante invece è meglio usare caratteri con «grazie» (serif ) come Times o Georgia. Per esprimere la dimensione dei caratteri (e tutte le altre grandezze assolute) per la stampa è preferibile abbandonare i pixel a vantaggio di altre unità di misura più legate al mezzo cartaceo come i punti (pt), i millimetri (mm) o i pollici (in); inoltre, visto che la lettura su carta è meno faticosa che sullo schermo, è possibile diminuire la dimensione dei caratteri per risparmiare carta e inchiostro. Tra gli elementi che non hanno grande utilità passando dallo schermo alla carta ci sono i collegamenti ipertestuali che, ovviamente, sul foglio non possono essere attivati. Per essi può allora essere utile far apparire in stampa l’indirizzo a cui puntano nel modo seguente: |a:link:after, a:visited:after {content " ["attr(href)"]";} In questo modo, dopo ogni collegamento, visitato o no, viene stampato l’indirizzo a cui esso punta, racchiuso tra parentesi quadrate. Infine segnaliamo la possibilità di controllare le interruzioni di pagina in stampa grazie alle proprietà ‘page-break-before’, ‘page-break-after’, ‘page-break-inside’ che possono valere auto (valore per difetto), always, avoid in modo da forzare o evitare interruzioni prima, dopo o all’interno di un certo blocco. 94 I fogli di stile Parte iii Il Web dinamico « 95 96 97 Capitolo 5 Introduzione al Web dinamico Tra i documenti del Web esiste una importante suddivisione: ci sono pagine «statiche», di cui ci siamo occupati fino a questo momento, e pagine «dinamiche» che ci accingiamo a esaminare nel presente capitolo. La spiegazione del significato dei due termini è molto importante anche perché permette di chiarire che le pagine dinamiche non sono assolutamente quelle che contengono oggetti in movimento (come ad esempio immagini gif animate) ma sono qualcosa di molto più sofisticato. Un documento è statico quando viene definito una volta per tutte e messo a disposizione degli utenti in una forma che non concede loro la possibilità di alterazioni; il contenuto e l’aspetto della pagina possono essere variati solo dalle persone responsabili del sito di cui essa fa parte. Un documento è invece dinamico quando viene creato, tutto o in parte, in seguito ad operazioni interattive svolte dall’utente. Un esempio classico è quello di una persona che richiede sul sito Internet di una azienda informazioni su un prodotto da essa commercializzato inserendo i parametri di ricerca in una pagina definita a tale scopo; i dati vengono inviati al servente Web dell’azienda che interroga la base di dati dei prodotti e costruisce «al volo»la pagina HTML di risposta da inviare al browser dell’utente. La tecnologia che per prima ha permesso la realizzazione di documenti Web dinamici è stata la CGI (Common Gateway Interface); si tratta di un protocollo standard che descrive come un servente Web possa invocare programmi esterni per elaborare dati ricevuti dall’utente ed inseriti in appositi moduli definiti in pagine HTML. Ulteriori possibilità di creazione di pagine Web dinamiche sono offerte dalle «applet» ‘Java’, dagli «script attivi» scritti con linguaggi di scripting come ‘JavaScript’, dal linguaggio ‘PHP’. Vediamo una prima classificazione di questi strumenti in base alle loro caratteristiche: • una applicazione CGI può essere scritta con uno qualsiasi dei linguaggi di programmazione esistenti, anche quelli più «tradizionali» come ‘c’ o ‘Fortran’; è «lato servente» (serverside) in quanto viene eseguita sulla macchina in cui risiede il servente Web ed è «esterna», cioè fisicamente scritta in un file separato da quello contenente il codice della pagina HTML; • le applet e gli script attivi sono «lato cliente» (client-side) cioè eseguiti sulla macchina in cui è in esecuzione il programma di navigazione; le prime sono esterne i secondi invece sono «incorporati» (embedded) in quanto il loro codice è scritto all’interno dello stesso file che contiene il sorgente HTML; • gli script PHP, infine, sono lato servente e incorporati. Anche il linguaggio HTML mette a disposizione degli strumenti utili alla definizione di documenti dinamici: i form o moduli, grazie ai quali possono essere raccolti i dati immessi dagli utenti. Iniziamo l’esame delle pagine interattive proprio dai moduli illustrandone l’uso in associazione ai programmi o agli script CGI. Gli argomenti successivi sono: l’interfacciamento alle basi di dati con PHP, gli script attivi, le applet, alcuni cenni al dynamic HTML, alle servlet Java e al Web ad oggetti. Non vengono invece prese in considerazione soluzioni proprietarie come le pagine ASP (Active Server Page). « 98 Introduzione al Web dinamico 99 Capitolo 6 Moduli e programmi CGI « I moduli si definiscono in un documento HTML con il tag ‘<form>’ ma la loro gestione, o meglio, la gestione dei dati in essi contenuti, non avviene con gli strumenti dell’HTML ma grazie a dei programmi esterni chiamati programmi o script CGI. Occorre quindi esaminare due aspetti distinti: • definizione in HTML degli elementi che compongono il modulo; • scrittura, in linguaggio di programmazione, del programma che deve gestire i dati immessi con il modulo. Più in dettaglio, la corretta gestione di un modulo passa attraverso le seguenti fasi: • inserimento nella pagina HTML dei tag per la definizione del modulo; • indicazione, tramite un attributo dell’elemento ‘<form>’, del nome del programma esterno che deve elaborare i dati; • visualizzazione del modulo da parte del browser con raccolta degli input dell’utente e invio degli stessi al servente Web; • attivazione, da parte del servente Web, del programma indicato; ad esso vengono forniti i dati ricevuti dal modulo; • elaborazione dei dati da parte del programma; • restituzione dei risultati al programma di navigazione, solitamente tramite la creazione di una nuova pagina Web da visualizzare. La figura 6.1 schematizza le fasi appena illustrate. F | igura 6.1. I CGI si differenziano in due categorie in base al linguaggio di programmazione utilizzato per realizzarli: • programmi CGI, se si usano linguaggi compilati come ‘c’, ‘c++’, ‘Java’; 100 Moduli e programmi CGI • script CGI, se si usano linguaggi interpretati come ‘Perl’, ‘shell’ di Unix o Linux, ‘Python’. Nel proseguo usiamo indifferentemente il termine «programma CGI», o anche solo CGI, per riferirci ad entrambe le tipologie di strumenti. Nei prossimi paragrafi esaminiamo le due fasi della gestione di un modulo: la sua definizione in HTML e l’elaborazione dei dati con i programmi CGI. 6.1 Creazione di moduli HTML « I moduli iniziano con il tag ‘<form>’ e terminano con ‘</form>’; si tratta di un elemento di blocco che può contenere qualsiasi altro elemento ma non altri moduli; i suoi attributi sono: • ‘action’, per specificare l’URI a cui inviare i dati del form; • ‘method’, per specificare l’azione da svolgere sui dati; i valori possibili sono "get" o "post"; • ‘enctype’, per indicare il tipo di MIME usato per il trasferimento delle informazioni; • ‘target’, per definire una nuova finestra dove visualizzare la risposta elaborata dal CGI. Esistono poi i cosiddetti attributi di evento come ‘onmouseover’, ‘onclick’, ‘onsubmit’, ‘onreset’ che però vengono solitamente gestiti con gli script attivi. Gli attributi più importanti sono ‘action’ e ‘method’. Il valore di ‘action’ corrisponde all’indirizzo a cui inviare i dati; può essere o un indirizzo di posta elettronica o il nome del programma CGI (completo di percorso) che dovrà ricevere ed elaborare in qualche modo i dati del form. Il valore di ‘method’ può essere "get" oppure "post"; nel primo caso i dati vengono accodati all’URI indicato in ‘action’, nel secondo caso i dati vengono passati attraverso lo «standard input» al servente. Questi aspetti vengono ripresi e approfonditi nel paragrafo 6.8 relativo al passaggio dei dati di un modulo a un programma CGI. Riguardo all’attributo ‘enctype’ è opportuno soffermarsi brevemente sui tipi MIME (Multipurpose Internet Mail Extension) creati originariamente per descrivere gli allegati di posta elettronica e ora usati, più generalmente, per riconoscere la natura dei file presenti sul Web. Sono composti da due parti: «tipo-principale/tipo-specifico», come ad esempio: image/gif (immagini di tipo gif), text/plain (testo puro) e molti altri. Elenchi completi di tipi MIME si trovano facilmente in Internet, ad esempio all’indirizzo hhttp:// www.asciitable.it/mimetypres.asp i. Il tipo di MIME da usare per trasferire i dati dal modulo al servente Web è: application/x-www-form-urlencoded e deve essere specificato solo nel caso si usi il metodo "post"; questo valore è comunque quello attribuito per difetto all’attributo ‘enctype’. In pratica serve a comunicare al servente che i dati saranno inviati attraverso lo standard input ma codificati alla stessa maniera di quando sono inviati accodati all’URI. Moduli e programmi CGI 101 6.2 Controlli dei moduli « Gli elementi specifici usati all’interno dei moduli sono tag di testo chiamati «controlli»; i più importanti sono: • ‘<input>’, per creare vari tipi di input diversi; • <‘select>’, per creare menu a scorrimento le cui opzioni sono indicate con il tag ‘<option>’; • ‘<textarea>’, per l’immissione di testo esteso; • ‘<fieldset>’, per raggruppare più controlli di un modulo. I primi tre prevedono l’attributo ‘name’ che permette di indicare il nome della variabile o del campo che contraddistingue l’elemento in questione. Talvolta si utilizza anche l’attributo ‘value’ per assegnare un valore alla variabile o al campo; più spesso però il valore assunto corrisponde a ciò che l’utente ha digitato o scelto in corrispondenza di quel campo. Il nome ed il valore dei campi sono naturalmente di fondamentale importanza per il programma CGI che deve elaborare i dati inviati dal modulo; in pratica siamo in presenza della distinzione tra nome e contenuto di una variabile, ben nota a chi conosca i rudimenti della programmazione. 6.2.1 Elemento ‘input’ « Vediamo prima di tutto un esempio molto semplice di modulo con un campo di input: |<html> |<head> |<title>Esempio di modulo</title> |</head> |<body> |<h4>ESEMPIO DI INPUT CON RICHIAMO DI PROGRAMMA CGI</h4> |<form action="/cgi-bin/cgi-prova.sh" method="get"> |<p/><br/><b>Inserire dato da passare al programma </b> |<input type="text" name="datoin" size="5" maxlentgh="3"/> |<input type="submit" value="Invio"/> |</form> |</body> |</html> L’aspetto del modulo è quello mostrato in figura 6.3. F | igura 6.3. 102 Moduli e programmi CGI In questo esempio si chiede l’inserimento di un dato che viene passato con metodo "get" al programma "cgi-prova.sh" (presumibilmente scritto con i comandi della shell di GNU/Linux o Unix, data l’estensione ‘.sh’) residente nella directory ‘/cgi-bin’. Il dato viene identificato come "datoin" dal programma, viene immesso in una casella lunga cinque caratteri ma può essere lungo al massimo tre caratteri. L’invio dei dati avviene premendo sul pulsante definito dal controllo "submit"; in questo esempio tale controllo non ha l’attributo ‘name’ che può servire nel caso si debbano distinguere più pulsanti di invio presenti in uno stesso modulo. Tra gli attributi di ‘<input>’ il più importante è ‘type’, il cui valore permette di definire vari tipi di controlli: • "submit", crea un pulsante da usare per l’invio dei dati; • "reset", crea un pulsante per la reinizializzazione dei campi del modulo; • "text", crea un campo di testo di una sola riga; • "radio", crea un pulsante di opzioni; • "checkbox", crea una casella di selezione • "image", come "submit" ma con una immagine al posto del pulsante; • "hidden", crea un elemento che non appare nel modulo ma ha un nome e un valore; • "password", crea un campo per l’immissione di password in cui i dati immessi sono visualizzati come asterischi; • "button", crea un pulsante generico definito e gestito dal programmatore; • "file", usato per inviare un file insieme ai dati del modulo. Nei prossimi due esempi sono presenti tutti i controlli della lista ancora non esaminati (ad eccezione di "button" che viene usato in seguito) nonché altri possibili attributi del tag ‘<input>’: |<html> |<head><title>Esempio con controlli vari</title></head> |<body> |<div align="center"><b>Esempio con controlli vari</b></div> |<p/> |<form action="/cgi-bin/cgi-prova.sh" method="get"> |<input type="hidden" name="nascosto" value="aaa"/> |<p>Fascia di età:</p> |<p><input type="radio" name="fascia" value="0-15"/>0-15</p> Moduli e programmi CGI 103 |<p><input type="radio" name="fascia" value="16-30" checked/>16-30</p> |<p><input type="radio" name="fascia" value="30-50"/>30-50</p> |<p><input type="radio" name="fascia" value="50-99"/>50-99</p> |<p/> |Seleziona i tuoi campi di interesse: |<p/> |<input type="checkbox" name="int" value="computer" checked/> Computer |<input type="checkbox" name="int" value="musica"/> Musica |<input type="checkbox" name="int" value="sport"/> Sport |<p/> |Inserisci la password: |<input type="password" name="psw" size="8" maxlength="8"/> |<p/> |<input type="image" src="tux.jpg" width="50" height="55" |title="Premi qui per inviare i dati" alt="Invio" align="right"/></p> |<p><input type="reset" value="Pulisci campi"/></p> |</form> |</body> |</html> L’aspetto di questo modulo è quello della figura 6.5. F | igura 6.5. Alcuni degli attributi utilizzati in questo esempio sono di immediata comprensione, anche perché già visti in precedenza (come ‘src’, ‘alt’, ‘align’). L’attributo ‘checked’ viene usato in caso di controlli che prevedono più alternative per preimpostarne una o alcune. I controlli "hidden" possono essere utili nel caso si debbano inviare dei dati fissi al programma CGI senza che l’utente possa vederli e tantomeno variarli. L’invio dei dati del modulo avviene cliccando sull’immagine che appare in fondo a destra. |<html> |<head><title>Esempio con trasferimento di file</title></head> |<body> Moduli e programmi CGI 104 |<div align="center"><b>Trasferimento di file</b> |</div> |<p/> |<form enctype="multipart/form-data" action="/cgi-bin/cgi-prova.sh"> |<p/> |File da inviare: <input type="file" name="file"/> |<p/> |<input type="submit" size="5" value="Invio"/> |</form> |</body> |</html> Questo modulo ha l’aspetto mostrato in figura 6.7. F | igura 6.7. Il controllo "file" permette di inviare un file al programma CGI; presenta un bottone "Browse" o "Sfoglia", inserito automaticamente, per permettere la ricerca del file nell’ambito della macchina locale. Si noti che in questo contesto si deve valorizzare l’attributo ‘enctype’ con "multipart/formdata". 6.2.2 L’elemento ‘select’ « Con il tag ‘<select>’ si crea un menu a cascata le cui opzioni sono indicate ognuna con un tag ‘<option>’ e la cui definizione si conclude con ‘</select>’. Il tag ‘<select>’ prevede obbligatoriamente l’attributo ‘name’; altri attributi utilizzabili in questo contesto sono: • ‘size’ (attributo di ‘select’), per indicare il numero di voci di menu visibili contemporaneamente; • ‘multiple’ (attributo di ‘select’), per dare la possibilità all’utente di selezionare più di una voce; • ‘selected’ (attributo di ‘option’), per indicare una voce selezionata per difetto; • ‘value’ (attributo di ‘option’), per indicare un testo, associato alla scelta effettuata, da inviare al programma CGI; in assenza di tale attributo, il testo inviato coincide con il nome dell’opzione. Moduli e programmi CGI 105 6.2.3 L’elemento ‘textarea’ « Con il tag ‘<textarea>’ si può creare una casella di testo contenente più righe. Si deve chiudere con ‘</textarea>’ ed è obbligatorio l’attributo ‘name’. Ci sono anche gli attributi ‘rows’ e ‘cols’ con i quali si indica l’ampiezza della casella di testo senza però limitare la quantità di caratteri inseribili; quasi tutti i browser infatti inseriscono le barre di scorrimento a sinistra ed in basso in caso la quantità di caratteri immessi superi la dimensione della casella. Si può inoltre definire un testo pre-inserito semplicemente scrivendolo tra i tag ‘<textarea>’ e ‘</textarea>’. Nel seguente esempio viene mostrato l’uso di un menu a cascata e di una casella di testo. |<html> |<head><title>Esempio con menu a cascata e casella di testo</title> |</head> |<body> |<div align="center"><b>Esempio con menu a cascata e casella di testo</b> |</div> |<p/> |<form action="/cgi-bin/cgi-prova.sh" method="post"> |Componenti da acquistare:<p/> |<select name="comp" multiple size="6"> |<option selected>Main board</option> |<option selected>Cpu</option> |<option selected>Ram</option> |<option>Floppy disk 120 Mb</option> |<option>Floppy disk 1,44 Mb</option> |<option>Hard disk IDE</option> |<option>Hard disk SCSI</option> |<option>Scheda video</option> |<option>Scheda audio</option> |</select> |<p/> |Inserire un commento<p/> |<textarea name="commento" rows="5" cols="50"> |Testo inserito preventivamente |</textarea> |<p/> |<input type="submit" value="Invio"/> |</form> |</body> |</html> Il modulo che si ottiene è quello della figura 6.9. Moduli e programmi CGI 106 F | igura 6.9. 6.2.4 Raggruppamento e ordinamento dei controlli di un modulo « Con l’elemento ‘<fieldset>’ si possono raggruppare, incorniciandoli automaticamente, più controlli di un modulo, tutti quelli presenti fino al tag di chiusura ‘</fieldset>’; all’interno si può usare il tag ‘<legend>’ per aggiungere una legenda posizionandola con l’attributo ‘align’. Resta infine da segnalare l’attributo ‘tabindex’, utilizzabile per tutti i controlli di un modulo, con il quale si può cambiare l’ordine di selezione degli stessi assegnandogli un valore intero. Valori alti hanno la precedenza rispetto a quelli bassi o negativi; in caso di assenza di questo attributo, l’ordine di selezione dei controlli corrisponde a quello di inserimento all’interno del modulo: dall’alto in basso e da sinistra verso destra. 6.3 L’attributo ‘accesskey’ « L’attributo ‘accesskey’ può essere usato con i controlli ‘<input>’, ‘<textarea>’, ‘<button>’ e anche con i tag per i collegamenti ‘<a>’ e ‘<area>’; il suo scopo è quello di definire una «scorciatoia» da tastiera per attivare il controllo o il collegamento. Il suo uso è molto banale, come mostrato nel seguente esempio riguardante un controllo per l’invio dei dati di un modulo: |<input type="submit" value="[I]nvio" accesskey="I"/> In questo modo diventa possibile attivare l’invio dei dati, oltre che come di consueto attraverso il mouse, anche con la tastiera; la modalità di selezione della scorciatoia dipende dal browser utilizzato. Nel nostro esempio, in cui la scorciatoia è il carattere «I», se usiamo Firefox si devono premere i tasti [ Shift+Alt+I ], se usiamo Internet Explorer i tasti [ Alt+I ]. Moduli e programmi CGI 107 6.4 Prerequisiti per l’uso di CGI (cenni alla configurazione di ‘Apache’) « Gli esempi di pagine Web mostrati finora possono essere visualizzati, con un programma di navigazione, anche semplicemente aprendoli come file locali (usando quindi il «protocollo» file://); da questo momento le pagine devono invece essere richieste ad un servente Web (con ‘http://’) in modo che possano essere correttamente eseguiti i CGI richiamati dai moduli presenti in esse. Inoltre è necessario che sul servente sia possibile eseguire i programmi nel linguaggio di programmazione scelto per realizzare i CGI (ad esempio se si scrivono in linguaggio Perl, deve essere installato l’interprete di questo linguaggio). In questo paragrafo e nei successivi si fa riferimento al servente Web ‘Apache’ (usato in circa i due terzi dei siti Web esistenti), su piattaforma GNU/Linux. 6.4.1 Configurazione di ‘Apache’ « Viene presa in considerazione la versione più recente del programma, cioè la ‘2’ e si suppone di utilizzare una distribuzione GNU/Linux derivata da ‘Debian’ (nel nostro caso ‘Ubuntu-7.04’). Nel proseguo, anche in paragrafi successivi, si fa spesso riferimento alla documentazione di alcuni pacchetti software di GNU/Linux o al manuale in linea di certi comandi; può allora essere utile chiarire quanto segue: • il manuale in linea relativo a un comando si ottiene eseguendo: $ man nome_comando si scorre il testo una riga alla volta con i tasti freccia e il tasto [ Invio ]; e una pagina alla volta con la barra spaziatrice e i tasti [ pagina su ] e [ pagina giu ]; si possono effettuare ricerche di testo premendo [ shift / ] e inserendo la stringa da cercare seguita da [ Invio ] e dalla pressione di [ n ] per trovare successive occorrenze; si esce dal manuale premendo [ q ]; • i file di documentazione dei pacchetti installati in un sistema GNU/Linux sono solitamente in ‘/usr/share/doc/nome_pacchetto’; • gli «HOWTO» e le FAQ (Frequently Asked Questions) sono rispettivamente in ‘/usr/ share/doc/HOWTO’ e ‘/usr/share/doc/FAQ’. Si tenga presente che sulla configurazione e l’uso di Apache sono stati scritti interi volumi; qui ci accontentiamo di fornire le informazioni necessarie al suo funzionamento su un singolo nodo di rete (‘localhost’ o numero IP 127.0.0.1), contesto sufficiente per i nostri scopi, e alla configurazione richiesta per l’esecuzione di programmi CGI. Moduli e programmi CGI 108 Quello che segue presuppone il possesso dei diritti dell’utente amministratore di un sistema GNU/Linux cioè dell’utente ‘root’. In Ubuntu, dopo l’installazione del sistema, esso non è abilitato, ma l’utente definito in sede di installazione appartiene al gruppo dei cosiddetti utenti ‘sudoers’ cioè abilitati, previo reinserimento della loro password quando richiesto, ad eseguire comandi con i privilegi dell’utente amministratore. Si può allora operare come segue per attivare un terminale nell’ambiente grafico in cui eseguire i comandi come utente ‘root’: 1. premere [ Alt+F2 ] per ottenere l’interfaccia di esecuzione comandi; 2. scrivere nella riga di comando: gksudo gnome-terminal e cliccare su «esegui»; 3. rispondere alla richiesta di password dell’utente corrente. Nella figura 6.11 vediamo il modulo per l’esecuzione dei comandi con inserito il comando appena citato. F | igura 6.11. Nella figura 6.12 vediamo il successivo modulo per l’inserimento della password. F | igura 6.12. Infine nella figura 6.13 vediamo il terminale aperto in cui si possono eseguire i comandi con i privilegi di ‘root’ (lo si capisce dal fatto che il prompt dei comandi termina con il carattere ‘#’ anziché con ‘$’). F | igura 6.13. Moduli e programmi CGI 109 La prima operazione da svolgere è naturalmente l’installazione del pacchetto Apache2; si consiglia di utilizzare le versioni già pronte per la distribuzione utilizzata e, nel caso di Ubuntu, di procedere con uno dei programmi dedicati all’aggiornamento dei pacchetti software, come ‘Synaptic’ (in ambiente grafico) o ‘apt-get’ (in ambiente testuale nel terminale in cui si hanno i diritti dell’amministratore). Per maggiori dettagli si consultino manuali e altra documentazione, anche in linea, relativa a questi programmi o in generale all’aggiornamento dei pacchetti software in GNU/Linux e in Ubuntu in particolare. Alla fine dell’installazione il programma ha già una configurazione sufficiente per poter essere utilizzato e viene anche inserito tra i cosiddetti «demoni» (programmi costantemente in esecuzione, in background, cioè «dietro le quinte», e pronti a rispondere a richieste di servizi provenienti dalla stessa macchina o da altre collegate in rete) che vengono attivati automaticamente ad ogni avvio della macchina. Se comunque fosse necessario avviare manualmente il demone di Apache2 si può provvedere con il seguente comando: # apache2ctl start Invece per fermarlo: # apache2ctl stop Per riavviarlo: # apache2ctl restart Per verificarne lo stato: # apache2ctl status I file di configurazione del servente Apache2 risiedono nella directory ‘/etc/apache2/’; il file più importante è ‘apache2.conf’. Ci sono poi le sottodirectory ‘mods-available’, ‘site-available’, ‘mods-enabled’, ‘site-enabled’; nelle prime due sono presenti i file di configurazione rispettivamente dei moduli aggiuntivi e dei siti gestibili, nelle altre due i file di configurazione (che non sono altro che dei collegamenti simbolici a file delle altre due sottodirectory) rispettivamente dei moduli e dei siti abilitati. Per gli scopi che ci prefiggiamo, nel file ‘/etc/apache2/apache2.conf’ non è necessario alcun intervento; di seguito riportiamo un piccolo estratto di tale file. 1 2 3 4 5 6 7 8 9 10 11 12 13 |# |# ServerRoot: The top of the directory tree under which the server’s |# configuration, error, and log files are kept. |# |# NOTE! If you intend to place this on an NFS (or otherwise network) |# mounted filesystem then please read the LockFile documentation (available |# at <URL:http://httpd.apache.org/docs-2.1/mod/mpm_common.html#lockfile>); |# you will save yourself a lot of trouble. |# |# Do NOT add a slash at the end of the directory path. |# |ServerRoot "/etc/apache2" | Moduli e programmi CGI 110 14 15 16 17 18 19 20 21 22 |User www-data |Group www-data | |# Include module configuration: |Include /etc/apache2/mods-enabled/*.load |Include /etc/apache2/mods-enabled/*.conf | |# Include the virtual host configurations: |Include /etc/apache2/sites-enabled/ La numerazione delle righe non è presente nel file ed è stata aggiunta per spiegarne più agevolmente il contenuto: • il file contiene molte righe di commento (quelle che iniziano con «#») a scopi esplicativi; questa è una buona consuetudine spesso rispettata nell’ambiente GNU/Linux; • la riga 12 riguarda la dislocazione dei file di configurazione; • le righe 14 e 15 indicano utente e gruppo con i diritti dei quali viene eseguito il demone di Apache2; infatti, per motivi di sicurezza, solitamente i demoni non vengono eseguiti con i diritti dell’utente ‘root’ ma con quelli di un utente non privilegiato spesso definito appositamente nel sistema, in questo caso ‘www-data’; • le righe 18, 19 e 22 servono ad includere, in questo file di configurazione, i file relativi alla configurazione di moduli aggiuntivi e siti abilitati. Nella directory ‘/etc/apache2/sites-enabled’ troviamo il file ‘000-default’ che è un collegamento simbolico al file ‘/etc/apache2/sites-available/default’ e che contiene le configurazioni necessarie per la gestione del sito predefinito. I collegamenti simbolici sono ulteriori riferimenti a file esistenti nel file system; in GNU/Linux se ne fa un uso molto frequente per vari scopi che qui non approfondiamo. Per visualizzare o modificare uno di questi file si può agire indifferentemente sul file effettivo o su uno dei suoi collegamenti simbolici. Nel caso della configurazione di Apache l’idea è quella di avere nelle sottodirectory «-available» tutti i file utilizzabili e rendere attivi solo quelli che servono creando un collegamento ad essi nelle rispettive sottodirectory «-enabled». Anche nel file ‘/etc/apache2/sites-enabled/000-default’ non sono normalmente necessari molti interventi; di seguito viene riportato il suo contenuto. 1 2 3 4 5 6 7 8 9 10 11 12 |NameVirtualHost * |<VirtualHost *> | ServerAdmin webmaster@localhost | | DocumentRoot /var/www/ | <Directory /> | Options FollowSymLinks | AllowOverride None | </Directory> | <Directory /var/www/> | Options Indexes FollowSymLinks MultiViews | AllowOverride None Moduli e programmi CGI 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 111 | Order allow,deny | allow from all | # This directive allows us to have apache2’s default start page | # in /apache2-default/, but still have / go to the right place | RedirectMatch ^/$ /apache2-default/ | </Directory> | | ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ | <Directory "/usr/lib/cgi-bin"> | AllowOverride None | Options ExecCGI -MultiViews +SymLinksIfOwnerMatch | Order allow,deny | Allow from all | </Directory> | | ErrorLog /var/log/apache2/error.log | | # Possible values include: debug, info, notice, warn, error, crit, | # alert, emerg. | LogLevel warn | | CustomLog /var/log/apache2/access.log combined | ServerSignature On | | Alias /doc/ "/usr/share/doc/" | <Directory "/usr/share/doc/"> | Options Indexes MultiViews FollowSymLinks | AllowOverride None | Order deny,allow | Deny from all | Allow from 127.0.0.0/255.0.0.0 ::1/128 | </Directory> | |</VirtualHost> Illustriamo brevemente almeno le opzioni di configurazione più importanti: • la riga 5 permette di stabilire quale è la directory radice del sito, cioè quella dove risiedono i documenti da esso relativi; questo significa che quando con un browser si effettua la richiesta: http://localhost/esempi/esempio1.html, il servente cerca il file ‘esempio1.html’ nella directory ‘/var/www/esempi’ e se esso risulta presente e leggibile dall’utente ‘www-data’, lo invia come risposta al programma di navigazione; • le righe da 10 a 18 definiscono le proprietà della directory radice; in particolare con ‘Options Indexes’ si fa in modo che quando una richiesta è relativa a una directory senza indicazione di un file specifico, viene inviata come risposta la lista del contenuto di quella directory; • la riga 17 può essere commentata (inserendo un «#» in testa) in modo da evitare che le richieste inviate a ‘localhost’ senza indicazione di una risorsa specifica siano dirottate sulla directory ‘/var/www/apache2-default’; • la riga 20 indica che la directory in cui devono risiedere i programmi CGI è ‘/usr/lib/ cgi-bin/’ e viene riconosciuta dal servente come ‘/cgi-bin/’; ecco il motivo per cui Moduli e programmi CGI 112 negli esempi dei paragrafi precedenti il valore dell’attributo ‘action’ dei vari moduli era "/cgi-bin/nome_cgi" • le righe da 21 a 26 definiscono le proprietà della directory ‘/cgi-bin/’; in particolare è importante che ci sia ‘Options ExecCGI’, condizione necessaria affinché si possano eseguire i CGI ma non sufficiente, nel senso che questi ultimi devono anche avere i giusti permessi di esecuzione relativamente all’utente ‘www-data’; • le righe da 28 a 35 riguardano il log di Apache; non entriamo nei dettagli della loro descrizione (comunque di solito non occorre modificarle). Riguardo ai log di Apache sottolineiamo l’importanza della consultazione dei relativi file: ‘/var/log/apache2/access.log’ e ‘/var/log/apache2/error.log’ (gli altri file con nomi simili presenti nella directory ‘/var/log/apache2’ vengono creati automaticamente dal meccanismo di «rotazione» dei file di log e contengono messaggi meno recenti). Nel primo si trovano i messaggi di log riguardanti gli accessi fatti al servente. L’altro file contiene i messaggi ed è importantissimo se ci sono problemi nell’esecuzione di un CGI; in tal caso infatti la risposta che il servente invia al browser è un enigmatico e poco utile messaggio del tipo: «500 Internal Server Error» senza alcuna indicazione sui motivi che hanno causato il malfunzionamento; solo consultando il file ‘/var/log/apache2/error.log’ si può sperare di avere qualche informazione utile per cercare di individuare e correggere l’errore nel CGI «incriminato». 6.4.2 Gestione dei «siti-utente» « Una modifica interessante che può essere fatta alla configurazione predefinita di Apache2 è quella riguardante l’attivazione dei cosiddetti «siti-utente» che sono degli spazi Web, uno per ogni utente del sistema GNU/Linux, gestiti dal servente Apache2 e raggiungibili all’URI: http:// localhost/~nome_utente/. Per attivare questa funzionalità occorre (sempre con i diritti dell’utente ‘root’) attivare e configurare il modulo ‘userdir’ creando i necessari collegamenti simbolici in ‘/etc/apache2/ mods-enabled’ con i seguenti comandi: # cd /etc/apache2/mods-enabled # ln -s ../mods-available/userdir.load . # ln -s ../mods-available/userdir.conf . Si ricordi di riavviare il servente dopo ogni modifica alla sua configurazione. Il file ‘/etc/apache2/mods-enabled/userdir.conf’ ha il seguente contenuto: 1 2 3 4 5 6 7 8 9 |<IfModule mod_userdir.c> | UserDir public_html | UserDir disabled root | | <Directory /home/*/public_html> | AllowOverride FileInfo AuthConfig Limit | Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec | </Directory> |</IfModule> Moduli e programmi CGI 113 Anche in questo caso commentiamo alcune direttive importanti. • La riga 2 stabilisce che il nome della directory contenente i documenti del sito personale è ‘public_html’; questo significa che ogni utente deve creare e gestire una sottodirectory con questo nome all’interno della propria directory personale (di solito ‘/home/ nome_utente’) e fare in modo che essa sia raggiungibile, e il suo contenuto leggibile, da parte dell’utente ‘www-data’; • la riga 3 stabilisce che il sito personale non è attivo per l’amministratore (per motivi di sicurezza); • le righe da 5 a 8 definiscono le proprietà delle directory dei siti personali (notare l’uso di «*» per indicare qualsiasi nome di utente). Per fare in modo che sia possibile eseguire dei CGI residenti nella directory del sito personale anziché solo nella directory ‘/usr/lib/cgi-bin/’ occorre modificare la riga 7 inserendo, tra le opzioni, anche ‘ExecCGI’ e aggiungere in coda una riga ulteriore con questo aspetto: |AddHandler cgi-script .cgi .pl .sh In tale riga .cgi, .pl, .sh sono alcune estensioni usate spesso nei nomi dei CGI (se ne possono aggiungere altre). Con queste modifiche l’utente può eseguire dei CGI memorizzati nella directory del proprio sito personale che, come detto, è solitamente ‘/home/nome_utente/public_html’; è comunque consigliabile creare in essa delle sottodirectory in cui posizionare le varie risorse del sito suddivise per tipologia, ad esempio: ‘doc’ per i file HTML, ‘imm’ per le immagini, ‘cgi’ per i CGI e così via. Con uno spazio personale organizzato in questo modo, per aprire un modulo HTML contenuto nel file ‘doc/modulo.html’, dovremmo collegarci al seguente URI: http://localhost/ ~nome_utente/doc/modulo.html; al suo interno, per inviare i dati al CGI ‘cgi/provacgi.cgi’, occorrerebbe valorizzare l’attributo ‘action’ del modulo con il valore "../cgi/provacgi.cgi". Il vantaggio di poter usare i siti personali risiede principalmente nel fatto che ogni utente può manipolare a suo piacimento i documenti del proprio sito senza essere costretto dopo ogni variazione a trasferire i file nelle posizioni predefinite da Apache (‘/var/www’, ‘/usr/lib/ cgi-bin’), senza contare poi che gli amministratori di sistema spesso impediscono queste operazioni. L’uso dei siti-utente è poi senza dubbio utile, forse indispensabile, nel caso si debbano collaudare siti o applicazioni Web e nelle attività didattiche riguardanti questi argomenti. 6.4.3 Permessi su file e directory di un sito Web « In precedenza si è accennato al fatto che certe directory devono essere raggiungibili e certi file leggibili o eseguibili da parte dell’utente ‘www-data’; ricordiamo infatti che, solitamente, i processi (programmi in esecuzione) del servente Apache2 vengono eseguiti con i diritti di tale utente e del gruppo di uguale nome. Questo significa appunto che le directory che devono essere attraversate e i file che devono essere letti o eseguiti devono permettere queste operazioni all’utente o al gruppo succitati. Moduli e programmi CGI 114 Occorre quindi fornire alcune informazioni su come assegnare i permessi adeguati affinché il nostro sito funzioni regolarmente. Nel caso del sito predefinito le operazioni di assegnazione o variazione dei permessi devono essere fatte dall’amministratore; nel caso di sito personale, invece, può farle anche l’utente «proprietario» di quel sito, visto che le risorse risiedono nel proprio spazio personale dove egli ha «pieni poteri». Riassumiamo quali devono essere i permessi delle varie risorse fornendo anche possibili comandi per loro assegnazione (ricordando comunque che essa può essere fatta anche in ambiente grafico con strumenti più amichevoli): • le directory ‘/var’ e ‘/var/www’ devono essere attraversabili da tutti gli utenti («other» nel gergo Linux) in modo da esserlo anche per ‘www-data’; questo dovrebbe essere già vero in un sistema GNU/Linux «normale», se così non fosse si può provvedere nel modo seguente: # chmod o+x /var # chmod o+x /var/www • i documenti del sito devono essere leggibili per tutti gli utenti (e quindi anche per ‘www-data’): # chmod o+r /var/www/* • le directory ‘/usr’ e ‘/usr/lib/cgi-bin’ devono essere attraversabili da tutti gli utenti (quasi sempre lo sono già) e i programmi CGI ivi contenuti devono essere leggibili e eseguibili da tutti gli utenti in modo da esserlo anche per ‘www-data’: # chmod o+rx /usr/lib/cgi-bin/* Analoghe considerazioni valgono per le risorse utilizzate in un sito-utente: deve essere possibile per tutti raggiungere la directory ‘/home/nome_utente/public_html’ e eventuali sottodirectory e i file in esse contenuti devono essere leggibili e, nel caso di CGI, anche eseguibili per tutti gli utenti. A titolo di esempio ecco il comando per rendere leggibili e attraversabili tutte le sottodirectory di ‘public_html’ e leggibili e eseguibili tutti i file in esse contenuti, per tutti gli utenti, in modo ricorsivo: $ chmod -R o+rx ~/public_html/* 6.5 Approfondimenti sul protocollo HTTP « Come accennato in precedenza, i CGI ricevono dati in input dal browser tramite il servente Web e possono manipolarli liberamente per produrre una risposta da inviare «indietro» al programma di navigazione. Prima di proseguire è dunque importante fornire maggiori dettagli (senza pretese di completezza) sui principi di funzionamento del protocollo HTTP che sovrintende al dialogo tra programma di navigazione e servente Web (e quindi programma CGI). Nel paragrafo 1.4.2 si è già visto come il protocollo HTTP regoli l’interazione tra un programma di navigazione e un servente Web tramite una sequenza di quattro fasi: Moduli e programmi CGI 115 • connessione: il cliente apre una connessione sulla porta 80 verso l’indirizzo del servente; • richiesta documento: se il servente è in ascolto sulla porta 80 e accetta la connessione, il cliente invia la richiesta della pagina desiderata (ad esempio ‘index.html’); • risposta: il servente prepara la risposta e la invia al cliente; • disconnessione: la connessione viene chiusa dal servente mentre il browser del cliente interpreta la pagina di risposta e la presenta sullo schermo. Vediamo in dettaglio le fasi più importanti che sono quelle della richiesta e della risposta. 6.5.1 La richiesta « La richiesta deve essere così strutturata: • una riga iniziale indicante il metodo, la risorsa richiesta e la versione del protocollo HTTP; • una serie di intestazioni facoltative; • un eventuale corpo. Il corpo della richiesta deve essere preceduto da «CRLF» (ritorno di carrello e riga nuova, codici ASCII 13 e 10) in modo da rendere la richiesta stessa compatibile con i sistemi operativi della famiglia Unix (che concludono una riga con il solo «LF») e con quelli tipo MS-Dos, MS-Windows (che concludono una riga con «CRLF»). Non viene fatta distinzione tra maiuscole e minuscole eccetto che nell’indicazione del file richiesto. Le versioni del protocollo accettate sono: ‘HTTP/1.0’ e ‘HTTP/1.1;’ con questa ultima è possibile anche effettuare più richieste per ogni connessione anziché una sola come previsto dalla versione precedente. Il metodo permette di specificare il tipo di richiesta da effettuare sulla risorsa specificata; i metodi previsti sono: • GET, è il più usato nelle normali attività di navigazione e permette di inviare informazioni al servente in coda all’URI della risorsa richiesta; • POST, si usa principalmente per trasmettere, nel corpo della richiesta, i dati di un modulo HTML al servente; • HEAD, simile a GET ma richiede solo le intestazioni della risorsa; è usato prevalentemente per scopi diagnostici, cioè per verificare se un indirizzo è accessibile; • PUT, trasmette la risorsa specificata al servente; in questo modo sarebbe possibile fare upload di file, ma di solito i serventi Web sono configurati per impedire questa operazione; • DELETE, permette di cancellare la risorsa dal servente; anche in questo caso è un’operazione spesso non abilitata; • OPTIONS, permette di ottenere la lista dei metodi gestiti dal servente; • TRACE, restituisce copia della richiesta; usato solo per scopi diagnostici; • CONNECT, permette ai serventi proxy di cambiare versione del protocollo HTTP. Moduli e programmi CGI 116 Le intestazioni servono ad aggiungere informazioni alla richiesta; ad esempio ‘Accept-Language:’ che indica quali lingue vuole il programma di navigazione, oppure ‘Host:’ che indica il nome del servente. Vale la pena soffermarsi su quest’ultima intestazione che è obbligatoria a partire dalla versione ‘1.1’ del protocollo. A prima vista parrebbe che essa fornisca un’informazione ridondante in quanto, nel momento in cui il cliente effettua la richiesta, il nome del servente cui si rivolge è già stato specificato nella precedente fase di connessione. Invece questa informazione è importantissima perché permette di configurare i serventi Web in modo che possano gestire più siti Web associati allo stesso indirizzo IP e identificati da nomi diversi. Vediamo come questo è possibile: supponiamo di avere i siti www.sito1.it e www.sito2.it entrambi associati all’indirizzo IP 82.88.114.44 e gestiti da un servente Web Apache; quando i clienti effettuano richieste ai due siti esse vengono indirizzate, grazie alla risoluzione dei nomi fatta dal DNS, allo stesso indirizzo 82.88.114.44. Il servente non sarebbe quindi in grado di distinguere le richieste originariamente dirette a sito1 da quelle dirette a sito2; ecco perché è indispensabile l’informazione circa il nome del sito Web interessato dalla richiesta, fornita con l’intestazione ‘Host:’. Per questo motivo ormai tutti i programmi di navigazione utilizzano il protocollo HTTP/1.1 e specificano il nome del servente, mediante l’intestazione ‘Host:’, nelle loro richieste di documenti HTML. L’aspetto di una tipica richiesta può essere il seguente: |GET /index.html HTTP/1.1 |Host: www.maxplanck.it |Accept-Language: it en |<CRLF> (riga vuota) 6.5.2 La risposta « Anche la risposta ha una struttura ben definita: • una riga contenente un codice di stato di tre cifre; • una o più intestazioni; • il corpo della risposta preceduto da una riga vuota. Ad ogni codice di stato è associata una stringa esplicativa e i codici sono divisi in categorie in base alla prima cifra: • 1xx, codici informativi; ad esempio: «101 Switching Protocol»; • 2xx, richiesta servita con successo; ad esempio: «200 OK» o «204 No content»; • 3xx, richiesta reindirizzata all’URI indicato nella direttiva ‘location’; ad esempio: «301 Moved permanently»; • 4xx, richiesta errata; ad esempio: «400 Bad request», «403 Forbidden», «404 Not Found»; Moduli e programmi CGI 117 • 5xx, errore del servente; ad esempio: «500 Internal Server Error». Le intestazioni servono ad aggiungere informazioni alla risposta; ad esempio ‘Date:’ che indica data e ora della trasmissione, oppure ‘Server:’ che descrive il servente. Esistono anche altri tipi di intestazioni che permettono di fornire informazioni aggiuntive circa la trasmissione del corpo della risposta; ad esempio: ‘Content-Type:’ per indicare il tipo MIME del contenuto della risposta, oppure ‘Content-Length:’ per specificarne la lunghezza in byte. Ecco l’aspetto di una possibile risposta: |HTTP/1.1 200 OK |Date: Sun, 12 Aug 2007 20:00:00 GMT |Content-Type: text/html |Content-Length: 75 |<CRLF> (riga vuota) |<html><head><title>Risposta</title></head><body>Prova risposta</body></html> 6.5.3 Simulazione di una connessione HTTP da linea di comando « Il protocollo HTTP regola un «semplice» scambio di file di testo tra due nodi di rete; si può allora verificarne il funzionamento utilizzando l’applicazione TELNET per effettuare la connessione e la successiva richiesta di una risorsa ad un servente Web. Il servizio TELNET risponde di solito alla porta 23 ma si può utilizzare il comando ‘telnet’ per connettersi ad altri tipi di servizi semplicemente indicando il relativo numero di porta (se non si indica la porta viene usata la 23); quindi per connettersi al servente Web installato sulla macchina locale si esegue il comando: $ telnet localhost 80 Se la connessione viene stabilita correttamente si può poi effettuare la richiesta rispettando le regole illustrate in precedenza; la risorsa desiderata viene ricevuta (a meno di errori) sul terminale usato per la connessione e quest’ultima termina (dopo alcuni secondi nel caso del protocollo HTTP/1.1). Nella figura 6.20 viene mostrato il procedimento fino all’ottenimento della risposta; gli unici input sono le righe sottolineate che corrispondono all’attivazione della di connessione e all’effettuazione della richiesta HTTP (si noti la riga vuota dopo l’intestazione ‘Host:’). Come si vede la risposta appare come testo puro, quindi senza che i tag HTML vengano interpretati, cosa del tutto normale in questo contesto, data la mancanza di un programma di navigazione in grado di interpretarli. F | igura 6.20. Moduli e programmi CGI 118 6.6 Creazione della pagina di risposta da parte del CGI « I programmi CGI, nel momento in cui devono creare pagine Web di riposta da inviare al cliente, devono rispettare le regole appena illustrate; quindi devono creare un file di testo con una intestazione ‘Content-Type:’ con l’indicazione del tipo MIME, seguita da una riga vuota e dal contenuto effettivo della risposta. Il tipo MIME più utilizzato in questo contesto è ovviamente text/html. Ovviamente il corpo della risposta deve essere coerente con quanto dichiarato nell’intestazione e quindi deve essere un sorgente HTML. Un altro tipo di risposta che può essere fornita da un programma CGI consiste nell’invio di una pagina Web già pronta, residente sul servente o presso qualsiasi altro indirizzo in rete; in tal caso la risposta deve contenere solo una intestazione di tipo ‘Location’ in questa forma: |Location: URI della pagina da inviare Anche in questo caso è necessario aggiungere una riga vuota dopo l’intestazione. 6.7 Variabili di ambiente per i CGI « Un programma CGI ha a disposizione un gruppo di «variabili di ambiente» che vengono valorizzate automaticamente dal servente HTTP e che il programma può usare per i suoi scopi. Segue l’elenco delle più importanti di tali variabili con una breve descrizione del loro significato: Nome variabile CONTENT_LENGTH CONTENT_TYPE GATEWAY_INTERFACE HTTP_ACCEPT HTTP_REFERER HTTP_USER_AGENT PATH_INFO Significato Numero di byte nello standard input, se il metodo di invio è "post". Tipo MIME dei dati inviati. Versione del CGI in esecuzione (di solito CGI/1.1). Elenco di tipi MIME che il browser è in grado di accettare. Nome della pagina HTML che ha inviato i dati. Nome e versione del browser che ha inviato i dati. Informazioni aggiuntive passate aggiungendo un percorso in coda all’URI specificato come valore di ‘action’. Moduli e programmi CGI Nome variabile PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST REMOTE_USER REQUEST_METHOD SCRIPT_NAME SERVER_ADMIN SERVER_NAME SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE 119 Significato Percorso completo ottenuto da quello contenuto nella variabile precedente aggiungendo in testa il «document root» del servente Web cioè il percorso di base dei documenti HTML (di solito ‘/var/www/’). Stringa di input se il metodo di invio è "get". Indirizzo IP della macchina che ha inviato i dati. Nome della macchina che ha inviato i dati. Nome dell’utente che ha inviato i dati (valorizzato solo se il servente richiede l’autenticazione dell’utente). Metodo usato per l’invio dei valori: "post" o "get". Nome del programma CGI completo di percorso. Indirizzo di posta elettronica dell’amministratore del servente. Nome della macchina su cui viene eseguito il programma CGI Porta per il collegamento al servente Web (quasi sempre 80). Protocollo HTTP usato dal servente (di solito HTTP/1.1). servente Web utilizzato, ad esempio Apache 2.2.3 Il valore di queste variabili si ottiene nell’ambiente della shell di GNU/Linux anteponendo al loro nome il simbolo «$». In altri linguaggi l’operazione è meno immediata; ad esempio in Perl occorre usare il vettore associativo ‘$ENV’ (per maggiori dettagli si consiglia di consultare manuali riguardanti tale linguaggio). Di seguito vediamo un esempio in cui si usa un modulo di input che richiama un programma CGI, denominato ‘cgi-var.sh’, scritto con i comandi della shell ‘Bash’ di GNU/Linux; tale programma crea un documento di risposta in cui sono visualizzati i valori delle variabili appena elencate. Sorgente HTML del modulo: |<html> |<head> |<title>Esempio di modulo per visualizzare variabili</title> |</head> |<body> |<h2>Esempio di input e visualizzazione di variabili d’ambiente</h2> |<form action="/cgi-bin/cgi-var.sh" method="get"> |<p><br/><b>Inserire dato da passare al programma </b> |<input type="text" name="dato" size="5" maxlength="3"/> |</p> |<input type="submit" value="Invio"/> |</form> |</body> |</html> L’aspetto del modulo è quello mostrato in figura 6.24. Moduli e programmi CGI 120 F | igura 6.24. Di seguito viene riportato il programma CGI ‘cgi-var.sh’: |#!/bin/sh |# |# Programma cgi scritto in shell per la visualizzazione delle variabili di ambiente |# |echo "Content-type: text/html" |echo |echo "<html>" |echo "<head>" |echo "<title>Test variabili di ambiente CGI</title>" |echo "</head>" |echo "<body>" |echo "<h4>Test variabili di ambiente CGI</h4>" |echo "<pre>" |echo |echo "CONTENT_LENGTH = $CONTENT_LENGTH" |echo "CONTENT_TYPE = $CONTENT_TYPE" |echo "GATEWAY_INTERFACE = $GATEWAY_INTERFACE" |echo "HTTP_ACCEPT = $HTTP_ACCEPT" |echo "HTTP_REFERER = $HTTP_REFERER" |echo "HTTP_USER_AGENT = $HTTP_USER_AGENT" |echo "PATH_INFO = $PATH_INFO" |echo "PATH_TRANSLATED = $PATH_TRANSLATED" |echo "QUERY_STRING = $QUERY_STRING" |echo "REMOTE_ADDR = $REMOTE_ADDR" |echo "REMOTE_HOST = $REMOTE_HOST" |echo "REMOTE_USER = $REMOTE_USER" |echo "REQUEST_METHOD = $REQUEST_METHOD" |echo "SCRIPT_NAME = $SCRIPT_NAME" |echo "SERVER_ADMIN = $SERVER_ADMIN" |echo "SERVER_NAME = $SERVER_NAME" |echo "SERVER_PORT = $SERVER_PORT" |echo "SERVER_PROTOCOL = $SERVER_PROTOCOL" |echo "SERVER_SOFTWARE = $SERVER_SOFTWARE" |echo |echo "Standard input:" |cat |echo "</pre>" |echo "</body>" Moduli e programmi CGI 121 |echo "</html>" L’aspetto del documento di risposta creato da ‘cgi-var.sh’ è mostrato nella figura 6.26. F | igura 6.26. Se nel modulo cambiamo il metodo di invio dei dati da "get" a "post" otteniamo la risposta mostrata nella figura 6.27. F | igura 6.27. 122 Moduli e programmi CGI 6.8 Passaggio dei dati del modulo al programma CGI « Al momento della definizione di un modulo, come abbiamo visto, occorre specificare il nome e la locazione del CGI che deve trattare i dati e anche il modo in cui essi vengono trasferiti al CGI stesso. Ricordando che allo scopo si usano gli attributi ‘action’ e ‘method’ del tag ‘<form>’, vediamo il seguente esempio di definizione di un modulo (tralasciando i dettagli dei controlli) in cui si fanno queste ipotesi: • il programma CGI si chiama ‘cgi-prova.sh’ e risiede nella directory ‘/cgi-bin’ del servente Web; • nel modulo sono inseriti due campi con attributo ‘name’ "cognome" e "nome" rispettivamente; • i valori dei due campi inseriti dall’utente sono "Paperino" e "Paolino" rispettivamente. |<form action="/cgi-bin/cgi-prova.sh" method="get"> |... |(controlli vari del modulo) |.... |</form> In caso di invio con metodo "get" i dati, nella forma «nome=valore», vengono accodati all’URI indicato come valore di ‘action’ separati da esso con il simbolo «?»; inoltre ogni coppia nomevalore è separata dalla successiva dal carattere «&». Quindi l’URI effettivo diventa: |/cgi-bin/cgi-prova.sh?cognome=Paperino&nome=Paolino Il programma ‘cgi-prova.sh’ riceve i dati nella variabile di ambiente ‘QUERY_STRING’ che assume il valore "cognome=Paperino&nome=Paolino". L’alternativa è usare il metodo "post" nel qual caso i dati vengono passati attraverso il canale di input standard mentre la variabile ‘QUERY_STRING’ rimane vuota; il programma CGI deve quindi preoccuparsi di leggere lo standard input dove trova la stringa: "cognome=Paperino&nome=Paolino". Il metodo "post" è quello da usare obbligatoriamente nel caso i dati debbano essere trasferiti ad un indirizzo di posta elettronica; negli altri casi si possono usare indifferentemente i due metodi. Occorre però osservare che il metodo "get" è il meno indicato per due motivi: rende visibili i dati accodati agli URI, anche se questi sono di tipo password, ed è soggetto ai limiti di lunghezza degli stessi (circa 2 Kbyte) e quindi dà problemi in presenza di una grossa mole di dati da trasferire. Inoltre il metodo "get" è, secondo le specifiche del protocollo HTTP, «sicuro» (non genera variazioni nello stato interno del servente) ma è anche «idempotente» (l’effetto sul servente di più richieste identiche è lo stesso di quello di una sola richiesta) e questo fa si che i programmi di navigazione possano memorizzare nella propria memoria cache le relative pagine di risposta. Con il metodo "post" invece il servente viene ricontattato ogni volta che la pagina viene ricaricata e appare anche una opportuna domanda all’utente circa la sua reale volontà di inviare di nuovo i Moduli e programmi CGI 123 dati; per questo è consigliabile usare il metodo "post" in tutte le situazioni in cui l’elaborazione dei dati del modulo provoca un qualche aggiornamento di dati residenti sul servente. Se il modulo di provenienza dei dati prevede la possibilità di più valori per uno stesso campo (si pensi ad un controllo ‘<select>’ con attributo ‘multiple’), nella stringa dei dati troviamo più coppie nome-valore riguardanti quel campo, ad esempio: "cognome=Paperino&nome=Paolino&hobby=musica&hobby=pittura". Nel caso infine si usi un modulo per trasferire un file, il programma CGI deve essere di tipo particolare: non deve aspettarsi stringhe in input né in ‘QUERY_STRING’ né nello standard input, ma deve essere predisposto alla lettura del file inviato attraverso quest’ultimo. 6.9 Decodifica dei dati di input del CGI « Come abbiamo visto, indipendentemente dal metodo usato per l’invio, l’input arriva al programma CGI come una stringa composta da coppie nome=valore come la seguente: |nome1=valore1&nome2=valore2&nome3=valore3..... Questo formato di invio prende il nome di «codifica URL» e si basa sulle seguenti regole: • ogni coppia «nome=valore» è separata dal carattere «&»; • gli elementi di ogni coppia sono separati dal simbolo di uguale; • se un campo non contiene alcun valore, la coppia corrispondente diventa «nome=»; • gli spazi nell’input sono rappresentati da simboli «+»; • i caratteri speciali, cioè quelli con codice ASCII maggiore di 127, e i caratteri riservati «=», «&», «%», «/», «~», «@», «+» vengono rappresentati con il loro valore esadecimale preceduti dal simbolo «%». Vediamo in dettaglio le codifiche dei caratteri riservati: Carattere % & + / = @ ~ Codifica %25 %26 %2B %2F %3D %40 %7E Il programma CGI deve per prima cosa fare il parsing dell’input, cioè scandirlo e decodificarlo, tenendo conto di tutte le regole appena illustrate, e deve ottenere dalla stringa di input i nomi delle variabili e i rispettivi valori in modo che siano utilizzabili a fini elaborativi; solo successivamente può svolgere le elaborazioni sulle variabili così ottenute. 124 Moduli e programmi CGI 6.9.1 Esempio di decodifica dati in Perl « Come esempio viene proposto un programma scritto in Perl che svolge i compiti appena illustrati: |#!/usr/bin/perl |# |# cgi per decodifica variabili da modulo html |# versione autonoma con output variabili |# |print "Content-type: text/html\n"; |print "\n"; |print "<html>\n"; |print "<head>\n"; |print "<title>Decodifica</title>\n"; |print "</head>\n"; |print "<body>\n"; | |$metodo=$ENV{REQUEST_METHOD}; |if ($metodo eq "POST" || $metodo eq "post") { | read (STDIN,$dati,$ENV{CONTENT_LENGTH}); |} |else { | $dati =$ENV{QUERY_STRING}; |} |print "<p>Dati = $dati\n"; |# decodifica di +, & %xx ecc.) |$i=0; |@vars=(); |@vars = split(/&/,$dati); |foreach $_ (@vars) |{ | s/\+/ /g; |# sostituisce %xx con il relativo carattere; |# g = sost. globale; e=2.a parte è una espressione | s/%([0-9a-fA-F][0-9a-fA-F])/sprintf("%c",hex($1))/eg; | /=/; | @val[$i]=$’; | @nom[$i]=$‘; | $i++; |} |for ($j=0;$j<$i;$j++) { | print "<p>nomevar = $nom[$j]<br>valore = $val[$j]<br><br>\n"; |} |print "</body>\n"; |print "</html>\n"; Tralasciamo la spiegazione dei dettagli di funzionamento del programma per la quale è necessaria la conoscenza almeno delle basi del linguaggio Perl. Osserviamo solo (per chi conosce tale linguaggio o per chi, invogliato da questo esempio, si accinge a conoscerlo) che il programma proposto effettua la decodifica dell’input e presenta una risposta banale contenente nomi e valori delle variabili; tale risposta, nell’ipotesi che la stringa di input sia: "cognome=Paperino&nome=Paolino", viene mostrata nella figura 6.33. Moduli e programmi CGI 125 F | igura 6.33. Con opportune modifiche si può far diventare il programma un modulo utilizzabile da altri programmi Perl (con l’istruzione ‘use’) allo scopo di ottenere la sola decodifica dell’input per una successiva elaborazione: sicuramente occorre eliminare tutte le istruzioni di output (le ‘print’); per le altre modifiche da effettuare si rimanda alla consultazione di manuali sul linguaggio Perl in particolare sulla creazione e uso di sottoprogrammi. Facendo ancora riferimento alla risposta mostrata nella figura 6.33 possiamo fare un paio di osservazioni interessanti: • il CGI eseguito risiede nel sito personale dell’utente fulvio e non nel sito predefinito del servente Apache; • il CGI è stato eseguito senza passare da un modulo HTML scrivendo nella barra di navigazione direttamente l’URI: http://localhost/~fulvio/ decod.pl?cognome=Paperino&nome=Paolino; si è cioè simulata la sua attivazione da un modulo Web con passaggio dei dati effettuato con metodo "get"; questo «trucco» è molto utile e spesso utilizzato sia in fase di verifica dei CGI sia nell’ambito di applicazioni Web che devono attivare dei CGI, inviando dei dati, senza passare necessariamente da un modulo HTML. 6.9.2 Altri strumenti per la decodifica « Essendo la fase di decodifica necessaria in qualsiasi elaborazione CGI, esistono moltissimi strumenti, reperibili anche in Internet, che svolgono questa operazione; un esempio e’ il programma ‘uncgi’ scritto in linguaggio c, scaricabile all’indirizzo hhttp://www.midwinter.com/~koreth/uncgi.html i. Il programma è freeware ed è utilizzabile anche in applicazioni commerciali previa richiesta all’autore. Una volta scaricato il programma si deve compilarlo, seguendo le istruzioni allegate, e installare l’eseguibile ottenuto nella directory dei CGI. Per illustrarne il funzionamento facciamo ancora riferimento alla stringa di input: "cognome=Paperino&nome=Paolino". Per fare in modo che tale input venga decodificato dal programma ‘uncgi’ l’attributo ‘action’ deve assumere il valore "/cgi-bin/uncgi/cgi-prova.sh". In questo caso il suo effetto non è quello di far eseguire il programma ‘cgi-prova.sh’ residente nella sottodirectory ‘uncgi’ di ‘/cgi.bin’ in quanto ‘uncgi’ non è una sottodirectory; il 126 Moduli e programmi CGI valore dell’attributo viene invece interpretato come richiesta di eseguire in sequenza i programmi ‘uncgi’ e ‘cgi-var.sh’ entrambi memorizzati in ‘/cgi-bin’. Il programma ‘uncgi’ riceve la stringa contenente i dati di input e la decodifica indifferentemente rispetto al metodo di invio utilizzato ("get" o "post"); al termine della sua esecuzione rende disponibili, come variabili di ambiente, le variabili della stringa di input decodificate con nome preceduto dal prefisso "WWW_". L’altro programma quindi può essere scritto senza preoccuparsi della fase di decodifica e tenendo conto che le variabili provenienti dal modulo sono disponibili come variabili di ambiente con nomi: "WWW_cognome" e "WWW_nome". 6.10 Esempio completo di esecuzione di un CGI « A questo punto possiamo illustrare un esempio completo in cui vengono utilizzati: • un modulo per l’immissione di alcuni dati di input; • il programma CGI per il trattamento degli stessi, scritto in Perl con utilizzo di ‘uncgi’ per la decodifica; • il documento di risposta creato da tale programma. Sorgente HTML del modulo: |<html> |<head> |<title>Modulo di prova</title> |</head> |<body> |<h2 style="text-align:center;">Immissione dei dati</h2> |<form action="/cgi-bin/uncgi/cgi-modulo.pl" method="post"> | <table> | <tr> | <td>Inserire il cognome </td> | <td><input type="text" name="cognome" size="20" maxlength="20"/></td> | </tr><tr> | <td>Inserire il nome </td> | <td><input type="text" name="nome" size="20" maxlength="20"/></td> | </tr><tr> | <td>Inserire la professione </td> | <td><input type="text" name="professione" size="20" maxlength="20"/></td> | </tr><tr> | <td>Vuoi informazioni via e-mail? </td> | <td>Si<input type="checkbox" name="risp" value="si"/> | No<input type="checkbox" name="risp" value="no"/></td> | </tr><tr> | <td>Indirizzo e-mail </td> | <td><input type="text" name="email" size="40" maxlength="40"/> | </tr><tr> | <td><input type="submit" value="Invio"/> | <td><input type="reset"/> | </tr> | </table> |</form> Moduli e programmi CGI |</body> |</html> La pagina contenente il modulo ha l’aspetto mostrato in figura 6.35. F | igura 6.35. Il programma CGI si chiama ‘cgi-modulo.pl’ e questo è il suo listato: |#!/usr/bin/perl |# |# cgi-modulo.pl |# |#============================================================================== |# Funzione messaggio |#============================================================================== |sub messaggio { | print ("<p>Clicca <a href=$ENV{’HTTP_REFERER’}> qui</a> per correggere\n"); | return 0 | }; |#============================================================================= |# Main |#============================================================================= |$cognome = $ENV{’WWW_cognome’}; |$nome = $ENV{’WWW_nome’}; |$professione = $ENV{’WWW_professione’}; |$risp = $ENV{’WWW_risp’}; |$email = $ENV{’WWW_email’}; |print ("Content-type: text/html\n"); |print ("\n"); |print ("<html>\n"); |print ("<head>\n"); |print ("<title>Test CGI</title>\n"); |print ("</head>\n"); |print ("<body>\n"); |print ("<h1>Resoconto immissione dati</h1>\n"); |if ($cognome eq "") { | print ("<p>Cognome obbligatorio\n"); | &messaggio; 127 Moduli e programmi CGI 128 | } |else { | if ($nome eq "") { | print ("<p>Nome obbligatorio\n"); | &messaggio; | } | else { | if (($risp eq "si") && ($email eq "")) { | print ("<p>Se vuoi e-mail inserisci il tuo indirizzo\n"); | &messaggio; | } | else { | print ("<p>Cognome:    "); | print ("    $cognome </p>\n"); | print ("<p>Nome:      "); | print ("        $nome </p>\n"); | print ("<p>Professione:    "); | print (" $professione </p>\n"); | print ("<p>Richiesta mail:  $risp </p>\n"); | print ("<p>Indirizzo:     "); | print ("      $email </p>\n"); | } } }; |print ("</body>\n"); |print ("</html>\n"); Infine nella figura 6.37 vediamo l’aspetto del documento di risposta creato dal programma. F | igura 6.37. 6.11 Considerazioni finali sui CGI « Come più volte fatto notare, i programmi CGI vengono sempre eseguiti sul servente Web al quale ci si collega; ciò comporta alcuni limiti, in particolare: • problemi di sicurezza, in quanto attraverso i programmi CGI alcuni utenti potrebbero accedere, volontariamente o meno, a dati confidenziali contenuti nel servente; Moduli e programmi CGI 129 • problemi di prestazioni, perché il servente deve elaborare le richieste provenienti da più utenti anche contemporaneamente, e la velocità di risposta può diminuire anche drasticamente in caso di sovraccarico del sistema; inoltre le prestazioni dipendono fortemente dalla velocità della connessione tra i nodi di rete coinvolti visto che tra essi c’è un continuo scambio di dati; • problemi di accessibilità, in quanto, a causa dei problemi di sicurezza, molti gestori di siti Web non consentono agli utenti di creare CGI personalizzati sul proprio servente. Ci sono però anche importanti aspetti positivi relativi alla natura dei CGI: • compatibilità, perché i CGI, essendo eseguiti sulla macchina remota e producendo risultati in formati universalmente riconosciuti come HTML, non risentono di eventuali differenze di comportamento dei vari programmi di navigazione; • utilità, in quanto i CGI possono raccogliere dati statistici sugli accessi ad un sito, leggere e scrivere dati centralizzati su un servente, interrogare o aggiornare basi di dati in esso gestite. Di quest’ultimo aspetto, cioè l’interazione tra pagine Web e basi di dati, che è molto importante, si occupa in modo più esteso il prossimo paragrafo. 130 Moduli e programmi CGI 131 Capitolo 7 Web, basi di dati e linguaggio PHP « La possibilità di interfacciare una base di dati relazionale con il Web è senza dubbio assai interessante in quanto unisce la potenza, l’affidabilità, la sicurezza dei moderni RDBMS (Relational Data Base Management System) con la facilità d’uso e la diffusione ormai universale degli strumenti di navigazione sia in Internet che nelle Intranet aziendali. I campi di impiego di questa tecnologia sono numerosissimi: si pensi ad esempio alla possibilità di fornire ai cittadini l’accesso via Internet a dati di interesse pubblico o personale, oppure, all’interno di una azienda, alla gestione di archivi con interfacce basate sui normali, e molto «amichevoli», programmi di navigazione, con le quali si riducono al minimo i problemi di compatibilità e di installazione sui computer degli utilizzatori. 7.1 Architetture ‘three-tier’ e pattern ‘MVC’ « Le applicazioni Web si basano generalmente su una architettura a tre livelli (‘three-tier’): • ‘front-end’ o ‘presentation tier’ o ‘interfaccia’: è il livello costituito dai moduli visualizzati con i browser sui computer clienti; • ‘middle tier’ o ‘logica applicativa’: è il livello occupato dal servente Web o meglio da un ‘Application server’ (ad esempio ‘Tomcat’) che sovrintende all’elaborazione dei dati, grazie a strumenti quali i CGI, PHP, ASP, servlet Java, Jsp e simili; • ‘back-end’ o ‘data tier’ o ‘gestione dati persistenti’: qui risiede il servente RDBMS. Tale architettura è schematizzata nella figura 7.1. F | igura 7.1. Tra i tre componenti il dialogo avviene secondo il modello client-server, nel senso che l’interfaccia è cliente della logica applicativa che a sua volta è cliente della gestione dati persistenti. 132 Web, basi di dati e linguaggio PHP Il motivo dell’adozione di una architettura con dei livelli distinti risiede essenzialmente nella possibilità di progettare, costruire, manutenere ciascuno dei moduli in modo indipendente dagli altri. Non necessariamente i vari livelli devono appartenere a nodi di rete distinti; spesso anzi i due serventi, Web e RDBMS, sono installati sulla stessa macchina. Generalmente è invece in esecuzione su nodi distinti il livello ‘front-end’ a meno che non si effettuino prove di collegamento direttamente sulla macchina servente (identificata in tal caso come localhost) cosa che può avvenire generalmente nelle fasi di realizzazione o di prova dei programmi. Quando si parla di livelli architetturali delle applicazioni Web si fa spesso riferimento anche allo schema (pattern) MVC (Model View Controller) proposto originariamente con il linguaggio ‘Smalltalk’ e ora molto diffuso per lo sviluppo di interfacce grafiche in applicazioni orientate agli oggetti. Il suo uso è presente in numerose tecnologie attuali, anche in ambito Web: nei framework basati su PHP (‘Symfony’, ‘Zend Framework’), su Ruby (‘Ruby on Rails’), su Python (‘Django’), su Java (‘Swing’, ‘Struts’), o su .NET di Microsoft. Con l’appena citato termine framework (piano di lavoro) si intende una struttura di supporto per la progettazione e realizzazione del software basata su librerie usabili con uno o più linguaggi e corredate da strumenti di aiuto alla programmazione come editor avanzati e debugger. I principali vantaggi dell’uso dei framework risiedono nella standardizzazione delle operazioni più comuni per lo sviluppo del software e nella possibilità di riutilizzare componenti già pronti senza doverli riprogettare e riscrivere ogni volta da zero. Anche lo schema MVC comprende tre livelli con compiti distinti: • ‘model’: fornisce i metodi per accedere ai dati usati dall’applicazione; • ‘view’: visualizza i dati e gestisce il dialogo con gli utenti; • ‘controller’: riceve, tramite la ‘view’, i comandi dell’utente e li esegue alterando eventualmente lo stato degli altri due componenti. Lo schema non è in contrasto con quanto richiesto in una applicazione ‘three-tier’ in quanto implica la separazione fra la logica applicativa che spetta al ‘controller’ e al ‘model’, e l’interfaccia utente che è a carico della ‘view’. In qualche caso si tende anzi a confondere lo schema MVC con le architetture a tre livelli; ciò non è corretto per almeno due motivi: • esso opera una separazione logica ulteriore nel solo livello di interfaccia organizzando le relative funzionalità e gestendo l’interazione con gli altri strati applicativi; • nelle applicazioni three-tier il livello interfaccia non comunica direttamente con il ‘data tier’ e le comunicazione «transitano» sempre attraverso il ‘middle tier’; nello schema MVC invece abbiamo una interazione «triangolare» (vedi figura 7.2), con la ‘view’ che invia gli aggiornamenti al ‘controller’, il ‘controller’ che aggiorna il ‘model’, e la ‘view’ che riceve aggiornamenti direttamente dal ‘model’. Web, basi di dati e linguaggio PHP 133 F | igura 7.2. Dal punto di vista storico, si può inoltre notare che l’architettura three-tier si presenta negli anni ’90 nell’ambito delle applicazioni distribuite, con la separazione dei tre livelli su piattaforme distinte, mentre MVC nasce nel decennio precedente, presso lo Xerox PARC, inizialmente per applicazioni non distribuite. Maggiori dettagli sulle architetture ‘three-tier’ e, in generale, sulle applicazioni multi-livello, sono disponibili nel capitolo 10 dedicato alla programmazione distribuita. Nei prossimi paragrafi esaminiamo più da vicino i metodi e gli strumenti utili alla gestione dei dati di un database tramite un’interfaccia Web. 7.2 Strumenti necessari per la gestione di basi di dati via Web « Gli strumenti scelti per trattare questo argomento e per produrre qualche semplice esempio fanno tutti parte del software libero. Ovviamente questa non è l’unica scelta che poteva essere fatta, data la presenza sul mercato di molte alternative proprietarie anche tecnicamente molto valide; la preferenza per questa categoria di programmi è però ampiamente motivata da tutta una serie di considerazioni per approfondire le quali si consiglia di consultare i numerosi documenti, dedicati a tali argomenti, sul sito hhttp:// www.linuxdidattica.org i. Qui elenchiamo brevemente solo alcuni dei motivi più importanti per la scelta di programmi e strumenti liberi: • motivi «etici»: opportunità di usare software libero anziché proprietario in ambito educativo; • motivi didattici: maggiore validità dei programmi liberi in ambito didattico (si pensi alla possibilità di sfruttare in tale contesto i sorgenti dei programmi); • motivi pratici e di legalità: disponibilità e di copie illimitate e legali dei programmi da far utilizzare a chi ne ha necessità in qualsiasi ambito (didattico e non); • motivi economici: gratuità del software; • motivi tecnologici: si parla di prodotti che sono all’avanguardia nel loro settore e molto diffusi anche in ambito professionale (ad esempio Apache nell’ambito dei serventi Web). 134 Web, basi di dati e linguaggio PHP Gli strumenti cui si fa riferimento nel proseguo di questo paragrafo sono: • GNU/Linux (distribuzione ‘Debian’, o derivata, nel nostro caso ‘Ubuntu-7.04’) come sistema operativo delle macchine che fungono da serventi Web; • ‘Apache’ (versione ‘2’) come servente Web; • ‘MySQL’ versione ‘5.0’ e ‘PostgreSQL’ versione ‘8.2’ come RDBMS; • ‘PHP’ versione ‘5’ come linguaggio per il motore applicativo e l’interfaccia tra Web e le basi di dati. Anche se in questa sede non vengono forniti dettagli sul reperimento e l’installazione dei pacchetti software necessari (come al solito si rimanda ad appositi testi o alla documentazione presente anche in Internet o ai manuali in linea in ambiente GNU/Linux), forniamo un elenco degli stessi facendo riferimento alla piattaforma Ubuntu-7.04: • ‘apache2’, il servente Web; • ‘apache2-mpm-prefork’, modulo da usare nel caso si voglia avere un servente Web non basato sui thread ma sui processi come la vecchia versione ‘Apache 1.3’; • ‘apache2-utils’, programmi di utilità per Apache2; • ‘apache2.2-common’, moduli standard di Apache2; • ‘libmysqlclient15off’, librerie per la parte cliente di MySQL; • ‘mysql-client-5.0’, eseguibili del cliente MySQL; • ‘mysql-common’, file richiesti da MySQL; • ‘mysql-server-5.0’, eseguibili del servente MySQL; • ‘postgresql-8.2’, eseguibili del servente PostgreSQL; • ‘postgresql-client-8.2’, eseguibili del cliente PostgreSQL; • ‘postgresql-client-common’, gestore di versioni multiple del cliente PostgreSQL; • ‘postgresql-common’, gestore di versioni multiple o di cluster multipli del servente PostgreSQL; • ‘libapache2-mod-php5’, modulo per PHP5 per Apache2 (solo versione a processi); • ‘php5’, interprete PHP5; • ‘php5-common’, esempi e documentazione di PHP5; • ‘php5-mysql’, modulo per la connessione a una base di dati MySQL da script PHP5; • ‘php5-pgsql’, modulo per la connessione a una base di dati PostgreSQL da script PHP5; • ‘php5-cli’, interprete PHP5 da linea di comando (non essenziale); • ‘phpmyadmin’, applicazione Web, scritta in PHP, per gestire basi di dati MySQL (non essenziale); • ‘phppgadmin’, applicazione Web, scritta in PHP, per gestire basi di dati PostgreSQL (non essenziale). Web, basi di dati e linguaggio PHP 135 Supponiamo di avere installato con successo tutto il software sulla macchina su cui effettuare le prove e di avere quindi il servente Apache che risponde all’indirizzo http://localhost; dotato di tutto il necessario per l’esecuzione di script PHP5 e per l’interfacciamento a basi di dati MySQL e PostgreSQL. Segnaliamo che è possibile lavorare con questi strumenti anche in ambiente MS-Windows (versioni superiori alle ‘9x’ o alla ‘home’) in quanto esistono pacchetti Apache, MySQL, PostgreSQL, PHP5 anche per questa piattaforma. Inoltre esistono prodotti come ‘EasyPHP’ o ‘XAMPP’ installando i quali si hanno a disposizione in MS-Windows, già pronti all’uso: un servente Apache, un servente MySQL, un interprete PHP5 e l’applicazione ‘phpmyadmin’ per la gestione via Web delle basi di dati, cui si accede collegandosi a http://localhost/mysql. A proposito dei due RDBMS prescelti segnaliamo come il primo sia nettamente più utilizzato nell’ambito delle applicazioni di rete: molti siti di commercio elettronico si appoggiano infatti su archivi gestiti con MySQL. Per sottolineare questo fatto facciamo notare che è stato addirittura coniato un acronimo: LAMP, le cui lettere indicano i componenti che sono alla base di molte applicazioni Web esistenti: Linux, Apache, MySQL, PHP. Tra i motivi della grande diffusione di MySQL ci sono l’estrema semplicità di configurazione e gestione e le buone prestazioni specialmente per basi di dati di dimensioni non elevate (come quelle su cui si basano solitamente i negozi in rete). Tali pregi hanno superato, per gli sviluppatori, i difetti che erano presenti almeno nelle versioni precedenti alla ‘5.0’ e che consistono principalmente nella non completa aderenza allo standard SQL (Structured Query Language), nell’assenza di viste logiche, di trigger, di selezioni annidate. Nel caso di PostgreSQL, tali difetti non erano presenti neanche nelle prime versioni, ma questo non gli ha permesso di godere delle preferenze degli addetti ai lavori (non è il primo caso, in ambito informatico, in cui un prodotto superiore dal punto di vista tecnologico ha meno successo di uno con caratteristiche inferiori). In queste dispense, per eliminare ogni possibile discussione, si è scelto di considerare entrambi i prodotti. Nei due RDBMS la gestione fisica dei dati non è banale e non prevede la memorizzazione degli stessi in su un unico file per ogni base di dati, come avviene invece per altri gestori di basi di dati (ad esempio ‘Access’ di Microsoft o ‘SQLite’); quindi, a differenza che in questi ultimi, per fare salvataggi di sicurezza dei dati di un archivio, non è sufficiente salvare un file, ma occorre utilizzare gli appositi strumenti messi a disposizione dai serventi RDBMS. La trattazione su MySQL e PostgreSQL è ovviamente parziale: vengono introdotti solo i comandi necessari alla gestione di piccole basi di dati in vista di una successiva interrogazione con il linguaggio PHP; si considerano note le nozioni relative alle basi di dati relazionali in generale, al loro progetto (passando per i modelli concettuale e logico), alla sintassi e alle regole del linguaggio SQL. Web, basi di dati e linguaggio PHP 136 7.3 Basi di dati con MySQL « MySQL è un sistema di gestione di basi di dati relazionali multi-piattaforma distribuito da ‘MySQL AB’ come software libero sotto licenza GPLV 2 (General Public License version 2). 7.3.1 Attivazione del servente MySQL « Una volta installato MySQL con successo si può iniziare ad usarlo senza grosse difficoltà; la directory predefinita a partire dalla quale vengono salvati gli archivi è ‘/var/lib/mysql’ e l’amministratore della base di dati è, almeno inizialmente, l’utente ‘root’ (si rimanda al paragrafo 6.4.1 per quanto riguarda il modo in cui si possono acquisire i privilegi di tale utente in Ubuntu). Prima di iniziare si deve attivare il demone ‘mysqld’ con il comando (eseguito sempre con i diritti di ‘root’): # /etc/init.d/mysql start Con comandi analoghi contenenti, invece di start, restart, stop, status si ottiene il riavvio, la fermata, lo stato corrente del demone. Si tenga comunque presente che, in caso di corretta installazione del pacchetto, il demone viene inserito tra quelli attivati automaticamente all’accensione della macchina grazie alla presenza del file ‘/etc/rc2.d/S19mysql’ che è un collegamento simbolico a ‘/etc/init.d/mysql’; in mancanza si può provvedere a definire tale collegamento con i comandi: # cd /etc/rc2.d # ln -s ../init.d/mysql . Il servente MySQL risponde alle richieste sulla porta 3306; questa è l’impostazione predefinita modificabile intervenendo nel file di configurazione ‘/etc/mysql/my.cnf’ cambiando la riga: |port = 3306 7.3.2 Dialogo con il servente MySQL con ‘mysql’ « Per verificare il funzionamento del servente MySQL possiamo collegarci ad esso come utente ‘root’ eseguendo ‘mysql’ che è il programma di interfaccia in modalità testuale. Il comando prevede numerose opzioni, qui elenchiamo solo le più importanti: • ‘-u’: per indicare il nome dell’utente con il quale ci colleghiamo al servente; • ‘-p’: per immettere la password dell’utente; • ‘-h’: per indicare quale è il servente cui ci si collega. Per avere tutte le informazioni sull’uso di questo comando si può consultare il manuale in linea eseguendo: $ man mysql Vediamo un esempio di comando per il collegamento a un servente MySQL: Web, basi di dati e linguaggio PHP 137 $ mysql -h localhost -u root -p mysql si riceve la richiesta di inserire la password per l’utente ‘root’ e, se non ci sono errori, ci si collega alla base di dati mysql (quella che contiene tutte le informazioni amministrative del servente). La stringa di invito dei comandi (prompt dei comandi) di MySQL ha il seguente aspetto: mysql> Per chiudere la connessione occorre digitare il comando: mysql> \q Si può anche eseguire ‘mysql’ senza alcuna opzione e senza indicazione della base di dati da utilizzare; in questo caso si effettua un collegamento alla macchina locale senza socket di rete ma usando il cosiddetto «Unix-domain socket», l’utente usato ha stesso nome di quello correntemente collegato al sistema GNU/Linux e la base di dati da utilizzare è indefinita. Per cambiare la base di dati corrente si esegue il comando (l’utente deve avere i permessi di uso su di essa come mostrato più avanti): mysql> use nome_basi_dati Per creare una base di dati si esegue: mysql> CREATE DATABASE nome_base_dati; e per cancellarla: mysql> DROP DATABASE nome_base_dati; Lavorare come utente ‘root’ è quasi sempre inopportuno per motivi di sicurezza e questo vale anche nel caso di MySQL; vediamo allora come si crea un utente, chiamato dba, «normale» per GNU/Linux, ma dotato di tutti i privilegi necessari per essere l’amministratore del RDBMS. Prima di tutto creiamo (da utente ‘root’) l’utente nel sistema GNU/Linux, supponendo ovviamente che non esista già: # adduser dba inserendo la password, confermandola e rispondendo alle altre richieste di informazioni sull’utente che sono comunque non essenziali. Poi colleghiamoci a MySQL e definiamo anche qui il nuovo utente: mysql> CREATE USER dba; quindi assegniamogli i privilegi: mysql> GRANT ALL PRIVILEGES ON *.* TO dba@"%" ←,→ IDENTIFIED BY ’parola_segreta’ WITH GRANT OPTION; spieghiamo brevemente le parti salienti del comando: • «*.*» significa che ci riferisce a qualsiasi base di dati e qualsiasi tabella in essa contenuta; • "%" può essere sostituito da una indicazione più restrittiva dei nodi di rete da cui l’utente può collegarsi, ad esempio: 172.16.% oppure 172.16.1.1; Web, basi di dati e linguaggio PHP 138 • se si vuole dare la possibilità all’utente di collegarsi senza password (sconsigliato) basta eliminare la parte «IDENTIFIED BY ....»; • infine con «WITH GRANT OPTION» che è facoltativo, si da all’utente dba, visto che deve essere l’amministratore, la possibilità di assegnare i privilegi ad altri utenti. A questo punto si può chiudere il collegamento come utente ‘root’ e accedere da una console al sistema GNU/Linux come utente dba, oppure da utente ‘root’ eseguire il cambio di identità con il comando: # su dba Quindi ci si collega a MySQL: $ mysql -h localhost -u dba -p mysql Notiamo che in questo caso l’uso di «-u dba» è superfluo ma non provoca alcun errore. Si possono creare altri utenti, altre basi di dati e assegnare i relativi privilegi; ad esempio per assegnarli all’utente fulvio per la base di dati prova: mysql> GRANT ALL PRIVILEGES ON prova.* TO fulvio@"%"←,→IDENTIFIED BY ’parola_segreta’; Per togliere questi privilegi: mysql> REVOKE ALL PRIVILEGES ON prova.* FROM fulvio@"%"; 7.3.3 Comandi utili per usare MySQL « Elenchiamo una serie di informazioni utili all’amministrazione e all’uso di un servente MySQL, sottolineando come esse siano solo una piccola parte di quelle necessarie e come presuppongano, in qualche caso, la conoscenza delle regole del linguaggio SQL: • accesso da remoto: nel file ‘/etc/mysql/my.cnf’, commentare la riga: |skip-networking o valorizzare opportunamente la riga: |bind-address=127.0.0.1 o fare entrambe le cose. • cambiare password ad un utente: mysql> SET PASSWORD FOR nome_utente = PASSWORD(’parola_segreta’); • ottenere l’aiuto rispettivamente per i comandi di ‘mysql’ e di SQL: mysql> help mysql> help comando • connettersi ad altra base di dati: mysql> use nome_base_dati Web, basi di dati e linguaggio PHP 139 • ottenere la lista delle basi di dati gestite dal servente: mysql> SHOW DATABASES; • ottenere la lista delle tabelle presenti nella base di dati: mysql> SHOW TABLES; • visualizzare la struttura di una tabella: mysql> DESCRIBE nome_tabella • cancellare un utente: mysql> DROP USER nome_utente • salvare una base di dati (comprese le definizioni delle strutture delle tabelle) in un file: $ mysqldump nome_base_dati > nome_file il comando ‘mysqldump’ prevede le opzioni «-u», «-p», «-h», con lo stesso significato visto per ‘mysql’, e tante altre per le quali si rimanda alla consultazione del manuale in linea; per ripristinare in una base dati, appositamente creata, il contenuto di un file di salvataggio si può usare il comando: $ mysql nome_base_dati < nome_file Si noti che le parole riservate del linguaggio SQL si scrivono in maiuscolo anche se vengono riconosciute pure in minuscolo e che i comandi SQL, a differenza di quelli di ‘mysql’, devono sempre terminare con «;». A proposito della possibilità di connettersi a MySQL da remoto, si osservi che essa non è indispensabile nel contesto delle applicazioni Web che si interfacciano con una base di dati; infatti, siccome il servente MySQL è quasi sempre residente sulla stessa macchina del servente Web, per quest’ultimo è sufficiente connettersi «localmente» a MySQL. 7.3.4 Creazione di una tabella in MySQL per le prove « Creiamo, come utente dba, con le modalità mostrate in precedenza, l’utente fulvio per MySQL e una base di dati con stesso nome assegnando gli opportuni privilegi. Colleghiamoci poi a MySQL come utente fulvio e creiamo in tale base di dati una tabella di nome rubrica per le successive prove di gestione via Web con PHP; la tabella contiene alcuni indirizzi e numeri telefonici e ha una chiave costituita da codice auto-incrementante: $ mysql -h localhost -u fulvio -p fulvio mysql> CREATE TABLE rubrica(codice INT AUTO_INCREMENT, cognome←,→VARCHAR(20), nome VARCHAR(20), -> indirizzo VARCHAR(40), telefono VARCHAR(15), data_nas DATE,←,→email VARCHAR(30), PRIMARY KEY (codice)); come si vede il comando può essere spezzato su più righe; le righe successive alla prima sono righe di continuazione come evidenziato anche dalla stringa di invito che cambia aspetto. Web, basi di dati e linguaggio PHP 140 Il comando viene considerato concluso quando si incontra il simbolo «;». Inseriamo alcune registrazioni all’interno della tabella con i comandi: mysql> INSERT INTO rubrica (cognome, nome, indirizzo, telefono,←,→data_nas, email) -> VALUES(’Paperino’, ’Paolino’, ’via Roma 1 Paperopoli’, -> ’010011234567’,’1980-01-01’,’[email protected]’); mysql> INSERT INTO rubrica (cognome, nome, indirizzo, telefono,←,→data_nas, email) -> VALUES(’Rossi’, ’Mario’, ’via Roma 34 Treviso’, -> ’04220101010’,’1981-01-01’,’[email protected]’); Si noti come i valori del campo ‘codice’ non vengano inseriti perché, essendo esso auto-incrementante, viene opportunamente valorizzato dal servente MySQL. Verifichiamo i dati inseriti con il comando: mysql> SELECT * FROM rubrica; che dovrebbe dare il risultato mostrato in figura 7.6. F | igura 7.6. Le stesse operazioni possono essere fatte mediante il più amichevole programma ‘phpmyadmin’ utilizzabile, dopo l’installazione e la configurazione per le quali si rimanda alla documentazione del programma stesso, collegandosi all’URI: http://localhost/phpmyadmin. Web, basi di dati e linguaggio PHP 141 7.4 Basi di dati con PostgreSQL « PostgreSQL è un sistema di gestione basi di dati relazionali multi-piattaforma molto avanzato e quasi del tutto rispondente allo standard SQL; è stato sviluppato originariamente dal dipartimento di informatica dell’Università di Berkeley in California ed è distribuito come software libero con una licenza speciale. 7.4.1 Attivazione del servente PostgreSQL « Una volta installato PostgreSQL con successo si può iniziare ad usarlo senza grosse difficoltà; la directory predefinita a partire dalla quale vengono salvati gli archivi è ‘/var/lib/ postgresql/8.2/main/’ e l’amministratore della base di dati è l’utente ‘postgres’ al quale è consigliabile assegnare una password, operazione che deve essere svolta dall’utente ‘root’ di Linux (si rimanda al paragrafo 6.4.1 per quanto riguarda il modo in cui si possono acquisire i privilegi di tale utente in Ubuntu). Prima di iniziare si deve attivare il demone ‘postgres’ con il comando (eseguito sempre con i diritti dell’utente ‘root’): # /etc/init.d/postgresql-8.2 start Con comandi analoghi contenenti, invece di start, restart, stop, status si ottiene il riavvio, la fermata, lo stato corrente del demone. Si tenga comunque presente che, in caso di corretta installazione del pacchetto, il demone viene inserito tra quelli attivati automaticamente all’accensione della macchina grazie alla presenza del file ‘/etc/rc2.d/S19postgresql-8.2’ che è un collegamento simbolico a ‘/etc/init.d/ postgresql-8.2’; in mancanza si può provvedere a definire tale collegamento con i comandi: # cd /etc/rc2.d # ln -s ../init.d/postgresql-8.2 . Il servente PostgreSQL risponde alle richieste sulla porta 5432; questa è l’impostazione predefinita modificabile intervenendo nel file di configurazione ‘/etc/postgresql/8.2/main/ postgresql.conf’ cambiando la riga: |port = 5432 La prima volta che viene eseguito il programma di amministrazione delle basi di dati, vengono creati i file fondamentali per la loro gestione. Per verificare il buon funzionamento del servente PostgreSQL creiamo (da utente ‘root’) un utente nel sistema GNU/Linux con nome, ad esempio, fulvio, supponendo ovviamente che non esista già: # adduser fulvio Poi ci si connette su una console come utente ‘postgres’, oppure da utente ‘root’ si esegue il cambio di identità con il comando: # su postgres e si crea l’utente fulvio anche per PostgreSQL: 142 Web, basi di dati e linguaggio PHP $ createuser fulvio Il sistema pone a questo punto delle domande relative al nuovo utente: è opportuno rispondere in modo che non sia un superuser e che sia abilitato a creare basi di dati ma non altri utenti. Se si deve eliminare un utente PostgreSQL il comando (da eseguire sempre come utente ‘postgres’) è: $ dropuser nome_utente 7.4.2 Dialogo con il servente PostgreSQL con ‘psql’ « Una volta creato l’utente desiderato (fulvio) possiamo accreditarci con le sue credenziali ed eseguire ‘psql’ che è il programma di interfaccia, in modalità testuale, verso il servente PostgreSQL. Il comando prevede numerose opzioni, qui elenchiamo solo le più importanti: • ‘-U’: per indicare il nome dell’utente con il quale ci colleghiamo al servente; • ‘-W’: per immettere la password dell’utente; • ‘-h’: per indicare quale è il servente cui ci si collega. Per avere tutte le informazioni sull’uso di questo comando si può consultare il manuale in linea eseguendo: $ man psql Vediamo un esempio di comando per il collegamento a un servente PostgreSQL: $ psql -h localhost -U fulvio -W template1 si riceve la richiesta di inserire la password per l’utente fulvio e, se non ci sono errori, ci si collega alla base di dati template1 (una di quelle di esempio già presenti sul servente). La stringa di invito dei comandi (prompt dei comandi) di PostgreSQL contiene il nome della base di dati corrente e ha il seguente aspetto: template1=> Per chiudere la connessione occorre digitare il comando: template1=> \q Si può anche eseguire ‘psql’ senza alcuna opzione e senza indicazione della base di dati da utilizzare; in questo caso si effettua un collegamento alla macchina locale senza socket di rete ma usando il cosiddetto «Unix-domain socket», l’utente usato ha stesso nome di quello correntemente collegato al sistema GNU/Linux e la base di dati da utilizzare ha lo stesso nome dell’utente. Questa base di dati deve ovviamente esistere e l’utente deve potersi collegare senza inserire password, altrimenti il tentativo di collegamento non ha successo. Un utente può eventualmente creare la propria base di dati predefinita (o qualsiasi altra) nel modo seguente: $ createdb nome_base_dati Web, basi di dati e linguaggio PHP 143 Per cancellare una base di dati il comando è invece: $ dropdb nome_base_dati 7.4.3 Comandi utili per usare PostgreSQL « Elenchiamo a questo punto una serie di informazioni utili all’amministrazione e all’uso di un servente PostgreSQL, sottolineando, ancora una volta, come esse siano solo una piccola parte di quelle necessarie e come presuppongano la conoscenza delle regole del linguaggio SQL: • abilitare la connessione da clienti remoti: nel ‘/etc/postgres/8.2/main/ postgresql.conf’ valorizzare opportunamente la riga: |listen_addresses = ’localhost’ che è inizialmente commentata (il valore per difetto è comunque ‘localhost’); aggiungere poi in ‘/etc/postgres/8.2/main/pg_hba.conf’ una riga come questa: |host all all ip_rete mashera_rete trust oppure, se si vuole limitare l’accesso con password MD5: |host all all ip_rete maschera_rete md5 eventualmente commentare la riga: |local all all ident sameuser se si vuole disattivare la possibilità di collegarsi in locale al servente PostgreSQL, senza immettere password, per gli utenti del sistema GNU/Linux; vedere i commenti presenti in entrambi i file e la documentazione di PostgreSQL per avere maggiori dettagli; • amministrare un utente: collegarsi come utente ‘postgres’ e eseguire: $ psql template1 poi: template1=> UPDATE pg_authid SET rolpassword=’parola_segreta’←,→WHERE rolname=’nome_utente’; per le versioni di PostgreSQL precedenti alla ‘8.1’ il comando è invece: template1=> UPDATE pg_shadow SET passwd=’parola_segreta’←,→WHERE usename=’nome_utente’; • cambiare password ad un utente: template1=> ALTER user nome_utente WITH password ’parola_segreta’; • assegnare privilegi per una tabella: template1=> GRANT [ALL] [priv] ON nome_tabella TO public; Web, basi di dati e linguaggio PHP 144 in questo caso i privilegi (tutti se ‘ALL’, o quelli specificati) vengono assegnati allo schema ‘public’ quindi a tutti gli utenti, in alternativa si può specificare il nome di un utente; • togliere privilegi per una tabella ad un utente: template1=> REVOKE [ALL] [priv] ON nome_tabella FROM nome_utente; • creare utente con password criptata MD5 (sempre da utente ‘postgres’): $ createuser -e nome_utente • ottenere l’aiuto rispettivamente per i comandi di ‘psql’ e di SQL: template1=> \? template1=> \h [comando] premere [ q ] per uscire dalla visualizzazione dell’aiuto; • connettersi ad altra base di dati: template1=> \c nome_base_dati • ottenere la lista delle basi di dati gestite dal servente: template1=> \l • ottenere la lista delle tabelle presenti nella base di dati: template1=> \dt • visualizzare la struttura di una tabella: template1=> \d nome_tabella • salvare una base di dati (comprese le definizioni delle strutture delle tabelle) in un file: $ pg_dump nome_base_dati > nome_file il comando ‘pg_dump’ prevede le opzioni «-U», «-W», «-h», con lo stesso significato visto per ‘psql’, e tante altre per le quali si rimanda alla consultazione del manuale in linea; per ripristinare in una base dati, appositamente creata, il contenuto di un file di salvataggio si può usare il comando ‘pg_restore’ (vedere manuale in linea) o, più semplicemente, il comando: $ psql -d nome_base_dati -f nome_file Si può notare che, ancora una volta, le parole riservate del linguaggio SQL si scrivono in maiuscolo, anche se non è obbligatorio, e che i comandi SQL, a differenza di quelli di ‘psql’, devono sempre terminare con «;». Anche relativamente alla possibilità di connettersi a PostgreSQL da remoto vale la stessa considerazione fatta in precedenza per MySQL: non è indispensabile nel contesto delle applicazioni Web che si interfacciano con una base di dati; infatti, siccome il servente PostgreSQL è quasi sempre residente sulla stessa macchina del servente Web, per quest’ultimo è sufficiente connettersi «localmente» a PostgreSQL. Web, basi di dati e linguaggio PHP 145 7.4.4 Creazione di una tabella in PostgreSQL per le prove « Creiamo, come utente fulvio nella base di dati omonima, una tabella di nome rubrica per le successive prove di gestione via Web con PHP; la tabella contiene alcuni indirizzi e numeri telefonici e ha una chiave costituita da codice auto-incrementante: fulvio=> CREATE TABLE rubrica(codice serial, cognome VARCHAR(20),←,→nome VARCHAR(20), fulvio(> indirizzo VARCHAR(40), telefono VARCHAR(15),←,→data_nas DATE, email VARCHAR(30)); come si vede il comando può essere spezzato su più righe; le righe successive alla prima sono righe di continuazione come evidenziato anche dalla stringa di invito che cambia aspetto. Il comando viene considerato concluso quando si incontra il simbolo «;». Inseriamo alcune registrazioni all’interno della tabella con i comandi: fulvio=> INSERT INTO rubrica (cognome, nome, indirizzo,←,→delefono, data_nas, email) fulvio-> VALUES(’Paperino’, ’Paolino’, ’via Roma 1 Paperopoli’, fulvio(> ’010011234567’,’1980-01-01’,’[email protected]’); fulvio=> INSERT INTO rubrica (cognome, nome, indirizzo,←,→telefono, data_nas, email) fulvio-> VALUES(’Rossi’, ’Mario’, ’via Roma 34 Treviso’, fulvio(> ’04220101010’,’1981-01-01’,’[email protected]’); Si noti come i valori del campo ‘codice’ non vengano inseriti perché, essendo esso auto-incrementante, viene opportunamente valorizzato dal servente PostgreSQL. Verifichiamo i dati inseriti con il comando: fulvio=> SELECT * FROM rubrica; che dovrebbe dare il risultato mostrato in figura 7.12. F | igura 7.12. 146 Web, basi di dati e linguaggio PHP Le stesse operazioni possono essere fatte mediante il più amichevole programma ‘phppgadmin’ utilizzabile, dopo l’installazione e la configurazione per le quali si rimanda alla documentazione del programma stesso, collegandosi all’URI: http://localhost/phppgadmin. 7.5 Introduzione al linguaggio PHP « Il PHP (inizialmente Personal Home Pages, adesso PHP Hypertext Preprocessor) nasce nel 1995 per mano di Rasmus Lerdorf allo scopo di semplificare la gestione di alcune pagine HTML. La primissima versione era originata dal alcuni script Perl ma successivamente Lerdorf ne scrisse una versione in linguaggio c. Le tappe più importanti della successiva evoluzione sono state: • nel giugno 1998 esce PHP3 con il nuovo «motore» ‘Zend’ (frutto del lavoro di Zeev Suraski e Andi Gutmans), il supporto per molte basi di dati (oltre a quello già presente per mSQL, PostgreSQL, MySQL) e la possibilità di essere usato su macchine MS-Windows; PHP risulta installato in circa il 10% dei domini esistenti; • nel maggio 2000 esce PHP4 e la licenza passa da GPL a licenza speciale (PHP); viene inserito il supporto per le sessioni; • nel 2004 è la volta di PHP5 che, grazie al motore Zend versione 2 estende il linguaggio secondo il modello della programmazione ad oggetti; inoltre viene introdotto il supporto all’XML e ai Web Services; attualmente PHP è installato su oltre il 30% dei serventi Web. Si tratta di un linguaggio interpretato, multi-piattaforma, che viene utilizzato principalmente per dotare di capacità elaborativa i documenti HTML (anche se esiste la possibilità di eseguire script da linea di comando grazie al pacchetto ‘php5-cli’). Le istruzioni PHP sono incorporate all’interno dei sorgenti HTML e vengono eseguite dal lato servente grazie alla presenza del motore Zend. Il linguaggio si presta particolarmente per la scrittura di applicazioni Web per l’amministrazione di basi di dati; i gestori di basi di dati supportati sono moltissimi e fra essi troviamo MySQL, PostgreSQL, Oracle, Sybase, Informix. Una trattazione completa del linguaggio PHP non rientra negli scopi di queste dispense; ci limitiamo a illustrare le sue caratteristiche di base, aiutandoci con degli esempi, per essere poi in grado di realizzare dei banali interfacciamenti a basi di dati MySQL e PostgreSQL. Web, basi di dati e linguaggio PHP 147 Qualche dettaglio in più viene fornito sulla gestione delle sessioni e sulla prevenzione della «SQL injection» che sono argomenti molto importanti ma non sempre considerati in modo adeguato nei testi, nei manuali e in genere nella documentazione riguardante l’uso di PHP. 7.6 Cenni alla sintassi del linguaggio PHP « I comandi PHP si inseriscono all’interno di un documento HTML in qualunque posizione ma si tengono separati dal resto del sorgente racchiudendoli tra le stringhe ‘;<?php’ e ‘?>’. I documenti contenenti comandi PHP devono avere estensione ‘.php’ e non ‘.html’; il viceversa non è vero: si possono cioè scrivere documenti privi di istruzioni PHP il cui nome ha estensione ‘.php’ senza temere alcun malfunzionamento (semplicemente, malgrado l’estensione, essi non vengono elaborati dal motore ‘Zend’ di PHP). Vediamo subito un esempio che permette anche di verificare il buon funzionamento del PHP sulla nostra macchina: definiamo nella directory radice del servente Web (solitamente ‘/var/www/’) un file chiamato ‘phpinfo.php’ contenente questa unica riga: |<?php phpinfo(); ?> Se si apre il documento collegandosi a http://localhost/phpinfo.php e se tutto funziona correttamente, si ottiene una risposta, mostrata parzialmente nella figura 7.14, contenente numerose informazioni riguardanti il PHP, il servente Web ed altro ancora. F | igura 7.14. Il linguaggio PHP può essere utilizzato anche indipendentemente dalla connessione a basi di dati, come evidenziato dal seguente esempio in cui vediamo un documento HTML per con un modulo per l’immissione di dati, arricchito con alcuni comandi PHP; i dati di input vengono passati ad un altro file e trattati ancora con istruzioni PHP. Web, basi di dati e linguaggio PHP 148 Ecco il sorgente del primo documento: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |<html> |<head> |<title>Modulo 1 con php</title> |</head> |<body> |<h2>Modulo gestito con PHP</h2> |<p/> |Sei collegato al servente Web: |<b><?php |//echo $SERVER_NAME; |echo $_SERVER[’SERVER_NAME’] |?></b> |<p/> all’indirizzo: |<b><?php echo $_SERVER[’SERVER_ADDR’]; ?></b> |<p/>Servente fornito da: |<b><?php echo $_SERVER[’SERVER_SOFTWARE’]; ?></b> |<p/>Sei collegato dall’indirizzo: |<b><?php echo $_SERVER[’REMOTE_ADDR’]; ?></b> |<p/><br/> |Inserisci i tuoi dati anagrafici |<p/> |<form action="./modulo1_ris.php" method="post"> |<p/>Cognome: <input type="text" name="cognome" size="20" maxlength="20"/> |<p/>Nome: <input type="text" name="nome" size="20" maxlength="20"&/gt; |<p/>Eta’: <input type="radio" name="eta" value="1-18"/>1-18 | <input type="radio" name="eta" value="19-40"/>19-40 | <input type="radio" name="eta" value="41-65"/>41-65 | <input type="radio" name="eta" value="66-99"/>66-99 |<p/>E-mail: <input type="text" name="email" size="30" maxlength="30"/> |<p/><input type="reset" value="Reset"/> |<input type="submit" value="Invia"/> |</form> |</body> |</html> Come al solito i numeri di riga sono stati aggiunti per facilitare la spiegazione delle varie parti del sorgente; prima però di commentarlo in dettaglio forniamo alcune informazioni sulla sintassi dei comandi PHP che ha grandi somiglianze con quella del linguaggio c: • le istruzioni PHP si scrivono in minuscolo e si concludono sempre con «;»; • i blocchi di istruzioni sono delimitati da «{» e «}» • i commenti si inseriscono con «//» su una riga singola oppure compresi tra «/*» e «*/» anche su più righe • gli operatori e molte istruzioni (ad esempio ‘if’, ‘for’, ‘while’) sono gli stessi del linguaggio c. Altre caratteristiche il linguaggio PHP le ha invece ereditate dal Perl: • i nomi delle variabili devono iniziare con il simbolo «$» Web, basi di dati e linguaggio PHP 149 • nelle istruzioni di output le variabili vengono ‘interpolate’ se contenute tra doppi apici e lasciate inalterate se tra apici singoli; • c’è il supporto alle espressioni regolari; • esiste l’istruzione ‘foreach’ e si possono usare vettori associativi. Notiamo inoltre che, come il Perl, anche PHP è un linguaggio «debolmente tipizzato»; ciò significa che non occorre dichiarare il tipo delle variabili prima di utilizzarle e che le conversioni di tipo eventualmente necessarie vengono fatte, quando possibile, automaticamente a tempo di esecuzione. Vediamo adesso qualche dettaglio riguardante il documento precedente: • nella prima parte (righe 9-18) vengono visualizzate informazioni sulla connessione grazie all’istruzione ‘echo’ e all’uso di alcune variabili di ambiente; il resto del documento contiene la definizione del modulo per l’immissione di semplici dati anagrafici; • le variabili di ambiente di cui sopra fanno parte del gruppo di variabili messe a disposizione dal servente HTTP (vedi paragrafo 6.7) e sono utilizzabili dal PHP grazie al vettore associativo ‘$_SERVER’; • un vettore associativo è un vettore contenente una serie di coppie chiave-valore cui si accede specificando la chiave dell’elemento cercato invece di un indice come nei vettori tradizionali; quindi, ad esempio, a riga 14, riferendosi alla chiave ’SERVER_ADDR’. si ottiene il rispettivo valore, cioè l’indirizzo IP del servente; • a riga 10 abbiamo una istruzione PHP commentata che è stata inserita per poter accennare al vecchio metodo con cui venivano gestite le variabili di ambiente in PHP: fino alla versione ‘4.2’ era possibile accedere direttamente a tali variabili, come si vede nell’istruzione commentata, ed era addirittura possibile usare le variabili provenienti da un modulo semplicemente facendo riferimento al loro nome preceduto da un «$» (questo fatto è illustrato nel listato del prossimo documento); nelle versioni più recenti di PHP tutto questo non è più possibile a meno che non si cambi nel file di configurazione ‘/etc/php5/apache2/ php.ini’ la riga: |register_globals = Off in: |register_globals = On cosa comunque altamente sconsigliata per motivi di sicurezza; in luogo di questo accesso diretto alle variabili, ormai deprecato, si devono utilizzare i vettori associativi «superglobali» (cioè accessibili da qualsiasi punto di un sorgente PHP) di cui un esempio è ‘$_SERVER’ e altri molto importanti sono ‘$_POST’ e ‘$_GET’ introdotti nel prossimo documento. L’aspetto del documento è quello mostrato nella figura 7.18. Web, basi di dati e linguaggio PHP 150 F | igura 7.18. Molto importante è notare che, se si visualizza il sorgente della pagina con l’apposita funzione disponibile nel programma di navigazione, il codice PHP non risulta visibile; esso infatti non viene inviato alla macchina cliente visto che non è compito di quest’ultima l’elaborazione di quelle istruzioni. Si noti che i dati del modulo vengono inviati a ‘modulo1-ris.php’ che risiede nella stessa directory del documento di partenza; qui infatti non è obbligatorio definire una directory apposita, come la ‘/cgi-bin’ usata per i CGI, dove memorizzare gli script PHP. Il file per l’elaborazione dei dati e la creazione della risposta non è altro che un ulteriore pagina HTML corredato da istruzioni PHP; il suo contenuto è: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |<html> |<head> |<title>Modulo 1 risposta con php</title> |</head> |<body> |<h2>Risposta gestita con PHP</h2> |<p/> |Sei collegato al servente Web: |<b><?php echo $_SERVER[’SERVER_NAME’] ?></b> | all’indirizzo: |<b><?php echo $_SERVER[’SERVER_ADDR’]; ?></b> |<p/> |Servente fornito da: |<b><?php echo $_SERVER[’SERVER_SOFTWARE’]; ?></b> |<p/> |Sei collegato dall’indirizzo: |<b><?php echo $_SERVER[’REMOTE_ADDR’]; ?></b> |<p/><br/> |Hai inserito i seguenti dati: |<!-- <p/>Cognome: <?php echo $cognome; ?> --> Web, basi di dati e linguaggio PHP 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 151 |<?php |if ($_SERVER[’REQUEST_METHOD’]=="post") { | $cognome=$_POST[’cognome’]; | $nome=$_POST[’nome’]; | $eta=$_POST[’eta’]; | $email=$_POST[’email’]; |} |else { | $cognome=$_GET[’cognome’]; | $nome=$_GET[’nome’]; | $eta=$_GET[’eta’]; | $email=$_GET[’email’]; |} |?> |<p/>Cognome:<b> <?php print("$cognome"); ?> |<!-- <p/>Cognome:<b> <?php print(’$cognome’); ?> --> |<?php print("</b><p/>Nome:<b> $nome"); ?> |</b><p/>Eta’:<b> <?php echo $eta; ?> |</b><p/>E-mail:<b> <?php echo $email; ?> |</b><p/><br/> |<?php |$var1 = strstr($_SERVER[’HTTP_USER_AGENT’], "Mozilla"); |if (!strstr($var1, "compatible") and ($var1)) { | echo "Stai usando il browser Mozilla o uno da esso derivato"; } |elseif (strstr($var1, "MSIE")) { | echo "Stai usando il browser Internet Explorer"; } | else { | echo "Stai usando un browser diverso da Explorer e Mozilla"; } |?> |</body> |</html> La prima parte ricalca quella del primo documento; successivamente vengono visualizzati i dati inviati dal modulo. Notiamo subito che, a differenza di quanto avviene con i CGI, non è necessario far precedere il contenuto della risposta dall’intestazione HTTP e dalla riga vuota in quanto questo a questo provvede automaticamente il motore PHP nel momento in cui viene incontrata la prima istruzione di output (‘echo’ o ‘print()’). Commentiamo più in dettaglio le parti più significative del sorgente: • la riga 20 è commentata e mostra come si potrebbe accedere direttamente alle variabili del modulo se fosse attivata l’opzione ‘register_globals’; la cosa, come detto, è decisamente da evitare e quindi si usa il vettore super-globale ‘$_POST’ oppure ‘$_GET’ in base a quale è il metodo di invio dei dati (righe dalla 22 alla 33); in alternativa si potrebbe usare il vettore super-globale ‘$_REQUEST’ che contiene i dati provenienti dal modulo qualunque sia il metodo utilizzato per l’invio; • alle righe 35 e 36 vediamo l’uso della funzione ‘print()’ al posto della ‘echo’; • la riga 37 può essere considerata speculare rispetto alle altre righe in cui si emette un output in quanto in essa abbiamo la funzione di uscita del PHP che si preoccupa di emettere una Web, basi di dati e linguaggio PHP 152 parte di codice HTML oltre al valore di una variabile; nelle altre righe abbiamo invece l’uscita PHP inserita all’interno dei normali tag HTML (separata ovviamente dalle stringhe «<?php» e «?>»); i due modi di far convivere il codice HTML con le istruzioni PHP sono ugualmente efficaci e la preferenza dipende dalle caratteristiche del documento di risposta o dell’elaborazione che si sta effettuando: si può addirittura scrivere un file PHP in cui tutto il contenuto della risposta, compresi i tag HTML, viene emesso all’interno di istruzioni ‘echo’ o funzioni ‘print()’ nel codice PHP; • sempre osservando le righe 35, 36 e 37 possiamo sottolineare il concetto di «espansione» di una variabile: quando si usa una variabile in output ad essa viene sostituito il suo valore anche se è contenuta fra doppi apici come una costante stringa; per evitare questo comportamento occorre usare gli apici singoli come mostrato nella riga 36 che è commentata; il suo effetto sarebbe quello di emettere la stringa "$cognome" piuttosto che il valore di tale variabile; • alle righe 41-49 si cerca di determinare con quale browser l’utente ha compilato il modulo e inviato i dati: a riga 42 viene definita una variabile con il risultato della funzione ‘strstr()’ definita sulla stringa contenuta nella variabile di sistema ‘HTTP_USER_AGENT’ e sulla stringa "Mozilla"; il risultato è la stringa ottenuta da quella di partenza escludendo la parte precedente la parola "Mozilla"; nelle righe 43-48 ci sono alcune istruzioni condizionali la cui sintassi è esattamente uguale a quella del linguaggio c (si noti ad esempio l’uso del simbolo «!» per la negazione) in cui si usa ancora la funzione ‘strstr()’; la logica complessiva è la seguente: se ‘$var1’ è diversa dalla stringa vuota e non contiene la stringa "compatible" stiamo usando il programma di navigazione Mozilla o uno da esso derivato, altrimenti se contiene la stringa "MSIE" stiamo usando Internet Explorer, altrimenti stiamo usando un programma di navigazione diverso da entrambi. L’aspetto della risposta è quello mostrato nella figura 7.20. F | igura 7.20. Web, basi di dati e linguaggio PHP 153 Se il modulo di provenienza dei dati prevede la possibilità di più valori per uno stesso campo (caso di un controllo ‘<select>’ con attributo ‘multiple’), occorre attribuire al campo un nome terminante con «[]» in modo che in PHP siano poi disponibili i valori immessi all’interno di un vettore; se ad esempio il nome nel modulo è scelte[] in PHP abbiamo che $_REQUEST[’scelte’] è un vettore e non un singolo valore. 7.7 Validazione dell’input con PHP (cenno alle espressioni regolari) « Le istruzioni PHP possono essere anche utilizzate per controllare la correttezza dei dati inseriti in un modulo. In certi casi però controlli di questo tipo vengono svolti direttamente sulla macchina cliente con codice eseguito su quest’ultima usando ad esempio ‘JavaScript’. Questa soluzione presenta l’indubbio vantaggio di far diminuire il carico di lavoro del servente ma non è sempre praticabile: se ad esempio si deve controllare la presenza di un codice prodotto in un archivio residente sulla macchina remota, non si può fare a meno di utilizzare un modulo di elaborazione che venga eseguito su quest’ultima e cioè lato servente. Inoltre l’utente che sta usando la procedura potrebbe aver disabilitato l’esecuzione di codice ‘JavaScript’ sul suo programma di navigazione, rendendo così inefficaci i controlli inseriti sul lato cliente. Facendo riferimento all’esempio del paragrafo precedente, supponiamo di voler controllare che il campo denominato email sia non vuoto e sia un indirizzo di posta elettronica scritto correttamente; il controllo viene fatto usando istruzioni PHP da aggiungere ovviamente al file ‘modulo1_ris.php’. Vengono mostrate le singole istruzioni da utilizzare lasciando al lettore l’individuazione delle opportune modifiche alla logica di elaborazione necessarie al loro inserimento nel file in oggetto. Il controllo sulla valorizzazione del campo email può essere fatto con la funzione ‘strlen()’ che restituisce la lunghezza in byte dell’argomento: |if (strlen($email)==0) { | echo "<p/>Il campo E-mail è obbligatorio; torna al modulo e correggi!" |} |else { | ........ Per quanto riguarda invece la correttezza dell’indirizzo di posta possiamo supporre che esso debba avere la seguente forma: • almeno 2 caratteri diversi da spazio e da «@»; • il simbolo «@»; • almeno un carattere diverso da spazio, da punto e da «@»; • un punto; • almeno altri due caratteri diversi da spazio, da punto e da «@». Web, basi di dati e linguaggio PHP 154 Per controllare che la variabile sia aderente a questo formato (nel gergo tecnico si dice che si ha un match tra essa e la sequenza di cui sopra, chiamata pattern) si utilizza uno strumento molto efficace, proposto originariamente per il linguaggio Perl, ma ormai esportato in molti altri linguaggi: le espressioni regolari (REGEXP). Le espressioni regolari sono tanto potenti quanto ostiche, specialmente per i non esperti, anche a causa della loro sintassi davvero succinta e per niente amichevole. Una loro trattazione, anche solo superficiale, richiederebbe probabilmente una dispensa apposita; ci limitiamo quindi a pochi esempi, fra i quali includiamo la soluzione da adottare per il controllo del nostro indirizzo di posta, confidando che questo piccolo «assaggio» possa spingere chi necessita di approfondimenti a consultare la vasta mole di documentazione reperibile sull’argomento. La funzione da usare per le espressioni regolari è ‘preg_match()’ che, nella forma più comune ha due argomenti: il pattern e la stringa da controllare; se la stringa soddisfa il pattern la funzione ritorna vero, altrimenti ritorna falso. Ecco dunque l’istruzione per effettuare il controllo di correttezza sull’indirizzo di posta elettronica: |if (!preg_match("/^[^@ ]{2,}@[^@ \.]+\.[^@ \.]{2,}$/",$email)) { | echo "<p/>Il campo E-mail non è valido; torna al modulo e correggi!" |} |else { | ...... Nella tabella seguente cerchiamo di fornire una spiegazione del pattern scandendolo da sinistra a destra e sottolineando ancora una volta che la mole di nozioni trascurate nella spiegazione è nettamente superiore a quella delle nozioni presenti: Simbolo pattern ^ [^@ ] {2,} @ [^@ \.] + \. [^@ \.] {2,} $ nel Spiegazione inizio della stringa, essa deve iniziare come specificato nel proseguo del pattern; un carattere diverso da «@» e da spazio; le parentesi quadrate indicherebbero la scelta di uno qualsiasi dei caratteri in esse contenuti e il carattere «^» indica la negazione; il carattere o il gruppo di caratteri indicati in precedenza devono essere ripetuti due o più volte; deve esserci il carattere «@»; un carattere diverso da «@», da spazio e da punto; il carattere punto viene indicato mascherandolo con il carattere di escape «\» perché è un carattere speciale per i pattern (significherebbe «qualsiasi carattere»); quanto appena indicato deve essere ripetuto una o più volte (equivale a {1,}); deve esserci il carattere punto; un carattere diverso da «@», da spazio e da punto; quanto appena indicato deve essere ripetuto due o più volte; fine della stringa, essa deve finire secondo quanto appena indicato nel pattern. Come ulteriore esempio supponiamo di voler controllare la validità del campo cognome del modulo del paragrafo precedente; la regola che deve essere soddisfatta è che siano presenti solo caratteri alfabetici minuscoli (eccetto la prima maiuscola), il carattere spazio e l’apostrofo (sem- Web, basi di dati e linguaggio PHP 155 plifichiamo leggermente la questione imponendo che nei cognomi composti sia maiuscolo solo il primo carattere). |$cognome=stripslashes($cognome); |if (!preg_match("/^[A-Z]{1}[ a-z’]*$/",$cognome)) { | echo "<p/>Il campo Cognome non è valido; torna al modulo e correggi!" |} |else { | ...... In questo esempio vediamo anche l’uso della funzione ‘stripslashes()’ che permette di eliminare il carattere «\» aggiunto automaticamente nell’input per mascherare eventuali «’». Esiste anche la funzione ‘addslahes()’ che permette invece di aggiungere il carattere «\» prima di caratteri che possono causare problemi se presenti in campi da inserire in una base di dati; si tratta dei caratteri «’», «"» e «\». Anche in questo caso utilizziamo una tabella per la spiegazione del pattern per il controllo del cognome: Simbolo pattern nel Spiegazione inizio della stringa; un carattere qualsiasi compreso tra «A» e «Z», quindi maiuscolo; il carattere o il gruppo di caratteri indicati in precedenza devono essere presenti solo una volta; un carattere spazio o alfabetico minuscolo o apostrofo; quanto appena indicato deve essere ripetuto zero o più volte; fine della stringa. ^ [A-Z] {1} [ a-z’] * $ Infine ipotizziamo di dover controllare un numero di telefono (contenuto nella variabile ‘$telefono’) imponendo che debba essere costituito da un insieme di due, tre o quattro cifre, seguite dal segno meno e da almeno altre 4 cifre. |if (!preg_match("/^[0-9]{2,4}-[0-9]{4,}$/",$telefono)) { | echo "<p/>Il campo Telefono non è valido; torna al modulo e correggi!" |} |else { | ...... Ed ecco la tabella per la spiegazione del pattern: Simbolo pattern ^ [0-9] {2,4} [0-9] {4,} $ nel Spiegazione inizio della stringa; un carattere qualsiasi compreso tra «0» e «9», quindi una cifra; il carattere o il gruppo di caratteri indicati in precedenza devono essere presenti da due a quattro volte; deve esserci il segno meno; una cifra; quanto indicato in precedenza deve essere presente quattro o più volte; fine della stringa. 156 Web, basi di dati e linguaggio PHP 7.8 Le sessioni in PHP « In questo paragrafo prendiamo in esame un argomento molto interessante: la gestione delle sessioni in PHP; prima di entrare nei dettagli e di illustrare qualche esempio è però opportuno introdurre il concetto di stato di una applicazione e le motivazioni per cui le sessioni sono importanti per la gestione dello stato nelle applicazioni Web. 7.8.1 Il concetto di stato di un applicazione « Quando si utilizza una normale applicazione su un singolo sistema di elaborazione (quindi senza coinvolgere la rete come accade invece per le applicazioni Web) non si riesce a cogliere immediatamente l’esistenza di due entità al suo interno: • la parte dell’applicazione che svolge le funzioni di interfaccia con l’utente; • la parte di logica di programmazione. In molti casi questi due componenti appaiono indistinti, ma ogni volta che l’utente interagisce con l’interfaccia (ad esempio inserendo dei dati o effettuando delle scelte su un menu) essa comunica con la logica di programmazione la quale svolge certe elaborazioni ed eventualmente fornisce una risposta ancora all’interfaccia utente. Possiamo anche dire che ogni azione svolta con l’interfaccia utente provoca un cambiamento nello «stato» dell’applicazione, cioè alla condizione in cui si trovano, istante per istante, i dati e le variabili dell’applicazione stessa. Questo cambiamento di stato può essere provocato anche da altri fattori indipendenti dalle azioni dell’utente e previsti direttamente nella logica di programmazione. Il punto interessante è però il seguente: mentre nelle applicazioni tradizionali la comunicazione tra interfaccia e logica di programmazione avviene con continuità e quindi la gestione dei cambiamenti di stato non è problematica e talvolta non viene neppure affrontata in modo esplicito, nelle applicazioni Web siamo costretti ad affrontare il problema in quanto il protocollo HTTP è «privo di stato». Questo significa che non esiste alcun meccanismo automatico che tenga traccia dei cambiamenti di stato degli oggetti dell’interfaccia utente (i moduli visualizzati con il browser sulle macchine clienti) e li comunichi alla logica di programmazione (ad esempio script PHP eseguiti sul servente) e viceversa. Nelle applicazioni Web la comunicazione tra interfaccia e logica di programmazione non è automatica ma guidata dall’utente e talvolta può essere anche molto lenta. Inoltre uno script della logica di programmazione (supponiamo scritto in PHP) viene attivato solo al momento della richiesta dell’utente e dell’invio dei dati e quando termina vengono persi i valori di tutti i dati e di tutte le variabili usate nell’elaborazione; anche se l’utente ha l’impressione che l’applicazione sia ancora attiva (perché vede comparire sul suo browser una qualche risposta) in effetti nessun programma è in quel momento in esecuzione ed una nuova attivazione dello script non può avere a disposizione i valori dei dati dell’elaborazione precedente. Questo naturalmente avviene a meno che non si individui un meccanismo che permetta di mantenere lo stato nell’ambito di una applicazione che usa il protocollo HTTP facendo in modo che tutti i dati dell’applicazione (o almeno quelli che interessano) siano persistenti. Si tratta quindi di trovare il modo di attivare e gestire una «sessione di lavoro» che consiste in tutte le interazioni che l’utente svolge dal momento in cui si collega la prima volta all’applicazione Web, basi di dati e linguaggio PHP 157 residente sul servente (eventualmente accreditandosi), al momento in cui chiude il collegamento oppure scade un contatore di tempo di inattività. 7.8.2 Mantenere lo stato nelle applicazioni con PHP « Esistono vari metodi per mantenere lo stato usando il linguaggio PHP; illustriamoli brevemente eccetto quello considerato migliore (sessioni native in PHP) che viene approfondito maggiormente: • campi nascosti nei moduli: si tratta di utilizzare controlli ‘<input>’ di tipo "hidden" per comunicare all’applicazione i dati che devono essere conservati tra una attivazione e l’altra di uno script; questo metodo è utilizzabile solo in presenza di un esiguo volume di dati da rendere persistenti; • accodamento alla stringa dell’URI: si tratta di passare i dati all’applicazione accodandoli all’URI del ricevente come accade quando si invia un modulo con metodo "get"; in questo caso si è soggetti alle stesse limitazioni già discusse nel paragrafo riguardante l’invio dei dati dei moduli HTML (paragrafo 6.8); • uso di basi di dati: i valori delle variabili possono essere memorizzati in una tabella di una base di dati; anche questa soluzione ha una controindicazione: il sovraccarico di lavoro per il servente per effettuare gli accessi alla base di dati; • uso dei cookies (biscottini): i cookies sono un modo per memorizzare sul computer cliente un piccolo quantitativo di dati che devono persistere nell’ambito di una sessione di lavoro; sebbene l’idea non sia tecnicamente da scartare, è bene non fare troppo affidamento su questa soluzione perché, avendo i cookies acquisito una cattiva fama presso il pubblico dei navigatori in Internet (si può abusare del loro uso per acquisire ad esempio informazioni sulle preferenze degli utenti a loro insaputa), spesso vengono addirittura disattivati con apposite scelte nella configurazione del browser; eventualmente quindi è il caso di usarli solo per compiti utili ma non fondamentali per il funzionamento di una procedura Web (ad esempio per memorizzare le preferenze estetiche di un utente relativamente a un certo sito); • sessioni native in PHP: si tratta senza dubbio della soluzione migliore e quindi le dedichiamo un piccolo approfondimento nel prossimo paragrafo. 7.8.3 Sessioni native in PHP « L’idea fondamentale che sta alla base della gestione delle sessioni in PHP è quella di memorizzare i dati, che devono rimanere persistenti nell’ambito di queste ultime, sul servente; in questo modo si elimina la necessità di comunicare i dati stessi al cliente con i conseguenti problemi di riservatezza o di ingombro. Al cliente viene comunque assegnata una chiave chiamata «identificatore di sessione» che gli permette di identificarsi univocamente per una certa sessione e di vedersi associare i relativi dati persistenti. In PHP la chiave di sessione si chiama SID (Session Identifier) ed è un numero intero associato ad una e una sola sessione. Schematizzando al massimo la gestione di una sessione nativa in PHP può quindi essere così riassunta: Web, basi di dati e linguaggio PHP 158 • quando si crea la sessione (con opportuna funzione illustrata più avanti) il servente genera il relativo SID e lo comunica al cliente; • le variabili registrate per quella sessione (anche qui con apposita funzione) vengono memorizzate nella memoria di massa del servente in un file identificabile in base al numero di sessione (a volte il nome del file è proprio il SID o almeno lo contiene); • quando il cliente deve accedere alle variabili registrate per la sessione, basta che comunichi al servente il SID; • se è possibile usare i cookies il SID viene gestito sul cliente grazie ad essi, altrimenti viene passato al servente ponendolo in coda all’URI delle richieste; la cosa fondamentale è però che di tutto questo si occupa il motore PHP in modo trasparente per lo sviluppatore che si deve preoccupare solo di usare in modo adeguato le funzioni di avvio e chiusura di una sessione e di registrazione e lettura delle relative variabili. La figura 7.28 rappresenta quanto appena illustrato. F | igura 7.28. Le funzioni da usare per gestire le sessioni in PHP sono le seguenti: • ‘session_start()’: serve ad avviare una sessione; • ‘session_register(’nome_var’)’: serve a registrare la variabile nome_var (da indicare senza «$» iniziale e tra apici o virgolette); le variabili di sessione registrate sono disponibili nel vettore associativo super-globale ‘$_SESSION’; • ‘session_unregister(’nome_var’)’: serve a eliminare la registrazione della variabile nome_var (da indicare senza «$» iniziale e tra apici o virgolette); • ‘session_destroy()’: serve a chiudere la sessione; una sessione viene chiusa automaticamente terminando l’esecuzione del browser da cui si è generata oppure Web, basi di dati e linguaggio PHP 159 dopo 1440 secondi (24 minuti) di inattività; tale valore può essere cambiato modificando nel file di configurazione ‘/etc/php5/apache2/php.ini’ il valore di ‘session.gc_maxlifetime’. Si tenga presente che una sessione viene avviata automaticamente al momento che si esegue per la prima volta una ‘session_register()’ anche in mancanza di una ‘session_start()’. Si osservi anche che la funzione ‘session_start()’ deve essere invocata in ogni pagina in cui si vuole fare riferimento a quella sessione. Le istruzioni che provocano l’avvio di una sessione devono essere posizionate in un punto dello script PHP che non interferisca con l’invio automatico di intestazioni HTTP e quindi prima di qualsiasi istruzione PHP che emetta un output e anche di qualsiasi contenuto HTML scritto esternamente al codice PHP; la cosa migliore da fare è allora definire un blocco PHP apposito proprio all’inizio del file. In certi casi (ad esempio quando più applicazioni sono ospitate in un unico servente) può essere importante che il file con i dati di sessione venga salvato in una posizione separata per ogni applicazione; in questo modo si può evitare il rischio che altri script PHP accedano ai dati di un’altra sessione. A tal fine si deve usare la direttiva ‘ini_set()’ prima di ‘session_start()’ nel modo seguente: | | ini_set("session.save_path", "percorso_in_cui_salvare"); Concludiamo questa panoramica sulle sessioni in PHP con un esempio in cui gestiamo un contatore di accessi ad un sito Web (o, più in piccolo, ad una pagina). Il valore del contatore viene memorizzato in un file, ovviamente sul servente (in questo modo accenniamo anche all’uso dei file in PHP) e letto e incrementato ad ogni nuova richiesta di scaricamento della pagina. Se questo meccanismo fosse gestito senza uso di sessioni avremmo un inconveniente molto grave: ogni volta che la pagina viene ri-visitata senza essere usciti dalla sessione di lavoro (ad esempio con un semplice «rinfresco» oppure tornando indietro dopo avere seguito un collegamento che si origina da essa) otterremmo un incremento del contatore, cosa evidentemente non corretta (a meno che non vogliamo «gonfiare» i dati di accesso al nostro sito). Con l’uso delle sessioni, invece, l’incremento del contatore può essere fatto solo in presenza di una sessione appena avviata e non nelle visite successive nell’ambito della stessa sessione. Vediamo dunque il listato del file, chiamato ‘conta_sisess.php’, che gestisce il contatore delle visite correttamente: 1 2 3 4 5 6 7 8 9 |<?php |session_start(); |session_register(’sessione’); |$nomefile="conta.txt"; |if (!file_exists($nomefile)) { | $fp=fopen($nomefile,"w"); | fclose($fp); |} |$fp=fopen($nomefile,"r"); Web, basi di dati e linguaggio PHP 160 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |$num=fread($fp,4); |fclose($fp); |$sess=$_SESSION[’sessione’]; |$sess++; |$_SESSION[’sessione’]=$sess; |if ($sess == 1) |{ | $fp=fopen($nomefile,"w"); | $num++; | fwrite($fp,$num,4); | fclose($fp); |} |$sid=session_id(); |print ("<html><head><title>Contatore con sessione</title></head>\n"); |print ("<body><h2 style=\"text-align:center;\">Pagina←,→con contatore</h2>\n"); |print ("<p/>Numero visite (con gestione sessione - SID = $sid) = $num\n"); |print ("<p/>Clicca <a href=\"chiudi_sess.php\">qui</a> per←,→chiudere la sessione\n"); |print ("</body></html>"); |?> Commentiamo il listato servendoci dei numeri di riga aggiunti per questo scopo: • Lo script inizia con l’attivazione della sessione e la regitrazione della variabile $sessione (righe 2 e 3); • alla riga 4 si assegna il nome del file in cui memorizzare il valore del contatore a $nomefile; nel nome non è presente alcuna indicazione di percorso, questo significa che tale file risiede nella stessa directory in cui è memorizzato lo script; • con le righe da 5 a 8 si crea il file, se non esiste, tramite una operazione di apertura in scrittura (riga 6) con successiva chiusura; si noti la forte somiglianza tra queste funzioni di PHP per la gestione dei file e quelle analoghe del linguaggio c; la creazione del file ha successo solo se l’utente ‘www-data’ (che ricordiamo essere quello con i cui privilegi vengono eseguiti i processi del servente Web) ha il permesso di scrivere nella directory in cui il file deve essere memorizzato; • rimaniamo ancora sulla riga 6 per sottolineare come la funzione di apertura di un file restituisca un valore, chiamato puntatore al file, (nel nostro caso assegnato a $fp) che poi deve essere utilizzato per tutte le successive operazioni da svolgere su quel file; in pratica con l’apertura si viene a creare un legame tra il nostro programma e il file fisico residente nella memoria di massa e tale legame è esplicitato dal puntatore al file; • nelle righe da 9 a 11 si apre il file in lettura (a questo punto esiste sicuramente), si legge il valore del contatore e si chiude il file; anche qui si possono notare forti analogie con il linguaggio c; • la riga 10 merita qualche ulteriore chiarimento: viene assegnato alla variabile $num il valore letto nel file partendo dall’inizio (il file è stato appena aperto) e per una lunghezza di quattro byte; tale valore è infatti un contatore, quindi un numero intero, e gli interi vengono memorizzati utilizzando quattro byte come in c e in molti altri linguaggi; • con le righe dalla 12 alla 14 si legge il valore della variabile di sessione, lo si incrementa facendolo transitare in $sess (anche l’operatore «++» è ripreso dal linguaggio c) e lo si memorizza ancora nella variabile di sessione; Web, basi di dati e linguaggio PHP 161 • se il valore appena incrementato è uno significa che è la prima volta che tale operazione è stata fatta e quindi deduciamo che la sessione è stata appena avviata e dobbiamo incrementare il contatore; questo è il «ragionamento» svolto nel blocco di selezione presente alle righe da 15 a 21; • in particolare a riga 17 si apre il file in scrittura; nella successiva si incrementa il valore del contatore e a riga 19 lo si scrive nel file a partire dall’inizio (il file è stato appena aperto in scrittura) utilizzando quattro byte come specificato dal terzo parametro della funzione ‘fwrite’; infine a riga 20 si chiude il file; • a riga 22 si pone in $sid l’identificativo della nostra sessione per poi visualizzarlo (questo non riguarda la gestione del contatore di accessi ed è stato aggiunto solo per mostrare l’aspetto di un SID); • le righe da 23 a 27, con una serie di ‘print()’ creano la risposta in formato HTML da inviare al browser che si è collegato a questa pagina; viene anche previsto un collegamento ad un’altra pagina (‘chiudi_sess.php’) per poter chiudere la sessione; • importante notare, nelle righe 24 e 26, l’uso delle virgolette sia nell’ambito dell’istruzione PHP (cioè la ‘print()’) sia all’interno del codice HTML da essa creato; ovviamente queste ultime non possono essere usate liberamente, perché causerebbero errore di sintassi nell’istruzione PHP, e quindi vengono «mascherate» facendole precedere dal simbolo «\» • notiamo anche, sempre in queste istruzioni di ouput, l’uso del carattere speciale «\n» che corrisponde al codice ASCII 10 cioè a «riga nuova» o line feed (LF); serve per scrivere il sorgente HTML della pagina di risposta su più righe invece che su un’unica riga (cosa che sarebbe comunque lecita). Nella figura 7.31 viene mostrato l’aspetto della risposta accompagnato dalla finestra di visualizzazione del relativo sorgente. F | igura 7.31. Aggiungiamo anche i listati dei file ‘chiudi_sess.php’, da attivare, per chiudere la sessione, tramite collegamento presente nella pagina appena mostrata, e ‘conta_nosess.php’ che è la versione di pagina con contatore di accessi non corretta in quanto non gestita con le sessioni. Per questi due file non viene mostrato l’aspetto in caso di apertura con il browser e non vengono commentate le istruzioni in quanto non contengono sostanziali novità rispetto a quanto illustrato finora. 162 Web, basi di dati e linguaggio PHP Questo è il listato di ‘chiudi_sess.php’: |<?php |session_start(); |session_destroy(); |print ("<html><head><title>Chiusura sessione</title></head><body>\n"); |print ("Sessione chiusa! Arrivederci\n"); |print ("</body></html>"); |?> Mentre questo è ‘conta_nosess.php’: |<?php |$nomefile="conta.txt"; |if (!file_exists($nomefile)) { | $fp=fopen($nomefile,"w"); | fclose($fp); |} |$fp=fopen($nomefile,"r"); |$num=fread($fp,4); |fclose($fp); |$fp=fopen($nomefile,"w"); |$num++; |fwrite($fp,$num,4); |fclose($fp); |print ("<html><head><title>Contatore senza sessione</title></head>\n"); |print ("<body><h2 style=\"text-align:center;\">Pagina←,→con contatore disonesto</h2>\n"); |print ("<p/>Numero visite (senza gestione sessione) = $num\n"); |print ("</body></html>"); |?> 7.9 Pagine PHP che richiamano se stesse « Una tecnica molto diffusa, nell’ambito della applicazioni scritte in PHP, è quella di scrivere pagine che svolgono sia il compito di raccolta dati attraverso un modulo, sia quello di elaborazione invio della risposta. Prima di tutto occorre fare in modo che lo script invii i dati a se stesso; a tale scopo occorre inserire "$_SERVER[’PHP_SELF’]" (variabile globale contenente il nome dello script PHP in esecuzione) come valore dell’attributo ‘action’ del modulo. Usando poi una campo nascosto del modulo come variabile flag si riesce a discriminare se lo script viene attivato per la prima volta, e allora deve emettere il modulo per l’input dei dati, oppure se è stato richiamato dal modulo, e allora deve elaborare questi ultimi e, eventualmente, emettere una risposta. La logica di funzionamento dello script è quella rappresentata nello schema visibile nella figura 7.34, realizzato in «stile» diagramma di flusso. Web, basi di dati e linguaggio PHP 163 F | igura 7.34. Nell’esempio viene anche fatto uso di campi riguardanti data e ora in modo da poter illustrare alcune funzioni PHP dedicate a questo tipo di dati. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |<?php |print ("<html><head><title>Modulo autocontrollante</title></head>\n"); |print ("<body>\n"); |$giorno=date("d/m/Y"); |$ora=date("H:m:s"); |$PHP_SELF=$_SERVER[’PHP_SELF’]; |// se nascosto settato prende i valori in arrivo dal form |if (isset($_REQUEST[’nascosto’])) { | $cogn=$_REQUEST[’cognome’]; | $nom=$_REQUEST[’nome’]; | $datan=$_REQUEST[’data_nas’]; | $g=substr($datan,0,2); | $m=substr($datan,2,2); | $a=substr($datan,4,4); | |// controlli | $controlli=1; | if (!preg_match("/^[A-Z]{1}[ a-z’]*$/",$cogn)) { | echo "<p/>Il campo Cognome non è valido!\n"; | $controlli=0; | } | if (!preg_match("/^[A-Z]{1}[ a-z’]*$/",$nom)) { | echo "<p/>Il campo Nome non è valido!\n"; Web, basi di dati e linguaggio PHP 164 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | | | | | | |} |// |if | | | | | $controlli=0; } if(!checkdate($m,$g,$a)) { print("<p/>Errore nella data!\n"); $controlli=0; } se controlli ok e nascosto settato -- tutto ok (($controlli) and (isset($_REQUEST[’nascosto’]))) { print ("<h2>Dati inviati</h2>\n"); print ("<p/>Cognome: $cogn\n"); print ("<p/>Nome: $nom\n"); print ("<p/>Data di nascita: $g/$m/$a\n"); print ("<p/>Grazie. Clicca <a href=\"$PHP_SELF\">qui</a>←- ,→per tornare al modulo iniziale"); |} |else { |// emette il modulo | print ("<h1>Modulo raccolta dati</h1>\n"); | print ("<p/>Treviso, $giorno $ora<p/>\n"); | print ("<h2>Inserisci i tuoi dati</h2>\n"); | print ("<p/><form action=\"$PHP_SELF\" method=\"post\">\n"); | print ("Cognome: <input type=\"text\" size=\"15\" name=\"cognome\"←,→ value=\"$cogn\"/>\n"); | print ("<p/>Nome: <input type=\"text\" size=\"15\" name=\"nome\"←- ,→ value=\"$nom\"/>\n"); | print ("<p/>Data di nascita (ggmmaaaa): <input type=\"text\"←,→ size=\"8\" maxlength=\"8\" name=\"data_nas\" value=\"$datan\"/>\n"); | print ("<input type=\"hidden\" name=\"nascosto\" value=\"1\"/>\n"); | print ("<p/><input type=\"submit\" value=\"Invia\"/>\n"); | print ("<input type=\"reset\" value=\"Reset\"/>\n"); | print ("</form>\n"); |} |print ("</body></html>"); |?> Vediamo le parti più significative del listato: • le righe 2,3 e 53 creano la parte di pagina HTML necessaria sia per il modulo che per la risposta; • alle righe 4 e 5 viene usata la funzione ‘date()’ che prevede due parametri: un formato e una marca temporale (timestamp); una marca temporale è un numero intero che rappresenta il numero di secondi trascorsi dalle ore 00:00 del 1 gennaio 1970 (istante zero per i sistemi Unix e derivati); per ottenere la marca temporale corrente si può usare la funzione ‘time()’ che non prevede argomenti, mentre con la funzione ‘mktime(ora, minuto, secondo, giorno, mese, anno)’ si ottiene la marca temporale calcolata dall’istante zero a quello indicato negli argomenti; • quando nella funzione ‘date()’ si indica solo il primo parametro, come nelle righe 4 e 5, si suppone che il secondo sia il valore restituito da ‘time()’ e quindi si ottiene la data e ora corrente formattata secondo quanto indicato nel primo parametro; • i formati qui utilizzati sono solo due fra quelli possibili e il loro significato è del tutto intuitivo: notiamo solo che con «a» si indica l’anno di due cifre mentre con «A» di quattro, con «h» l’ora tra zero e dodici mentre con «H» tra zero e ventiquattro; Web, basi di dati e linguaggio PHP 165 • alla riga 6 si acquisisce il nome del file che è in esecuzione per usarlo per il richiamo a se stesso; • la riga 8 è quella fondamentale per la logica dello script: viene controllato se la variabile del modulo chiamata "nascosto" possiede un valore oppure no (a questo serve la funzione ‘isset()’); • il controllo di riga 8 da esito positivo se lo script è stato richiamato per l’invio dei dati che quindi vengono acquisiti (righe 9-15); il ramo vero della selezione si estende fino a riga 30 comprendendo anche i controlli sui valori • il caso contrario si ha quando lo script è stato avviato per la prima volta e in tal caso non si fa niente (il ramo falso della selezione è vuoto); • nelle righe da 12 a 14 vengono estratti dalla data inserita nel modulo i tre componenti giorno, mese e anno con l’uso della funzione ‘substr()’ che serve a estrarre una sottostringa da una stringa e prevede tre parametri: la stringa, il byte di partenza, la quantità di byte da estrarre (si tenga presente che il primo byte di una stringa è quello di posto zero); • in questa parte dello script si nota bene come il linguaggio PHP operi le conversioni automatiche di tipo delle variabili: $g, $m, $a sono stringhe e vengono fornite come parametri ad una funzione che si aspetta numeri; siccome però il loro contenuto è effettivamente numerico, il tipo viene convertito automaticamente e non si ha alcuna segnalazione di errore (cosa che invece accadrebbe se fossimo in presenza di linguaggi più rigorosi nella gestione delle variabili come il linguaggio c). • nelle righe da 16 a 29 ci sono i controlli sui valori in arrivo dal modulo con il banale uso di un flag (variabile $controlli); • in particolare a riga 26, per il controllo sulla data, viene usata un’altra funzione riguardante le date: ‘checkdate()’ che serve a controllarne la validità; i parametri, come si vede, devono essere passati nell’ordine usato negli Stati Uniti: mese, giorno, anno; se la data è valida la funzione restituisce vero altrimenti restituisce falso; • da riga 32 a riga 52 c’è l’altra selezione fondamentale per lo script: se il campo nascosto è settato e i controlli sono andati bene, viene emesso un riepilogo dei dati inseriti seguito da un collegamento per il ritorno al modulo iniziale (righe da 33 a 38); in caso contrario viene emesso il modulo in cui i campi di input sono eventualmente precaricati con i valori precedenti (righe da 40 a 52); • questa seconda eventualità può infatti verificarsi in due casi: prima esecuzione dello script, e allora i campi sono vuoti, oppure errore nell’input, e allora i campi contengono i valori immessi precedentemente. Nelle due successive figure 7.36 e 7.37 vediamo il caso in cui si hanno errori nell’input e quello in cui l’immissione si conclude positivamente. F | igura 7.36. Web, basi di dati e linguaggio PHP 166 F | igura 7.37. 7.10 Gestione degli errori in PHP « Come per tutti gli altri linguaggi di programmazione, anche programmando in PHP è possibile commettere tre tipi di errori: • errori di sintassi: si sbaglia la scrittura di una istruzione o di una funzione; il motore PHP rileva l’errore e l’esecuzione dello script neanche inizia; • errori a tempo di esecuzione (runtime): si manifestano al momento che il codice viene eseguito (esempio tipico è la divisione per zero); possono essere fatali se interrompono l’esecuzione dello script, oppure non fatali; • errori logici: lo script funziona regolarmente ma non produce i risultati aspettati (ad esempio se si inverte la logica di funzionamento di una selezione a due vie); questi errori non vengono ovviamente segnalati dal motore PHP, deve essere il programmatore ad individuarli con una attenta attività di verifica del comportamento dei programmi. Nelle due successive figure, 7.38 e 7.39 vediamo quello che appare nella finestra del browser rispettivamente in caso di un errore di sintassi e di un errore a tempo di esecuzione (si vuole aprire un file che non esiste). F | igura 7.38. Web, basi di dati e linguaggio PHP 167 F | igura 7.39. Come si vede, nel secondo caso l’errore non è fatale e lo script prosegue ugualmente fornendo un risultato ovviamente non corretto. Quando una procedura scritta in PHP viene resa attiva presso gli utenti (si dice che passa «in produzione»), è lecito aspettarsi che tutti gli errori di sintassi siano stati eliminati; gli errori a tempo di esecuzione sono invece più subdoli perché possono manifestarsi solo in certe condizioni (il file da aprire esisteva fino a ieri e oggi non esiste più); in questo caso un buon programmatore dovrebbe prevedere opportuni controlli all’interno dello script in modo da intercettare le possibili situazioni di errore gestendole con opportuni messaggi all’utente («L’archivio xyz, fondamentale per la procedura si è danneggiato; contattare l’amministratore del sistema»). Nell’ambito della gestione degli errori possono essere proficuamente utilizzate i comandi ‘break’, per forzare l’uscita da un blocco di istruzioni (ad esempio da un ciclo), e ‘exit’ per forzare la conclusione dello script. Se lo sviluppatore è ragionevolmente certo di avere previsto la gestione di tutti gli errori a tempo di esecuzione della sua procedura (o almeno dei più probabili), può essere opportuno disabilitare la visualizzazione sul browser dei messaggi di errore PHP che può generare sconcerto nell’utente oltre che fornirgli informazioni inopportune. Per fare questo occorre intervenire nel file di configurazione ‘/etc/php5/apache2/php.ini’ per cambiare la riga: |display_errors = On ponendo il valore a Off . Questa modifica fa si che, in caso di errore, l’utente riceva una pagina bianca; ciò probabilmente 168 Web, basi di dati e linguaggio PHP non fa diminuire il suo sconcerto, ma almeno evita che gli vengano visualizzate informazioni inopportune. Avendo disattivato la visualizzazione dei messaggi di errore può essere opportuno attivare la loro registrazione in un file apposito del servente; per fare questo occorre (sempre nel file di configurazione) cambiare la riga: |log_errors = Off ponendo il valore a On e togliere il commento (che in questo file si ottiene con il «;») alla riga: |;error_file = filename inserendo il nome del file desiderato (ad esempio ‘/var/log/php.log’) al posto di filename; il file in prescelto deve essere scrivibile dall’utente ‘www-data’ per i motivi ormai più volte spiegati. Rimanendo nella sezione di gestione degli errori del file di configurazione, può servire intervenire sulla riga della variabile ‘error_reporting’ per alterare il livello di errori che vengono segnalati; a tale proposito sono presenti nel file molte righe commentate che spiegano in dettaglio i valori che possono essere assegnati. 7.11 Inclusione di codice e scrittura di funzioni in PHP « Quando si realizzano applicazioni Web di una certa portata, può essere molto utile definire una volta per tutte alcune caratteristiche comuni a tutte le pagine del sito oppure porzioni di codice da utilizzare in punti diversi dell’applicazione stessa; per questo motivo sono presenti in PHP due funzioni con le quali si possono caricare in un uno script porzioni di codice o di sorgente HTML. Le due funzioni sono ‘include()’ e ‘require()’; entrambe caricano, al momento dell’esecuzione,il file indicato come argomento e segnalano un problema nel caso esso non esista; la ‘require()’ in tale situazione blocca l’esecuzione, la ‘include()’ invece prosegue comunque. Al fine di evitare possibili problemi dovuti alla inclusione successiva di uno stesso file, è talvolta utile usare le funzioni ‘include_once()’ e ‘require_once()’ che si comportano come le precedenti alla prima inclusione ma ignorano tentativi di caricamento successivi. I file da includere possono avere dei nomi arbitrari, ma c’è la consuetudine di assegnare ‘.html’ a file contenenti HTML e estensione ‘.inc’ a file con codice PHP; quest’ultima scelta può essere pericolosa perché, in caso di errata configurazione del servente Web, i programmi di navigazione potrebbero visualizzare il contenuto di tali file, mostrando quindi eventuali dati riservati (ad esempio i parametri di connessione ad una base di dati gestita dall’applicazione scritta in PHP). Si suggerisce quindi di assegnare l’estensione ‘.php’ ai file da includere contenenti istruzioni del linguaggio. Come esempio vediamo un tipico utilizzo della ‘include()’ in cui si effettua l’inclusione di due file HTML contenenti rispettivamente la testata e la coda che si suppongono comuni a tutte le pagine del nostro sito; evidentemente l’inclusione deve essere fatta in modo analogo in tutte le pagine interessate: |<?php |include("testata.html"); |?> Web, basi di dati e linguaggio PHP 169 |..... |(contenuto della pagina) |..... |<?php |include("coda.html"); |?> L’inclusione di codice PHP si usa molte volte per rendere disponibili, all’interno degli script, le definizioni di una serie di funzioni che essi possono utilizzare; ovviamente qui parliamo di funzioni definite dal programmatore, che vanno ad aggiungersi a quelle predefinite nel linguaggio PHP. Rendere disponibili le funzioni in modo centralizzato in uno o più file da includere permette una gestione più comoda delle modifiche nel caso in cui esse siano necessarie in molti script diversi; questo naturalmente non significa che la definizione di funzioni non possa avvenire direttamente all’interno degli script; nel proseguo, per comodità di esposizione, faremo proprio riferimento al caso in cui le funzioni siano definite nello stesso script in cui sono richiamate. Dal punto di vista del motore PHP non c’è alcuna differenza rispetto al fatto che la dichiarazione di una funzione sia nello script che la usa piuttosto che in un file esterno da includere; infatti l’inclusione provoca la copia delle istruzioni contenute in quest’ultimo nello script prima che esse siano eseguite. Una funzione PHP è caratterizzata da un nome, un insieme di parametri opzionali e, in genere, da un valore di ritorno. Vediamo un esempio di definizione di una funzione: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |<?php |function inverti($p) |{ | if ((!isset($p)) || ($p!="")) { | $ris=""; | for ($i=strlen($p);$i>0;$i--) { | $ris=$ris.substr($p,$i-1,1); | } | return $ris; | } | else { | return ""; | } |} |?> • Nella riga 2 c’è l’intestazione della funzione con la parola riservata ‘function’ seguita dal nome e dal parametro (se fossero più di uno si separano con virgole, se assenti si lasciano vuote le parentesi); • il corpo della funzione è racchiuso tra le consuete parentesi graffe (righe 3 e 14); • se il parametro contiene una stringa non vuota (riga 4), tale stringa viene invertita (righe 5-10), altrimenti non si inverte (righe 11-13); Web, basi di dati e linguaggio PHP 170 • alle righe 9 e 12 (che sono ovviamente alternative) si ha la restituzione del valore di ritorno della funzione grazie alla parola riservata ‘return’. Una possibile invocazione della funzione può essere la seguente: |<?php |$b=inverti($a); |?> La variabile $a è il «parametro attuale» passato alla funzione; il valore restituito da essa è assegnato a $b. Il passaggio dei parametri avviene per valore a meno che nella definizione della funzione non sia presente un «&» prima del nome del parametro; in tal caso il passaggio avviene per riferimento (in queste dispense si danno per scontate le conoscenze teoriche circa le due modalità di passaggio dei parametri ad una funzione). Le variabili hanno un campo d’azione o scope coincidente con la funzione in cui sono definite oppure con la pagina se sono definite fuori da qualsiasi funzione. Per fare in modo che una variabile definita fuori da una funzione sia visibile anche al suo interno, occorre usare, nel corpo della funzione, la parola riservata ‘global’ seguita dal nome della variabile; in mancanza di ciò la variabile usata nella funzione viene ad essere a tutti gli effetti «nuova» e del tutto diversa da quella, con stesso nome, definita esternamente (anche questi concetti, presenti in tutti i linguaggi di programmazione, vengono dati per noti e non sono ulteriormente approfonditi). Notiamo infine come una funzione possa anche non prevedere un valore di ritorno: potrebbe essere ad esempio una funzione che esegue solo una serie di ‘print()’, oppure una funzione che contiene solo del sorgente HTML (cosa possibile anche se non di uso frequente); in tal caso non è necessario ‘return’ al suo interno e la sua invocazione avviene senza la presenza di una assegnazione. 7.12 La funzione ‘header()’ di PHP « La funzione ‘header()’ è utile in tutti quei casi in cui si vuole alterare il comportamento del motore PHP che automaticamente provvede ad inserire, prima di qualsiasi output, l’intestazione HTTP «normale» cioè quella contenente la riga ‘Content-Type: text/html’ seguita da una riga vuota. La funzione deve essere usata prima che sia stato emesso qualsiasi output sia con le funzioni a ciò preposte del PHP sia a causa della presenza di sorgente HTML nella pagina che preceda la funzione stessa. Grazie al suo uso è possibile alterare l’intestazione per gli scopi sotto elencati: • definire tipi di contenuti diversi da ‘text/html’; ad esempio: |header("Content-Type: image/png"); permette di definire un output in formato png; • reindirizzare ad altra pagina; ad esempio: Web, basi di dati e linguaggio PHP 171 |header("Location: http://www.maxplanck.it/index.html); • costringere il browser a richiedere sempre l’ultima versione di una pagina senza usare quella eventualmente memorizzata nella memoria cache: |header("Cache-Control: no-cache, must-revalidate"); 7.13 Gestione di basi di dati MySQL e PostgreSQL con PHP « In questo paragrafo vengono prese in esame alcune delle funzioni che PHP mette a disposizione per lavorare con basi di dati MySQL e PostgreSQL; l’elenco completo si può trovare in molti documenti o siti, ad esempio in hhttp://www.php.net/manual i. Essendo le problematiche di uso di una base di dati simili qualunque sia il software di gestione, facciamo gli esempi riferendoci solo a PostgreSQL evidenziando le differenze con MySQL riguardo alle funzioni PHP da richiamare. Compito Apertura connessione ad una base di dati Selezione di una base di dati Esecuzione di una istruzione SQL Numero record restituiti da una istruzione SQL Valori estratti con una interrogazione SQL Chiusura di una connessione ad una base di dati Funzione per MySQL mysql_connect() mysql_select_db() mysql_query() Funzione per PostgreSQL pg_connect() pg_query() mysql_num_rows() pg_num_rows() mysql_fetch_array() pg_fetch_array() mysql_close() pg_close() Non vengono forniti dettagli sui parametri richiesti dalle funzioni e sui loro valori di ritorno; queste informazioni possono essere desunte dall’uso delle funzioni fatto nei prossimi esempi e poi approfondite consultando i manuali di PHP. Nell’esempio seguente viene realizzato un modulo per inserire i dati nella tabella rubrica definita in precedenza nella base di dati fulvio in PostgreSQL e in MySQL. Con lo stesso modulo è anche possibile effettuare un’interrogazione all’archivio specificando alcuni parametri; i dati da inserire o da usare per la ricerca vengono passati ad un file PHP che effettua l’operazione richiesta e crea una opportuna pagina di risposta. La gestione del modulo non è rifinita: mancano molti controlli sui campi di input e le funzionalità sono molto lontane da quelle che dovrebbero essere previste in una procedura di gestione di dati via Web «reale»; d’altra parte questo esempio è inserito solo a scopo didattico ed è quindi volutamente limitato. Il sorgente del modulo, chiamato ‘modulo.html’ è definito come segue (il file può avere estensione ‘.html’ in quanto non contiene codice PHP): |<html> |<head> |<title>Gestione tabella Rubrica</title> |</head> |<body> |<h3 style="text-align:center;">Gestione Rubrica</h3> |<form method="post" action="./phpsql.php"> Web, basi di dati e linguaggio PHP 172 |<p><b>Cognome: </b> |<input type="text" name="cognome" maxlength="25" size="20"/>** |</p> |<p><b>Nome       :</b> |<input type="text" name="nome" maxlength="25" size="20"/>** |<p><b>Data di nascita (ggmmaaaa): </b> |<input type="text" size="8" maxlength="8" name="data_nas"/> |</p> |<p><b>Indirizzo  :</b> |<input type="text" name="indirizzo" maxlength="40" size="40"/> |</p> |<p><b>Telefono  :</b> |<input type="text" name="telefono" maxlength="15" size="15"/>** |</p> |<p><b>E-mail      :</b> |<input type="text" name="email" maxlength="30" size="30"/> |</p><br/> |** = campi validi per l’interrogazione<p/> |(lasciarli <b>tutti vuoti </b>per ottenere la |<b>lista completa </b>del contenuto dell’archivio)<p/> |<input type="reset" value="Azzera"/> |<input type="submit" value="Inserisci" name="sub"/> |<input type="submit" value="Interroga" name="sub"/> |</form> |</body> |</html> Il modulo viene visualizzato come mostrato nella figura 7.51. F | igura 7.51. Il file "phpsql.php" che svolge le operazioni sulla base di dati è il seguente: 1 2 |<html> |<head> Web, basi di dati e linguaggio PHP 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 173 |<title>Interrogazione / inserimento Rubrica</title> |</head> |<body> |<?php |// include il file con le impostazioni per la connessione |require("connetti_psql.php"); |// per mysql: require ("connetti_mysql.php"); |// la variabile della connessione è $conn |$cognome=$_POST[’cognome’]; |$nome=$_POST[’nome’]; |$data_nas=$_POST[’data_nas’]; |$indirizzo=$_POST[’indirizzo’]; |$telefono=$_POST[’telefono’]; |$email=$_POST[’email’]; |$sub=$_POST[’sub’]; |// verifica se richiesto un inserimento o una interrogazione |if ($sub == "Interroga") { | echo "<p/><h3>Risultato dell’interrogazione | </h3>"; |// interrogazione: prepara la variabile alt in base ai parametri richiesti | $alt=0; | if ($cognome != "") $alt=100; | if ($nome != "") $alt += 10; | if ($telefono != "") $alt += 1; |/* L’istruzione switch permette di eseguire l’interrogazione appropriata | in base all’impostazione dei parametri */ | switch ($alt) { | case 111: | $query="SELECT * FROM rubrica WHERE cognome=’$cognome’ AND | nome=’$nome’ AND telefono=’$telefono’;"; | break; | case 110: | $query="SELECT * FROM rubrica WHERE cognome=’$cognome’ AND | nome=’$nome’;"; | break; | case 101: | $query="SELECT * FROM rubrica WHERE cognome=’$cognome’ AND | telefono=’$telefono’;"; | break; | case 100: | $query="SELECT * FROM rubrica WHERE cognome=’$cognome’;"; | break; | case 11: | $query="SELECT * FROM rubrica WHERE | nome=’$nome’ AND telefono=’$telefono’;"; | break; | case 10: | $query="SELECT * FROM rubrica WHERE nome=’$nome’;"; | break; | case 1: | $query="SELECT * FROM rubrica WHERE telefono=’$telefono’;"; | break; | default: | $query="SELECT * FROM rubrica;"; 174 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 Web, basi di dati e linguaggio PHP | } // fine switch | $richiesta=pg_query($conn,$query); |// per mysql: $richiesta=mysql_query($query); | $righe=pg_num_rows($richiesta); |// per mysql: $righe=mysql_num_rows($richiesta); | |/* se l’interrogazione ha restituito un risultato, da esso vengono | estratti i dati e vengono formattati nel documento di risposta */ | if ($righe > 0) { | $cont=0; | while ($cont < $righe) { | $riga = pg_fetch_array($richiesta); |// Per mysql: |// $riga = mysql_fetch_array($richiesta); | $v1 = $riga["cognome"]; | $v2 = $riga["nome"]; | $v3 = $riga["data_nas"]; | $v4 = $riga["indirizzo"]; | $v5 = $riga["telefono"]; | $v6 = $riga["email"]; | print ("<p/>Cognome : "); | print ($v1); | print ("<br/>Nome : "); | print ($v2); | print ("<br/>Data nas. : "); | print ($v3); | print ("<br/>Indirizzo : "); | print ($v4); | print ("<br/>Telefono : "); | print ($v5); | print ("<br/>Email : "); | print ($v6); | print ("<p/>"); | $cont++; | } // fine while | } | else { | print ("<p/>Nella base dati non presente alcuna | informazione<br/> con le caratteristiche specificate!"); | } // fine if ($righe) |} |else { |// Inserimento: il cognome deve essere indicato | if (! $cognome) | echo "<p/><B> Il cognome è obbligatorio"; | else { | $g=substr($data_nas,0,2); | $m=substr($data_nas,2,2); | $a=substr($data_nas,4,4); | if(!checkdate($m,$g,$a)) { | echo "<p/>Errore nella data\n"; | } | else { | $inser = "insert into rubrica Web, basi di dati e linguaggio PHP 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 175 | (cognome, nome, indirizzo, telefono, data_nas, email) | values (’$cognome’, ’$nome’, ’$indirizzo’, ’$telefono’, | ’$a-$m-$g’, ’$email’)"; | $ris = pg_query($conn, $inser ); |// per mysql: $ris = mysql_query($inser); | if ($ris != 1) | echo "Errore SQL in inserimento"; | else | echo "Inserimento di $cognome $nome effettuato"; | } | }// fine if (! $cognome) |} // fine if ($sub.....) |pg_close($conn); |// per mysql: mysql_close($conn); |print ("<p/>"); |print ("<hr width=\"30%\"><p/> |<a href=\"./modulo.html\">Nuova operazione</a>"); |?> |</body> |</html> Nel caso venga richiesta una interrogazione fornendo come unico parametro il cognome Paperino si ottiene la risposta riportata nella figura 7.53. F | igura 7.53. Di seguito viene mostrato il contenuto dei due file ‘connetti_psql.php’ ‘connetti_mysql.php’ utilizzati per la connessione alle rispettive basi di dati. |<?php |// imposta le variabili per la connessione al database e lo apre |$pg_database="fulvio"; |$pg_host="localhost"; |$pg_port=5432; |$pg_user="fulvio"; |$pg_psw="laurai"; |$conn=pg_connect("dbname=$pg_database host=$pg_host port=$pg_port←,→user=$pg_user password=$pg_psw"); |if (! $conn) { | echo "<p/>Connessione al database non riuscita"; e Web, basi di dati e linguaggio PHP 176 | |} |?> exit(); |<?php |// imposta le variabili per la connessione al database e lo apre |$my_database="fulvio"; |$my_host="localhost"; |$my_user="fulvio"; |$my_psw="laurai"; |$conn=mysql_connect($my_host, $my_user, $my_psw); |if (! $conn) { | echo "<p/>Connessione al database non riuscita"; | exit(); |} |else { | mysql_select_db($my_database, $conn); |} |?> Le funzioni per la connessione alle basi di dati usate in questi due file sono di facile comprensione e il ruolo dei parametri richiesti dovrebbe apparire chiaro dal nome degli stessi. Qualche parola in più può essere spesa per spiegare almeno alcune parti del listato di ‘phpsql.php’ completando i commenti già in esso presenti: • con il test sulla variabile ‘$sub’ (riga 19) si stabilisce se l’utente ha richiesto una interrogazione o un inserimento; nel primo caso viene preparata la variabile ‘$alt’ in base ai parametri di ricerca selezionati e poi viene controllata l’istruzione ‘switch’ per impostare le interrogazioni appropriate alla base di dati; • a riga 58 viene eseguita l’interrogazione: il risultato viene posto in ‘$richiesta’ e il numero di record estratti in ‘$righe’; • se sono stati estratti dei dati dall’archivio (controllo a riga 65) si esegue un ciclo con l’istruzione ‘while’ (riga 67) tante volte quante sono le righe estratte; • ad ogni iterazione si estraggono i dati di un record (righe da 68 a 76) e si stampano a video (righe da 77 a 89); • nel caso invece l’utente abbia richiesto un inserimento (riga 99 e seguenti), si controlla che sia stato indicato almeno il cognome e che la data di nascita sia valida; • superati i controlli si inseriscono in archivio i dati provenienti dal modulo (righe da 110 a 114) controllando anche che l’operazione sia conclusa positivamente (righe da 116 a 119); • a questo punto resta solo da chiudere la connessione alla base di dati (riga 123) ed emettere sul documento di risposta la stringa che funge da collegamento per tornare al modulo di partenza. 177 Capitolo 8 Script attivi, DHTML, applet, servlet (cenni) « In questo paragrafo vengono presi brevemente in esame strumenti che permettono di aggiungere logica elaborativa alle pagine Web dal lato cliente come gli ‘script attivi’ e le ‘applet Java’; in questo contesto viene anche dato un accenno al DHTML (Dynamic HTML) e alle ‘servlet’ altra espressione delle potenzialità del linguaggio Java nell’ambito della realizzazione di applicazioni Web (in questo caso dal lato servente). 8.1 JavaScript e Java « Gli script attivi sono programmi o porzioni di codice eseguiti dal lato cliente e sono molto usati per rendere più dinamiche e interattive le pagine Web. Esistono fondamentalmente due linguaggi per la scrittura di script attivi: ‘JavaScript’ creato dalla Netscape (‘JScript’ nella versione della Microsoft) e VBS CRIPT (Visual Basic Scripting edition); quest’ultimo è un linguaggio di script sviluppato da Microsoft per essere simile a ‘Visual Basic’ e si rivolge esclusivamente agli utenti che usano piattaforme Windows essendo supportato solo da Internet Explorer. JavaScript invece è supportato da tutti i browser più importanti e quindi continuiamo ad occuparci solo di quest’ultimo. Prima di proseguire è però opportuno chiarire le notevoli differenze tra i linguaggi Java e JavaScript malgrado la somiglianza dei nomi (in effetti il nome originale di JavaScript era LiveScript e fu cambiato per motivi commerciali): • Java è un linguaggio compilato (anche se non nel senso «classico» del termine, mentre JavaScript è interpretato; • le applicazioni Java possono essere anche indipendenti ed essere eseguite fuori da qualsiasi applicazione Web (si dice che Java può essere usato anche per applicazioni stand-alone, il codice JavaScript invece è sempre legato ad un documento HTML e non può essere eseguito separatamente (da questo punto di vista tra Java e JavaScript c’è la stessa differenza esistente tra Perl e PHP, se non si fa uso del pacchetto ‘php5-cli’); • le applet Java sono confinate in una ben definita regione della pagina, il codice JavaScript invece può controllare un intero documento e rispondere alla pressione di pulsanti, click del mouse o altri eventi simili; • le applet Java sono programmi separati dal codice HTML, vengono scaricati dalla rete ed eseguiti da un browser compatibile con Java; il codice JavaScript è invece generalmente incorporato all’interno del sorgente HTML ed è eseguito da un browser compatibile con JavaScript. Ciò che accomuna le applet Java e i JavaScript è invece il fatto che, per motivi di sicurezza, non possono interagire con il file system del sistema su cui è in esecuzione il programma di navigazione e quindi non possono leggere o scrivere file. Questa attenzione alla sicurezza differenzia fortemente le applet Java dalla tecnologia concorrente delle ACTIVE X (Active eXtension) di Microsoft. ActiveX non è un linguaggio di programmazione ma un formato per dati ricavato da due tecnologie Microsoft esistenti: OLE (Object Linking and Embedding) che permette ai programmi di comunicare con altre applicazioni e COM (Component Object Model) che è un formato per la definizione di interazioni tra oggetti, poi evolutosi nella tecnologia DCOM (Distributed COM) per la definizione di iterazioni remote tra oggetti. 178 Script attivi, DHTML, applet, servlet (cenni) Gli ActiveX possono essere scritti in molti linguaggi ma sono molto difficili da includere nelle pagine Web senza usare altri strumenti Microsoft, inoltre sono supportati solo da Internet Explorer e, cosa più grave, possono interagire con la macchina cliente salvando o modificando file, lanciando l’esecuzione di altri programmi, aprendo documenti ed altro ancora. Ovviamente tali strumenti, se non usati con i dovuti accorgimenti, possono rappresentare un pericolo riguardo ad esempio alla diffusione attraverso Internet di virus informatici o alla violazione della riservatezza dei dati contenuti nel computer di un utente. Attualmente gli ActiveX si sono evoluti nei cosiddetti ‘componenti WinForm’, nell’ambito del nuovo ambiente di sviluppo ‘.NET’ della Microsoft. 8.2 Script attivi « Come detto prendiamo in esame il linguaggio JavaScript per la scrittura di script attivi. L’elemento da utilizzare nel sorgente HTML è ‘<script>’ che può essere posizionato sia nella sezione ‘head’ che nella sezione ‘body’ e prevede la scrittura di istruzioni JavaScript prima del tag di chiusura ‘</script>’. Può essere opportuno «mascherare» le istruzioni JavaScript come commenti HTML per evitare che vecchi programmi di navigazione, per errore, le mostrino insieme al contenuto della pagina; ecco un esempio: |<!-- Begin script | |(istruzioni JavaScript) | |// --> Si noti che i commenti di JavaScript si inseriscono con i caratteri «//» oppure «/*» e «*/» nel caso di commenti multilinea. Il tag ‘<script>’ prevede come attributi ‘language’ e ‘type’ da valorizzare, nel caso si usi JavaScript, rispettivamente con "JavaScript" e "text/javascript". Un altro attributo è ‘src’ con il quale si può fare riferimento ad uno script esterno che viene caricato dal browser ed eseguito. |<script type="text/javascript" src="nome_file.js"></script> Il file nome_file.js deve contenere solo codice JavaScript e non necessita delle righe di commento iniziale (quella con «Begin script») e finale. Gli script esterni (da non confondere assolutamente con gli script CGI di cui abbiamo parlato in precedenza e che sono entità completamente separate ed eseguite dal lato servente) risiedono su file autonomi che hanno di solito estensione ‘.js’, contengono esclusivamente comandi JavaScript e possono essere utili in quanto permettono di modificare una volta sola il codice usato in molti documenti HTML diversi. Si tenga però conto dell’aggravio di tempo necessario a ricevere dal servente anche il file contenente lo script oltre alla pagina Web che lo richiama e del fatto che alcuni serventi Web possono non essere configurati per un corretto invio degli script esterni. Script attivi, DHTML, applet, servlet (cenni) 179 Vediamo adesso un semplice esempio in cui si usa una funzione scritta in JavaScript per far immettere all’utente il proprio nome e poi presentarlo in una pagina di risposta. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |<html> |<head><title>Esempio con JavaScript</title> |<script language="JavaScript" type="text/javascript"> | <!-- Begin script | function InsNome() { | nomeut = prompt("Inserire il proprio nome:",""); | if (nomeut == "" || nomeut == null) { | nomeut = "Utente sconosciuto"; | } | return (nomeut); | } | // --> |</script> |</head> |<body> |<div style="text-align: center;"> |<b>Esempio con JavaScript</b></div> |<p/><br/> |Il nome inserito è: |<script language="JavaScript" type="text/javascript"> | <!-- Begin script | document.write (InsNome()); | // --> |</script> |</body> |</html> Alcuni brevi commenti al listato: • nella prima parte (righe da 3 a 13) viene definita una funzione chiamata ‘InsNome()’ che non necessita di alcun parametro e serve a far inserire all’utente il proprio nome con la funzione ‘prompt()’; • il nome inserito viene poi controllato con l’istruzione ‘if’ (riga 7) nella cui condizione vediamo l’uso di ‘||’ che significa ‘or’ (in questo anche JavaScript segue le convenzioni del linguaggio c, tanto è vero che la ‘and’ si scrive ‘&&’); • il nome è valorizzato automaticamente se vuoto (riga 8); • l’ultima istruzione della funzione è ‘return’ (riga 10) che serve a restituire il risultato della funzione stessa, in questo caso il nome inserito dall’utente; • nella seconda parte (righe da 20 a 24) del documento c’è un altro blocco di codice JavaScript: in esso viene richiamata la funzione ‘InsNome()’ all’interno dell’istruzione ‘document.write’ (riga 22) con la quale il nome inserito viene scritto all’interno della pagina HTML. La visualizzazione di questo documento avviene secondo la seguente logica: • viene iniziata la visualizzazione della sezione corpo; Script attivi, DHTML, applet, servlet (cenni) 180 • viene eseguito il codice JavaScript all’interno del corpo e quindi l’istruzione di scrittura; • all’interno di quest’ultima c’è però il richiamo alla funzione ‘InsNome()’ e quindi, prima che la scrittura sia ultimata, appare una piccola maschera con la richiesta del nome per effetto dell’istruzione ‘prompt’ (vedere figura 8.4); • ad inserimento effettuato la maschera di input scompare e il nome viene visualizzato insieme al resto del contenuto del ‘body’ (vedere figura 8.5). F | igura 8.4. F | igura 8.5. 8.2.1 Attributi di evento « Nell’‘HTML 4.x’ sono disponibili una serie di attributi di evento che si possono abbinare ad immagini, collegamenti e ad altri elementi; ad ogni evento si può poi associare del codice JavaScript da eseguire nel momento in cui l’evento in questione si verifica. Vediamo quali sono gli attributi di evento iniziando da quelli maggiormente utili: • ‘onclick’: si verifica quando si clicca con il mouse su un elemento; Script attivi, DHTML, applet, servlet (cenni) 181 • ‘ondbclick’: quando si fa doppio clic con il mouse su un elemento; • ‘onkeypress’: quando un tasto viene premuto e rilasciato su un elemento; • ‘onkeydown’: quando un tasto viene premuto su un elemento; • ‘onkeyup’: quando un tasto viene rilasciato su un elemento; • ‘onmousedown’: si verifica quando si clicca con il mouse su un elemento (senza rilasciare); • ‘onmouseup’: si verifica quando si rilascia il pulsante del mouse su un elemento; • ‘onmouseover’: quando il puntatore del mouse passa su un elemento provenendo da «fuori» di esso; • ‘onmouseout’: quando il puntatore del mouse «lascia» un elemento. I seguenti attributi si possono usare solo all’interno dei moduli: • ‘onsubmit’: si verifica quando un modulo viene inviato (si usa solo nel tag ‘<form>’); • ‘onreset’: quando il contenuto di un modulo viene ripristinato (si usa solo nel tag ‘<form>’); • ‘onselect’: quando si seleziona del testo (si usa solo con i tag ‘<input>’ e ‘<textarea>’); • ‘onchange’: quando cambia il valore di un controllo (si usa solo con i tag ‘<input>’, ‘<textarea>’ e ‘<select>’). I seguenti attributi si possono usare con i moduli e con i collegamenti: • ‘onfocus’: si verifica quando un elemento viene selezionato (si dice che «riceve il fuoco») con il mouse o la tastiera; • ‘onblur’: quando un elemento perde il fuoco. Infine i seguenti attributi si possono usare solo nei tag ‘<body>’ e ‘<frameset>’: • ‘onload’: si verifica quando il navigatore termina il caricamento del documento; • ‘onunload’: quando il navigatore accede ad un altro documento. Per usare correttamente gli attributi di evento si deve definire il linguaggio di script di default del documento: a questo scopo si usa il seguente elemento ‘<meta>’: |<meta http-equiv="Content-Script-Type" content="text/javascript"/> Nel seguente esempio abbiamo l’uso di JavaScript per controllare l’input in due campi di un modulo: |<html> |<head><title>Esempio con JavaScript</title> |<meta http-equiv="Content-Script-Type" |content="text/javascript"/> 182 Script attivi, DHTML, applet, servlet (cenni) |<script language="JavaScript" type="text/javascript"> | <!-- Begin script | function Contr(campo) { | if (campo.length > 0) { | return (true); | } | else { | alert("Campo " + campo.name + " obbligatorio!"); | return (false); | } | } | // --> |</script> |</head> |<body> |<div style="text-align:center;"> |<b>Input gestito con JavaScript</b></div> |<p/><br/> |<form action="/cgi-bin/uncgi/cgi-modulo.pl" method="get"> |Cognome: <input name="cognome" type="text" |onblur="Contr(cognome)"/><p/> |Nome: <input name="nome" type="text" |onblur="Contr(nome)"/><p/> |<input type="submit" value="invio"/> |</form> |</body> |</html> Infine ecco un esempio in cui viene presentata una immagine cliccando sulla quale si apre un’altra pagina HTML: |<html> |<head><title>Finestra da aprire in JavaScript</title> |<meta http-equiv="Content-script-type" |content="text/javascript"/> |</head> |<body> |<div style="text-align:center;"> |<b>Finestra da aprire con JavaScript</b></div> |<p/><br/> |<a href="#" onclick=’window.open("esejs3b.html")’> |<img src="tux.jpg" width="80" height="80"/></a> |</body> |</html> Per verificare il comportamento del codice JavaScript, soprattutto in presenza di risultati inaspettati, è possibile utilizzare la console degli errori del programma di navigazione; in Mozilla Firefox si accede ad essa selezionando l’apposita voce nel menu «Strumenti». Script attivi, DHTML, applet, servlet (cenni) 183 8.2.2 Limiti di JavaScript « L’uso di JavaScript offre senz’altro grandi possibilità (che gli esempi appena illustrati mostrano in misura molto modesta) ma non bisogna sottovalutare alcuni aspetti negativi: • alcuni browser non supportano gli enunciati JavaScript e anche quelli che li supportano si comportano spesso in modo diverso di fronte ad una stessa istruzione; • il linguaggio ha dei limiti dovuti alle importanti ragioni di sicurezza citate in precedenza; • JavaScript viene spesso usato per creare effetti che alla lunga possono risultare noiosi e fastidiosi; alcuni utenti preferiscono addirittura disabilitare, intervenendo su opportune opzioni dei programmi di navigazione, l’esecuzione degli script. Per questi motivi è lecito aspettarsi che un documento contenente istruzioni JavaScript possa venire visualizzato da programmi di navigazione non in grado di eseguirle correttamente; è quindi opportuno prevedere, subito dopo la fine di uno script, l’uso dei tag ‘<noscript>’ e ‘</noscript>’ all’interno dei quali inserire le parti di sorgente HTML alternative allo script stesso. 8.3 DHTML « Il DHTML non è uno specifico linguaggio e neanche una qualche evoluzione dell’HTML, è invece un insieme di tecniche utilizzabili in modo coordinato per costruire pagine Web dinamiche dal lato cliente. Le tecnologie coinvolte nell’uso del DHTML sono: • un linguaggio per script attivi; • i fogli di stile; • un modello ad oggetti del documento o DOM (Document Object Model) che permette di integrare le altre due tecnologie definendo un’interfaccia di programmazione indipendente da linguaggio e piattaforma per accedere a contenuto, stile e struttura di un documento DHTML; grazie al DOM è possibile gestire e controllare ogni singolo oggetto del documento con una opportuna sintassi derivata dalla programmazione ad oggetti. Il consorzio W3C ha definito gli standard ufficiali per ognuna delle tre entità appena elencate che sono (ad agosto 2011) : • ‘ECMAScript’, per il linguaggio di scripting; è nato da JavaScript ‘1.1’ e la versione più recente è la ‘Edition 5.1’ (JavaScript ‘1.8’); • ‘CSS Level 2.1’, per i fogli di stile; il ‘CSS Level 3’ è in via di definizione ed è parzialmente supportato dai programmi di navigazione; • ‘DOM Level 3’, per il modello di documento; è l’evoluzione, proposta nel 2004, del ‘DOM Level 1’ (1998) e del ‘DOM Level 2’ (2000). Maggiori dettagli sui livelli DOM e, più in generale, sull’uso delle tecniche del DHTML, si possono reperire sui testi relativi all’argomento cui si fa riferimento nella bibliografia. 184 Script attivi, DHTML, applet, servlet (cenni) 8.4 Applet Java « Le Applet Java sono state uno dei primi strumenti usati per rendere dinamiche le pagine Web ma ultimamente hanno perso molto d’importanza a vantaggio di altri prodotti come le animazioni e i filmati ottenuti con ‘Macromedia Flash’; qui accenniamo molto brevemente al loro utilizzo. 8.4.1 Caratteristiche del linguaggio Java « Java è un linguaggio di programmazione creato nel 1995 da Sun Microsystem (forse la più agguerrita concorrente di Microsoft) e deve il suo nome a una varietà di caffè tropicale. Inizialmente ideato per essere incorporato nei microchip che governano gli elettrodomestici si è poi affermato come linguaggio di programmazione soprattutto nell’ambito del Web. Uno dei principali motivi del successo di Java in tale contesto è la sua sicurezza intrinseca: si viene infatti a creare un firewall, cioè una barriera protettiva, tra l’applicazione di rete in ambiente Java e il computer dell’utente. Quando si scaricano con un browser compatibile le applicazioni Java non ci sono rischi di comportamenti illeciti da parte di queste ultime o di infezioni virali in quanto i programmi Java vengono confinati in un apposito ambiente di esecuzione senza alcuna possibilità di accedere ad altre risorse dei computer. Altro aspetto fondamentale è quello della portabilità: un programma scritto in Java può essere eseguito indifferentemente su ogni sistema operativo e su ogni piattaforma senza necessità di modifiche. Ciò che consente a Java di essere così sicuro e portabile è il fatto che l’output della compilazione di un sorgente non è codice eseguibile ma ‘bytecode’ cioè un codice intermedio costituito da un insieme ottimizzato di istruzioni che vengono eseguite da una «macchina virtuale» detta JVM (Java Virtual Machine). Tale macchina virtuale viene emulata dall’ambiente di esecuzione di Java, attingendo alle risorse della macchina reale. Il programma eseguibile non ha alcuna possibilità di uscire dai confini dell’ambiente emulato e questo va a tutto beneficio della sicurezza. Inoltre è sufficiente realizzare sistemi run-time di Java diversi, per le varie piattaforme esistenti, affinché su tutte possano essere eseguite le applicazioni scritte in Java; in questo anche la portabilità è assicurata. L’ambiente di esecuzione (o run-time) di Java non è altro che un interprete del bytecode; il fatto che i programmi Java vengano interpretati e non compilati e poi eseguiti, comporta senza dubbio problemi a livello di prestazioni. Tali problemi però vengono largamente compensati, almeno a livello di applicazioni per il Web, dai vantaggi riguardanti la sicurezza e la portabilità. Altri motivi per cui Java è molto apprezzato dai programmatori sono: • è semplice (almeno per chi già conosce i linguaggi c e c++); • è orientato agli oggetti con un approccio molto rigoroso e usabile (il tema della programmazione ad oggetti è di una tale vastità e complessità che scoraggia qualsiasi tentativo di semplificazione e sintesi; gli interessati a tale argomento a anche a maggiori approfondimenti sul linguaggio Java possono consultare i numerosissimi testi dedicati a questi argomenti); Script attivi, DHTML, applet, servlet (cenni) 185 • è multithreaded perché consente di scrivere programmi suddivisi in thread indipendenti grazie ad una sofisticata soluzione, presente nell’ambiente di esecuzione, per la sincronizzazione multiprocesso; • è solido e affidabile sia perché fortemente «tipizzato» (le variabili devono essere dichiarate prima di essere utilizzate e non sono possibili conversioni implicite di tipo), sia perché privo di puntatori (il cui uso da parte di programmatori non esperti è spesso fonte di errori), sia perché dotato di un meccanismo automatico per la garbage collection che analizza la memoria e libera quella inutilizzata (in altri linguaggi come il c++ questa operazione è invece a carico del programmatore ed è spesso fonte di errori); • è distribuito in quanto è stato progettato appositamente per lo sviluppo di applicazioni distribuite; quindi un’applicazione Java può essere costituita da più moduli, residenti su diversi computer, in grado di operare congiuntamente attraverso una rete telematica. 8.4.2 Creazione ed esecuzione delle applet Java « Per creare una applet Java si devono compiere le seguenti operazioni: • scrivere il sorgente Java salvandolo in un file con estensione ‘.java’ e con nome uguale a quello della classe definita nel sorgente stesso (supponiamo sia ‘EseJava’); • compilare il sorgente utilizzando un compilatore Java come JDK (Java Development Kit) disponibile gratuitamente presso hhttp://java.sun.com/j2se/ i; il comando è: $ javac EseJava.java si ottiene un file con stesso nome ed estensione ‘.class’; nel nostro esempio ‘EseJava.class’; • l’eseguibile ottenuto può essere eseguito anche indipendentemente da qualsiasi pagina Web, tramite l’interprete java con il comando: $ java EseJava.class Per inserire l’applicazione Java all’interno di una pagina Web si usa l’elemento di testo ‘<applet>’ con chiusura ‘</applet>’; qualsiasi testo inserito tra questi due marcatori viene visualizzato nel caso il browser non sia in grado di eseguire le applet Java. Vediamo gli attribuiti di questo elemento (i primi tre sono obbligatori): • ‘code’, per indicare il nome del file bytecode da eseguire; • ‘width’ e ‘height’, per indicare le dimensioni in pixel dell’area rettangolare nella quale eseguire l’applet; • ‘hspace’, ‘vspace’, ‘align’, con lo stesso significato visto per il tag ‘<img>’; • ‘name’, per assegnare un nome all’applet (può servire in caso più applet debbano comunicare tra loro); • ‘codebase’, indica la directory che contiene tutti i file a cui la applet fa eventualmente riferimento per il suo funzionamento. 186 Script attivi, DHTML, applet, servlet (cenni) Un altro elemento che si può usare con le applet è ‘<param>’ che serve ad indicare un parametro da passare all’applicazione Java; si possono passare più parametri usando più volte questo tag (l’ordine con cui avviene il passaggio non è influente). Naturalmente si possono passare parametri solo ad una applet che sia stata scritta per accettarli e utilizzarli in qualche maniera; di solito le applet già pronte sono documentate ed è quindi possibile sapere se sono previsti parametri, con quali scopi e con quali nomi. L’elemento ‘<param>’ si inserisce tra ‘<applet>’ e ‘</applet>’ e prevede gli attributi ‘name’, per indicare il nome del parametro e ‘value’, per indicare il valore. Quando un documento contenente l’applet viene richiesto, quest’ultima viene inviata dal servente insieme a tutti gli altri eventuali file multimediali; se il programma di navigazione è in grado di interpretare il linguaggio, grazie alle opportune estensioni (plugins), il programma viene eseguito. Vediamo un esempio di pagina contenente una applet: |<html> |<head><title>Esempio con applet Java</title> |</head> |<body> |<div> |<b>Esempio con applet Java</b></div> |<p/><br/> |Qui sotto ci dovrebbe essere l’applet <p/> |<applet code="EseJava2.class" width="500" height="500"> |Java non va |</applet> |</body> |</html> Concludiamo con una osservazione circa il fatto che con ‘HTML 4.x’ è sconsigliato l’uso dell’elemento <applet> che dovrebbe essere sostituito da <object> di cui abbiamo parlato nel paragrafo 3.4. L’esempio precedente dovrebbe quindi essere inserito nella pagina Web in questo modo: |<object codetype="application/octet-stream" classid="java:EseJava2.class" | width="500" height="500"> |Il Browser non supporta Java |</object> Non tutti i browser, specie le vecchie versioni, accettano questa sintassi per l’inserimento delle applet; per il futuro è comunque da preferire l’uso dell’elemento ‘<object>’ in quanto permette di inserire anche applicazioni scritte in linguaggi di programmazione diversi da Java. Nella figura 8.11 viene mostrata la pagina dell’esempio precedente dove è eseguita una applet che disegna alcune figure geometriche. Script attivi, DHTML, applet, servlet (cenni) 187 F | igura 8.11. 8.5 Servlet Java e JSP « Le ‘servlet’ Java, come suggerisce il nome, hanno delle analogie con le applet, sono scritte in Java, ma vengono eseguite sul servente anziché sul cliente. Esse vengono quindi attivate dalle pagine Web esattamente come i programmi CGI, con i relativi vantaggi (indipendenza dalla piattaforma cliente, possibilità di accedere a basi di dati ecc.) ma si differenziano (in meglio) anche da questi ultimi. Infatti in presenza di normali CGI il servente HTTP esegue un processo ex-novo ogni volta che riceve una nuova richiesta di attivazione di una certa applicazione; le servlet invece vengono eseguite e conservate in un determinato spazio di memoria in modo da potere essere richiamate in modo rapidissimo al sopraggiungere di successive richieste di esecuzione. Per potere utilizzare le servlet Java occorre installare una estensione di Apache di nome ‘JServ’ (reperibile presso hhttp://www.apache.org i); al termine dell’installazione non dovrebbero essere necessarie altre operazioni o configurazioni particolari, si ricordi solo che le applicazioni servlet eseguibili devono risiedere per default nella directory ‘/home/http/servlets’ anziché in ‘/home/http/cgi-bin’. Il principale difetto delle servlet java è che esse, come le applicazioni CGI, costruiscono la risposta al loro interno definendo delle stampe virtuali in codice HTML; è quindi evidente che ogni variazione nella risposta comporta la necessità di ricompilare la servlet. Le JSP (Java Server Pages) sono un tentativo di risolvere questo inconveniente in quanto non sono altro che pagine HTML che incorporano codice Java, sempre eseguito dal lato servente. In pratica possiamo affermare che una JSP sta ad una servlet come una pagina PHP sta ad un programma CGI. Più in dettaglio le JSP rappresentano un esempio di tecnologia Java in grado di integrare in uno stesso file codice HTML, componenti riutilizzabili come i ‘Javabeans’, codice Java e script Java-like. 188 Script attivi, DHTML, applet, servlet (cenni) Una pagina JSP appare come una normale pagina HTML contenente anche tag JSP attraverso i quali si possono definire singole operazioni (ad esempio chiamate al codice esterno di un componente riusabile Javabeans) o blocchi di codice Java, chiamati ‘scriptlet’, che vengono compilati ed eseguiti quando si accede al documento. Una pagina JSP viene eseguita da un motore JSP installato sul servente Web, che non fa altro che creare dinamicamente ed in modo trasparente la servlet corrispondente. Questo permette di conservare i vantaggi delle servlet e di superare i problemi dovuti alla loro eccessiva rigidità riguardo alla creazione e alla modifica delle pagine di risposta. Ovviamente i lati positivi di una soluzione sono sempre, almeno in parte, bilanciati da quelli negativi: le JSP impongono la presenza sul servente di un compilatore Java, non necessario per le servlet, e hanno una minore velocità di esecuzione. Parte iv Nuovi sviluppi del Web « 189 190 191 Capitolo 9 Da HTML a XML (cenni) « Come abbiamo visto all’inizio di queste dispense, l’HTML deriva dall’SGML che è un linguaggio a marcatori molto più potente e complesso, disponibile da molti anni in varie forme e per vari scopi. L’SGML specifica degli identificatori di contenuto con i quali formattare il testo in modo coerente per permettere ai sistemi di gestione dei documenti di reperire facilmente le informazioni; si presta bene per la gestione di grandi quantità di dati con struttura omogenea come cataloghi, manuali tabelle statistiche. Siccome usa marcatori basati sul contenuto e non sul formato, è possibile cambiare agevolmente le regole di formattazione per inviare il documento a dispositivi di memorizzazione o di visualizzazione di tipo diverso. Nonostante questi pregi l’SGML è utilizzato solo da organizzazioni di una certa mole, come l’IBM o alcuni enti statali americani, in quanto è notevolmente complesso e difficile da usare in modo corretto. Il grande pregio dell’SGML è di non essere solo un linguaggio di formattazione o di contrassegno ma un «metalinguaggio» con il quale si possono definire linguaggi di contrassegno per oggetti molto diversi: formule matematiche, spartiti musicali, formule chimiche, ipertesti (questo è il caso dell’HTML). In questo capitolo ci occupiamo di uno di tali linguaggi, l’XML (eXtensible Markup Language), che ha ultimamente assunto un ruolo molto importante in numerosi ambiti della gestione e della comunicazione dei dati. 9.1 Limiti dell’HTML « L’HTML conserva traccia delle sue origini soprattutto nella sintassi dei marcatori ma è indubbiamente molto più semplice e molto più limitato nelle funzionalità rispetto a SGML. Malgrado questo ha svolto un ruolo importante contribuendo in modo decisivo alla diffusione e al successo delle pagine Web presso il grande pubblico. I limiti più evidenti dell’HTML sono: • la rigidità, in quanto ha un numero finito di tag; • la scarsa coerenza, in quanto prevede sia tag che indicano la natura di un elemento, come ‘<title>’, sia tag che indicano la sua rappresentazione, come ‘<font>’, sia, ancora, tag ibridi, come ‘<p align="center">’ o ‘<TABLE>’ usato per migliorare il layout del documento. E’ utile soffermarsi a questo punto sulle caratteristiche che ogni elemento di un documento possiede: • sintassi: cioè come è scritto; • semantica: cosa significa, cosa rappresenta, in che relazione sta con gli altri elementi; • rappresentazione: come appare sullo schermo o in stampa; • comportamento: come reagisce all’interazione con l’utente (vale per gli elementi dinamici). 192 Da HTML a XML (cenni) La maggior parte dei tag dell’HTML ha sintassi, semantica, rappresentazione e comportamento predefiniti e quindi i programmi di navigazione dovrebbero essere in grado di trattarli uniformemente; il condizionale dipende dal fatto, più volte evidenziato, che spesso i browser non rispettano gli standard. Come abbia o già osservato, con il passare degli anni e con la sempre maggiore diffusione, l’HTML si è via via discostato dalla sua natura iniziale di strumento per la definizione della struttura dei documenti, per divenire un linguaggio di formattazione, spostando quindi l’accento dalla semantica alla rappresentazione degli elementi. Questo è avvenuto malgrado l’introduzione dei CSS che permettono di definire la formattazione della pagina, liberando da questo onere i tag HTML e restituendoli alla loro funzione originale di descrittori del contenuto. Abbiamo quindi, da una parte un linguaggio ricco di potenzialità, molto rigoroso e versatile ma eccessivamente complesso come l’SGML, dall’altra un linguaggio molto semplice e di larga diffusione ma molto rigido e incoerente come l’HTML; in questo contesto si inserisce il linguaggio XML. 9.2 Genesi e natura dell’XML « XML è un linguaggio a marcatori derivato dall’SGML con lo scopo dichiarato di conservarne l’80% delle potenzialità con solo il 20% della complessità. E’ stato creato da un gruppo di lavoro del W3C coordinato da Tim Berners Lee e si propone come base per gli sviluppi futuri del Web. Con XML è possibile definire nuovi marcatori (questo è il motivo del termine extensible) e specificare separatamente sintassi, semantica, rappresentazione e comportamento di ogni tag. Grazie alla possibilità di definire nuovi marcatori si può affermare che anche l’XML, come l’SGML è un metalinguaggio attraverso il quale definire linguaggi da usare in vari ambiti; ad esempio già esistono: • CML (Chemical Markup Language) per la chimica; • M ATH ML (Mathematical Markup Language) per la matematica; • WML (Wireless Markup Language) per le navigazione con i telefonini. La differenza sostanziale tra HTML e XML è che quest’ultimo si usa per descrivere il significato dei dati e non il loro aspetto; questo è un grosso passo avanti che, insieme alla flessibilità e versatilità del linguaggio, apre prospettive di utilizzo al di là della rappresentazione dei dati nelle reti e nel Web. L’XML si propone infatti come possibile formato universale per la rappresentazione dei dati superando i cronici problemi di incompatibilità tra formati generati con applicazioni diverse. Si noti che il nuovo standard per i documenti di ufficio, ODF (Open Document Format) e anche il formato proprietario (non standard) di Microsoft OOXML (Office Open XML) si basano su XML, e sono solo due delle numerose tecnologie informatiche che si appoggiano a tale linguaggio. Si deve infine notare come l’XML non sia stato concepito per sostituire HTML, ma per integrarlo ed estenderlo, tanto è vero che quest’ultimo può essere reinterpretato nell’architettura XML dando origine ad un nuovo linguaggio: l’XHTML (eXtensible HTML). Da HTML a XML (cenni) 193 9.3 Documenti XML ben formati e validi « Un documento XML è un semplice file di testo, realizzabile quindi con un qualsiasi editor, contenente testo e marcatori; questi ultimi sono racchiusi fra i simboli «<» e «>» come in HTML ma con regole sintattiche molto più rigide: • ogni tag deve essere necessariamente chiuso con il relativo tag di chiusura; • non è possibile avere annidamenti con tag sovrapposti; ciò significa che la seguente porzione di codice: |<u>Testo sottolineato<b> e grassetto </u></b> che in HTML è accettata, anche se scorretta, in XML (o meglio in XHTML, dato il contesto) è del tutto vietata; • i valori degli attributi devono essere sempre racchiusi tra virgolette; • deve essere sempre presente almeno un elemento e fra gli elementi uno ed uno solo ha un ruolo speciale ed è chiamato radice; • gli altri elementi sono tutti «figli», «nipoti» e comunque discendenti della radice secondo una struttura gerarchica. Un documento che rispetti queste regole si dice «ben formato» o «conforme». Vediamo un primo esempio di documento XML (‘biblioteca.xml’) in cui si definiscono dati relativi ad una biblioteca usando dei tag definiti liberamente a questo scopo: |<?xml version="1.0" standalone="yes" ?> |<biblioteca> | <libro> | <titolo>XML - Le basi</titolo> | <autore>S. St. Laurent</autore> | <casaed>Tecniche Nuove</casaed> | <argomento>Web - XML</argomento> | <annoed>1999</annoed> | </libro>11 | <libro> | <titolo>Primi passi con Linux</titolo> | <autore>P. D’Ignazio</autore> | <casaed>Infomedia</casaed> | <argomento>S.O. - Linux</argomento> | <annoed></annoed> | </libro> |</biblioteca> L’indentatura, come al solito, serve solo ad aumentare la leggibilità del sorgente. Si deve notare che il linguaggio è case sensitive, quindi ‘<LIBRO>’ e ‘<libro>’ sono tag diversi. 194 Da HTML a XML (cenni) Nel caso di elementi vuoti si può usare la notazione abbreviata: |<annoed></annoed> può essere sostituito con |<annoed/> Nell’esempio l’elemento radice è <biblioteca> mentre la prima riga è un po’ particolare in quanto rappresenta una istruzione di elaborazione XML; tali istruzioni iniziano con i caratteri «<?» e terminano con «?>». Questa istruzione presenta due attributi: ‘version’ il cui ruolo è ovvio e ‘standalone’ il cui significato verrà chiarito più avanti. Le regole elencate in precedenza forniscono solo un primo livello di validazione; un secondo livello si ottiene grazie alla DTD (Document Type Definition) che è un testo che descrive le regole sintattiche per il documento XML e può essere contenuto in quest’ultimo oppure, più frequentemente, risiedere in un file autonomo. La seconda alternativa è ovviamente da preferire in caso di più documenti definiti con una stessa DTD in quanto permette di scrivere quest’ultima una volta sola. Un documento che rispetti le regole sintattiche di una DTD si dice «valido». Il file ‘biblioteca.xml’ deve essere così modificato nella parte iniziale: |<?xml version="1.0" standalone="yes" ?> |<!DOCTYPE biblioteca [ | <!ELEMENT biblioteca (libro+)> | <!ELEMENT libro (titolo, autore*, casaed, argomento,annoed?)> | <!ELEMENT titolo (#PCDATA)> | <!ELEMENT autore (#PCDATA)> | <!ELEMENT casaed (#PCDATA)> | <!ELEMENT argomento (#PCDATA)> | <!ELEMENT annoed (#PCDATA)> | ]> |<biblioteca> |<libro> |...... La DTD può essere esterna e residente, ad esempio, nel file ‘biblioteca.dtd’ seguente: |<?xml version="1.0" ?> |<!ELEMENT biblioteca (libro+)> |<!ELEMENT libro (titolo, autore*, casaed, argomento, annoed?)> |<!ELEMENT titolo (#PCDATA)> |<!ELEMENT autore (#PCDATA)> |<!ELEMENT casaed (#PCDATA)> |<!ELEMENT argomento (#PCDATA)> |<!ELEMENT annoed (#PCDATA)> Da HTML a XML (cenni) 195 Allora il documento ‘biblioteca.xml’ assumerebbe questo aspetto: |<?xml version="1.0" standalone="no" ?> |<!DOCTYPE biblioteca SYSTEM "biblioteca.dtd"> |<biblioteca> | <libro> |...... A questo punto dovrebbe essere chiaro il significato dell’attributo standalone: vale "no" quando almeno una definizione DTD è esterna al documento. La parola chiave ‘SYSTEM’ si usa per DTD definite localmente; in certi casi è utile usare DTD pubbliche già definite con questa sintassi: |<!DOCTYPE nome PUBLIC "nome DTD" "url DTD"> Le linee contenute nella DTD si chiamano «dichiarative», iniziano con i simboli «<!», seguiti dal tipo di dichiarativa e terminano con «>». Il nome scritto nella dichiarativa ‘!DOCTYPE’ (che ricordo essere presente anche nei sorgenti HTML) deve coincidere con la radice del documento XML a cui la DTD si riferisce; tra le parentesi quadrate è racchiusa la definizione del documento. Il tipo ‘!ELEMENT’ permette di specificare il tipo di elemento; la sua sintassi è: |<!ELEMENT nome contenuto> Nel nostro esempio il primo elemento ha nome ‘biblioteca’ e contiene uno o più di uno (questo è il significato del simbolo«+») elementi ‘libro’. A sua volta ‘libro’ contiene una sequenza di elementi (la sequenza si indica elencando gli oggetti separati da virgola) ‘titolo’, ‘autore’, ‘casaed’, ‘argomento’, ‘annoed’. Se invece si dovesse avere la scelta tra una lista di elementi, la sintassi da usare sarebbe: ‘(el1 | el2 | el3 ....)’. ‘autore’ è opzionale e può esserci una o più volte (è il significato del simbolo «*»); ‘PREZZO’ può esserci zero o una volta (è il significato del simbolo«?»). Gli altri elementi devono tutti comparire una ed una sola volta. La parola chiave ‘#PCDATA’ indica che quell’elemento è un elemento di testo. Un altro tipo di dichiarativa è ‘!ATTLIST’ che permette di indicare gli attributi di un elemento, con questa sintassi: |<!ATTLIST nome terna*> dove «terna» è composta da ‘nome-attributo tipo-attributo valore-default’; ad esempio: |<!ATTLIST argomento | id ID | nome-fig CDATA | visible (yes | no) #REQUIRED #IMPLIED "yes" > 196 Da HTML a XML (cenni) ‘ID’ indica l’identificativo del tag e permette di identificarlo univocamente nel documento, ‘CDATA’ una stringa di testo, ‘#REQUIRED’ impone che l’attributo sia specificato, ‘#IMPLIED’ indica che l’attributo non è obbligatorio. Un altro valore possibile è ‘#FIXED’ che indica un attributo con valore fisso. Il terzo tipo di dichiarativa è quello per le entità, ‘!ENTITY’ che può essere di due tipi: generale o di parametro. Le entità generali sono definite nelle DTD ma si usano poi nei documenti XML; la loro sintassi è: |<!ENTITY nome definizione> ad esempio per definire il carattere «&» si usa: |<!ENTITY amp "&"> oppure per definire un’entità associata ad un testo ripetitivo da inserire più volte in un documento: |<!ENTITY sost "Questo è il testo sostitutivo"> Il riferimento alle entità si effettua anteponendo il simbolo «&» e posponendo il simbolo «;». Quindi se in un documento si vuole inserire il testo dell’esempio sopra illustrato si scrive: |&sost; Le entità di parametro si usano esclusivamente nelle DTD esterne; la loro sintassi è: |<!ENTITY % nome definizione> Queste entità vengono di solito usate per fare riferimento a definizioni di dati contenute in file esterni. Non approfondiamo ulteriormente questi argomenti; maggiori dettagli sulle DTD si possono reperire liberamente sul sito del consorzio W3C: hhttp://www.w3.org i. 9.4 Parser ed applicazioni XML « Come abbiamo visto un documento XML contiene solo la definizione di un insieme di dati ottenuta grazie ad un set arbitrario di marcatori; sorgono a questo punto due problemi: 1. il documento deve essere analizzato e validato; 2. i dati devono in qualche modo essere gestiti (ad esempio visualizzati con un browser). Gli stessi problemi in verità esistono anche per i documenti HTML che però contengono tag appartenenti ad un insieme rigido e prefissato; quindi è bastato costruire in modo opportuno i programmi di navigazione, istruendoli su come interpretare e gestire i vari tag ed i problemi sono stati risolti. Nel caso dell’XML le cose sono un po’ più complicate; la questione della validazione viene affrontata dai parser XML che svolgono le seguenti operazioni: Da HTML a XML (cenni) 197 • analizzano il documento verificando che sia conforme e, nel caso sia specificata una DTD, valido; • lo suddividono nelle sue componenti generando una qualche forma di output specifico per la piattaforma di esecuzione. Esistono due tipi di parser: • i parser DOM, che forniscono in output una struttura gerarchica ad albero che rispecchia la struttura del documento XML; tale struttura è indipendente dalla piattaforma ed è adatta per applicazioni interattive perché viene sempre mantenuta interamente in memoria centrale; • i parser SAX (Simple Api for XML), che leggono il documento XML e generano eventi corrispondenti alla sua struttura; richiedono un uso più limitato della memoria ma impediscono di tornare indietro nell’analisi degli elementi XML; sono preferiti nel caso di filtraggio dei dati o di applicazioni lato servente nelle quali non sia richiesta la rappresentazione in memoria dei dati. Attualmente tutti i browser più recenti sono in grado di effettuare il parsing di un documento XML. Il problema della gestione dei dati viene invece affrontato dalle applicazioni XML che si occupano di manipolare le informazioni ricevute dal parser trasformandole in elementi di varia natura adatti ad essere visualizzati, stampati, memorizzati o inviati ad altri dispositivi di output. Nel caso il documento XML debba essere solo visualizzato con un programma di navigazione è possibile ricorrere semplicemente ai CSS, a patto che il browser sia almeno in grado di fare il parsing. Riprendendo l’esempio ‘biblioteca.xml’ vediamo un possibile ‘biblioteca.css’, che permette la sua visualizzazione con Firefox: |/* CSS per esempio biblioteca.xml */ |biblioteca { background-color: white} |libro { display: block; | padding-bottom: 0.4in} |titolo { display: block; | text-align: center; | color: blue; | padding: 0.2in; | font-style: italic; | font-weight: bold; | font-size: 18pt} |autore, casaed, argomento, annoed { display: block; | text-align: left; | text-indent: 3.8in; | color: black; | font-size: 12pt} Per usarlo occorre aggiungere a ‘biblioteca.xml’, come seconda linea: |<?xml-stylesheet type="text/css" href="biblioteca.css" ?> foglio di stile, Da HTML a XML (cenni) 198 Il risultato che si ottiene aprendo ‘biblioteca.xml’ con Firefox è quello mostrato nella figura 9.19. F | igura 9.19. Con i fogli CSS si può comunque solo modificare il formato degli elementi XML ed agire solo sui singoli elementi; se si vuole invece manipolare in modo più consistente un documento XML, ad esempio riordinando gli elementi o nascondendone alcuni, si deve ricorrere ai fogli XSL. L’XSL (eXtensible Style Language) comprende sia un linguaggio di trasformazione, l’XSLT (XSL Transformation), che uno di formattazione, l’XSL:FO (XSL: Formatting Object), entrambi definiti usando XML. La trattazione sull’uso di questi linguaggi nonché dei linguaggi ‘XLink’ e ‘XPointer’ per il collegamento tra documenti XML e anche dell’‘XMLSchema’ definito anch’esso in XML e alternativo alle DTD, esula dagli scopi di queste dispense; si rimanda, come al solito, all’ampia letteratura disponibile sull’argomento. 199 Capitolo 10 Programmazione distribuita « Nell’ambito delle applicazioni informatiche si è soliti distinguere tra: • architetture locali: tutti i componenti sono sulla stessa macchina; • architetture distribuite: le applicazioni e i componenti possono risiedere su nodi diversi messi in comunicazione da una rete. I vantaggi della seconda alternativa consistono principalmente nella possibilità di uso concorrente dei programmi, nella centralizzazione dei dati, nella distribuzione del carico elaborativo, il tutto al prezzo di una maggiore complessità specialmente riguardo alla comunicazione fra i vari compenenti. Le applicazioni distribuite si possono classificare in base al «grado» di distribuzione: 1. Applicazioni ‘client-server’: sono presenti solo due livelli e le operazioni sono svolte quasi interamente sul servente. Come esempio possiamo citare i classici siti Web statici o dinamici; gli strumenti per la realizzazione di tale tipo di applicazioni sono i socket di rete, la cui programmazione è possibile in vari linguaggi, tra cui ‘c’, ‘c++’, ‘Java’. Qui non viene approfondito tale argomento; per chi fosse interessato è possibile consultare la mia dispensa «Programmazione dei socket di rete in GNU/Linux» reperibile presso il sito hhttp://www.linuxdidattica.org i, oppure l’ottimo lavoro di Simone Piccardi «Guida alla programmazione in Linux» presso hhttp://gapil.truelite.it i. 2. Applicazioni ‘multi-livello’: si ha un numero maggiore di livelli, allo scopo, soprattutto, di alleggerire il carico elaborativo dei serventi. Quelle che vengono suddivise infatti sono le funzionalità del lato servente, lasciando sostanzialmente invariate le caratteristiche della parte cliente che ha il compito di ospitare l’interfaccia dell’applicazione. Un esempio di tale tipo di architettura è quello del modello ‘three-tier’ già citato nel paragrafo 7.1; ricordiamo brevemente la sua struttura in tre strati o livelli: • ‘front-end’ o ‘presentation tier’ o ‘interfaccia’; • ‘middle tier’ o ‘logica applicativa’; • ‘back-end’ o ‘data tier’ o ‘gestione dati persistenti’. Questa nomenclatura è tipica delle applicazioni Web; più in generale si può fare riferimento ad una suddivisione in tre livelli, applicabile a qualsiasi applicazione software, che è la seguente: • ‘PL’ (Presentation Layer): è la parte di visualizzazione dei dati (moduli, «controlli» di input, ecc.) necessari per l’interfaccia utente; • ‘BLL’ (Business Logic Layer): è la parte principale dell’applicazione, che definisce le varie entità e le loro relazioni indipendentemente dalle modalità di presentazione all’utente e di salvataggio negli archivi; • ‘DAL’ (Data Access Layer): contiene tutto il necessario alla gestione dei dati persistenti (sostanzialmente sistemi di gestione di basi di dati). Il numero di livelli può essere anche maggiore di tre, allo scopo di suddividere ulteriormente i compiti dei vari strati; in questo caso si parla di applicazioni ‘multi-tier’ o ‘n-tier’. Programmazione distribuita 200 3. Applicazioni ‘completamente distribuite’: in questo ogni livello non risiede più su un singolo nodo di rete ma è distribuito geograficamente; siamo in presenza di una architettura «ad oggetti», con oggetti clienti che invocano servizi offerti da oggetti serventi e con una distribuzione del carico elaborativo che diviene la massima possibile. Uno scenario di questo tipo viene talvolta denominato «Web a oggetti» e contribuisce alla diffusione della «componentistica software», termine con il quale si indica una tecnologia tendente a portare nel campo della produzione del software alcune metodologie di tipo industriale classico, migliorando o superando i metodi artigianali preesistenti. Con essa lo sviluppo delle applicazioni si scompone in due attività distinte: • creazione di componenti («semilavorati» software); • costruzione di applicazioni integrando i componenti già pronti. Il problema principale, nelle architetture completamente distribuite, è quello della definizione di regole per l’interazione fra i vari componenti; a tale proposito sono state proposte soluzioni eterogenee, che hanno portato alla nascita di tecnologie diverse per la rappresentazione degli oggetti coinvolti nelle applicazioni, e che dipendono da protocolli di comunicazione differenziati. Le tecnologie più importanti sono: • ‘CORBA’ (Common Object Request Broker Architecture): è uno standard aperto e multipiattaforma sviluppato da OMG per permettere la comunicazione fra componenti indipendentemente dalla loro collocazione sui nodi di una rete e dal linguaggio di programmazione utilizzato. OMG (Object Management Group è un consorzio creato nel 1989 da varie aziende tra cui Microsoft, HP, NCR, SUN, allo scopo di creare sistemi di gestione di architetture distribuite. • ‘RMI’ (Remote Method Invocation): è una tecnologia che consente a processi Java distribuiti di comunicare attraverso una rete; è specifica appunto del mondo Java. • ‘DCOM’ (Distributed Component Object Model): è una tecnologia informatica introdotta nel 1996 da Microsoft come contraltare di CORBA ed è basato l’estensione in rete della precedente tecnologia COM. Occore notare come RMI, nelle versioni più recenti, sia completamente compatibile con CORBA e questo riduce praticamente a due le alternative in ambito di architetture completamente distribuite. La comunicazione tra gli oggetti avviene solitamente in reti TCP/IP e può usare protocolli come l’HTTP oppure protocolli definiti appositamente come, per CORBA, l’IIOP (Internet InterOrb Protocol). L’indipendenza dal linguaggio di programmazione pone la questione di come descrivere gli oggetti CORBA o DCOM in modo che i programmi possano fare riferimento ad essi qualunque sia il linguaggio in cui sono scritti; a questo scopo è stato definito un apposito linguaggio per la definizione di interfacce, l’IDL (Interface Definition Language) per CORBA e l’MIDL (Microsoft IDL) per DCOM. La creazione di soluzioni software basate su queste tecnologie richiede risorse considerevoli (un broker CORBA ha costi molto elevati) e pone spesso problemi di funzionamento in Internet: con DCOM infatti ci sono difficoltà di dialogo con oggetti posti all’esterno di una rete locale e entrambe le tecnologie richiedono di configurare appositamente eventuali firewall presenti nella rete. Programmazione distribuita 201 A questo aggiungiamo che la stessa Microsoft considera deprecata DCOM a vantaggio del suo nuovo ambiente integrato di sviluppo .NET. Non deve quindi stupire che siano state cercate ulteriori soluzioni per la programmazione distribuita che fossero davvero universali e meno complicate delle precedenti. Una prima proposta è stata XML-RPC (XML-Remote Procedure Call) che consiste nell’uso dei servizi RPC appoggiandosi a XML come formato per la codifica delle richieste di esecuzione remota; RPC è nato per l’invocazione di subroutine residenti su computer remoti nel modello client-server e non è particolarmente adatto ad applicazioni orientate agli oggetti. Il passo avanti decisivo è stato allora quello di proporre la distribuzione in rete, non più dei componenti software, ma dei servizi che essi forniscono; questo ha portato alla definizione e all’uso dei Web Services (Servizi Web) ai quali è dedicato il prossimo capitolo. 202 Programmazione distribuita 203 Capitolo 11 Introduzione ai Web Services Con i Web Services si supera definitivamente il modello client-server classico; i servizi sono visti come «mattoni» con cui costruire altri servizi, eventualmente più complessi e sofisticati. Non è più importante conoscere quale sia il servente o fornitore e quale il cliente o fruitore di un servizio; il fruitore può a sua volta divenire fornitore aggregando servizi esistenti e creandone di nuovi. Quindi, con i Web Services, l’architettura delle applicazioni non si basa più sui «ruoli» bensì sui servizi; ciascun componente «espone», i suoi rendendoli utilizzabili agli altri componenti grazie ad appositi «registri» che contengono le informazioni sui registri pubblicati. La definizione di Web Service fornita dal consorzio W3C è la seguente: «sistema software progettato per supportare l’interoperabilità tra diversi elaboratori su di una medesima rete». Un’altra possibile definizione può essere: «servizio riutilizzabile che può essere richiamato con tecnologie Internet e che dialoga in XML». Si può subito notare che non viene fatto alcun riferimento a tecnologie specifiche (ad esempio ai linguaggi da utilizzare) ma si pone l’accento sull’uso di XML e sugli strumenti di Internet; questo per due motivi fondamentali: • XML è un linguaggio di formattazione delle informazioni nato per essere multipiattaforma e quindi permette di definire flussi di dati fruibili in qualsiasi ambiente; inoltre, a differenza di quanto accade con i flussi di comunicazione degli altri sistemi per la programmazione distribuita, la formattazione avviene in «testo puro» e questo facilita la leggibilità dei dati e le eventuali attività di debug; • l’uso dei protocolli Internet (HTTP, SMTP, FTP ecc.) permette di superare con poco sforzo la barriera dei firewall perché essi sono solitamente configurati per lasciar transitare informazioni veicolate con tali strumenti; inoltre il supporto per i protocolli di Internet è ormai diffuso nella globalità dei sistemi esistenti e fa parte del software di base di qualsiasi piattaforma. I motivi che stanno portando ad una grossa diffusione dei Web Services sono: • semplicità delle specifiche; • uso di tecnologie standard aperte (come XML e HTTP) già esistenti e diffuse; • uso concreto da parte di molte aziende; • disponibilità di numerosi strumenti per la loro realizzazione. A fronte di questi vantaggi c’è però anche qualche punto a sfavore: • solitamente è richiesto un grosso volume di traffico di dati in rete; • il carico computazionale per la codifica e decodifica dei dati è elevato; • siccome è una tecnologia «di moda», qualche volta viene usata a sproposito, anche quando si ha il completo controllo su tutte le tecnologie coinvolte in una certa applicazione e quindi non ci sono grosse esigenze di interoperabilità. « Introduzione ai Web Services 204 A causa dei primi due svantaggi appena elencati c’è la tendenza ad usare strumenti di comunicazione maggiormante ottimizzati ma proprietari (ad esempio ‘RMI’ nel mondo Java, ‘.Net Remoting’ per .Net di Microsoft) con il rischio di compromettere l’essenza stessa dei Web Services cioè l’interoperabilità. 11.1 Componenti dei Web Services « Dal punto di vista tecnologico i Web Services sono basati su: • protocollo di comunicazione: lo standard che si è affermato maggiormente è SOAP (Simple Object Access Protocol) basato su HTTP e XML; • strumenti per la descrizione dei servizi; in questo caso lo standard è costituito dal linguaggio formale WSDL (Web Services Definition Language); • strumenti per la catalogazione e la scoperta dei servizi: in questo caso si è affermato lo standard UDDI (Universal Description Discovery and Integration) che è un registry (archivio di registrazioni indicizzato) basato su XML e indipendente dalla piattaforma che permette la scoperta e l’interrogazione dei servizi offerti sul Web, delle aziende che li offrono e delle modalità di fruizione. Lo schema della figura 11.1 riassume il ruolo dei componenti appena elencati. F | igura 11.1. (..... Da completare .......) Questo capitolo sarà completato in una delle prossime versioni di questa dispensa. 205 Capitolo 12 Web 2.0 A partire dal 2004 si è iniziato a sentir parlare sempre più frequentemente di ‘Web 2.0’ relativamente ad una serie di nuovi servizi e applicazioni presenti in Internet. Il termine viene però anche usato per sottolineare una nuova fase di «vitalità» della rete, successiva alla crisi della «new economy» registrata nei primi anni del nuovo millennio, nonché per sottolineare una modalità innovativa di uso delle le risorse di Internet con un ruolo più attivo da parte degli utenti. Una possibile definizione di Web 2.0 è la seguente: «insieme delle diverse applicazioni presenti nel Web che permettono un elevato livello di interazione tra l’applicazione stessa e l’utente che ne fa uso». Occorre notare che questa terminologia è stata proposta solo per designare l’attuale stato evolutivo del Web rispetto alla condizione precedente, per la quale, in origine, non era previsto alcun «numero di versione». Dal momento però che il termine Web 2.0 è diventato di uso comune, si è pensato di «battezzare» con un numero di versione anche le fasi evolutive precedenti; abbiamo dunque: • Web 1.0: è il Web statico, diffuso nei primi anni ’90; • Web 1.5: è il Web dinamico, che ha portato, tra l’altro, alla diffusione delle applicazioni Web, all’avvento del Commercio Elettronico, all’integrazione con le basi di dati. Una osservazione importante riguarda la natura evolutiva della storia del Web: ogni «versione» non ha cancellato quanto già presente ma ha portato ampliamenti e miglioramenti soprattutto a livello di servizi per gli utenti. Dal punto di vista tecnologico le basi sono rimaste immutate e sono costituite dal protocollo HTTP e dal linguaggio HTML, risalenti al Web 1.0, cui si sono via via affiancate altre tecnologie come i CSS, i CGI, i linguaggi per le elaborazioni lato servente. Per completezza è opportuno segnalare che si parla già anche di «Web 3.0» per indicare vari possibili sviluppi futuri fra i quali quello prevalente sembra essere il ‘Web Semantico’, che qui però non approfondiamo. Tornando al Web 2.0, è utile distinguere due punti di vista, o accezioni, per la sua descrizione: • ‘accezione «filosofica» o «sociale»’: sottolinea gli aspetti innovativi dell’uso del Web che privilegiano la condivisione e la creazione dei contenuti rispetto alla loro semplice fruizione; • ‘accezione tecnologica’: descrive gli strumenti che stanno alla base del Web 2.0 e che permettono una forte integrazione, dinamicità e efficienza dei contenuti e delle applicazioni. « Web 2.0 206 12.1 Web 2.0: punto di vista «sociale» « A partire dal 2004 si hanno una serie di novità che giocano un ruolo decisivo per l’affermazione del Web 2.0: • la connettività in rete aumenta in modo considerevole grazie alla sempre maggiore diffusione della banda larga; • l’uso della rete da parte degli utenti aumenta quantitativamente ma soprattutto muta dal punto di vista qualitativo in quanto essi diventano sempre più «coautori» dei contenuti e non più semplici fruitori; vediamo alcuni esempi: – diffusione di strumenti di autoproduzione e pubblicazione sul Web di contenuti digitali, (soprattutto foto e video) come youtube.com e flickr.com; – esplosione del fenomeno delle comunità in rete, come facebook.com, twitter.com, last.fm e molte altre; esse possono essere considerate le discendenti delle BBS (Bullettin Board System) e dei Newsgroup, affermatisi in rete in epoca «pre-Web», ma con livelli di diffusione e partecipazione enormemente superiori; – affermazione dei siti personali e dei ‘Blog’, facilmente gestibili e aggiornabili, con conseguente nascita del cosiddetto «Citizen Journalism» o «Giornalismo Partecipativo» – nascita delle enciclopedie collettive in rete (come ‘Wikipedia’) in cui i contenuti sono inseriti dagli utenti; la loro affermazione, pur positiva sotto molti punti di vista, comporta però, al pari di altri fenomeni nuovi, come il Giornalismo Collettivo, problematiche di tipo deontologico e di attendibilità; • si affermano le Web Applications (applicazioni modulari, interoperabili e di estrema semplicità d’uso) dotate di sempre maggiori possibilità di integrazione o convergenza, accompagnate dal grande successo di piattaforme per la fruizione dei contenuti alternative al tradizionale Computer; anche in questo caso possiamo illustrare qualche esempio: – grazie al meccanismo del ‘Mashup’ l’utente può usufruire dei servizi di più applicazioni Web che lavorano in «sinergia» come nel caso del sito flickr.com che permette di condividere foto indicando il luogo dello scatto grazie all’integrazione con maps.yahoo.com; altro esempio simile è quello di housingmaps.com che, negli Stati Uniti, integra gli annunci immobiliari di craiglist.com con le mappe di maps.google.com in modo fa fornire l’ubicazione delle abitazioni oggetto degli annunci; – negli ultimi anni è letteralmente esploso il fenomeno delle «Apps» per i dispositivi ‘iPhone’ e ‘iPad’della ‘Apple’ e parallelamente per la piattaforma ‘Android’, proposta da ‘Google’, basata su Linux e utilizzata in numerosi smartphone e dispositivi mobili di vari altri produttori. Sicuramente in questi anni un ruolo fondamentale per l’affermazione del Web 2.0 è stato svolto da ‘Google’, sia per l’importanza dei servizi offerti da questa azienda, che vanno al di là del «tradizionale» motore di ricerca e che hanno rivoluzionato il mondo delle applicazioni Web, sia per la proposta della piattaforma ‘Android’, sia infine, per il lancio di A JAX, che come vedremo tra breve, è uno dei pilastri tecnologici su cui si basano le applicazioni del Web 2.0. Web 2.0 207 Tali applicazioni vengono spesso definite «beta», cioè non definitive, e siccome la loro evoluzione è continua, anche grazie all’interazione con gli utenti e fra gli utenti, si può prevedere che difficilmente raggiungeranno uno stato consolidato; questa situazione viene illustrata denominando le applicazioni del Web 2.0 come «never ending beta applications». 12.2 Web 2.0: punto di vista tecnologico « La novità tecnologica più importante degli ultimi anni per il Web è stata A JAX (Asynchronous JavaScript And XML). Questo acronimo è stato proposto per la prima volta nel 2005 in un articolo del Jesse James Garrett, intitolato: «Ajax: A New Approach to Web Applications», in cui spiega il nuovo approccio per le applicazioni Web che ‘Google’ aveva iniziato ad usare (e che ancora usa), nelle piattaforme ‘Google Suggest’ e ‘Google Maps’. Secondo la definizione di Garrett Ajax non è una nuova tecnologia, ma un aggregato di più tecnologie già esistenti, le quali, se usate in sinergia, permettono di aumentare l’interazione, la dinamicità e l’efficienza delle applicazioni Web. Grazie anche ad Ajax si è avuta una massiccia evoluzione e diffusione delle cosiddette RIA (Rich Internet Application) progettate e realizzate come le corrispondenti applicazioni «desktop» e che forniscono gli stessi servizi di queste ultime, pur essendo sulla rete (Web based) e quindi usabili dagli utenti in modo diffuso e decentrato. Il concetto di «ricchezza» in queste applicazioni va interpretato sotto due punti di vista: • ricchezza del modello dati; significa che dal lato del cliente è possibile rappresentare e gestire strutture dati più complesse, riducendo in questo modo il carico elaborativo dal lato del servente e interagendo con quest’ultimo in modo più snello ed essenziale grazie alla comunicazione asincrona; le risposte elaborate dal servente possono essere parti di pagine e non più necessariamente intere pagine HTML (pagine modulari); • ricchezza dell’interfaccia; significa avere interfacce che sono esteticamente e funzionalmente simili a quelle delle tradizionali applicazioni «desktop». Nei prossimi paragrafi vengono forniti alcuni dettagli relativi all’uso di Ajax. 12.3 Generalità su Ajax « Ajax si basa sui seguenti elementi: 1. presentazione standard utilizzando XHTML e CSS; 2. interazione con l’utente e visualizzazione dinamica dei contenuti tramite DOM; 3. scambio e manipolazione delle informazioni utilizzando preferibilmente XML e XSLT; 4. richiesta delle informazioni in maniera asincrona tramite l’oggetto JavaScript ‘XMLHttpRequest’; 5. uso di JavaScript per «legare» insieme tutte le tecnologie sopracitate. Web 2.0 208 Con Ajax si può superare il modello classico «richiesta/risposta» delle applicazioni Web, effettuando chiamate asincrone verso il servente. Ricordiamo infatti che il flusso tradizionale delle applicazini Web, secondo il protocollo HTTP, è il seguente: • richiesta pagina da parte del cliente al servente; • elaborazione richiesta ed invio risposta da parte del servente; Qualsiasi aggiornamento dei dati presentati nella risposta presuppone l’invio di ulteriori richieste da parte del cliente. Ricordiamo inoltre che in questo tipo di applicazioni il ‘front-end’ (moduli HTML e risposte) è separato anche fisicamente dalla ‘logica applicativa’ (oltre che dal ‘back-end’), cosa che non avviene nei normali programmi «desktop» nei quali tutte le componenti coesistono in un’unica unità elaborativa. Questo rende il comportamento delle applicazioni Web particolarmente complesso, lento e macchinoso. La novità di Ajax consiste nella possibilità di effettuare chiamate asincrone verso il servente, utilizzando codice JavaScript, anche senza che l’utente faccia una richiesta esplicita tramite il programma di navigazione. Così è possibile ad esempio aggiornare alcuni dati presenti sulla pagina senza necessità di ricaricarla interamente. Gli schemi delle figure 12.1 e 12.2 illustrano il comportamento delle applicazioni Ajax paragonandolo a quello delle applicazioni Web tradizionali. F | igura 12.1. Web 2.0 209 F | igura 12.2. Il cardine di tutto il meccanismo è l’oggetto JavaScript ‘XMLHttpRequest’ grazie al quale si effettuano richieste sincrone e asincrone sfruttando il protocollo HTTP. Lo scambio di dati che si può realizzare con questo oggetto sarebbe da effettuare, secondo chi ha coniato l’acronimo Ajax, usando il formato XML; in realtà ciò non è assolutamente obbligatorio e si possono utilizzare molti altri formati fra cui il testo puro. Grazie ad Ajax la pagina Web può divenire un’entità attiva, dinamica e fortemente responsiva con un comportamento interattivo simile a quello delle applicazioni «desktop»; ecco quindi che sempre più spesso anche nel campo delle applicazioni Web si sente parlare di oggetti come «controlli», «eventi», «finestre» ed altri, tipici della programmazione tradizionale. Con Ajax la navigazione può essere più piacevole, dinamica e coinvolgente per l’utente; inoltre buona parte dell’elaborazione viene spostata nel cliente alleggerendo il carico del servente e diminuisce anche la quantità di dati da scambiare non essendo più necessario richiedere intere pagine. Ci sono però anche alcuni svantaggi o problemi da tenere in considerazione: • le applicazioni Ajax non garantiscono compatibilità tra i diversi browser; • è necessario che JavaScript sia attivo nel cliente e questo rende necessarie alternative che consentano il corretto funzionamento dell’applicazione nel caso ciò non sia vero; 210 Web 2.0 • il pulsante «indietro» del programma di navigazione diventa inutile in quanto le applicazioni Ajax possono aggiornare di volta in volta una singola porzione di documento; • l’inserimento di segnalibri è praticamente impossibile perché i contenuti delle pagine Ajax sono dinamici; • per lo stesso motivo anche l’indicizzazione da parte dei motori di ricerca può essere molto difficoltosa; • l’accessibilità e l’usabilità dei contenuti può essere compromessa; si pensi ad esempio alla necessità da parte di ipovedenti o ciechi di disabilitare o sovrascrivere il foglio di stile della pagina compromettendo il corretto funzionamento di Ajax che diventerebbe solo un ulteriore intralcio per la navigazione. 12.4 L’oggetto XMLHttpRequest « Storicamente l’oggetto XMLHttpRequest trova origine nel pacchetto di supporto a XML introdotto da ‘Microsoft’ nel browser ‘Internet Explorer 5’ e precisamente da un componente ‘Activex’ chiamato ‘XMLHttp’. Successivamente anche tutti gli altri programmi di navigazione hanno seguito questa strada, privilegiando però il linguaggio JavaScript e adottando l’oggetto ‘XMLHttpRequest’. Dalla versione ‘7’ del suo browser, anche ‘Microsoft’ supporta questo oggetto e questo è sicuramente un beneficio per gli sviluppatori che non sono più costretti a usare oggetti diversi per creare applicazioni Ajax funzionanti con i più diffusi programmi di navigazione. Per usare l’oggetto ‘XMLHttpRequest’ occorre compiere le seguenti operazioni fondamentali: • istanziare l’oggetto; • eseguire il metodo ‘open()’ in modo da inizializzarlo; • associare la funzione che deve gestire la risposta del servente e che prende il nome di ‘callback function’; • effettuare la richiesta al servente Vediamole in dettaglio: • per istanziare l’oggetto basta scrivere: |var oggXHR = new XMLHttpRequest(); • il metodo ‘open()’ prevede come parametri il tipo di richiesta (get o post), l’indirizzo URL a cui inviarla, una variabile booleana da impostare a true affinché la richiesta sia asincrona (con false si ha invece una richiesta sincrona) e opzionalmente un nome utente e relativa password; avremo quindi, ad esempio: |var oggXHR = new XMLHttpRequest(); |oggXHR.open("get","esempio.xml", true); • la ‘callback function’ (necessaria solo nel caso di chiamate asincrone) viene uti- Web 2.0 211 lizzata per ricevere le notifiche sullo stato di avanzamento della richiesta, in modo che il codice JavaScript possa comportarsi di conseguenza e viene associata all’evento ‘onreadystatechange’. Nell’esempio che segue si suppone che la funzione si chiami funzCallback: |var oggXHR = new XMLHttpRequest(); |oggXHR.open("get","esempio.xml", true); |oggXHR.onreadystatechange = funzCallback; Per utilizzare al meglio tale funzione è opportuno conoscere almeno le principali proprietà dell’oggetto XMLHttpRequest, riassunte nella tabella seguente: Proprietà readyState responseText responseXML status statusText Descrizione valore intero che indica lo stato della richiesta: 0 = non ancora aperta (corrispondente alla costante UNSENT dell’ogetto XMLHttpRequest) 1 = aperta ma non ancora partita (OPEN) 2 = inviata (SENT) 3 = risposta in caricamento (LOADING) 4 = completata (DONE) risposta del servente in formato stringa risposta del servente elaborata dal parser XML e convertita in oggetto DOM valore numerico dello stato HTTP (ad esempio 404) stringa associata allo stato (ad esempio "Not Found") Naturalmente la funzione di callback ha a disposizione i dati della risposta e anche i valori delle altre proprietà come ‘status’ e ‘statusText’ solo nel momento in cui il valore della variabile ‘readyState’ è 4. Vediamo una possibile funzione di callback che effettui qualche controllo sull’esito della richiesta: |function funzCallback() { | try { | if (oggXHR.readyState == 4) { // risposta completa | if (oggXHR.status == 200) { | alert (’Test Ajax OK’); | } | else { | alert (’Errore HTTP’); | } | } | } catch (e) { | alert (’Errore nella funzione di callback: ’ + e); | } |} • l’invio della richiesta si effettua con il metodo ‘send()’ che ha come parametro il corpo della richiesta (necessario solo se il tipo di richiesta è post). Web 2.0 212 12.4.1 Chiamate di tipo get « Vediamo adesso un listato che riepiloga quanto illustrato finora eseguendo una richiesta di tipo get con lo scopo di ricevere il file ‘eseAjax.html>’ al caricamento della pagina Web in cui il codice JavaScript è inserito: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |<html> |<head><title>Esempio Ajax</title> |<script language="JavaScript" type="text/javascript"> | <!-- Begin script | var oggXHR = new XMLHttpRequest(); | function funzCallback() { | try { | if (oggXHR.readyState == 4) { // risposta completa | if (oggXHR.status == 200) { | risTesto = oggXHR.responseText; | document.getElementById(’carica’).innerHTML = risTesto; | } | else { | alert (’Errore HTTP’); | } | } | } catch (e) { | alert (’Errore nella funzione di callback: ’ + e); | } | } | function provaAjax() { | oggXHR.onreadystatechange = funzCallback; | oggXHR.open("get","eseAjax.html", true); | oggXHR.send(); | } | // --> |</script> |</head> |<body onLoad="provaAjax()";> |<div id="carica" style="text-align:center;"> |Ajax non funziona! |</div> |</body> |</html> Al fine di verificare il funzionamento di quanto esposto, è opportuno ricordare che Ajax si appoggia comunque al protocollo HTTP e quindi la pagina deve essere richiesta ad un servente Web (eventualmente http://localhost) e non aperta con file:// o con la scelta «Apri file» del menu «File». Soffermiamoci sulle parti salienti del listato: • alla riga 5 c’è l’istanziazione di XMLHttpRequest con la variabile oggXHR definita globalmente in modo che sia visibile in tutte le parti del codice JavaScript; • il comportamento della funzione di callback funzCallback dovrebbe essere abbastanza chiaro: in particolare si notino le righe 10 e 11 nelle quali, in caso di richiesta esaudi- Web 2.0 213 ta positivamente, viene acquisito il contenuto della pagina ricevuta e inserito come testo HTML dell’elemento inviduato dall’identificativo carica; • tale elemento è una sezione (‘<div>’) del corpo della pagina, definita alla riga 30; • da riga 21 a riga 25 troviamo la funzione che definisce la richiesta e la invia con il metodo ‘send’; • tale funzione viene richiamata al caricamento di questa pagina grazie all’evento ‘onLoad’ definito a riga 29; • se va tutto bene si vede apparire sul browser il contenuto della pagina eseAjax.html, altrimenti la scritta definita a riga 31. 12.4.2 Chiamate di tipo post « Con una chiamata di tipo post si può richiedere una risposta al servente inviandogli contemporaneamente dei dati, da inserire nel corpo della richiesta, come argomento del metodo ‘send’. Affinché l’invio dei dati funzioni correttamente è necessario che: • venga impostata una intestazione della richiesta con il metodo ‘setRequestHeader’ nella quale si specifica la chiave Content-Type e il valore application/x-www-form-urlencoded in modo da simulare l’invio dei dati da un modulo HTML; |oggXHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); • si codifichino le informazioni nel modo previsto cioè con «codifica URL», (della quale abbiamo parlato nel paragrafo 6.9); per effettuare tale codifica può essere usata la funzione JavaScript ‘encodeURIComponent()’. Come esempio realizziamo un modulo con un singolo campo in cui inserire il nome di una località che viene inviato con una chiamata di tipo post al servente; la risposta sarà il corrispondente codice di avviamento postale da far apparire a fianco del campo di input. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |<html> |<head><title>Esempio2 AJAX</title> |<script language="JavaScript" type="text/javascript"> | <!-- Begin script | var oggXHR = new XMLHttpRequest(); | function funzCallback() { | try { | if (oggXHR.readyState == 4) { // risposta completa | if (oggXHR.status == 200) { | risTesto = oggXHR.responseText; | document.getElementById(’cap’).innerHTML = risTesto; | } | else { | alert (’Errore HTTP’); | } | } | } catch (e) { Web 2.0 214 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | | | | | | | alert (’Errore nella funzione di callback: ’ + e); } } function provaAjax() { oggXHR.onreadystatechange = funzCallback; oggXHR.open("post","elabora.php", true); oggXHR.setRequestHeader("Content-Type",←- ,→"application/x-www-form-urlencoded"); | var dati = "loc=" + ←,→encodeURIComponent(document.forms.modulo1.loc.value); | oggXHR.send(dati); | } | function pulisci() { | document.getElementById(’cap’).innerHTML = ""; | } | // --> |</script> |</head> |<body> |<div style="text-align:center;font-weight:bold;"> |Ricerca CAP |<p/> |<form id="modulo1"> |<input type="text" name="loc"/> |<span id="cap"></span> |<p /><br /> |<input type="button" value="Trova CAP" onClick="provaAjax();"/> |<input type="reset" value="Pulisci" onClick="pulisci()"/> |</form> |</body> |</html> Rispetto all’esempio precedente le differenze principali sono alle righe da 23 a 26 dove viene effettuata la chiamata di tipo post, viene impostata l’intestazione della richiesta e viene fatto l’invio passando il parametro contenente il dato raccolto dal campo di input del modulo. Il dato ricevuto in risposta (righe 10 e 11) viene inserito nel modulo a fianco del campo di input (riga 40). Il piccolo modulo usato nell’esempio viene gestito con funzioni JavaScript, sia per l’invio della richiesta (riga 42) che per la pulizia dei dati (riga 43). Per l’elaborazione dal lato del servente si predispone uno script PHP, ‘elabora.php’ che effettua l’associazione tra codice e località usando un piccolo vettore associativo contente nomi e codici delle località Milano, Treviso e Roma (naturalmente questa soluzione non è realistica ed è proposta solo a titolo di esempio). |<?php |$tab[’Milano’]="20100"; |$tab[’Roma’]="00100"; |$tab[’Treviso’]="31100"; |$nomeLoc=$_POST[’loc’]; |$ris=$tab[$nomeLoc]; |if ($ris=="") { | $ris="Non trovato"; Web 2.0 215 |} |print ("$ris"); |?> Nelle due figure 12.12 e 12.13 vediamo il comportamento della pagina appena realizzata. F | igura 12.12. F | igura 12.13. 12.4.3 Chiamate sincrone « Anche se non è importante nell’ambito di Ajax, il metodo XMLHttpRequest permette di effettuare anche chiamate sincrone; basta usare il metodo ‘open’ passando come terzo parametro il valore false. In questo caso non è necessario gestire l’evento ‘onreadystatechange’ e quindi non serve la funzione di callback. |<html> |<head><title>Esempio Ajax sincrono</title> |<script language="JavaScript" type="text/javascript"> | <!-- Begin script | function provaAjax() { | var oggXHR = new XMLHttpRequest(); | oggXHR.open("get","eseAjax.html", false); | oggXHR.send(); | risTesto = oggXHR.responseText; | document.getElementById(’carica’).innerHTML = risTesto; 216 Web 2.0 | } | // --> |</script> |</head> |<body onLoad="provaAjax()";> |<div id="carica" style="text-align:center;"> |Ajax non funziona! |</div> |</body> |</html> Questo esempio produce lo stesso risultato di quello «asincrono» mostrato nel paragrafo 12.4.1 con la differenza che il cliente, rimane bloccato in attesa della risposta per tutto il tempo necessario al servente ad elaborare e inviare la risposta stessa. Si ha quindi un comportamento del tutto analogo a quello «classico» delle applicazioni Web tradizionali con tutte le conseguenze che da ciò discendono dal punto di vista della logica elaborativa e dei tempi di risposta della procedura. 12.4.4 Esempio di gestione di un modulo con Ajax « Per concludere questa rapida carrellata su Ajax vediamo un esempio un po’ più complesso in cui viene gestito un modulo di immissione dati su una macchina cliente grazie ad una interazione «continua» con il servente che deve ricevere e controllare le informazioni. In particolare supponiamo che il modulo serva a registrarsi ad un qualche tipo di servizio e richieda obbligatoriamente un nome utente, una password con relativa conferma, un indirizzo di posta elettronica. La logica di funzionamento dell’interfaccia è la seguente: • il nome utente non deve essere già esistente; • la password deve essere lunga almeno 6 caratteri; • l’indirizzo di posta deve essere sintatticamente corretto (secondo quanto stabilito nell’esempio del paragrafo 7.7) e non essere già esistente; • i controlli sui campi avvengono quando ognuno di essi perde il «focus» e prevedono la visualizzazione di un riscontro positivo o di un breve messaggio di errore, a fianco del campo stesso; • l’acquisisione definitiva dei dati da parte del servente avviene alla pressione di un apposito tasto, previo controllo sull’effettivo inserimento di tutti i campi. Anche stavolta il motore applicativo sul servente, scritto in PHP, viene solo abbozzato utilizzando dei vettori associativi con dati predefiniti e non, come sarebbe logico, archivi gestiti dal ‘back-end’ della procedura. A differenza degli esempi dei paragrafi precedenti, la parte relativa all’interfaccia viene realizzata scrivendo le funzioni JavaScript in un file separato dal file HTML. Analogamente agli esempi precedenti, non viene invece curato l’aspetto esteriore della pagina e dei messaggi di risposta; quindi l’uso dei CSS è ridotto al minimo indispensabile. Iniziamo mostrando il sorgente HTML con il modulo di immissione dei dati: Web 2.0 217 |<html> |<head><title>Modulo AJAX</title> |<style type="text/css"> |div.titolo { font-weight: bold; | } |div#risposta { | color: blue; | } |.campo { position: absolute; | left: 160px; | } |.campoCheck { position: absolute; | left: 370px; | color: blue; | } |</style> |<script language="JavaScript" type="text/javascript" src="moduloAjaxFunz.js"> |</script> |</head> |<body> |<div class="titolo"> |Immissione dati |</div> |<p/> |<form id="modulo1"> |Nome utente: <input class="campo" onblur="controlla(’nomeUtente’, ’1’);" |type="text" name="nomeUtente" id="nomeUtente"/> |<span class="campoCheck" id="campoCheck1"></span> |<br /> |Password: <input class="campo" onblur="controlla(’psw’, ’2’);" |type="password" name="psw" id="psw"/> |<span class="campoCheck" id="campoCheck2"></span> |<br /> |Ripeti password: <input class="campo" onblur="controlla(’psw2’, ’3’);" |type="password" name="psw2" id="psw2"/> |<span class="campoCheck" id="campoCheck3"></span> |<br /> |Indirizzo di posta: <input class="campo" onblur="controlla(’indPosta’, ’4’);" |type="text" name="indPosta" id="indPosta"/> |<span class="campoCheck" id="campoCheck4"></span> |<p /><br /> |<input type="button" value="Conferma" onClick="inviaDati();"/> |<input type="reset" value="Pulisci" onClick="pulisci(’4’)"/> |</form> |<div id="risposta"> |</div> |</body> |</html> Importante notare, all’interno del modulo, il richiamo della funzione controlla alla perdita del «focus» di ogni campo, la definizione delle aree per accogliere i messaggi di risposta di tale funzione (con uso del tag ‘<span>’), il richiamo delle funzioni inviaDati e pulisci rispettivamente alla pressione dei pulsanti di conferma e di reset. Web 2.0 218 Il file con le funzioni JavaScript e le chiamate Ajax è il seguente: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |var flagErr=0; |function controlla(campo, numCampo) { | oggXHR = new XMLHttpRequest(); | oggXHR.onreadystatechange = function() { // funzione di callback | try { | if (oggXHR.readyState == 4) { | if (oggXHR.status == 200) { | campoCheck = ’campoCheck’ + numCampo; | risTesto = oggXHR.responseText; | document.getElementById(campoCheck).innerHTML = risTesto; | if (risTesto!=’OK!’ && risTesto!=’’) { | flagErr=1; | } | else { | flagErr=0; | } | if (numCampo == ’3’ && risTesto != ’OK!’) { | document.getElementById(campo).value =""; | } | } | else { | alert (’Errore HTTP’); | } | } | } catch (e) { | alert (’Errore nella funzione di callback: ’ + e); | } | } // fine funzione di callback | oggXHR.open("post","moduloAjax.php", true); | oggXHR.setRequestHeader("Content-Type",←,→"application/x-www-form-urlencoded"); | var dati = campo + ’=’ +←,→encodeURIComponent(document.getElementById(campo).value); | if (numCampo == 3) { | dati = dati + ’&psw=’ + document.getElementById(’psw’).value; | } | oggXHR.send(dati); |} |function pulisci(num) { | flagErr=0; | for (i=1;i<=num;i++) { | campoCheck=’campoCheck’ + i; | document.getElementById(campoCheck).innerHTML = ""; | } |} |function inviaDati() { | if (flagErr==1) { | exit; | } | oggXHR = new XMLHttpRequest(); | oggXHR.onreadystatechange = function() { // funzione di callback | try { | if (oggXHR.readyState == 4) { Web 2.0 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | | | | | | | | | | | | | | 219 if (oggXHR.status == 200) { risTesto = oggXHR.responseText; document.getElementById(’risposta’).innerHTML = risTesto; } else { alert (’Errore HTTP’); } } } catch (e) { alert (’Errore nella funzione di callback: ’ + e); } } // fine funzione di callback oggXHR.open("post","moduloAjaxInvio.php", true); oggXHR.setRequestHeader("Content-Type",←- ,→"application/x-www-form-urlencoded"); | var dati = ’nomeUtente=’ + ←,→encodeURIComponent(document.getElementById(’nomeUtente’).value); | dati = dati + ’&psw=’ +←,→encodeURIComponent(document.getElementById(’psw’).value); | dati = dati + ’&psw2=’ +←,→encodeURIComponent(document.getElementById(’psw2’).value); | dati = dati + ’&indPosta=’ +←,→encodeURIComponent(document.getElementById(’indPosta’).value); | |} oggXHR.send(dati); Servendoci della numerazione delle righe commentiamo i punti più importanti del listato: • la funzione controlla (riga 2) viene richiamata passando come parametri il nome del campo da controllare e il numero progressivo dello stesso; • la sua funzione di callback (righe da 4 a 28) è scritta direttamente all’interno e non separatamente come negli esempi precedenti; • alla riga 31 viene preparato il dato da passare allo script ‘moduloAjax.php’ sul servente grazie al nome (parametro campo) e al rispettivo valore (acquisito con la funzione JavaScript ‘getElementById()’); • se il campo da controllare è la seconda password vengono passate entrambe le password per permettere il controllo sulla loro uguaglianza (righe da 32 a 34); • nella funzione di callback, alla riga 8, viene impostata il nome dell’area in cui far apparire il messaggio di risposta; • nelle righe dalla 11 alla 16 si imposta il flag flagErr in base al fatto che il campo sia errato o no; tale flag serve poi nella funzione inviaDati; • se il terzo campo è errato, cioè se la seconda password non coincide con la prima, si pulisce la seconda password (righe da 17 a 19); • la funzione pulisci elimina il testo di output dalle relative aree; il parametro che riceve indica il numero di aree da pulire (righe da 39 a 42); • la funzione inviaDati agisce solo se il relativo pulsante è stato attivato in assenza di errori sui campi (righe da 45 a 47) e prosegue passando tutti i dati allo script ‘moduloAjaxInvio.php’ sul servente (righe da 66 a 70); 220 Web 2.0 • nella sua funzione di callback si ha la visualizzazione del messaggio di risposta proveniente da tale script (riga 54). Vediamo infine i due listati PHP rispettivamente per il controllo dei singoli campi e per l’elaborazione finale dei dati inviati: |<?php |$ute[’pippo’]="[email protected]"; |$ute[’pluto’]="[email protected]"; |$ute[’paperino’]="[email protected]"; |$uteRev=array_flip($ute); |$nomeUtente=$_POST[’nomeUtente’]; |$psw=$_POST[’psw’]; |$psw2=$_POST[’psw2’]; |$indPosta=$_POST[’indPosta’]; |if (! empty($nomeUtente)) { | $ris="OK!"; | if ($ute[$nomeUtente]!="") { | $ris="Errore: utente esistente"; | } |} |if (! empty($psw)) { | $ris="OK!"; | if (strlen($psw) < 6) { | $ris="Errore: password troppo corta"; | } |} |if (! empty($psw2)) { | $ris="OK!"; | if ($psw != $psw2) { | $ris="Errore: password diverse"; | } |} |if (! empty($indPosta)) { | $ris="OK!"; | if (!preg_match("/^[^@ ]{2,}@[^@ \.]+\.[^@ \.]{2,}$/",$indPosta)) { | $ris="Errore: ind. posta non valido"; | } | else { | if ($uteRev[$indPosta]!="") { | $ris="Errore: ind. mail esistente"; | } | } |} |print ("$ris"); |?> |<?php |$nomeUtente=$_POST[’nomeUtente’]; |$psw=$_POST[’psw’]; |$psw2=$_POST[’psw2’]; |$indPosta=$_POST[’indPosta’]; |if (empty($nomeUtente) || empty($psw) || empty($psw2) || empty($indPosta)) { Web 2.0 221 | $ris="Errore: tutti i campi sono obbligatori!"; |} |else { | // eventuali istruzioni per la memorizzazione dei dati | $ris="Dati ricevuti!"; |} |print ("$ris"); |?> Data la banalità delle elaborazioni svolte, non è necessario fornire grosse spiegazioni sul comportamento dei due script; si noti solo l’uso della funzione ‘array_flip’ grazie alla quale si ha a disposizione un vettore associativo in cui è scambiato il ruolo dei valori con quello delle chiavi (la cosa è possibile solo se anche i valori, oltre alle chiavi, sono univici) e che viene usato per il controllo di non esistenza dell’indirizzo di posta. Per il resto sottolineiamo, ancora una volta, le semplificazioni presenti sia nello script dei controlli che in quello per l’invio dai dati, nel quale, tra l’altro, manca del tutto la parte di elaborazione e memorizzazione dei dati ricevuti. Le due figure 12.19 e 12.20 mostrano sommariamente il funzionamento dell’interfaccia nel caso ci sia un campo errato e in quello in cui l’invio dei dati è andato a buon fine. F | igura 12.19. F | igura 12.20. 222 Web 2.0 223 Capitolo 13 Bibliografia « 13.1 Testi « "Accesso a database via Web" di Luca Mari - Ed. Apogeo 2001 "Ajax per applicazioni Web" di Andrea Guidi, Andrea Romagnoli, Pasquale Salerno - Ed. Apogeo 2007 "Cascading Style Sheets la guida completa" di Eric A. Meyer - Ed. Hops 2004 "HTML per il World Wide Web" di Elisabeth Castro - Ed. Pearson 2003 "Linux e programmazione Web" II.a edizione di Michele Sciabarrà - Ed. McGraw-Hill 2001 "Linux la guida completa" III edizione di Richard Petersen - Ed. McGraw-Hill 2001 "PHP5 guida per lo sviluppatore" di autori vari - Ed. Hoepli 2004 "Programmare in PHP" di Rasmus Lerdorf e Kevin Tatroe - Ed. Hops 2002 "Reti di calcolatori" IV edizione di Andrew S. Tanenbaum - Ed. Pearson 2003 "Web 2.0 Ajax» di Luciano Noel Castro - Ed. Sprea 2008 "Web Services guida pratica" di Ivan Venuti - Ed. Master 2003 13.2 Siti Web « "Apache" - Uri: hhttp://www.apache.org i "Appunti di informatica libera" - Uri: hhttp://informaticalibera.net i "Elenco tag HTML deprecati" -Uri: hhttp://www.w3.org/TR/REC-html40/appendix/changes.html#h-A.3.1.2 i "Elenco dei tipi MIME" -Uri: hhttp://www.asciitable.it/mimetypres.asp i "Linuxdidattica" -Uri: hhttp://www.linuxdidattica.org i "HTML.IT" - Uri: hhttp://www.html.it i "Manuale PHP" -Uri: hhttp://www.php.net/manual i "Nic" -Uri: hhttp://www.nic.it i "Programma uncgi.c per decodifica input CGI" -Uri: hhttp://www.midwinter.com/~koreth/uncgi.html i "Sun" - Uri: hhttp://www.sun.com i "Validatore HTML" -Uri: hhttp://validator.w3.org i "W3C" - Uri: hhttp://www.w3.org i 13.3 Altre fonti « Tesina per l’esame di Stato di Cester Samuele, classe 5a-inf, a.s. 2009-2010, ITIS "Max Planck" Lancenigo (TV), dal titolo: "Web 2.0 e Social Network»