DREAMWEAVER MX Gli strumenti disponibili per la gestione di un sito COLDFUSION MX Introduzione all'ambiente e collegamento a database BB^^ Supplemento a IC Irogrammo n.66 Programmare FLASH MX Creare una lavagna interattiva con ActionScript Master inASP Sezione protetta del sito: ^ le funzioni avanzate Una Rete a COLORI Utilizzare grafica e interattività per lasciare il segno PHP Un servizio per rinvio di cartoline virtuali ASP.NET & Web Matrix Un'applicazione Web per effettuare sondaggi on-line PENSARE COME UN HACKER: IL CONCETTO DI ROBUSTEZZA ■ Editoriale Programmare ^ Web Design Dreamweaver MX: organizzare il proprio lavoro 4 Creare una lavagna interattiva con ActionScript 8 Tutorial Web Poli con ASP.NET & Web Matrix 13 Lato Server Introduzione a ColdFusion MX Creiamo la sezione protetta del nostro Sito (II parte) Cartoline in PHP Sicurezza 18 22 28 La sicurezza del software (II parte) 32 PASSI AVANTI ; Il passo avanti che l'uomo ha compiuto con la diffusione di Internet è stato gran- de. Tralasciando i comuni vantaggi (e le altrettanto comuni seccature), vorrei soffermarmi su un particolare non abbastanza dibattuto: il ritorno alla parola scritta. Quando ormai la televisione sembrava aver vinto la battaglia della co- municazione, e quando la "civiltà delle immagini" sembrava aver trionfato sul silenzio sbigottito e attonito degli spettatori-cittadini, l'arrivo di Internet ha di colpo fatto saltare questa stagnante situazione. Si leggevano sempre meno libri e giornali, mentre la corrispondenza epistolare sembrava soppiantata dal più comodo e meno impegnativo telefono... Beh, tutto questo è stato letteralmente sovvertito da Internet, che ha fatto riscoprire a tutti, e ai più giovani in partico- lare, la bellezza e l'utilità del leggere e dello scrivere. Molti hanno contestato l'intrinseca leggerezza della parola che compare sul Web. Devo confessare che anch'io ho l'impressione che quelle parole abbiano una forza ed una consisten- za minore rispetto a quelle stampate su carta: diciamo pure che il detto "scrip- ta manent" risulta meno plausibile quando riferito a parole composte di fosfori e cristalli così evanescenti... e non nascondo che, come molti, se ho testi parti- colarmente importanti da leggere o "studiare", sento la necessità di stamparli. Anche le lettere inviate via mail sembrano obbligare ad una immediatezza e ad una forma di "spontaneità" che va spesso a detrimento della "qualità" della lin- gua. Ciononostante, resta innegabile un rinnovato interesse verso la parola scritta, con tutto quello che ne consegue in termini di diffusione della conoscen- za. A tutto questo si oppone ora una minaccia: la banda larga. Fino ad ora, la ri- strettezza di banda ed il costo della stessa hanno fatto sì che l'informazione fos- se veicolata prevalentemente in forma testuale. Con l'incremento della banda disponibile, saremo facili profeti nel prevedere che molti degli attuali navigato- ri sposteranno la loro attenzione dalla pagina Web a forme diverse di intratteni- mento come video e film. Il rischio è insomma un nuovo medioevo della parola, un rapido abbandono della parola scritta appena riconquistata. Ovviamente non siamo qui ad augurarci un rallentamento nella diffusione della banda larga, ma ci permettiamo di sollevare un piccolo dubbio: saremo in grado di utilizzare que- sta tecnologia senza esserne travolti? Raffaele del Monaco Programmare "WEB Supplemento ad ioProgrammo Anno VII - N.ro 2 (66) - Febbraio 2003 - Periodicità: Mensile Reg. Trib. di CS al n.ro 593 - Cod. ISSN 1128-594X E-mail: ioprogrammo@edmaster.it http://www.edmaster.it/ioprogrammo Dir. Editoriale Massimo Sesti Dir. Responsabile Romina Sesti Produci Manager Antonio Meduri Editor Gianfranco Fortino Redazione Raffaele del Monaco, Antonio Pasqua Collaboratori M. Battista, A. Cangiano, P. Capitani, C. Giustozzi, F. Mestrone, G. Uboldi Segreteria di Redazione Veronica Longo REALIZZAZIONE GRAFICA CROMATIKA Sri C.da Lecco, zona ind. - 87030 Rende (CS) Tel. 0984 8319 - Fax 0984 8319225 Coord. grafico: Paolo Cristiano Coord. tecnico: Giancarlo Sicilia Impaginazione elettronica: Aurelio Monaco, Ferdinando Gatto PUBBLICITÀ Edizioni Master S.r.l. Responsabile Vendite Ernesto Redaelli Agenti Vendita Elisabetta Februo, Serenella Scarpa, Cornelio Morari Segreteria Ufficio Vendite: Daisy Zonato Via Cesare Correnti, 1 - 20123 Milano Tel. 02 8321612 - Fax 02 8321764 e-mail: advertising@edmaster.it EDITORE Edizioni Master S.r.l. Sede di Milano: Via Cesare Correnti, 1 - 20123 Milano Tel. 02 8321482 - Fax 02 8321699 Sede di Cosenza: C.da Lecco, zona ind. - 87030 Rende (CS) Amministratore Unico: Massimo Sesti Responsabile Amministraz. e Finanza: Benedetto Celsa Produzione e Logistica: Michele Carere, Eugenio Vocaturo Diffusione: Alessandra Cervello Marketing: Giuseppina Bruno, Leonardo Petrone, Antonio Meduri Assistenza tecnica: ioprogrammo@edmaster.it r Servizio Abbonati: ftel.02 8321482 ) e-mail: servizioabbonati@edmaster.it Stampa: Elcograf Industria Grafica (LC) Stampa CD-Rom: Disctronics Italia (MI) Distribuzione per l'Italia: Panini & C S.p.A. - Roma Finito di stampare nel mese di Gennaio 2003 Nessuna parte della rivista può essere in alcun modo riprodotta senza autorizzazione scritta della Edizioni Master. Manoscritti e foto originali, anche se non pubblicati, non si restituiscono. Edizioni Master non si assume alcuna responsabilità per eventuali errori od omissioni di qualunque tipo. Nomi e marchi protetti sono citati senza indicare i relativi brevetti. Edizioni Master non sarà in alcun caso responsabile per i danni diretti e/o indiretti derivanti dall'uti- lizzo dei programmi contenuti nel CD-Rom e/o per eventuali anomalie degli stessi. Nessuna responsabilità è, inoltre, assunta dalla Edizioni Master per danni o altro derivanti da virus informatici non riconosciuti dagli antivirus ufficiali all'atto della masteriz- zazione del supporto. sili A.N.E.S. L'Universo Tecnologico MASTER «g"™™™» Edizioni Master edita: Idea Web, GoiOnLine Internet Magazine, Win Magazine, Quale Compu- ter, DVD Magazine, Office Magazine, ioProgrammo, Linux Magazine, Softline Software World, MPC, Discovery DVD, Computer Games Gold, inDVD, I Fantastici CD-Rom, PC VideoGuide, Il CD-Rom di Idea Web, I Corsi di Win Magazine, Le Collection. WEB 3 * Web Design WHBB Dreamweaver MX: organizzare il proprio lavoro Dopo aver visto le caratteristiche principali per la creazione delle pagine HTML con l'ultima versione di Dreamweaver, diamo un'occhiata alle funzioni di gestione di un sito: sfruttiamo la capacità di integrazione con un server e di verifica dei collegamenti tra le pagine, nonché la possibilità di creare asset riutilizzabili per i nostri progetti web. Nel numero precedente ci siamo occupati del- le caratteristiche principali per la creazione di pagine HTML che Dreamweaver mette a di- sposizione del designer web. In realtà però il compito del prodotto non si esaurisce nel- l'aiuto per la creazione di codice HTML, ma va ben oltre, permettendo all'utente di lavorare su progetti di respiro più ampio che includono tutte le risorse necessarie alla Fig. 1-11 pannello Site nel gruppo Files | E E) (no site defined) Define a Site I yfr Desktop creazione di un sito (quindi, numerose pagine HTML linkate tra loro, i vari GIF e JPEG associati, applet, e ri- sorse varie) e che potete gestire in maniera molto effi- ciente grazie ai tool messi a disposizione da Dreamwea- ver. Inoltre i progetti possono essere legati ad un piat- taforma server specifica (a scelta tra ASP, PHP, JSP, Cold- Fusion, .NET), il che vi permette in un secondo tempo di sfruttare un ventaglio di opzioni di generazione di codi- ce dinamico atte alla creazione di applicazioni web vere e proprie, piuttosto che semplici siti! Inoltre, Dreamwea- ver si occupa anche della pubblicazione dei file sul ser- ver, tenendo a memoria le impostazioni per l'accesso FTP, HTTP, o RDS, oltre ad eventuali note di design che potre- ste voler associare ad alcuni file, rendendo trasparente l'upload e download dei file da e verso il PC locale. Ve- dremo insomma che di fatto, una volta inizializzato un sito inteso come progetto Dreamweaver, avrete la possi- bilità di sfruttare molte funzionalità del prodotto che hanno a che fare con integrazione, versioning e pubbli- cazione dei file, oltre agli strumenti per aumentare la produttività e l'organizzazione del proprio materiale. IL SITO COME PROGETTO DI DREAMWEAVER Per poter accedere alle meravigliose funzionalità promes- se nell'introduzione delle righe precedenti, è necessario lavorare su un progetto completo piuttosto che una sin- gola pagina. In Dreamweaver i progetti si chiamano - giustamente - "siti" e per crearne uno si hanno diverse possibilità: dal menu Site /New Site..., oppure dal pannello Site (lo vedete in Figura 1) selezionando le stesse voci di prima dal menu privato del pannello, oppure cliccate sul sottomenu EditSites... sempre dal menu Site e poi selezio- nate il pulsante New... In un modo o nell'altro, alla fine vi trovate davanti la fi- nestra di creazione di un nuovo sito. Rispetto alla ver- sione 4 del prodotto, qui avete la possibilità di farvi gui- dare da un wizard nella creazione del progetto, in modo che vi vengono poste delle domande semplici relative al- le caratteristiche del vostro sito, del server che lo ospi- terà e di come accedere a tale server, per settare così au- tomaticamente le varie opzioni. L'alternativa è quella vecchio stile delle finestre di proprietà, dove avete a di- sposizione tutto relativamente al sito, ma ovviamente è richiesta un po' più esperienza e una conoscenza più ap- profondita del prodotto. Entrambe le possibilità, comun- que, sono accessibili dalla medesima finestra, è solo una questione di tab (Basic o Advanced, di cui avete un esempio rispettivamente nelle Figure 2 e 3). Ma vediamo quali sono le scelte che si possono fare nel creare un sito con Dreamweaver. Prenderò come riferi- mento di base la finestra avanzata, in quanto è quella WEB 4 TV Web Design Basic Advanced Site Definition ^ — ~^r—<^> How do you wanHo wort with youi files during development? Editand test loca y (my testing server is un th s : ornputer] Edit locally esting server Edil direi: tly : n reme te testing server usmg ocaì r ilv-mé E di! din: ctly on remote testina server using FTP or RDS Where on your e store your files? [ < Back ] [ Next > ] [ Cancel più completa: vi accorgerete così che tutte le informazio- ni richieste con il wizard saranno comunque spiegate nella sezione che segue. Sicuramente due dei parametri più importanti sono il no- me (che serve solo da identificativo) e la directory di la- voro (dove sarà salvato tutto il materiale relativo al pro- getto). È possibile inoltre specificare una directory di im- magini di default, dove Dreamweaver copierà eventuali file GIF o JPEG trascinati sui vostri documenti da qua- lunque punto del vostro computer mentre lavorate su pa- gine HTML. Esiste poi la possibilità di chiedere a Dream- weaver di gestire una cache locale di informazioni sul si- to che velocizza il lavoro e che si rende necessaria qUa- Elasic Ad va Category Remote Info Testing Server . naking Design Notes Site Map Layout File View Columns ì' [NuovoSitc : Locai RootFolder: C:¥Documi co Mesi R efresh Locai File List Àutomatically Default Images Folder: |£) HTTPAddress: | http:// : This addi i he Li iM iecker to detect HTTP lii i > rtoyourown site. Cache: 0EnableCache The cachi: and asset informati' m in the si I ! ds up the Asse ■ panel, link management, an i Site Map [ Cancel ] Help Fig. 2- Il wizard per la creazione di un nuovo sito Fig. 3 - Creazione un nuovo sito senza wizard lora vogliate utilizzare gli asset (di cui parleremo in se- guito). Continuerei il discorso adesso con la scelta del server. Dreamweaver vi mette a disposizione due blocchi di im- postazioni separati: da un lato, configurate la locazione finale delle pagine una volta che sono pronte per la pro- duzione (il web server, insomma), dall'altro indicate a Dreamweaver quale eventuale application server utilizza- te di modo che Dreamweaver possa interfacciarsi con es- so per aiutarvi a creare e testare pagine dinamiche lato server (il termine usato nel prodotto è testing server) . Nel primo caso dovete dare al prodotto le informazioni ne- cessarie a connettersi al server per scaricare/ caricare le varie risorse web. Avete a disposizione una scelta abba- stanza vasta di metodi d'accesso, quali FTP, WebDAV, RDS, SourceSafe... In questa sede potete anche specificare se volete che i file vengano rispediti al server ad ogni sal- vataggio e se volete abilitare il check-in/check-out dei file (niente a che vedere con gli aeroporti!): quest'ultima scelta vi offre un semplice, ma utile meccanismo per la- vorare in team. Se qualcuno lavora su un file, viene fat- to il check-out del file stesso, che è una specie di lock tramite il quale si impedisce ad altri utenti di modificare il contenuto del file fino a che non venga fatto nuova- mente il check-in. Il tutto è gestito trasparentemente da Dreamweaver, il quale vi dà anche la possibilità di se- gnalare il vostro nome e l'email, di modo che questi dati siano associati a tutti i check-out che fate, cosicché chi tenta di lavorare su un file bloccato sa almeno chi ci sta lavorando e come contattarlo! Vi ribadisco che questa funzionalità è utile a chi lavora su un sito insieme ad un gruppo di persone oppure se lavorate da soli ma da po- stazioni diverse, per cui vi può essere utile tenere traccia dei file in fase di modifica. Va da sé che è necessario che tutti i componenti del team lavorino con Dreamweaver ed aggiungerei che è conveniente disabilitare questa fun- zione se operate autonomamente, perché vi risparmia tempo e spazio, anche se poco. Passando invece al "testing server", direi che la scelta più importante è quella del tipo di modello server-side che utilizzate: questa opzione dipende unicamente dal vo- stro provider e dai servizi installati sulle macchina che ospita le vostre pagine. Da questa scelta dipendono a ca- scata tutte le funzionalità di generazione codice lato ser- ver che Dreamweaver mette a disposizione e di cui avre- mo modo di parlare diffusamente più avanti nella serie. Potete utilizzare un server che supporta ASP (sia con JScript che con VBScript), oppure la nuova piattaforma .NET (con Visual Basic o C#), nonché, per uscire dall'am- bito Microsoft, il linguaggio di scripting PHP in appoggio WEB 5 Web Design ad un database mySQL, o ancora la piattaforma Java En- terprise Edition (con JSP) e quella Macromedia con Cold- Fusion (nuova versione o in compatibilità con Dreamwea- ver 4). Nel gruppo di pannelli delle applicazioni (Applica- tion, vedi Figura 4) troverete una serie di comandi per crea- re automaticamente script di accesso ai dati e ai loro ren- dering sulla pagina, oltre ad una serie di server behaviour estensibile (li potete creare voi o scaricare dal sito della Macromedia). Comunque, come dicevo, di questo parlere- mo poi... Per ora aggiungiamo solo che, anche in questo caso, potete specificare le modalità d'accesso al server, anche se per default vengono riutilizzate quelle imposta- te per il web server, visto che normalmente si tratterà della stessa macchina. Databases J E indir| gs j " s erver B ehaviors ] Components ]= _jj]_^J DocurnentType:ÀSPVBScript To use dynamic data on this page: 1/ 1. Create a site for this file. «/ 2. Choose a document type . i/ 3. Set up the site's testine server . 4. Press the plus (+) button and choose Recordset. Fig.4- Il pannello delle risorse applicative (creazione di codice server-side di accesso ai dati) GESTIRE LE RISORSE Prima di vedere il nostro sito finalmente creato (come progetto, s'intende - magari bastassero pochi click per un sito vero e proprio!), parliamo ancora di un paio di op- zioni che si possono impostare. Innanzitutto introduciamo il concetto delle note di design: se abilitate questa caratteristica, avrete la possibilità di associare dei commenti personali ai file su cui lavorate. Queste informazioni supplementari sono memorizzate lo- calmente, ma se lavorate in un team potete far sì che le note siano condivise (tramite l'upload su server) con tut- ti i membri della squadra di lavoro. Tenete solo a mente che anche questa funzione (come il check-out), sebbene molto comoda può rivelarsi un inutile costo di perfor- mance per il prodotto quando è attiva senza essere usa- Fig. 5 - La map view del pannello Site ta. Un'altra pratica capacità di Dreamweaver sui siti è il cloaking (da "cloak" che significa mantello): le operazioni di aggiornamento e sincronizzazione dei file tra il server e la copia locale eseguite in blocco (su tutto il sito o su directory, piuttosto che su un singolo file alla volta) pos- sono spesso essere rallentate da grossi file di immagine o di dati o quant'altro che in realtà di aggiornamento non avrebbero bisogno. Grazie al cloaking è possibile specificare dei gruppi di fi- le (tramite l'estensione) che devono essere esclusi da operazioni batch (cioè, eseguite in blocco), oppure - una volta che l'opzione di cloaking è abilitata - si possono in- dicare specifiche directory che devono anch'esse essere escluse (non è invece possibile richiedere l'esclusione a livello del singolo file). Tutto il materiale filtrato dal cloaking potrà ovviamente essere manualmente aggiornato, sincronizzato e scaricato, senza che la sua presenza vada a rallentare le stesse attività quando siano svolte sul sito nel suo complesso. Infine, un'altra caratteristica importante del prodotto è il map layout, che vi consente - a partire da una pagina principale che indicate nella finestra avanzata di gestio- ne del progetto (quella della Figura 3, per intenderci) - di visualizzare la struttura del vostro sito evidenziando i le- gami tra i vari file che lo compongono. B= W\&,\ 1 Site:|MioSitoDiP,ova v| |^| Q g | f f *v W | D StoNaviBafatìrttaasp chisiamo.asp 1KB AS ! * •contatti.asp 1KB AS | §V index asp 1KB AS 1KBAS ffl© Desktop <| m | > M i i i i i °§ t ^ :jà ip i| al j| ip prodotti .asp évi • contatti.asp è»»" • contatti.asp &>#: • indcK.asp * ><, „ progcttiasp * >* • mdox.asp * > d „ indcx.asp è*B, contatti asp H-g], indcx.asp uu TrtUnr.HejL.nc.in.enr^e „ 6 Be l.H.UJ.L 1., ., Piuttosto che spiegare cosa intendo dire, comunque, cre- do sia più semplice indirizzarvi verso la Figura 5, che vi mo- stra la Map View del pannello Site espanso (il pulsante Ex- pand/Collapse vi consente di fare il passaggio tra la vista della Figura 5 e quella della Figura 1: è l'ultima della toolbar del pannello). Sebbene non si vedano nell'immagine, nella mappa com- paiono anche tutti i link a GIF, JPEG, applet e a qualun- que altro tipo di risorsa identificabile tramite un URL. Per visualizzare la map view, selezionate la voce corri- spondente nella combo box del pannello Site, così come lo vedete nella Figura 1. WEB 6 Web Design REPORT, CONTROLLI, E ORGANIZZAZIONE Lavorando su un sito di grandi dimensioni è facile per- dere il senso di quali risorse si abbiano a disposizione e di come siano utilizzate. Per venirci incontro in questo senso, Dreamweaver raccoglie tutto il materiale che è presente nella directory del progetto e lo organizza per tipo di risorsa (immagini, video, link, etc) nel pannello degli Assets (che significa, appunto, qualcosa di simile a risorsa, ma con un accento sulla sua importanza e il suo valore). | Size|Type | Full Path~ Il pannello lo potete vedere nella Figura 6, con tutte le ti- pologie sulla sinistra, un pannello di preview della risor- sa in alto e l'elenco in basso: troverete le immagini, i link (nel senso di URL), i video, i filmati Flash, gli script lato client, e perfino i colori che sono utilizzati nelle pagine HTML del vostro sito. Potete creare una lista di preferiti per ogni categoria, così da avere un accesso più rapido a quelle risorse che usate più di frequente, e con un sem- plice drag&drop potrete riutilizzare qualunque elemento trascinandolo su una pagina nuova. È da notare che l'ul- tima tipologia della toolbar verticale (le librerie) vi con- sente di creare degli elementi di una pagina (blocchi di HTML) che potete poi riutilizzare in vari file HTML diver- si, richiedendo che eventuali modifiche apportate alla li- breria vengano automaticamente riportate su tutte le pa- gine che la utilizzano. Infine, vediamo ancora come Dreamweaver ci permette di tenere sotto controllo tutto quello che facciamo. Parleremo da un lato del Site Reporter Fig. 6-11 pannello degli Assets. Qui saranno elencate tutte le risorse utilizzate dal nostro sito. e dall'altro del Link Checker. Entrambi producono un output che viene mostrato nel gruppo di pannelli Results, di cui abbiamo già parlato nel numero precedente, rispettiva- mente in Site Reports e Link Checker. Il primo viene invocato tramite il menu Site/Reports... e vi consente di ottenere una serie di informazioni sul vostro sito: i dati raccolti di- pendono da quello che avete richiesto nella finestra di dialogo che si apre dal menu, e può includere cose del ti- po il designer che detiene file in check-out, le note di design, ed eventuali avvertimenti sull'HTML quali pagine senza titolo (tag TITLE assente) etc. Il secondo strumen- to, invece, viene invocato o dal menu Site / Check Links Si- tewide del pannello Sites, oppure con il menu contestuale Check Links sull'elenco dei file sempre nello stesso pannel- lo. Lo scopo di questa funzione è quello di verificare tut- ti i link all'interno del sito per assicurarsi che puntino a pagine effettivamente esistenti: eventuali problemi sono categorizzati in External Links (non controllati in quanto non verificabili), Orphaned Links (pagine esistenti a cui nes- suno fa riferimento: di solito sono inutili e da cancella- re) e Broken Links (link verso pagine del sito che non esi- stono e che quindi vanno sistemati). Una combo box nel pannello Link Checker vi dà la possibilità di filtrare per ti- pologia di anomalia, mentre un doppio click su un ele- mento dell'elenco vi apre l'editor della pagina con il pro- blema, pronta per la vostra revisione! CE N'È ANCORA? Oggi abbiamo scorso le principali funzioni che ci consen- tono di organizzare il nostro materiale da lavoro web... Abbiamo parlato di siti e delle risorse che contengono, abbiamo visto come Dreamweaver ce le organizza in as- sets, vi ho parlato di alcune proprietà dei progetti web e delle possibilità di controllare i link e l'HTML dei vostri file. Ma Dreamweaver offre molto di più: adesso che avete creato un sito (o progetto, come volete!) potete utilizza- re anche i template, una potente feature del prodotto che garantisce riutilizzabilità e facile mantenibilità alle vo- stre pagine, oltre ai server behaviour di cui si è detto, cioè tutto quel codice server-side generato automatica- mente per l'accesso a database. E poi per quello che ri- guarda le pagine di per sé, ancora dobbiamo parlare di ti- meline, CSS, ed altre potenti caratteristiche di Dream- weaver. Insomma, ce n'è ancora abbastanza per potervi chiedere di restare ancorati a queste pagine per qualche altro nu- mero... A presto! Federico Mestrone WEB 7 Web Design lcnpcicjiici interattiva con ActìonScrìpt Fino a qucdche tempo fa disegnare figure geometriche usando solo poche righe di codice era una prerogativa di altri linguaggi di programmazione. Oggi, grazie ed nuovi metodi messi a disposizione da ActionScript, è possibile - con estrema facilità - creare linee, curve, forme e riempimenti senza coinvolgere gli strumenti di disegno del programma. Cui P ;d \soft\codice \drawing.zip Idrawing methods sono metodi attraverso i quali è possi- bile disegnare curve vettoriali in Flash. I vantaggi che ne conseguono sono fondamentalmente due: in termini di KB, la possibilità di risparmiare risorse del sistema e, in termini visivi, la facoltà di generare effetti interattivi molto interessanti. I metodi relativi al disegno devono sempre es- sere riferiti ad un clip, con una sintassi del tipo nomeClip.metodo(); e definiscono, attraverso l'utilizzo di coordinate, la possibilità di disegnare sullo stage. In altre parole, le curve e le figure vengo- no disegnate all'interno di un clip filmato il cui nome va specifi- cato quando si applica il metodo. Il clip in questione può essere vuoto (cioè privo di qualsiasi elemento grafico) o anche pieno. Fig. 1- Attraverso i relativi drawing methods abbiamo generato un semplice segmento all'interno dell'istanza del clip filmato dipi. Elenchiamo nella Tabella 1 i drawing methods. Facciamo subito un breve esempio per entrare nel vivo (tutti i sorgenti relativi agli esempi si trovano nella cartella \soft\codice\drawing.zip del CD-Rom allegato la rivista, mentre è possibile visionare la versione on li- ne del tutorial che illustreremo nel corso di questo articolo, al- l'indirizzo www.dynamicdesign.it/drawing). Apriamo Flash MX e, per creare un clip, seguiamo il percorso Inserisca Nuovo simbolo, sele- zioniamo l'opzione clip, diamogli come nome dipi e, infine, pre- miamo Ok. Apriamo la libreria (Finestra>Libreria), trasciniamo il no- stro clip sullo stage e, tramite la barra delle proprietà, scegliamo dipi come nome istanza. A questo punto, inseriamo nel primo fo- togramma le seguenti tre righe di codice: 1 root.clipl .lineStyle(2,Qx22899.5Q); 2_root.clip1.moveTo(0,0); 3_root.clip1.lineTo(250,50); Apriamo il filmato Flash esempiol e vediamone un'anteprima at- traverso il menu Controlla Prova filmato (vedi esempioLfla nella cartel- la del CD-Rom). In pratica abbiamo creato una linea senza utiliz- zare gli strumenti di disegno: il primo metodo specifica che la no- stra linea avrà come spessore 2 (il valore può andare da a 255), come colore RGB un valore esadecimale #228899 e, come traspa- renza, un valore alfa pari a 50. È interessante notare che il colo- re viene indicato con lo stesso procedimento usato per i metodi dell'oggetto Color di ActionScript, ovvero con "Ox" al posto del sim- bolo "#", che si usa in genere nell'HTML. Come è facile intuire os- servando il breve codice, la seconda riga indica le coordinate del punto di partenza del nostro segmento, mentre la terza fissa le coordinate del secondo punto. Le coordinate fanno riferimento al sistema di assi che ha come vertice il centro del clip, per cui il pri- mo punto, che ha come valore x ed y pari a 0, sarà posizionato esattamente al centro del clip filmato dipi. Se al posto del clip vuoto ne usiamo uno già composto da un elemento grafico (ad esempio un piccolo cerchio posto al centro della relativa linea temporale) il risultato non cambia più di tanto: semplicemente, l'elemento grafico creato con ActionScript si aggiunge all'elemento grafico preesistente. Se invece volessimo relazionare la posizione dei disegni al centro dello stage, basterebbe riferire i metodi di- rettamente alla _root, con una sintassi del tipo _root.nomeMetodo(); (vedi esempio3.fla nella cartella del CD-Rom). Tuttavia, poiché il più delle volte è utile disegnare figure da zero in clip privi di elementi grafici, può essere comodo impiegare il metodo createEmptyMovie- Clip(), che consente la creazione di un clip vuoto attraverso Action- Script. Ad esempio, nel caso volessimo sperimentare il metodo cur- veTo() perla creazione di una curva di Bezier (vedi esempio4.fla), po- tremmo fare a meno di creare manualmente il nostro clip vuoto, inserendo nel primo fotogramma un listato con una sintassi del tipo: 1 _root.createEmptyMovieClip("clip1 ",1 ) 2 root.clipl .lineStyle(2,0x228899,50); 3_root.clip1.m oveTo(0,0); 4 _root.clip1 .curveTo(60,45,250,50); WEB 8 Web Design In questo modo viene creato un clip sul livello specificato, ana- logamente a quanto accade utilizzando i metodi attachMovie() o du- plicateMovieClip() . Poiché non abbiamo indicato le coordinate del clip vuoto, questo, di default, verrà posizionato in corrispon- denza dell'origine dello stage, cioè nel punto coincidente con l'angolo in alto a sinistra dell'area di lavoro. Con alcuni piccoli ritocchi al codice appena illustrato, possiamo esplorare le potenzialità interattive dei drawing methods (vedi esempio5.fla): ritoccando il listato e aggiungendo un clip filmato denominato maniglia, è possibile modificare interattivamente la curva di Bezier. 1 _root.onEnterFrame=function(){ 2 _root.createEmptyMovieClip("clip1 ",1 ) 3 root.clipl .lineStyle(2,0x228899,50); 4 _root.clip1.moveTo(0,0); 5 a=_root.maniglia._x; 6 b=_root.maniglia._y; 7 _root.clip1 .curveTo(a,b,250,50); 8} 9_root.maniglia.onPress=function(){ 1 root.maniglia.startDrag(true); 11} 1 2 _root.man iglia.onRe lease=f unct ion(){ 13 root.man iglia.stopDragO; 14} nome utilizzo lineStyleQ; Indica le caratteristiche della linea e prevede tre parametri: spessore, colore, trasparenza. moveToQ; Indica le coordinate del punto iniziale della linea e prevede due parametri (xl e y2). lineTo(); Indica le coordinate del punto finale della linea e prevede due parametri (x2 e y2). curveTo(); Specifica che la linea sarà una curva di Bezier; in genere sostituisce linelb() e prevede quattro parametri (xc,yc,x2,y2). x2 e y2 indicano le coordinate del punto finale, xc e yc, invece, le coordinate del "nodo" a cui fa riferimento la curva di Bezier. beginFìllO; Indica il colore di riempimento e la trasparenza di una porzione specificata, e prevede due parametri (valoreRGB, valoreAlpha). beginGradientFill(); Indica un colore di riempimento sfumato, che può esser radiale o lineare. Questo metodo prevede quattro parametri: tipo di riempimento, array dei colori usati, array che indica il valoreAlpha di ogni colore, array che distribuisce i vari colori, matrice che definisce le caratteristiche del riempimento sfumato. endFill(); Indica dove finisce la porzione da colorare e lavora in associazione di beginFill() o beginGradientFill(); non prevede parametri. clear(); Consente di eliminare quanto disegnato nel clip specificato; non prevede parametri. Fig.2- Trascinando il cerchio al centro, vengono cambiate interattivamente le coordinate del punto di controllo che regola l'inclinazione della curva di Bezier. Tab. 1 - Elenco dei drawing methods disponibili in Flash MX. O trascina centro delo stage \ punto finale La creazione della curva è stata associata all'evento onEnterFrame, il quale farà in modo che i codici presenti tra la riga 2 e la riga 8 siano eseguiti ad ogni lettura del fotogramma (e quindi conti- nuamente). Inoltre, vengono utilizzati gli eventi onPress e onRe- lease, entrambi associati al clip maniglia affinché, ad ogni pres- sione e rilascio, sul clip siano attivati i metodi startDrag() e stop- Drag(), che gestiscono rispettivamente il trascinamento e la fine del trascinamento del clip specificato. Le coordinate del clip tra- scinabile costituiscono i parametri che regolano la curva di Be- zier (righe 5 e 6), per cui, quando l'utente sposta il clip maniglia, cambiano le caratteristiche della curva. Questo meccanismo di interazione è alla base della lavagna interattiva che creeremo tra breve. Tuttavia, prima di illustrare iltutorial vero e proprio, è op- portuno spendere due parole sui metodi che consentono di crea- re porzioni dotate di riempimenti. Con i drawing methods, in- fatti, è possibile generare non solo semplici linee, ma anche fi- gure più complesse. Per fare un esempio, analizziamo il seguen- te codice, presente nel primo fotogramma del filmato esempio6.fla: 1 _root.createEmpt yMovieCli p("clip1 ",1 ) 2 root.clipl .lineStyle(2,QxFFQQQQ,5Q); 3 //root.clipl .beginFill(0xFF6600,1 00); 4 _root.clip1 .moveTod 20,1 1 0); 5_root.clip1.lineTo(210,185); 6_root.clip1.lineTo(85,175); 7 _root.clip1 .lineTod 20,1 1 0); 8//_root.clip1.endFill(); Semplicemente, è stato creato un triangolo tracciando tre linee e facendo in modo che la terza terminasse esattamente dove vie- ne generata la linea di partenza. Le righe 3 e 8 del listato sono precedute dal doppio slash // che - analogamente a quanto av- viene in altri linguaggi di programmazione - ne impedisce l'ese- cuzione, trasformando il codice che segue in un commento. Ren- dendo attive le righe in questione, cioè cancellando le doppie barre iniziali, si ottiene una figura piena, poiché viene definita una porzione che inizia con beginFill() - il metodo che specifica un colore e una trasparenza - e termina con endFill(). Il discorso si complica quando si vogliono dare dei riempimenti sfumati. In- fatti il metodo beginGradientFill() non ha un utilizzo altrettanto im- mediato, a causa dei numerosi parametri previsti, alcuni dei qua- WEB9 Web Design li abbastanza macchinosi da definire. Analizziamo il listato trat- to dal primo fotogramma del filmato esempio7.fla: 1 tipo="linear"; 2 colori=[0xFFFF99,0xFF0000]; 3trasparenza=[100,100]; 4 distribuzione=[0,255]; 5 matrice={matrixType:"box",x:1 1 0,y:1 20,w:70,h:70,r:45}; 6 _root.createEmp tyMovieCl ip("clip1 ",1 ); 7 _root.clip1 .lineS tyle(0x000 000,50); 8 _root.clip1 .beginGradientFill(tipo,colori,trasparenza, distribuzione, matrice); 9 _root.clip1 .moveTod 20,1 1 0); 10_root.clip1.lineT o(21 0,1 85); 11 _root.clip1.lineTo(85,175); 1 2 _root.clip1 .lineTod 20,1 1 0); 13_root.clip1.endFill(); (120,110] [85,175] [210,185] Questo codice permette di attribuire al triangolo realizzato prece- dentemente un riempimento lineare, che va da un colore giallo chiaro al rosso. Molti dei parametri impiegati sono degli array e, proprio a causa della loro complessità, è necessario definirli se- paratamente, creando quattro variabili che saranno poi successi- vamente utilizzate dal metodo beginGradientFill(); Il primo parame- tro che abbiamo passato alla variabile tipo prevede solo due valo- ri, che sono rispettivamente "radiai" o "linear". H secondo invece è caratterizzato da un array di n elementi, ognuno dei quali costi- tuisce un valore esadecimale - in altre parole indica da quanti e quali colori sarà costituito il nostro riempimento sfumato. Segue poi un array costituito da tanti valori alfa quanti sono i colori uti- lizzati (nel nostro caso abbiamo dato la massima opacità ad en- trambi i colori). Abbiamo poi la miscelazione dei colori all'inter- no della porzione indicata: impostando questi valori si compie un'operazione analoga al trascinamento dei simboli corrispon- denti ai colori di un riempimento sfumato, quando si utilizza il pannello Mixer per disegnare in Flash MX. Infine, abbiamo un ar- ray associativo che definisce sei elementi. Il primo parametro è (120,110] [85,175] [210,185] WEB 10 Fig. 5 - Quando si usa il pannello Mixer per creare un riempimento radiale o lineare, è possibile distribuire interattivamente i vari colori. Fig. 3 -Nel momento in cui si usano beginFillO edendFillUpil programma identifica automaticamente la porzione da riempire a prescindere dalla forma disegnata. Fig. 4 - Allo stesso triangolo creato in precedenza abbiamo attribuito un riempimento sfumato lineare. sempre box; il secondo e il terzo definiscono le coordinate del- l'angolo superiore sinistro del riempimento sfumato rispetto al centro del clip; Il terzo e il quarto, la larghezza e l'altezza del riempimento. Il quinto parametro indica l'angolo di rotazione del riempimento sfumato (ha senso attribuirgli un valore diverso da zero solo quando si usa un tipo di riempimento lineare). Ultima- ta la nostra panoramica sui drawing methods, possiamo dedicar- ci ad un progetto più impegnativo che ci permetta di sfruttare pienamente le possibilità offerte. Nella cartella del cd-rom alle- gato alla rivista è possibile trovare sia il file completo, denomi- nato lavagna.fla, sia una versione "essenziale", denominata intera- zione_semplice.f la . Quest'ultima mostra il principio di funzionamen- to alla base della lavagna interattiva: infatti, se testiamo il filma- to con Controlli>Prova filmato noteremo che, cliccando sull'area di lavoro e trascinando con il puntatore del mouse, è possibile dise- gnare una linea a mano libera. Apriamo il file interazione_semplice .fla: ci sono tre livelli (azioni, clip e stage). Nel livello stage è posizio- nato un pulsante invisibile che copre tutta l'aera di lavoro e ha come nome istanza "stage", mentre, nel livello clip, è presente un clip filmato denominato dipi. Se apriamo la libreria ed esploriamo dipi, notiamo che è composto da due clip, mi ed m2, costituiti da piccoli cerchi trasparenti, posizionati uno sopra l'altro. Osservia- mo il codice presente nel primo fotogramma del livello azioni: 1 root.stage.useHandCursor = false; 2 _root.stage.onPress = functionQ { 3 _root.clip1.lineStyle(5, 0x000000); 4 _root.clip1 .moveTo(_root.clip1 .mi ._x, _root.clip1 .mi ._y); 5 _root.a = _root._xmouse; 6 _root.b = _root._ymouse; 7 startDrag( "_root.clip1.m2") ; 8} 9 _root.onEnterFrame = functionQ { 10 _root.clip1._x = _root.a; 11 _root.clip1._y = _root.b; 12 _root.clip1.lineTo(_root.clip1.m2._x, _root.clip1.m2._y); 13} 14 _root. stage.onRelease = _root. stage.onReleaseOutside=function () { 15 stopDragO; 16_root.clip1.clear(); Web Design 17 _root.clip1 m2. x = _root.clip1 mi. _X; 18 _root.clip1 m2. _y = _root.clip1 mi. _y; 19} Nella riga 1, settando la proprietà useHandCursor sul valore boolea- no false, viene disabilitata la mano che caratterizza il puntatore quando si passa sul pulsante stage. Attraverso l'evento onPress (dalla riga 2 in poi), ad ogni pressione del mouse sul pulsante in- visibile stage, con i metodi lineStyle e moveTo() viene creata una li- nea all'interno del clip filmato dipi; viene anche specificato che il punto iniziale della linea è contraddistinto dalle coordinate del clip mi. Successivamente, sempre in corrispondenza della pressio- ne effettuata dall'utente sul pulsante stage, vengono passate le coordinate x ed y del puntatore a due variabili a e b. Infine, vie- ne attivato il trascinamento del clip m2. Non è stato definito il metodo lineTo(), che stabilisce il punto finale della linea, poiché la sua definizione viene effettuata all'interno del blocco di codice gestito dall'evento onEnterFrame, a partire dalla riga 9. Qui il meto- do lineTo() utilizza come coordinate la x e la y del clip m2, che vie- ne trascinato dall'utente, e che quindi cambia continuamente fi- no a quando l'utente non interrompe il trascinamento: in altri termini, viene generata una piccola linea ad ogni minimo spo- stamento effettuato. Non solo: l'evento onEnterFrame stabilisce le coordinate del dipi, attribuendogli i valori delle variabili a e b usa- te in precedenza: ad ogni click dell'utente, il clip filmato dipi si posizionerà nel punto in cui si trova il mouse (l'origine della li- nea creata con il trascinamento). Grazie agli eventi onRelease e on- ReleaseOutside, quando si rilascia il mouse sul pulsante stage o al di fuori della sua area attiva, si interrompe il trascinamento del clip m2, che viene riposizionato in corrispondenza del clip mi (cioè al centro del clip filmato dipi). Invece, con l'azione dear (), viene cancellata la linea creata. Alla fine viene quindi ricreata la con- dizione iniziale che consente la creazione di una nuova linea. Tuttavia, il meccanismo appena descritto è ben lontano dalla pos- sibilità di creare una vera e propria lavagna interattiva, perché non presenta opzioni di regolazione (cioè non è possibile cancel- lare o ritoccare quanto disegnato) e soprattutto perché, per evi- tare di creare una poligono chiuso, la linea viene cancellata ad ogni rilascio del mouse - mentre invece ci sarebbe la necessità di creare una diversa linea che rimanga visibile ad ogni intervento dell'utente. Se vediamo il file lavagna.swf all'opera, notiamo che è possibile non solo memorizzare le linee create dall'utente, ma an- che intervenire su altri fattori, come ad esempio il colore delle li- nee. Apriamo lavagna.fla nella cartella del CD-Rom e osserviamo la disposizione dei livelli: è identica a quella utilizzata nella file in- terazione_semplice.fla. Infatti, la differenza è tutta nel codice. La tecnica, utilizzata per creare tante linee quanti disegni tracciati dall'utente, è basata sull'uso del metodo duplicateMovieClip(). Cioè, ogni volta che l'utente traccia una nuova linea, viene creato un duplicato chiamato dipi, distrutto poi con il metodo removeMovie- Clip(), non appena l'utente rilascia il pulsante del mouse: questo consente di non settare i clip mi ed m2 alla fine della creazione di ogni linea perché, ogni volta che si duplica il clip originale posto nel livello clip, la copia tiene conto delle coordinate iniziali dei Fig. 6 - utilizzando lo stesso meccanismo di programmazione visto in precedenza, si può creare una vera e propria lavagna interattiva. disegna qualcosa cori la matita cancella lutto clip interni. H passaggio più importante è costituito dalla dupli- cazione effettuata a partire dalla riga 31: viene creata una copia della linea appena generata, ogni volta che l'utente rilascia il ta- sto del mouse. Questo meccanismo tiene conto anche delle di- sposizione progressiva delle varie linee sui relativi livelli. A re- golare l'incremento dei vari livelli ci pensa la variabile n, settata inizialmente su 1 e poi incrementata in relazione ad ogni nuova linea creata. Sia il clip maschera, che funge da cornice della lava- gna, sia il clip matita, sono stati posizionati - grazie al metodo at- tadiMovie() - su un livello che prevede un numero altissimo di li- nee disegnate, allo scopo di evitare che le linee tracciate dall'u- tente coprano il bordo della lavagna. Per creare un tasto che fun- ga da gomma, è sufficiente settare l'evento onRelease, riferito al pulsante gomma, con una sintassi del tipo: 1 _root.maschera.gomma.onRelease=function(){ 2 colore=OxFFFFFF; 3 spessore=8; 4orientamento=180; 5} Fig. 7 -Con il metodo duplicate MovieClipf) viene creato un clip, il cui nome è composto dalla parola "traccia" seguita da un numero progressivo n. + P fi O V » (S _root. stage = ction(){ _root .n++; | duplicateMovieClip ["_root . clip", "dipi", 1+n) ; _uoot.clipl.liri! (spessore, colore); _root . clipl.moveTo ( _uoot. clipl. mi. _x, _root.clipl.ml._y) ; _root . a = _root ._xmouse; _root.to = _root ._ymouse; startDragf "_root . clipl .m2 ") ; | } _root. stage ase=_root . stage de= function () { | stopDrag ( ) ; duplicateMovieClip (" iHovieClip (_roo' I } _root . clipl" .clipl) ; ["+ root.n, dove le variabili colore e spessore sono i parametri passati al me- todo lineStyle(), che definisce le caratteristiche della linea ad ogni pressione del mouse, mentre la variabile orientamento regola la proprietà _rotation del clip matita (che si capovolge in modalità gomma). Maurizio Battista WEB 11 WEB POLL CON ASP.NET & WEB MATRIX TUTORIAL Web Poli con ASP.NET & Web Matrix Realizziamo un'applicazione web per effettuare sondaggi grazie alla semplicità e alla potenza del binomio ASPNET e Web Matrix. Sul CD \soft\codice \Web_Poll.zip Fig. 1 - Le funzionalità di Data Administration richiedono componenti client di SQL presenti in MSDEoSQL Server. Viene fornito un link al download (29,5 MB) di MSDE Fig. 2- I primi passi per la creazione del database Web Poli Lm interazione tra l'autore e il visitatore di un sito web * è un fattore che può determinarne il successo. Nel panorama innovativo delle trovate per l'intratteni- ^ mento degli utenti si sta affacciando da alcuni tem- r pi la "moda" dei sondaggi web (web poli). La possi- bilità di dare un giudizio del tutto anonimo su tematiche inte- ressanti per i visitatori e la curiosità di confrontare con uno sfor- zo, che si limita ad un click, la propria idea con quella degli altri utenti, sono fattori di stimolo psicologico che invitano all'uso di quest'utile strumento di indagine. Il sondaggio inoltre può ave- The Data e requires SQL clieni componente on your machine These clier ilable as part of Micros 5rorM5DE, MSDE s a light-weigl t database foi ;rnal web application , to downli . 'Il MSDE. QJ Works... Q Data ^ Open I... | re domande specifiche atte al miglioramento del sito stesso, co- stituendo quindi un possibile metodo di feedback. Le possibili im- plementazioni dell'applicazione Web sono molteplici, ma in que- st'articolo punteremo alla semplicità derivante dall'uso di Web Matrix come ambiente di sviluppo ASP.NET, e la sua totale inte- grazione con MSDE (Microsoft Sql Server 2000 Desktop Engine). L'applicazione web è costituita da tre pagine: polLaspx, vota.aspx e ri- sultati.aspx. L'utente potrà scegliere dalla pagina polLaspx uno dei sondaggi "attivi" (non ancora scaduti) oppure visualizzare i ri- sultati dei sondaggi conclusi (la cui data di "chiusura" delle vo- tazioni è passata). Vota.aspx permette la visualizzazione delle varie possibilità di risposta alle domande dei sondaggi, e presenta un pulsante per esprimere il proprio voto. Per evitare voti multipli in un solo giorno, da parte di uno stesso utente, dovrà effettuare anche controlli sull'indirizzo IP. Subito dopo aver votato, l'uten- te viene indirizzato verso la corrispondente pagina risultati.aspx per osservare i voti degli altri utenti in risposta al sondaggio appena votato. IL DATABASE Web Matrix ha al suo interno un utilissimo database manager che interagisce con MSDE o eventualmente SQL Server 2000, e per- mette la creazione di un database da zero. Il tab Data situato a destra dell'ambiente di sviluppo, ci invita al download gratuito di MSDE nel caso in cui non sia ancora installato. Subito dopo l'in- stallazione e la configurazione di MSDE (avvenuta seguendo le istruzioni fornite nella pagina web del download) all'interno di Web Matrix siamo pronti alla creazione del database che conterrà le informazioni del web poli. Dobbiamo creare due tabelle, Sondaggi e Votanti; quest'ultima verrà Tabella Sondaggi CAMPO TIPO ID_S0ND Int, Richiesto, Chiave Primaria e Autoincremento Domanda Text, Richiesto Datalnizio DateTime, Richiesto DataFine DateTime, Richiesto Opzionel, 0pzione2, 0pzione3, 0pzione4, 0pzione5, Opzioneó Text Votil, Voti2, Voti3, Voti4, Voti5, Voti6 Int Tabella Votanti CAMPO ID ID_S0ND IP Data TIPO Biglnt, Richiesto, Chiave Primaria e Autoincremento Int, Richiesto Text, Richiesto DateTime, Richiesto WEB 13 TUTORIAL Sondaggi Name; Voti6 Data Type: Int d □ Required □ Primary Key F'l= r □ Auto-increme Wai-Lhai First Value: Iniaueidentifie SmallDateTime v utilizzata per evitare voti multipli da parte di uno stesso indi- rizzo IP. Facendo click sul tab data, e successivamente sul pul- sante di "new connection", apparirà una finestra di dialogo per la connessione a un database esistente o la creazione di uno nuo- vo. Un click su "Create new database" all'interno di quella finestra, provocherà l'apertura di un altro form richiedente il nome del database e nel quale dobbiamo inserire WebPoll. A questo punto il tab data mostrerà un menù gerarchico contenente una con- nessione al database, e due voci "Tables" e "Stored Procedures". Non faremo uso di Stored Procedure, per cui selezionando Tables e facen- do click sul pulsante New Item (accanto a new connection) si aprirà una finestra di dialogo per la creazione di una tabella. L'inseri- mento delle informazioni sulla tabella e i campi è sorprenden- temente intuitivo, tanto da non meritare ulteriori spiegazioni. Dobbiamo ripetere la procedura di creazione anche per la tabel- la Votanti. I campi che bisogna inserire e le loro proprietà sono mostrati nelle Tabelle 1 e 2. Ogni sondaggio è identificato da un suo id nella tabella Sondaggi (ID_S0ND), Opzionel sino a 0pzione6, sono sei campi necessari per contenere le risposte al testo del sondaggio contenuto in Domanda. I campi che vanno da Votil sino a Voti6, contengono il numero di voti corrispondenti alle rispet- tive opzioni. In fine, Datalnizio e DataFine indicano l'intervallo tem- porale entro il quale il sondaggio risulta "attivo" e non ancora concluso. La tabella Votanti, invece, ha un ID per ogni voto, ID_S0ND che esprime il sondaggio a cui si sta rispondendo, IP è l'IP dell'utente che ha votato e Data è il campo contenente la da- ta del voto. In questo modo, potremo controllare se un utente (identificato dal suo IP) ha già votato oggi (Data) per un deter- minato sondaggio (ID_S0ND). Ogni sondaggio potrà quindi avere sei risposte possibili e que- sto può essere considerato un limite perché si potevano stabili- re delle relazioni tra tabelle e creare una struttura più flessibi- le con un numero dinamico di opzioni. Il database WebPoll, pur essendo lineare e volutamente semplice, risulta comunque una buona soluzione per la maggior parte delle esigenze dei son- daggi. Inoltre la sua immediatezza permette di focalizzare l'at- tenzione sul codice ASP.NET e gli strumenti offerti da Web Ma- trix. vr WEB POLL CON ASP.NET & WEB MATRIX Fig. 3 - La creazione del tutto intuitiva della tabella Sondaggi Fig. 4 - L'archivio dei sondaggi attivi e conclusi Fig. 5- Il wizard Select Data Method per la generazione di una delle due funzioni che effettuano la query di select sui sondaggi, per determinare quelli attivi o conclusi ARCHIVIO SONDAGGI La pagina poll.aspx si comporta come archivio sondaggi. Dovrà vi- sualizzare e separare i sondaggi che sono ancora attivi e quindi "votatali", da quelli la cui DataFine è già passata. Per i primi dovrà fornire un link alla pagina vota.aspx, passando come parametro l'ID del sondaggio su cui si è fatto click, mentre per i secondi dovrà semplicemente mostrare la pagina dei risultati parametrizzata sempre con l'ID. In Figura 4 è mostrato come appare la pagina una volta completata, in presenza di alcuni sondaggi nel database. File Modifica Visi. iti Strumenti ? jx*] \£\ ■■■}] ^D Cerca Preferiti v ..-/ Multimedia = ©DataFine indica che la data del sondaggio deve essere maggiore di quella odierna (per cui non ancora scaduta). MyQueryConclusi ha la condizione opposta (<). Il segno uguale può essere posto a pia- cimento, in base alla propria volontà di includere o meno il gior- no stesso di scadenza. Al caricamento della pagina verrà esegui- ta la routine di gestione dell'evento: Sub Page Load(sender as Qbject, e as EventArgs) Dim drConclusi as System.Data.SqlClient.SqlDataReader = MyQueryConclusi(DateTime.TodayO) Dim drAttivi as System.Data.SqlClient.SqlDataReader = MyQueryAttivi(DateTime.TodayO) Response.Write("

Web Polk/h1>") Response.Write("

Sondaggi attivi


") while (drAttivi.readQ) Response.Write(drAttivi("DataFine") & " - ") Response.Write("" & drAttiviC'Domanda") & "") Response.Write("
") end While Response.W rite("

") Response.W rite("
") Response.Write("

Sondaggi conclusi


") while (drConclusi.readO) Response.Write(drConclusi("DataFine") & " - ") Response.Write("" & drConclusiC'Domanda") & "") Response.Write("
") end While Response.W rite("

") End Sub Datelime.Today() indica la data odierna fissata all'ora 00.00.00 e viene passata alle due funzioni il cui risultato viene assegnato a due oggetti DataReader: drAttivi e drConclusi. Mediante il ciclo while si re- cuperano tutti i record contenuti nel DataReader e vengono vi- sualizzati esclusivamente i campi DataFine, e Domanda. Per la gene- razione del link col tag html viene recuperato anche l'ID_S0ND. Come facilmente osservabile, i sondaggi conclusi, a dif- ferenza di quelli attivi, non hanno come "target" del link la pagi- na di votazione parametrizzata mediante l'id del sondaggio in questione, ma la pagina dei risultati dello stesso. Nelle query ef- fettuate dalle funzioni abbiamo selezionato tutti i campi della ta- bella Sondaggi, mediante il carattere di asterisco f) per permettere la possibile visualizzazione anche di altri campi all'interno della pagina polLaspx; tuttavia è chiaro che per la nostra implementa- zione sono sufficienti i tre campi ID_S0ND, Domanda e DataFine. LA PAGINA VOTA.ASPX La pagina polLaspx, nel caso dei sondaggi attivi, rimanda alla pagi- na di votazione vota.aspx, alla quale "passa" l'ID del sondaggio co- me parametro visibile e recuperabile mediante il metodo Query- String. L'indirizzo presente nella barra degli indirizzi a cui verremo re-indirizzati avrà un formato simile al seguente: http://localho- st:8080/vota.aspx?id=2 . Il valore 2 del parametro id, indica che stia- mo accedendo alla votazione del sondaggio avente ID_S0ND = 2 nella tabella Sondaggi. La pagina dovrà apparire in maniera analo- ga a quella mostrata in figura (salvo i dati fittizi inseriti). Q***. -@-B@ fljP^c. &^ ( jp M ,., e 0' £ B □ à * ~^\B*> a tua rivista preferita? v„ a! Facendo click sulla veduta Design della finestra principale dell'IDE, appare nella toolbox di sinistra il gruppo Web Controls. Dovremo ef- fettuare dei Drag&Drop di un pannello, una label, sei radioButton e di un button. I nomi da assegnare sono rispettivamente, pnIVotazione (facoltativo), IblDomanda, rbl, rb2, rb3, rb4, rb5, rb6 e btnVota. Potremo sfruttare appieno il gruppo proprietà di Web Matrix senza agire sul codice, per modificare le principali caratteristiche di questi controlli. In particolare è necessario che alla proprietà GroupName dei radiobutton sia assegnato il valore "Opzioni". Per quanto ri- guarda il pulsante, dovremo modificare manualmente il codice (tasto destro -> Edit Tag) ottenendo: WEB Fig. 6 - La pagina per esprimere il proprio voto ad un sondaggio 15 TUTORIAL vr WEB POLL CON ASP.NET & WEB MATRIX In particolar modo onclick="btnVota_Click", permette di attivare la routine di gestione dell'evento denominata btnVota_Click che ana- lizzeremo nel seguito. Al caricamento della pagina, dovremo in qualche modo "associare" la domanda e le opzioni del sondaggio indicato dal parametro ID: Sub Page Load(sender as Object, e as EventArgs) Dim dr As System.Data.SqlClient.SqlDataReader Dim id As Integer = lnt32.Parse(Request.QueryString("id")) if (Not Page.IsPostback) then 'datareader risultante dal metodo MyQuerySondaggi 'avente id del sondaggio come parametro del metodo e della 'query sql dr = MyQuerySondag gi(id) while (dr.ReadO) IblDomanda.Text = drC'Domanda") rb1.Text = dr("0pzione1") rb2.Text = dr ("0pzione2") rb3.Text = dr ("0pzione3") rb4.Text = dr( "0pzione4") rb5.Text = dr( "0pzione5") rb6.Text = dr( "0pzione6") end while end if End Sub ID identifica il sondaggio e viene recuperato con il metodo Query- String. MyQuerySondaggi è del tutto analoga alle precedenti funzioni viste per la pagina poll.aspx e creata mediante i wizard di Web Ma- trix; tuttavia il parametro della query e della funzione è l'ID del sondaggio. Al solito viene restituito un DataReader che ci per- mette di ottenere il valore dei vari campi richiesti e di assegnarli alle proprietà Text dei Web Controls. La parte più complessa risie- de nella gestione dell'evento click: Sub btnVota_Click(sender As Object, e As EventArgs) Dim id As Integer = lnt32.Parse(Request.QueryString("id")) Dim v1,v2,v3,v4,v5,v6, updated, inserted As Integer Dim dr As System.Data.SqlClient.SqlDataReader = MyQuerySondaggi(id) Dim opz As String = Request.FormC'Opzioni") Dim ip As String = Request.ServerVariables("REMOTE_ADDR") Dim oggi As DateTime = DateTime.TodayQ if VotoValido(id) then 'recupero voti attuali while (dr.ReadO) v1=dr("Voti1") v2 = dr("Voti2") v3 = dr("Voti3") v4 = dr("Voti4") v5 = dr("Voti5") v6 = dr("Voti6") end while 'incremento dell'opzione votata Select Case opz Case"Rb1" v1=v1+1 case "Rb2" v2=v2+1 case "Rb3" v3=v3+1 case "Rb4" v4=v4+1 case "Rb5" v5=v5+1 case "Rb6" v6=v6+1 case else exit sub End Select 'update in Sondaggi updated = IVIyUpdateSondaggi(id, v1,v2,v3,v4,v5,v6) 'inserimento in Votanti inserted = MylnsertVotanti(id,ip,oggi) 'redirect al la pagina dei risultati Response. Redirect("risultati.aspx?id=" & id) else Response.Redirect("risultati.aspx?id=" & id) end if End Sub Alla variabile id è assegnato l'ID del sondaggio, ad opz il "nome" del radiobutton selezionato, ip è l'indirizzo IP del visitatore, mentre oggi è la data odierna. Il controllo if... then... else permette di ese- guire il codice solo nel caso in cui non abbia già votato. Per que- sta verifica ci si avvale della VotoValido a cui viene passato l'ID del sondaggio e che restituisce un valore boolean. Il codice necessa- rio, in realtà è solo una leggera modifica della solita "funzione di query" creata da Web Matrix: Function VotoValido(ByVal iD_Sond As Long) As Boolean Dim ipAttuale as String = Request.ServerVariables ("REMOTE_ADDR") Dim DataAttuale as DateTime = DateTime.TodayQ Dim connectionString As String = "server='localhost'; trusted connection=true; Database='WebPoH'" Dim sqlConnection As System.Data.SqlClient.SqlConnection = NewSystem.Data.SqlClient.SqlConnection(connectionString) Dim temp as boolean = true Dim queryString As String = "SELECT [Votanti].[lp], [Votanti].[ID_SOND], [Votanti].[Data] FROM [Votanti] W"& _ "HERE ([Votanti].[ID_SOND] = @ID_S0ND)" Dim sqlCommand As System.Data.SqlClient.SqlCommand = New System. Data.SqlClient.SqlCommand (queryString, sqlConnection) WEB POLL CON ASP.NET & WEB MA TUTORIAL sqlCommand.Parameters.Add("@ID_SOND", System.Data.SqlDbType.lnt).Value = iD SOND sqlConnection.Open Dim dr As System.Data.SqlClient.SqlDataReader = sqlCommand.ExecuteReader( System.Data.CommandBehavior.CloseConnection) while (dr.ReadQ) if ((dr("ip")=ipAttuale) And (dr("Data")=DataAttuale)) then temp = false else temp = true end if end while return temp End Function Il voto non è valido, solo nel caso in cui nella tabella Votanti sia re- gistrato un utente con lo stesso IP, che abbia già votato a que- sto sondaggio (ID_S0ND) nella data odierna. Non è l'unico modo per controllare voti multipli, ma è certamente un compromesso valido, preferibile all'uso di cookies che non sempre sono sup- portati dalle regole del browser in uso. Nel caso in cui il voto non sia valido, l'istruzione successiva al ramo Else, dirige l'utente ver- so la pagina dei risultati. Se il voto è valido, la pagina recupera dalla tabella Sondaggi, mediante il datareader dr, il numero di voti contenuti nei campi che vanno da Votil a Voti6 e li assegna alle va- riabili da vi a v6. L'istruzione SELECT. . .CASE successiva, permette di incrementare di un voto il valore della variabile corrispondente alla scelta effettuata. Se l'utente avrà fatto click sulla seconda opzione, la variabile v2 verrà incrementata. Successivamente vie- ne effettuato un aggiornamento di tale valore incrementato al- l'interno della tabella Sonda®, mediante il metodo MyllpdateSondag- gi. MylnsertVotanti invece si occupa dell'inserimento nella tabella Vo- tanti di una nuova entry, contente l'ID del sondaggio, l'IP del vo- tante e la data odierna. Come ultimo step, abbiamo un redirect verso la pagina dei risultati per mostrare all'utente l'opinione de- gli altri utenti sommata alla sua scelta. MyllpdateSondaggi e Mylnsert- Votanti sono due funzioni create come le funzioni precedenti, ma utilizzando rispettivamente i code builders "Update Data Method" e "Insert Data Method" e modificate manualmente. Entrambe restitui- scono valori interi (assegnati a updated e inserted) corrispondenti al numero di record (normalmente uno) affetti da cambiamento. Si veda il codice sorgente allegato alla rivista per i dettagli delle due funzioni. LA PAGINA RISULTATI.ASPX La pagina risultatì.aspx deve semplicemente mostrare, in maniera graficamente gradevole, i risultati del sondaggio identificato dal- riD passato come parametro nella barra degli indirizzi. Al carica- mento della pagina, la funzione MyQuery (identica a MyQuerySondaggi), si occupa di fornire un datareader contenete tutte le informazio- ni relative ai campi della tabella sondaggi aventi l'ID_S0ND del son- daggio. L'aspetto della pagina è mostrato in Figura 7. La routine di File Modifica Visualizza Q Indietro ~ Q • 1*1 1=1 Ù\P Ce ™ Ìt Prefem %jf Multimedia ®\&'&muà& if E 1 « ti 3 i j= La tua rivista Linux Me. GoiOnLine ioPrograrnrno IdeaWeb Internet Win Magazine preferita? ■ (6%) ■■(14%) ^^^^ (29%) ^(12%) ne ■■■■ (20%) ^^■(19%) Fig. 7 - La pagina dei risultati di un sondaggio gestione dell'evento caricamento di pagina, assegna a delle varia- bili i valori raccolti attraverso il datareader: domanda, le sei opzioni, i sei voti, la Datalnzio e quella di DataFine. A questo punto viene calcola- ta la percentuale dei voti rispetto al totale e assegnata alle varia- bili che vanno da vi a v6. Predisposta una tabella nel codice HTML, sarà sufficiente visualizzare i valori delle variabili contenenti la domanda del sondaggio, le varie opzioni e i valori percentuali. Vo- lendo avere una rappresentazione a istogramma bisognerà predi- sporre un'immagine rappresentante una barra colorata di dimen- sione fissa, da ridimensionare in maniera proporzionale alla per- centuale. Il codice di tutte le sei barre blu accanto alle opzioni, è analogo al seguente: <% Response.Write("" & " (" & vi & "%)")%> 300 è la larghezza dell'immagine scoregif, mentre vi contiene la percentuale di voti dell'opzione 1 sul numero totale di voti delle sei opzioni. Se la percentuale fosse 100%, avremmo l'attributo width = "300100/100" = "300", per cui la barra blu sarebbe visualizza- ta completamente. Se la percentuale fosse del 50% avremmo la barra visualizzata per metà, e così via. Per motivi di arrotonda- mento nel calcolo della percentuale, potrebbe accadere che la somma delle sei percentuali, non dia luogo a un 100% esatto, ma sia affetta da un errore di 1%. Per evitare questo si potrebbe por- re maggiore cura nell'approssimazione, controllando se è per di- fetto o per eccesso, oppure più semplicemente dedurre la per- centuale della sesta opzione (per esempio) sottraendo da 100 il totale delle altre cinque. CONCLUSIONI Web Matrix, attraverso i suoi wizard e l'ottima integrazione con MSDE, ha mostrato ancora una volta le potenzialità nel realizza- re in brevissimo tempo un'applicazione ASP.NET. Un migliora- mento possibile è quello di rendere l'applicazione più flessibile e gestire un numero variabile di opzioni anziché un massimo di sei. Risulta certamente una buona scelta anche l'aggiunta di control- li circa possibili errori dovuti a ID di sondaggio inesistenti o a problemi di connessione con il server. Un'ulteriore ampliamento interessante è quello di inserire un pannello di amministrazione per l'inserimento e l'editing di sondaggi all'interno di un'area ri- servata del sito. Antonio Cangiano " Lato Server COLDFUSION MX INTRODUZIONE Introduzione a ColdFusion MX Un giorno di parecchi anni fa, rientrai a casa con un pacchetto tra le mani. Entrai veloce nella mia stanza e, con un'impazienza indicibile, aprii quella scatola, che conteneva l'oggetto che avevo tanto desiderato nei mesi precedenti. . . il mio primo modem. Sul CI \soft\codice \coldfusion.zip ^p^^ ico icordo l'entusiasmo che provai quando, una volta collegato l'apparecchio, installati i driver e configu- rato l'accesso ad internet, feci il numero del mio pro- vider che, dopo un'attesa che sembrava non finire nai, mi lasciò entrare in quello che allora era un mondo misterioso: Internet. Quelli erano i primi anni del world wide web, anni in cui la grande Rete era vista ancora con diffi- denza e curiosità, anni in cui se dicevi di possedere un indirizzo e-mail ti guardavano come se avessi eseguito a mente una divi- sione a dieci cifre. Poi vennero gli anni dell'entusiasmo, della new-economy, l'era in cui si pensava che con Internet fosse pos- sibile fare tutto, trovare di tutto e, soprattutto, vendere di tutto, anni in cui anche il macellaio sotto casa accarezzava l'idea di un suo sito Internet, così da vendere la carne on-line alla stessa vec- chietta che ogni sera andava personalmente a comperarla. E poi, piano piano, siamo arrivati ai giorni nostri, periodo in cui la Re- te si è oramai dichiarata per quello che è, un'enorme contenito- re di informazioni e di opportunità a disposizione di chi voglia utilizzarlo, pronto a mutare con il cambiare delle mode e delle esigenze e capace unificare razze, religioni e nazionalità in un'u- nica popolazione globale. Sarà forse che lavorando nel settore informatico mi scontro quotidianamente con Internet, ma mi rie- sce difficile immaginare al giorno d'oggi un computer isolato, senza possibilità di accesso alla grande Rete. Internet è entrata nelle nostre vite prepotentemente, e questa veloce divulgazione del mezzo ha portato ad uno studio costante di nuove tecnolo- gie che permettessero di usufruirne meglio e più velocemente, semplificando lo sviluppo di contenuti distribuibili in Rete ed au- mentandone nel contempo la potenza. Nel corso di questo arti- colo verrete introdotti ad uno di questi strumenti, apparso da po- co nella sua ultima versione. Un server web, che rappresenta for- se il più semplice modo di sviluppare contenuti dinamici per In- WEB 18 ternet e che però, a dispetto della semplicità d'uso, propone ca- ratteristiche interessanti per poter essere utilizzato per sviluppa- re applicazioni on-line altamente professionali. ColdFusionMX fa parte di una famiglia di prodotti Macromedia appositamente stu- diati per essere integrati in progetti web-based. Ma vediamo di capirci qualcosa di più. I SERVER WEB Mi perdoneranno i più colti di voi, che già sanno quali sono i compiti che un web-server svolge, ma mi preme introdurre l'ar- gomento per tutti coloro che invece non hanno ben presente di cosa si tratti. Abbiamo detto che il prodotto in questione, Cold- FusionMX è un server web. Ma cosa è un server web? Un server web è quel programma, residente sul computer server, che una volta digitato un indirizzo nel browser, vi restituisce la pagina web che state cercando. Vediamo di spiegare meglio il tutto con un esempio. Ogni volta che provate a caricare una pagina di un sito che vi interessa digitando una stringa di testo nella barra de- gli indirizzi del vostro browser, altro non fate che indicare al vo- stro programma client (il browser) di collegarsi ad un computer server (quello del sito che volete visitare) ad una specifica appli- cazione che risiede su quel computerai server web) comunican- dogli, tramite un linguaggio di scambio di nome HTTP, che vole- te visualizzare una determinata pagina di quel sito. Il server web residente risponde quindi al client inviando al browser la pagina richiesta dall'utente sempre mediante protocollo http. Questo nel caso più semplice. È possibile, infatti, che il server web debba compiere delle azioni prima di poter inviare la pagina al client. Prendete ad esempio il caso in cui la pagina richiesta contenga l'esito di una ricerca eseguita tramite uno dei tanti motori di ri- cerca disponibili in internet. Ovviamente la pagina in questione, anche se è sempre la stessa, dovrà contenere risultati differenti a seconda della parola per cui si è effettuata la ricerca. E chi, se- condo voi, deve occuparsi di modificare i contenuti della sud- detta pagina ogni qual volta essa deve essere visualizzata in ri- sposta ad una nuova ricerca? Bravi, avete risposto bene, il server web. Infatti tutti i server web moderni, anche se in modi com- pletamente differenti, danno la possibilità di interpretare lin- guaggi di scripting server-side in modo da rendere la pagina web dinamica nel contenuto. Quindi, in un esempio più aderente al- la realtà, quando un client invia una richiesta http al server web, gli spedisce anche dei valori che indicano cosa esso desidera vi- sualizzare tra i tanti possibili contenuti di quella pagina. H ser- ver web riceve quei valori, li controlla e costruisce una pagina web personalizzata a seconda delle richieste ricevute dal brow- ser. L'utente non vede tutto questo processo, egli riceve esclusi- vamente la pagina che gli interessa e non si pone il problema di come quei dati siano arrivati sul proprio computer. Dal punto di vista del programmatore che deve fare in modo che ciò accada, la faccenda è piuttosto complessa. H primo tra i tanti problemi da affrontare quando si inizia a sviluppare un'applicazione web a contenuto dinamico è: che tecnologia utilizzerò? Oggigiorno ne esistono molte, ma le più conosciute sono soprattutto tre: COLDFUSION MX | INTRODUZIONE • La piattaforma .NET di Microsoft, programmabile per appli- cazioni web con il suo linguaggio ASP.NET ed utilizzabile con il server web Internet Information Services sempre di Micro- soft. • La piattaforma Java, programmabile con il linguaggio JSP e tramite blocchi di codice Java chiamati Servlet, ed utilizza- bile con il server web Tomcat disponibile gratuitamente. • La piattaforma MX, programmabile con un linguaggio a tag chiamato CFML ed utilizzabile con il server web ColdFu- sionMX di Macromedia. Tutte e tre le piattaforme hanno pregi e difetti, ma mentre le pri- me due hanno una curva di apprendimento piuttosto lenta, la terza è stata sviluppata con l'intento di renderla più immediata e intuitiva possibile. È di lei che parleremo nel corso dell'articolo e, imparando a conoscerla, vi accorgerete di come sia possibile, attraverso questo prodotto, arrivare presto e con semplicità, a svolgere compiti che con altre tecnologie richiedono un impegno molto, molto più elevato. La piattaforma Coldfusion è adatta per i neofiti quindi, ma ben si presta anche a chi cerca soluzioni pro- fessionali di semplice implementazione poiché, come vedremo, tanta semplicità non inficia affatto la potenza del prodotto. Ma ora basta con le chiacchiere ed andiamo a vedere veramente co- me poter utilizzare questo gioiellino messo a nostra disposizio- ne. COLDFUSION MX Una volta in possesso del prodotto in questione, occorre instal- larlo sul proprio computer, seguendo una procedura piuttosto semplice che andiamo subito a vedere. Dopo le prime schermate, che richiedono i dati dell'utente e i codici del prodotto, la prima schermata interessante che appare è quella riguardante la scelta del server web da utilizzare per utilizzare il prodotto. A questo punto potreste chiedervi: ma come? Sto installando un server web e mi si chiede quale server web utilizzare? In effetti è così, infatti ColdFusion analizza il sistema in cui viene installato e controlla la presenza di eventuali altri web server già presenti. Nel caso che durante l'installazione vengano trovati altri server web, viene messo l'utente nella condizione di scegliere se conti- nuare ad utilizzarne uno preesistente per analizzare tutte quelle richieste http che non necessitano dell'utilizzo di ColdFusion, nel qual caso il prodotto si limita a processare esclusivamente le ri- chieste web che lo interessano, oppure scegliere ColdFusion per assolvere tutte le richieste http che pervengono al server stesso. In ognuno dei due casi, il server ColdFusion viene installato ed è possibile accedervi collegandosi alla porta 8500 del proprio com- puter. Nei nostri esempi si utilizzerà esclusivamente il server ColdFusion per processare le pagine che via via realizzeremo. La schermata successiva della procedura di installazione riguarda la directory nella quale si desidera installare il prodotto, ed è se- guita da un'altra pagina che invece richiede il tipo di installazio- Lato Server ne da effettuare. Di norma non è necessario modificare le impo- stazioni predefinite di queste pagine. Subito dopo queste scher- mate si arriva alla richiesta di una password come Amministrato- re e come RDS User. Una volta immesse tali password l'installa- zione è praticamente ultimata e non resta altro da fare che la- sciare il tempo al sistema di configurare il prodotto secondo i pa- rametri scelti. Bene, ora avete ColdFusion installato sul vostro computer, non rimane che iniziale ad utilizzarlo per realizzare qualcosa di funzionante. LA PRIMA APPLICAZIONE Come primo esempio, per saggiare la semplicità d'uso e la po- tenza del prodotto, realizzeremo una pagina web che ci permet- te di eseguire interrogazioni su un database che andremo a crea- re. I prodotti concorrenti illustrati prima, offrono tutti questa funzionalità in modo relativamente semplice da implementare, ma sfido chiunque a trovare un modo più immediato di quello implementato in Coldfusion. . Una prima cosa importante da dire riguardo al prodotto trattato, è che esso viene fornito come servizio, quindi non c'è un vero e proprio file eseguibile. In effetti, esso è sempre attivo sul nostro computer, e per accedervi è sufficiente collegarsi alla porta 8500 tramite browser. Vedremo più in là come procedere per utilizza- re le funzioni di cui necessitiamo. Ma iniziamo ad interessarci al- l'esempio. Prima di tutto occorre creare il database che ci servirà per estrar- re i dati di cui abbiamo bisogno: Microsoft Access è più che suf- ficiente al nostro scopo. Avviate quindi Access e create un Data- base di nome "dbProva" formato di una sola tabella che chiamere- mo Persone. La tabella in questione possiederà tre campi, di nome nome cognome età. Se non disponete di Access o non sapete come utilizzarlo, potete prelevare dal CD allegato alla rivista quello re- lativo all'esempio che stiamo costruendo. Una volta in possesso del database, occorre popolarlo con dei dati fittizi che possano WEB 19 Fig. 1 -Ammini- strazione di Coldfusion. Lato Server COLDFUSION MX INTRODUZIONE essere richiamati. Immettete quindi dei nomi, cognomi ed età a piacimento fino a riempire almeno 5 o 6 record. Ovviamente se prelevate il database dal CD, esso è già riempito con dei dati e pronto per essere utilizzato. Per fare in modo che questo data- base possa essere in qualche modo gestito dalla nostra applica- zione web, occorre che il server sia in grado di connettervisi. Oc- corre quindi mettere al corrente ColdFusion che abbiamo creato il nostro database e che vogliamo utilizzarlo per ricavarne dei dati. Per fare ciò si deve accedere al pannello principale dell'ap- plicazione, in un modo però, che non tutti sono abituati a uti- lizzare. Ho spiegato prima che ColdFusion è effettivamente sempre atti- vo sul nostro computer e per utilizzarlo occorre collegarsi sulla porta 8500 del computer, ma come fare in pratica per utilizzare questa applicazione? Nel menù di avvio della barra degli stru- menti, sotto la voce Start -> Programmi -> Macromedia ColdFusion ap- paiono diverse icone che riportano le voci Administrator, Documenta- tion, Getting Started, etc.etc. In realtà queste icone altro non sono che collegamenti a pagine web presenti sul proprio PC, che for- niscono un'interfaccia con la quale comandare il programma. Proviamo a caricare la pagina di Amministrazione, che poi è quella che utilizzeremo per impostare il collegamento al nostro database. Se osservate nella barra degli indirizzi del browser, che si apre appena cliccato sull'icona, noterete che l'indirizzo della pagina caricata inizia per http://localhost:8500/. In effetti è un indirizzo un po' differente dai soliti che siamo abituati a vede- re. Le differenze sono date dalla parola localhost e da quel nu- mero che la segue dopo i due punti. Localhost, altri non è che un modo per far capire al nostro browser che il file che cerchia- mo non è in internet ma sul nostro computer e, per trovarlo, dobbiamo connetterci alla porta 8500 (il numero dopo i due punti) e seguire tutto il percorso che viene riportato nel resto della stringa. Il connettersi a quella determinata porta, che cor- risponde appunto a quella dove è in ascolto ColdFusion, fa in modo che le informazioni passino per il nostro server web, così da rendere possibile la comunicazione con il prodotto. Ma ritor- niamo al nostro pannello di amministrazione. Una volta immes- sa la password, che è la stessa che avete specificato durante l'in- stallazione, sarete liberi di accedere a tutti gli strumenti che vi consentono di gestire tutto il server web, con tutti possibili siti associati. Ciò che ci serve ora, dicevamo, è permettere ad una nostra ap- plicazione di utilizzare il database che abbiamo realizzato. Per farlo, dobbiamo seguire pochi semplici passi: • Fate click sul link Data Sources presente sotto la voce DATA & SER- VICES nella colonna di collegamenti sulla sinistra del pannel- lo di amministrazione. • Nel campo di testo Add New Data Source della casella Add New Da- ta Source, inserire un nome di riferimento per il database che vogliamo registrare. Sarà grazie a questo nome che potremo poi riferirci al db in questione. Il nome che sceglieremo sarà Prova. WEB 20 • Nella casella combinata sottostante, dove trovate scritto Dri- ver, dovete selezionare il tipo di driver da utilizzare per ge- stire il database in esame. Essendo questo db sviluppato con Microsoft Acces, non dovete far altro che selezionare questa voce dall'elenco. • Premete ora il tasto Add presente alla fine della casella. Ver- rete trasportati in un'altra pagina dove dovrete indicare do- ve si trova fisicamente il vostro database. • Premete il pulsante Browser Server corrispondente alla casella di testo Database File, verrete trasportati in un'altra pagina che vi permetterà di selezionare il database cercandolo nel si- stema. • Trovate il vostro Database e, dopo averlo selezionato, pre- mete il tasto Apply che vi riporterà alla pagina precedente. • Ora che il file di database è selezionato, non rimane altro da fare che premere sul pulsante Submit. Una volta completata questa serie di passaggi, dovreste vedere nella lista di sorgenti dati disponibili, anche la nuova appena creata con il nome Prova. Se nella casella Status trovate segnalato ok, significa che ColdFusion ha verificato il collegamento e rie- sce a comunicare con il db. Una volta controllato che il databa- se viene effettivamente riconosciuto dal sistema, altro non ri- mane che realizzare la pagina che il nostro server deve interpre- tare e nella quale deve, con criteri che dobbiamo fornire noi, vi- sualizzare la risposta che desideriamo. Per scrivere la nostra ap- plicazione ColdFusion, abbiamo prima di tutto bisogno di un editor di testo. Va bene di tutto, anche il semplice blocco notes di Windows, basta avere l'accortezza di salvare il file prodotto con il nome ProvaCFML e l'estensione .cfm. Una volta aperto l'edi- tor digitate il codice seguente: Prova CFML SELECT * FROM Persone
Contenuto del database di esempio:
#nome# #cognome# #eta# COLDFUSION MX INTRODUZIONE Lato Server
Come potete vedere, il file prodotto altri non è che semplice html con delle aggiunte, sempre però sotto forma di tag, che aggiun- gono funzionalità al nostro codice. Il linguaggio che ci permet- te di comunicare con ColdFusion, infatti, viene espresso sotto forma di tag, in tutto e per tutto simili ai normali tag html. Ma andiamo a vedere il funzionamento della pagina nel dettaglio. COME FUNZIONA COLDFUSION Il listato di esempio inizia con le normali dichiarazioni che iden- tificano l'inizio, la testa e il corpo del documento html, e prose- gue con il primo vero tag CFML. Identificare i tag CFML è sem- plice in quanto iniziano tutti con i medesimi caratteri Q then response.cookies("user_email") = "" response.cookies("user_password") = "" session.abandonQ end if %> <% 'email e password sono già memorizzati in cookie? if len(request.cookies("user_email"))>Q then 'rileva i dati contenuti nei cookie dim email, password email = request.cookiesC'user email") password = request.cookies("user_password") response.redirect("login.asp?email="&email&"&password= "&password) end if %> LoginForm - Sezione Protetta
LOGIN F0RM
 EMAIL
 
 PASSWORD:
  ;
Nella prima parte della pagina viene fatto un controllo sull'eventuale presenza della variabile err all'interno del- la querystring: se presente significa che si è stati redire- zionati al form di login dopo che si è verificato un erro- re nella pagina login.asp dove viene effettuata l'autentica- zione vera e propria; in tal caso vengono eliminati even- tuali cookie di memorizzazione dei dati utente (vedremo in seguito cosa contengono questi cookie), viene abban- donata la sessione (eliminazione di tutte le variabili ed oggetti di sessione) e viene semplicemente visualizzato il form per l'inserimento dei dati di login. Insomma, un ve- ro e proprio reset dell'applicazione. Il secondo controllo di questa pagina riguarda la (già ci- tata) presenza o meno dei cookie di memorizzazione di email e password sul pc dell'utente. Per fare ciò si con- trolla la lunghezza del cookie user_email: se uguale a zero, significa che il cookie non è presente, se maggiore di ze- ro il cookie è effettivamente presente. Nel primo caso viene visualizzato il form per il login, co- me di norma; nel secondo caso, invece, i dati presenti nei cookie relativi a email e password vengono letti e memo- rizzati in variabili temporanee e poi direttamente inviati a login.asp tramite la querystring; il redirect viene effet- tuato in questo frangente per cui, in questo caso, non verrà visualizzato alcun form di login, ma verrà effettua- ta subito l'autenticazione sul database utilizzando i dati appena letti dal cookie. Proseguendo, all'interno della creazione del form, trovia- mo il già menzionato checkbox che l'utente potrà sele- zionare per "farsi ricordare" dal sistema e i due link a for- gotpass.asp e registerform.asp. Nel secondo caso abbiamo utilizzato un normale tag
mentre nel primo link abbiamo creato il link in modo tale che esso apra una piccola popup, utilizzando quindi una funzioncina Javascript che racchiude la clas- sica window.open, funzione Javascript che apre una nuova fi- nestra definita dai valori dei parametri che le vengono passati nella chiamata. L0GIN.ASP A differenza della pagina login.asp dell' applicazione base che abbiamo realizzato il mese scorso, questa nuova ver- sione presenta un paio di novità. Innanzitutto i dati del- l'utente non sono più prelevati da un form tramite il me- todo Request.Form ma, potendo essi essere inviati sia dal form che tramite la querystring (nel caso di cookie me- morizzati), viene utilizzato il metodo Request che, essendo più "generico", consente di "coprire" i valori delle varia- bili sia che esse siano inviate tramite un submit di un form sia che esse siano passate tramite la querystring. Come sottolineato più volte nella prima parte dell'artico- lo, il punto chiave di login.asp è la ri- cerca nel database dei dati inviati dall'utente e, in caso di autenticazio- ne avvenuta con esito positivo, l'i- stanziamento di una variabile di ses- sione sessionfuserlogged") che servirà come "biglietto da visita" per tutte le pagine riservate del nostro sito. In questo caso, oltre a ciò, verifichere- mo se l'utente avrà selezionato o me- no il checkbox "remember me" per indicare all'applicazione la sua vo- lontà di essere "ricordato" nei suoi prossimi accessi. Per fare ciò, basta verificare che la lunghezza della request.form("remember") sia maggiore di uno; in tal caso istanzieremo due cookie, user_email e user_password, che conterranno rispettivamente le stringhe corrispondenti all'e-mail e alla password del- l'utente e a cui assegneremo (ragionevolmente) scaden- za pari a trenta giorni a partire dall'istante dell'autenti- cazione. Infine, se l'autenticazione si concluderà corret- tamente l'utente verrà redirezionato a riservato.asp, la pa- gina a contenuto protetto del nostro sito. In caso contra- rio, cioè se l'autenticazione avrà esito negativo, il client verrà reinviato a loginform.asp in cui si avrà la visualizza- zione del form con messaggio d'errore connessa all'elimi- nazione degli eventuali dati utente memorizzati all'inter- no dei cookie. Vediamo il listato completo di login.asp: email = replace(request("email"), ' ") password = r eplace(re quest("password"), ' <% 'rileva i dati inviati dal form o dalla querystring dim email, password WEB 24 dim cn, rs, sql 'connessione al database set cn = Server.Cre ateObjectC'ADODB.Co nnection") cn.Open "driver={Microsoft Access Driver (*.mdb)};dbq=" & Server.lVlapPathC'sezioneprotetta.mdb") sql = "SELECT ID, EMAIL, PASSWORD FROM users WHERE EMAIL='"&email&"' AND PASSWORD='"&password& 'cerca l'utente nel database set rs = cn.execute(sql) 'utente trovato if not rs.eof then session("userlogged") = true 'memorizza dati utente in cookie if len(request.form("remember"))>0 then response.cookies("user_email") = rsC'EMAIL") response.cookiesC'user email").expires = dateaddC'd", 30, nowQ) response.cookies("user_password") = rsC'PA SSWORD") response.cookies("user_password").expires = dateaddC'd", 30, nowQ) %> RISERVATO.ASP Veniamo ora alla pagina protetta dell'applicazione. Ri- spetto alla versione base implementata nella scorsa lezio- ne l'unica differenza è che, nel caso l'utente decida di uscire dall'ambiente riservato, oltre a venire chiusa la sessione con il comando Session.Abandon, vengono anche eliminati gli eventuali cookie di memorizzazione di nome utente e password tramite l'assegnamento ad essi di stringhe nulle. Eccone il listato: <% 'se l'utente non si era autenticato redirezionalo al form di login if not session("userlogged") then response.red irectC'Iog inform.asp") end if 'se l'utente precedentemente autenticato vuole uscire if request.querystring("action")="logout" then response.cookies("user_email") = "" response.cookies("user_password") = "" session.abandonQ response.redirectC'Ioginform.asp") end if %> Pagina principale - Sezione Protetta ASP CREIAMO LA SEZIONE PROTETTA DEL NOSTRO SITO Lato Server if errcode="email" then Utente autenticato.
Stai visualizzando una pagina ad accesso riservato.
Clicca qui per uscire. REGISTERFORM.ASP Analizziamo ora la prima delle due pagine dedicate alla registrazione di nuovi utenti (nel database utenti appun- to). In questa pagina avremo una prima parte di visua- lizzazione form molto simile al form per rinserimento dei dati per l'autenticazione, quindi composta da un campo per l'inserimento della propria e-mail e da un campo per rinserimento della password scelta che si desidera utiliz- zare in futuro per l'autenticazione. Segue un classico bottone di submit che consente di inviare il form a regi- sterform.asp (vedremo poi le funzionalità di questa pagi- na). In coda, viene verificata l'eventuale presenza dell'e- lemento err all'interno della querystring; utilizzeremo ta- le variabile per passare eventuali messaggi d'errore dalla pagina in cui tenteremo di effettuare la registrazione ve- ra e propria dell'utente all'interno del database. A se- conda dell'errore verificatosi essa permetterà di visualiz- zare tre tipi di messaggi differenti che indicheranno al- l'utente di quale tipo di problema si sta trattando. Segue il (piuttosto semplice) listato di registerform.asp: RegisterForm - Sezione Protetta <% dim errcode errcode = request.querystringC'err") if len(errcode)>0 then %> <% end if %>
REGISTRATA F0RM
<% response.writeC'Devi inserire un indirizzo email!") elseif errcode="password" then response.writeC'Devi scegliere la password che intendi utilzzare per l'accesso alla tua area riservata!") elseif errcode="mailexist" then response.writeC'Esiste già un utente con lo stesso indirizzo e-mail!") end if %>
Ecco come dovrebbe apparire il form di registrazione: REGISTRATICI FORM Indirizzo e-mail: Password: REGISTRAMI » Fig. 1 - Form di registrazione nuovo utente REGISTER.ASP In questa pagina avviene la registrazione vera e propria del nuovo utente o, per lo meno, il tentativo di registrazione dell'uten- te. Lo script si apre con la lettura dei valori di email e password diretta- mente dal form; segue l'apertura del- la connessione al database. Prima di effettuare l'inserimento nella tabella controlliamo che l'utente non abbia immesso dati nulli; in caso di valori nulli, a seconda di quale sia l'infor- mazione non inserita, assegneremo la stringa "email" o "password" alla variabile err, variabile che stiamo utilizzando per memorizzare l'even- tuale errore da passare a registerform.asp. Attenzione, nel caso dell'email, quello che facciamo è semplicemente un controllo sul fatto che sia di lunghezza maggiore di zero (come per la password del resto); un controllo più accu- rato richiederebbe anche la verifica della correttezza sin- tattica dell'indirizzo e-mail stesso ma tale trattazione esula dagli scopi di questo articolo; per un'analisi più COOKIE Un cookie è un file temporaneo memorizzato sul PC client e che può essere successivamente letto e/o modificato da altre pagine del "sito" che lo ha creato. È possibile impostarne la scadenza in modo da poterlo utilizzare in ses- sioni di navigazione successive. WEB 25 Lato Server ASP CREIAMO LA SEZIONE PROIETTA DEL NOSTRO SrTO approfondita della verifica della validità di un indirizzo e-mail rimando al seguente articolo disponibile in linea in cui sono prese in esame due varianti di tale applica- zione, sia con le funzioni ASP tradizionali, sia con l'uti- lizzo delle Regular Expression: http://www.aspcode.it/articoli /articoli.asp?actl=show_art&idx=89 Torniamo a noi. A questo punto viene verificato che nel database non sia già pre- sente Tindirizzo e-mail scelto dall'utente; nel caso risul- ti già registrato, lo script assegna il terzo valore possibi- le, "mailexist", alla variabile err. A questo punto, se non si sono verificati i sovracitati errori, lo script inserisce email e password indicate dall'utente all'interno della tabella users del database sezioneprotetta.mdb utilizzando una normale query SQL di inserimento ("INSERT INTO..."). Nel caso in cui si siano verificati errori, l'utente viene redirezionato a registerform.asp, pagina nella quale cui si troverà mostrato nuovamente il form di registrazione con, in aggiunta, il relativo messaggio di errore. Register - Sezione Protetta %> <% dim email, password email = request.form("email") pass word = request.form("password") dim cn, rs, sql set cn = Server.Cre ateObjectC'ADO DB.Connection") cn.Open "driver={Microsoft Access Driver (*.mdb)};dbq=" & Server.MapPathC'sezioneprotetta.mdb") dim err 'indirizzo email non immesso? if len(email)=0 then err = "email" 'password non immessa? elseif len(passw ord)=0 then err = "password" 'prova a registrare il nuovo ut ente else email = rep lacetemail, ' ") password = r eplacetpa ssword, ' ") sql = " SELECT ID FRO M users WH ERE EMAIL= m &email&" set rs = cn.e xecute(sql) 'se non c'è già un utente iscritto con quell'indirizzo email if rs.eof then sql = "INSERT INTO users(EMAIL, PASSWORD) "&_ "VALUES('"&ema il&'" > '"&password&"')" cn.execute(sql) WEB 26 Fig. 2 - Form di inserimento indirizzo e-mail per la richiesta della password personale. - Registrazione avvenuta con successo
- Effettua i login » <% 'se l'indirizzo email è già iscritto %> FORGOTPASS.ASP Come accennato nella presentazione della struttura del- l'applicazione, questa pagina ha la funzione di inviare via e-mail la password agli utenti che la dovessero avere malcapitatamente perduta. La pagina ne racchiude in sé due: se essa viene richiamata senza alcun valore all'in- terno della querystring, essa visualizza un form con un unico campo di input che l'utente utilizzerà per inserire il suo indirizzo e-mail, quello utilizzato al momento del- la registrazione, per intenderci. Il form viene inviato al- la pagina stessa ma con un valore di variabile all'inter- no della querystring; ecco l'uri associato all'action del form: forgotpass.asp?actl= send. Ed ecco l'aspetto del form per la richiesta della pas- sword: Quando la pagina viene richiamata con actl=send, viene eseguita la seconda porzione del codice in essa conte- nuto e precisamente l'invio in e-mail dei propri dati al- l'utente che ne ha appena fatto richiesta. Il primo step è la ricerca dell'indirizzo e-mail all'interno del database; in caso di mancata corrispondenza viene visualizzato un messaggio di errore con l'invito a riprovare correggendo l'indirizzo immesso. Se la ricerca ha esito positivo ven- gono eseguite le righe di codice successive che, tramite l'oggetto CDONTS (comunissimo oggetto per l'invio di messaggi e-mail tramite script lato server), spediscono nome utente e password all'utente che le ha richieste, accompagnate da un gentile messaggio di saluto. In questa sede non ci soffermeremo sui dettagli dell'invio ASP CREIAMO LA SEZIONE PROTETTA DEL NOSTRO STO Lato Server di un messaggio e-mail tramite ASP, argomento che tratteremo in futuri articoli e a cui potrete comunque intanto approcciare tramite un breve script raggiungibi- le al seguente uri: http://www.aspcode.it/articoli/articoli.asp?actl= show_art&idx=2. Di seguito è riportato il listato completo di forgotpass.asp: Ricorda Password <% 'se visualizzi il forni if Ien(re quest.que rystring("act1"))=0 then %>
Se hai dimenticato la password per l'accesso all'area utenti, inserisci l'indirizzo e-mail che hai utilizzato al momento dell'iscrizione, clicca sul pulsante INVIA. Entro pochi secondi ti verrà inviata la tua password.
E-MAIL &n bsp;
Questo indirizzo non è iscritto all'area riservata.


< < Torna indietro
<% else 'invia l'email con la password dim mail set mail = Server.Crea teObjectC'CDONTS.NewMail") mail.From = "info@miosito.com" mail.To = rsC'EMAIL") mail.Subject = "Dati area utente" mail-Body = "Gen tile utent e,"&vbcrlf&_ "ecco i dati per l'accesso alla tua area riservata:"&vbcrlf&vbcrlf&_ "E-Mail: "&rs("EMAIL")&vbcrlf&_ "Password: "&rs("PASSWORD")&vbcrlf&vbcrlf&_ "A presto."& vbcrlf&v bcrlf&_ "Lo staff" mail.lmportance = 2 mail.Send set mail = no thing 'fine invio email con password %> <% end if rs.close set rs = no thing cn.close set cn = no thing end if %> CONCLUSIONI E SVILUPPI In questa seconda parte relativa alla realizzazione di un'area ad accesso riservato possiamo finalmente dire di aver completato e reso molto più funzionale l'appli- cazione di cui, nel precedente lavoro, avevamo solo creato l'ossatura. Il progetto qui svolto potrà essere adattato ed utilizza- to come base per tutte le sezioni di siti web in cui si renda necessario creare un "confine" ad accesso con- sentito solamente a un limitato gruppo di utenti. Paolo Capitani WEB 27 Sul CD soft\codice\Post- card.zip Lato Server Cartoline in PHP In questo articolo vedremo come realizzare in PHI? tramite l'ausilio della libreria grafica GD, un semplice servizio per l'invio di cartoline virtuali. Cartoline: reali o virtuali? Molti di noi, maga- ri durante qualche spensierata navigazione tra i siti più "allegri" del web, avranno avu- to modo di utilizzare uno dei tanti servizi per l'invio di cartoline virtuali. No vi è anco- ra capitato? Uhm... strano! Comunque vediamo in- sieme di cosa si tratta... Tutti conosciamo il "principio di funzionamento" del- la cartoline illustrate; sono quei simpatici gadget fondamentalmente composti da una fotografia o un'illustrazione, inviati, tramite posta tradizionale, da chi si trova in viaggio in giro per il mondo ai ri- spettivi parenti e amici. Il loro scopo principale è quello di inviare un ricordo ad una persona cara, con tanto di dedica e firma da parte del "viaggiatore". In realtà oggi ogni occasione è buona per inviare del- le cartoline: compleanni, ricorrenze, eventi, ecc. Quindi appare ovvio come un simile sistema di co- municazione sia stato "clonato" anche nel mondo te- lematico, in modo da poter scambiare non più carto- line reali, composte cioè da carta, e francobolli, ma dei messaggi virtuali. Come anticipato, in giro per la rete è facile imbatter- si in numerosi siti che offrono servizi di questo gene- re, permettendo di inviare cartoline virtuali ai nostri amici. Quando le cartoline virtuali fecero la loro pri- ma apparizione su Internet erano semplicemente composte da un'immagine e un testo che il "mittente" intendeva recapitare al "destinatario", il quale riceve- va tramite email un messaggio di notifica che lo avvi- sava della presenza di una cartolina a lui indirizzata, con il relativo link da seguire per poterla visualizzare. La cartolina in questione era formata da una sempli- ce pagina HTML composta, naturalmente, dall'imma- gine scelta e dal testo inviato; i servizi più evoluti fa- cevano scegliere anche il tipo di carattere da utilizza- re, il colore di sfondo, la disposizione del testo e co- sì via. Con lo sviluppo delle tecnologie legate al web, soprattutto grazie all'introduzione delle animazioni in Flash, anche le cartoline virtuali hanno cambiato forma, trasformandosi in veri e propri documenti PHP CARTOLINE multimediali con tanto di musica ed animazioni. PROGETTIAMO L'APPLICAZIONE In questo articolo realizzeremo un semplice sistema per la creazione e l'invio di cartoline virtuali di tipo "tradizionale", cioè composte solo da immagini e te- sto, ma un po' diverso da quelli che siamo abituati a vedere. Nei sistemi classici, l'invio di una "cartolina virtuale" comporta la memorizzazione, sul server che ospita il servizio, dei dati (immagine e testo) impo- stati dal mittente, ed il conseguente invio, al destina- tario, di un'email di notifica. La cartolina, realizzata tramite codice HTML, verrà creata nel momento in cui il destinatario seguirà il link indicato nell'email di no- tifica, che lo condurrà al sito che offre il servizio, più precisamente nella pagina che contiene la cartolina a lui destinata. Tuttavia le informazioni necessarie a comporre la cartolina vengono memorizzate sul server che ospita il servizio e qui risiederanno per un perio- do di tempo prefissato; se il destinatario non dovesse accorgersi dell'email di notifica, o semplicemente se ne accorgesse troppo tardi, certamente non trovereb- be traccia del messaggio a lui inviato. Oppure, cosa succederebbe se il destinatario volesse conservare la cartolina che ha appena ricevuto? Di certo sarebbe un po' scomodo salvare tutti i documenti (sorgente HTML e immagini) che compongono la cartolina. Per risolve- re questi piccoli inconvenienti, e per meglio riportare nel mondo "virtuale" il funzionamento delle cartoline del mondo "reale", il nostro sistema funzionerà in mo- do un po' diverso. Le cartoline che realizzeremo sa- ranno composte da un'unica immagine nella quale verranno "incollati" tutti i componenti della cartolina stessa; in seguito questa sarà inviata direttamente nell'email del destinatario sotto forma di attach. In questo modo il mittente potrà essere certo che la car- tolina sarà recapitata al destinatario e quest'ultimo, naturalmente se troverà la cartolina di suo gradimen- to, potrà conservarla con la stessa semplicità con la quale si copia un file. Analizzando più in dettaglio la struttura del servizio che intendiamo realizzare possiamo individuare i pas- si che il mittente dovrà eseguire per inviare la propria cartolina: • scelta dell'immagine da applicare; • inserimento dei dati del destinatario e testo del- la cartolina; • visualizzazione dell'anteprima ed invio; WEB 28 PHP CARTOLINE Lato Server Per gestire in modo semplice le fasi di anteprima ed invio della cartolina faremo in modo di memorizzar- la, una volta creata, sul filesystem, in una apposita directory, sotto forma di file JPEG. In questo modo tutte le volte che la cartolina dovrà essere utilizzata (ad esempio per essere visualizzata sul browser o per essere spedita) non dovrà essere creata nuovamente. Non dobbiamo infatti dimenticare che la creazione della cartolina comporta la manipolazione di imma- gini, operazione che, soprattutto se ripetuta più vol- te per lo stesso cliente, potrebbe incidere negativa- mente sulle prestazioni del sistema. STRUMENTI NECESSARI E STRUTTURA DELLA CLASSE Naturalmente il servizio sarà implementato utilizzan- do il linguaggio di scripting PHP (http://www.php.net) con l'ausilio della libreria grafica GD (http://www.boutell.com /gd/), capace di generare e manipolare immagini nel formato JPEG, PNG e WBMP. Versioni precedenti di questa libreria possono mani- polare anche il più diffuso formato GIF, ma dalla 1.6 è stato eliminato a causa dell'algoritmo LZW, utiliz- zato dal formato GIF per la compressione delle imma- gini, di proprietà della Unisys. Per poter implementa- re questo servizio, per prima cosa dobbiamo accer- tarci che l'installazione del PHP di cui disponiamo, abbia il supporto abilitato per la GD. Per avere queste informazioni ci basterà preparare uno script conte- nente la chiamata alla funzione phpinfo() e successiva- mente invocarlo dal browser. Tra le informazioni che ci verranno restituite troveremo anche quelle relati- ve alla libreria GD (Figurai). r gd GD Support enabled GDVersion 2.0 or higher FreeType Support enabled FreeType Linkage with freetype JPG Support enabled PNG Support enabled WBMP Support enabled -^ a ^ m <& | Altrimenti possiamo attivare il supporto per la libre- ria GD intervenendo sul file di configurazione del PHP. In particolare, su sistemi Windows dovremo ag- giungere (o decommentare) la linea: extension=php_gd2.dll Fig. 1 - Output della funzione phpinfoO mentre su sistemi Linux, partendo dai sorgenti, do- vremo prima configurare il tutto tramite: ./configure --with-gd e poi compilare ed installare con i consueti: make; make instali A questo punto possiamo dedicarci allo sviluppo ve- ro e proprio dell'applicazione, che sarà realizzata uti- lizzando la programmazione ad oggetti, in modo da creare un'unica classe (PW_postcard) dotata di tutte le funzioni necessarie per la creazione e l'invio delle cartoline. Inoltre, per l'invio vero e proprio della car- tolina, faremo uso della classe smtp, implementata nel precedente numero della rivista. I metodi principali di cui disporrà la classe PW_post- card saranno show() e send(); com'è facile intuire il pri- mo servirà a visualizzare sul browser un'anteprima della cartolina da inviare, il secondo invece avrà il compito di contattare il server SMTP e di inviare la cartolina: function showQ { if ( !$this->_created ) $this->_createPostcard(); echo "_tmpfile."\">"; function sendQ { if (!$this->_created) $this->_createPostcard(); $client=new smtpQ; $client->from["name"]=$this->mail_from; $client->from["email"]=$this->mail_from; $client->to=$th is->to; $clie nt->subject=$this->mail_subject; $client->body=$this->mail_text; $client->add_attachment( $this->_tmpfile > "image/jpeg" > "base64"); $client->connect($this->SMTP,$this->SMTP_PORT); $client->sendmail(); $clie nt->close(); 1 Naturalmente la classe conterrà altri semplici metodi i cui compiti saranno quelli di fornire all'oggetto tut- WEB 29 Lato Server PHP CARTOLINE te le informazioni necessarie per la corretta composi- zione ed invio della cartolina. Entrambi i metodi show() e send() faranno uso del _crea- tePostcard(), il quale si occuperà della creazione della cartolina attraverso le funzioni messe a disposizione dalla libreria GD e della sua memorizzazione in una directory temporanea, che per default è la tmp, che deve essere presente nella stessa directory dello script che utilizza l'oggetto PW_postcard: function _createPostcard() { $source_size=getimagesize($this->img); $src=imagecreatefromjpeg($this->img); $n_righe=10; $dest_size[0]=$source_size[0]+16; //nuova larghezza $dest_size[1 ]=$source_size[1 ]+8+$n_righe*1 2; // nuova altezza $dest=imagecreatetruecolor($dest_size[0],$dest_size[1]); $bgcolor=imagecolorallocate($dest,25Q, 255,21 5); $fgcolor=imagecolorallocate($dest,Q,0,0); imagefill($dest,1,$source_size[1]+1,$bgcolor); imagecopy($dest,$src,8,8,0,0,$source_size[0], $source_size[1]); $logo=imagecreatefromjpeg($this->stamp); imagecopy($dest,$logo,$dest_size[ 01-110,12,0,0,97,41); $data=date("d/m/Y, H:i") ; imagestring($dest,2,8,$source_size[1 ]+1 0, "Data: ",$fgcolor) ; imagestring($dest,3,40,$source_size[1] +10,$data,$fgcolor); imagestring($dest,2,8,$source_size[1]+22,"Da:", $fgcolor); imagestring($dest,3,40,$source_size[1]+22, $this->from,$fgcolor); imagestring($dest,2,8,$source_size[1]+34, "Per: ",$fgcolor) ; imagestring($dest,3,40,$source_size[1]+34, $this->to,$fgcolor); $this->text=str_replace("\r","",$this->text); $tmp=stripslashes($this->text); $tmp=wordwrap($tmp); $array=explode("\n",$tmp); for ($i=0; $i_tmpfile=$this->TMPDIR.$this-> PREFIX.time().".jpg" imagejpeg($dest,$this->Jmpfile); $fp=fopen($this->_tmpfile,"r"); $this->image=fread($fp,filesize($this->_tmpfile)); fclose($fp); $this->_crea ted=1; 1 Inoltre, per evitare conflitti e sovrapposizioni, i no- mi dei file che contengono le cartoline dovranno es- sere generati in modo tale da risultare univoci. Il me- todo che utilizzeremo, semplice ma non del tutto si- curo, consiste nell'utilizzare come nome del file, o solo parte di esso, il valore restituito dalla funzione time(). Il numero in questione non è altro che lo Unix timestamp, ossia il numero di secondi trascorsi dalla cosiddetta Unix epoch, vale a dire dalle ore 0:00:00 del 1 gennaio 1970. In questa situazione già creare due cartoline nell'arco dello stesso secondo potrebbe comportare dei problemi; tuttavia per i nostri scopi rappresenta una soluzione accettabile. Una volta creata la cartolina, dopo essere stata me- morizzata nel file immagine in formato JPEG, per- marrà nella directory tmp fino a quando non verrà in- vocato il metodo free(); questo darà modo all'applica- zione, che fa uso dell'oggetto stesso, di utilizzare e visualizzare più volte la cartolina creata. Per quanto riguarda il metodo _createPostcard() è ne- cessario fare una ulteriore precisazione: il metodo deve essere considerato "privato", in quanto non do- vrà essere invocato dall'applicazione che fa uso del- l'oggetto, ma solo da metodi dell'oggetto stesso. In realtà questo non può essere garantito dall'inter- prete PHP che, almeno fino alla recente versione 4.3.0, non supporta ancora il concetto di variabili (o metodi) pubblici e privati, così come avviene in altri linguaggi orientati agli oggetti come C++ o Java. INVIAMO LE CARTOLINE La classe PW_postcard contiene solo gli strumenti base necessari all'implementazione di un servizio per l'in- vio di cartoline virtuali, per poter ottenere un servi- zio funzionante andranno aggiunti altri componenti, come script PHP, pagine HTML di supporto e natural- mente le immagini che raffigurano i soggetti delle cartoline. La versione presente sul CD allegato alla rivista uti- lizza il solo script index.php per eseguire tutti i passi necessari che portano all'invio della cartolina. In ba- se al contenuto della variabile $cmd lo script index.php PHP CARTOLINE Lato Server svolgerà le seguenti funzioni: • mostra cartoline (default) la prima pagina mostrata all'utente in modo che possa scegliere la cartolina da inviare. Viene in- vocata quando non viene passato un parametro $cmd valido, oppure se questo dovesse mancare. Utilizza lo script resize.php per creare "al volo" le thumbnail delle immagini presenti nella directory specificata dalla variabile $IMGS_PATH; File Edit View Go kmarl - indow Help 4.^.3 Forward Fleload S l-iji- http://localhosWnden.php Seleziona la cartolina da inviare as la m | Pone J^l • mostra form ($cmd=="form") visualizza la form per l'inserimento dei dati da al- legare alla cartolina, e cioè: mittente, email de- stinatario e testo; -lnx| ! le i il Vjew G< Bo< kmarl ; I >: ok ìA/ir fo'.-. el| Back Forward Reload S il |<$ http://localhost/inden.php?cmd ^| ^.Search| ^ ^ Ij Riempi la forni Mittente: Email Destinatario: Testo: SubrnitQuery Reset | ij^cr • mostra anteprima ($cmd=="preview") visualizza l'anteprima della cartolina, in modo da permettere al mittente di verificare come apparirà la cartolina da inviare, ed eventualmente permette di tornare indietro per modificare le scelte fatte; • invia ($cmd=="send") Fig. 4: FASE 3 Anteprima ed invio della cartolina. Fig. 2: FASE 1 Scelta della cartolina da inviare. Fig. 3: FASE 2 Inserimento dei dati. -|P|x| : ile Edi! •■"<;'■■:} ■ :> B< :>kn vi- ■ . :>oli V/indow | le!p ieloa 4 , Back ; ì' | .,/ http:,Vlocalhost/ ^3 ^- Seafch l ^ T H Anteprima della cartolina Data:B7/Bl/28B3, 16:4G Da: Rntonio Pasqua Per: ioprogrannoOednaster^it r Frogrannare il Heb -jjfc, a \g, m <& | Pone J invia la cartolina al destinatario e la cancella dal disco tramite la chiamata al metodo free(); Da notare, inoltre, che lo script index.php fa uso delle sessioni, in modo da memorizzare i dati riempiti dal mittente e riutilizzarli durante le varie fasi della composizione della cartolina. Senza questo meccani- smo diventerebbe molto scomodo passare i dati da uno "stato" all'altro dello script, dovendo ricorrere ai classici metodi GET o POST. CONCLUSIONI In questo articolo abbiamo presentato la realizzazio- ne di un semplice servizio per l'invio di cartoline vir- tuali, utilizzando strumenti gratuiti e facilmente re- peribili sulla rete. Lo scopo dell'articolo era quello di fornire le basi per poter iniziare ad utilizzare le funzioni messe a di- sposizione dal PHP, e dalla libreria GD, per la mani- polazione delle immagini. L'esempio proposto potrebbe tuttavia costituire la base per l'implementazione di un servizio più com- pleto, ad esempio che supporti la personalizzazione di font e colori, oppure l'utilizzo di un database co- me sistema di memorizzazione delle cartoline virtua- li inviate. Antonio Pasqua WEB 31 Sicurezza La sicurezza del software seconda parte di Corrado Giusto zzi CORRADO GIUSTOZZI Romano doc, classe 1959. Giornalista sci- entifico ed es- perto di sicu- : ; rezza informat- \{j.\ ica. Ha iniziato a ì\\ scrivere di co puter nel 1 e da allora pubblicato oltre mille articoli e tre libri. È stato diret- tore tecnico e vicedirettore di MCmi- crocomputer, ed ha fondato e diretto Byte Italia. Attivo sin dal 1985 sui te- mi della sicurezza e della critto- grafia, ha tra l'altro collaborato col Comando Generale dell'Arma dei Carabinieri in indagini sulla crimi- nalità informatica. Attualmente è security evangelist presso Secure Edge di Roma. La cosa più seria che ha fatto è sviluppare per l'Istituto dell'Enciclopedia Italiana il software di giochi linguistici del Vocabolario Italiano Treccani su CD-ROM. Il suo Web è ^e-'ééversgesy: Nella prima parte di questo articolo, pubbli- cata lo scorso mese, abbiamo iniziato a parlare dello sviluppo del software, in par- ticolare per quanto riguarda gli aspetti di correttezza e robustezza dei programmi. Abbiamo visto come non sia detto che un programma corretto sia necessariamente anche robusto: ossia, il solo fatto che un programma funzioni correttamente quando tutto va secondo le specifiche non ci assicu- ra che continuerà a farlo quando qualcosa da qualche parte andrà storto. Se poi diamo retta alle Leggi di Murphy dell'informatica, sappiamo che certamente qualcosa prima o poi andrà storto nella vita del no- stro programma; quindi non pos- siamo ignorare le esigenze di robu- stezza del software che scriviamo. Un programma robusto dunque, oltre ad essere auspicabilmente corretto, cercherà anche di assicu- rarsi della consistenza della situa- zione nella quale opera, per accor- gersi tempestivamente di eventua- li situazioni anomale che dovesse- ro verificarsi e prendere le dovute con tromisure: ad esempio cercare di correggere gli errori e ripristina- re una situazione di funzionamen- to nominale o, qualora ciò non fos- se possibile, almeno procedere ad una terminazione ordinata e rego- lare. Fare un programma sufficien- temente robusto tuttavia non è fa- cile, anche perché di solito non si è portati a prevedere tutte le pos- sibili cause di malfunzionamento cui il nostro software potrebbe an- dare soggetto. Di solito, quindi, anche gli sviluppatori di maggiore buona volontà si limitano ad eser- citare quel minimo di programma- WEB32 zione difensiva che si fa controllando i codici di ri- torno delle principali chiamate di sistema, o dissemi- nando dei costrutti tipo assert nei punti critici del programma. Meglio che niente, certo, ma purtroppo non è abbastanza. Anche perché in determinate si- tuazioni di utilizzo un programma "soltanto" robusto non è sufficiente: serve qualcosa di più, serve che es- so sia anche sicuro. Questo mese vedremo un esempio che ci dimostrerà proprio come anche un programma robusto non è ne- cessariamente sicuro, ossia non protegge contro uti- lizzi astutamente maliziosi mirati a sconvolgere ad arte il funzionamento del programma stesso. FORZARE UN CONTROLLO DI AUTENTICAZIONE Il caso, accettabilmente verosimile pur nella sua comprensibile generalità, riguarda un pezzo di software sicuramente corretto, ed anche ragionevol- mente robusto, che si dimostra invece niente affatto sicuro: esso infatti può essere facilmente "ingannato" da una particolare combinazione di dati di ingresso, e portato a produrre risultati non solo errati, ma er- rati in modo tale da consentire ad un utente malevo- lo di ottenere illecitamente un beneficio o un van- taggio. L'esempio è quello, semplicissimo, di una form Web che effettua un controllo di autenticazione allo sco- po di limitare l'accesso alle pagine seguenti, lascian- do cioè passare solo coloro che dimostrano di essere in possesso di credenziali valide. Concettualmente questo controllo si fa in un modo elementare: un qualsiasi linguaggio di scripting lega- to alla form riceve in input le credenziali impostate dall'utente remoto, ossia un codice di login ed una password, e con esse interroga il database locale con- tenente la lista degli utenti validi e delle relative pas- sword. Se la query è soddisfatta, ossia se viene effet- tivamente trovato nel database un record contenente i due campi indicati, l'utente è abilitato; altrimenti l'utente viene respinto. Supponiamo dunque che la nostra form di autentica- zione abbia due campi che l'utente remoto deve riem- pire: chiamiamoli UserID e Password. Lo script che gestisce la form, ricevuti i contenuti di questi campi, li userà per costruire una query SQL con cui interro- gherà il database server contenente gli utenti auto- rizzati. Questo database si chiama utenti e contiene due campi chiamati rispettivamente utente e password. A livello di form le variabili relative ai due campi di input sono chiamate, ad esempio: Sicurezza $FORM_UID e $FORM_PWD. Bene, in queste ipotesi assai generali un tipico esem- pio di codice in grado di generare la suddetta query potrebbe essere di questo tipo: SELECT * FROM utenti WHERE utente = = '$F0RM_USR' AND password = = '$F0RM_PWD' Così facendo, come si vede, si selezionano dal data- base utenti tutti quei record in cui il campo utente ha il valore fornito nella variabile $F0RM_UID e il cam- po password ha il valore fornito nella variabile $F0RM_PWD. Il risultato è TRUE se la query ritorna una tabella non vuota, ossia se viene trovato (almeno) un record che la soddisfa. Da notare che il record ritor- nato dalla query non viene affatto controllato: ciò che serve è solo sapere se esso esiste, ossia se la query stessa ha restituito un valore TRUE o no. Per sincerarci che tutto funzioni come si deve, vedia- mo cosa succede al nostro script in un caso reale pra- tico. Se l'utente ad esempio immette nel campo UserID la stringa "Mario" e nel campo Password la stringa "Pippo" (ovviamente senza le virgolette), la nostra query di- venta: SELECT * FROM utenti WHERE utente = 'Mario 1 AND password = 'Pippo' Ciò è esattamente quello che vogliamo. Sembra dun- que tutto corretto, e talmente semplice e lineare da non poter nascondere nessun problema, vero? E inve- ce no. Purtroppo questo pezzo di codice è corretto e anche robusto ma non sicuro, perché immettendo nel campo Password una stringa "grimaldello" appositamente costruita è possibile forzare il controllo di autentica- zione ed ottenere l'accesso anche non disponendo di credenziali valide. Vediamo come. Supponiamo che la stringa inserita nel campo Password sia, letteralmente: "boh 1 OR TRUE-" (sempre senza le vir- golette) e vediamo cosa succede al nostro script. Do- po la sostituzione, la query diventa: SELECT * FROM utenti WHERE utente = 'Mario' AND password = 'boli' OR TRUE--' Notiamo che ora il risultato della sostituzione è un comando SQL caratterizzato da una semantica com- pletamente differente da quella che ci aspettavamo. Adesso infatti la query, grazie alla clausola OR arta- tamente inserita, ritornerà sempre il valore TRUE, in- dipendentemente dal valore impostato per i campi utente e password, e dunque apparirà al chiamante come sempre soddisfatta. Il risultato è che l'utente remoto otterrà il permesso di accesso pur avendo presentato delle credenziali inesistenti. Semplice- mente, il controllo è stato ingannato! Da notare l'uso accorto dei due trattini in fondo alla stringa "grimaldello": essi servono per impedire l'errore di sintassi che verrebbe altrimenti generato per via del numero dispari di apici risultanti nella stringa SQL costruita dallo script. I due trattini sono infatti il simbolo SQL di commento, e fanno sì che tutto ciò che li segue (ossia l'apice "dispari" in fondo alla riga) venga ignorato. Il risultato è un'istruzione SQL sin- tatticamente corretta e perfettamente lecita. Perché funziona un trucco del genere? Semplicemen- te perché il programmatore non è stato... paranoico, ma si è limitato a fidarsi del buon funzionamento "naturale" del programma. In altre parole, egli non ha inserito un controllo di validità sul contenuto dei campi $F0RM_UID e $F0RM_PWD perché ha pensato che non ne valesse la pena. Il suo ragionamento è stato, più o meno, il seguente: se uno o entrambi di tali campi contenessero un valore invalido, la query cer- tamente non troverebbe una corrispondenza valida nel database e ritornerebbe quindi il valore FALSE, il che negherebbe comunque l'accesso all'utente. Al programmatore non è venuto in mente che un uten- te astuto e malizioso avrebbe potuto inserire una stringa fatta in modo tale da modificare il significa- to della query, facendole tornare sempre il valore TRUE a prescindere dal reale contenuto dei campi in- seriti, cosa che invece è puntualmente successa. Come difendersi da un attacco del genere? Ad esem- pio assicurandosi che i valori dei campi UserID e Pas- sword non contengano apici o trattini (che dunque de- vono essere banditi come caratteri invalidi dalle rea- li password degli utenti legittimi), o verificando l'in- nocuità del comando SQL risultante prima di passar- lo effettivamente in esecuzione al database server. MA CE DELL'ALTRO... Purtroppo questo esempio non è l'unico. Utilizzando sempre una stringa "grimaldello", in uno scenario ana- logo a quello appena visto, è addirittura possibile, sempre sfruttando l'ingenuità del programmatore re- sponsabile della routine di controllo, installare sul server un software a piacimento e mandarlo in ese- cuzione! Ma di questo, e di altro ancora, parleremo con più agio il prossimo mese. WEB 33