Realizzazione della community del sito frieund.com
Transcript
Realizzazione della community del sito frieund.com
Università degli Studi di Urbino “Carlo Bo” Facoltà di Scienze e Tecnologie Corso di Laurea in Informatica Applicata Progetto d'esame di linguaggi e applicazioni multimediali Realizzazione della community del sito frieund.com Anno Accademico 2008/2009 MONACCHI ANDREA - Matricola 227377 “Se in un primo momento l'idea non è assurda, allora non c'è nessuna speranza che si realizzi”. Albert Einstein La community di frieund.com – Linguaggi e applicazioni multimediali Indice 1. Analisi dei requisiti..................................................................................................................p.5 1.1 definizione dei target 1.2 descrizione del problema 2. Realizzazione della base di dati di supporto.............................................................................p.8 2.1 Il modello concettuale: lo schema E/R 2.2 Il modello logico e l'implementazione 3. Implementazione dell'applicativo web.....................................................................................p.13 3.1 Realizzazione del template grafico 3.1.1 Utilizzo del template grafico 3.2 La community 3.2.1 La pagina di iscrizione 3.2.2 Il modulo di login 3.2.3 Impostazioni account 3.2.4 Gestione aspetto del proprio profilo 3.2.5 Il proprio profilo 3.2.6 Ricerca di un profilo 3.2.7 Visualizzazione di un utente 3.3 I canali di frieund.com 3.3.1 Recipes 3.3.2 Travelling 3.3.3 Wow 3.3.4 Eu! City 4. I vantaggi competitivi di frieund................................................................................................p.28 5. Appendice...................................................................................................................................p.30 5.1 Sicurezza delle applicazioni 5.2 Ajax & JSON 5.3 Il captcha Pag. 3 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali Premessa Siamo nel 2009, ormai da tempo portiamo nelle nostre tasche spiccioli particolari che richiamano il nome di un continente, da anni non siamo più chiusi ai nostri piccoli confini ma viviamo in un mercato comune, monete che portano i segni di anni di tensioni e di un passato non molto lontano in cui siamo stati nemici almeno una volta, un tentativo di integrazione in un avvenire sempre meno rassicurante per il genere umano che tenta la carta della collaborazione, un integrazione tra milioni di persone, multiculturale e interreligiosa, una sfida del nuovo millennio che ai più scettici può apparire utopica ma che crea stabilità e sicurezza. Su questo entusiasmo nasce l'idea di Frieund, un sito internet che dovrebbe farsi partecipe proprio di questa voglia di riscatto e di pubblicità della propria terra, seguendo quelle che sono le linee e i principi guida dell'integrazione europea, nel rispetto delle diversità e delle tradizioni che sono la vera ricchezza e il vero patrimonio da custodire gelosamente e costituiscono un passato e una base per il nostro futuro. In un Europa di 27 paesi, è sempre più attuale il problema e la necessità di un confronto attivo che porti a conoscenza delle problematiche comuni e permetta l'insegnamento di certi principi nelle nuove generazioni. Per tali motivi è stato scelto come target primario l'adolescente, abituato alle nuove tecnologie, creativo e interattivo. Il sito prenderà la forma di un social network mantenendo quello che è il suo scopo di creare scambio di persone e idee. Pag. 4 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 1. Analisi dei requisiti In questo capitolo definiremo quali sono i nostri target e in quale modo vogliamo ottenere il raggiungimento del loro bisogno emozionale. 1.1 Definizione dei target Target Primario(adolescente) Secondario (universitario) Terziario (famiglia) Bisogno emozionale Socializzazione, appartenenza ad un gruppo ed espressione di se stessi Curiosità, innovazione, moda, alternatività, originalità, Passatempo, relax esclusività Stile del servizio Giovanile, informale, aggregante, un po' aggressivo, ribelle Dinamico, veloce, esclusivo, Familiare, rassicurante, alla moda, efficiente, semplice ed economico, innovativo calmo e rilassante età 1125 anni 2030 anni 3060 anni Livello reddito basso Medio basso medio Livello istruzione Medio / medio basso Alto Medio/ medio basso Occupazione studente Studente / ricercatore Lavoratore (medio) Frequenza uso internet alta Medio alta Medio bassa Punti di accesso Casa /scuola Casa / scuola / wifi campus casa Veloc. Connessione adsl adsl Pstn /adsl Tipo computer windows Mac os/ linux / windows windows Browser IE explorer / firefox Safari/ firefox /IExplorer IE explorer Portatile (1280x800) Fisso (1024x768) Ricerche web Viaggi, notizie, ricerche Profilo demografico Rapporto con le tecnologie Risoluz. Monitor Portatile/fisso 1280x800 | 1024x768 Comportamento online community Attitudini Interessi Community, messaggistica Scambi all'estero, community, Ricette, notizie su europa scambio informazioni e integrazione, normative Personalità Curiosa e dinamica, creativa e informale Ambiziosa e potenzialmente ricca per la creazione di contenuti di buon livello Stile di vita Divertimento e tecnologia, giovanile Relativamente frenetico, Frenetico e impegnato, internet come passatempo, per internet come passatempo Interessata e curiosa ma anche poco informata sulle nuove tecnologie Pag. 5 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali Target Primario(adolescente) Secondario (universitario) Terziario (famiglia) alcuni come fonte di notizie e stile di vita Comportamento sul sito Partecipe, dinamico, crea e scambia contenuti Esperienza on line Blog, social network, Ricerche web, tecnologia, mail e istant messaging informazioni accademiche Lettore e talvolta creatore di contenuti spettatore Ricerche web, mail, notizie Dai tre target si intuisce che il sito dovrà: Rendere l'esperienza del visitatore la più facile, unica ed emotivamente coinvolgente possibile; dovrà dare una sensazione di pienezza, di rotondità di ambiente accogliente e senza spigoli per lo studente adolescente, dovrà assumere la forma di una scala per l'universitario con un inizio e una fine, un processo cioè da compiere per arrivare alla meta in maniera rapida ed efficace; infine dovrà assomigliare ad un recinto o una aiuola dove muoversi con tranquillità e serenità nel caso delle famiglie. Pag. 6 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 1.2 Descrizione del problema Per una maggiore intuitività elenchiamo i servizi offerti sotto forma di tabella: Servizio / canale associato Travelling Hosting (scambi culturali e/o gemellaggi) Ricette Specialità dei paesi europei Interesse Target 1 e 2 Target 3 Eu! Eu! City con la visualizzazione delle città Storia integrazione europea Le lingue Le caratteristiche degli stati membri Sondaggi e valutazione sull'interesse del sito Interesse generale Community Profili degli utenti iscritti (stile Blog) Target 1 e 2 Pannello di controllo personale Wow Foto documentative dei paesi europei Interesse generale In particolare dovremo realizzare una base di dati di supporto e archiviazione nelle sezioni: Hosting per i dati relativi agli scambi culturali Ricette che conterrà tutti i piatti inseriti dagli utenti Eu! City per la memorizzazione delle città europee e la loro posizione sulla cartina Community che visualizzerà i profili e darà modo di gestire i propri dati Un archivio degli utenti iscritti e dei loro privilegi Wow che conterrà tutte le informazioni relative agli scatti fotografici Pag. 7 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 2 Realizzazione della base di dati di supporto Per poter memorizzare i dati di supporto alle nostre applicazioni dovremo implementare una base di dati. Ne riportiamo il modello concettuale e quello logico. 2.1 Il modello concettuale: lo schema E/R Pag. 8 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 2.2 Il modello logico e l'implementazione Le successive fasi di ottimizzazione e semplificazione hanno modificato il nostro schema E/R Procediamo alla traduzione nel rispettivo modello logico relazionale. Città(nome, nazione, posx, posy) Dati_accesso(username, password, privilegio) Utente(username, nome, sesso, lingua, data_nascita, mail, nome_città, nazione) Piatto(nome, lingua, categoria, procedimento, ingredienti, nome_città, nazione, utente) Profilo(utente, messaggio_personale, intervista, foto, stile) Valutazione(ospite, data, voto, commento, proprietario, indirizzo) Abitazione(proprietario, indirizzo, costo_giorno, numero_posti, informazioni_aggiuntive) Nel processo di normalizzazione è stata verificata anche la normalità degli schemi di relazione che sono in BCFN (forma normale di Boyce Codd). Pag. 9 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali Per riportare i passi di implementazione del modello logico relazionale presentiamo il dump del DB --MySQL Dump --- Host: 62.149.150.72 -- Generato il: 22 apr, 2009 at 12:02 AM -- Versione MySQL: 5.0.68 -- Versione PHP: 5.2.9 SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; /*!40101 /*!40101 /*!40101 /*!40101 SET SET SET SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; NAMES utf8 */; --- Database: `Sql180545_1` --- ---------------------------------------------------------- Struttura della tabella `abitazione` -CREATE TABLE IF NOT EXISTS `abitazione` ( `proprietario` varchar(30) collate utf8_bin NOT NULL, `indirizzo` varchar(60) collate utf8_bin NOT NULL, `foto` char(14) collate utf8_bin NOT NULL, `costo_giorno` smallint(3) unsigned NOT NULL, `numero_posti` tinyint(3) unsigned NOT NULL, `informazioni_aggiuntive` smallint(4) unsigned NOT NULL, `nome_citta` varchar(40) collate utf8_bin NOT NULL default '', `nazione` char(3) collate utf8_bin NOT NULL, PRIMARY KEY (`proprietario`,`indirizzo`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; --- Dump dei dati per la tabella `abitazione` --- ---------------------------------------------------------- Struttura della tabella `citta` -CREATE TABLE IF NOT EXISTS `citta` ( `nome` varchar(40) collate utf8_bin NOT NULL, `nazione` char(3) collate utf8_bin NOT NULL, `posx` smallint(4) unsigned NOT NULL, `posy` smallint(4) unsigned NOT NULL, PRIMARY KEY (`nome`,`nazione`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; Pag. 10 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali --- Dump dei dati per la tabella `citta` --- ---------------------------------------------------------- Struttura della tabella `dati_accesso` -CREATE TABLE IF NOT EXISTS `dati_accesso` ( `username` varchar(30) collate utf8_bin NOT NULL, `password` char(40) collate utf8_bin NOT NULL, `privilegio` enum('A','L','S') collate utf8_bin NOT NULL, PRIMARY KEY (`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; --- Dump dei dati per la tabella `dati_accesso` --- ---------------------------------------------------------- Struttura della tabella `piatto` -CREATE TABLE IF NOT EXISTS `piatto` ( `nome` varchar(40) collate utf8_bin NOT NULL, `lingua` char(3) collate utf8_bin NOT NULL, `categoria` enum('V','D','C','F','P') collate utf8_bin NOT NULL, `ingredienti` text collate utf8_bin NOT NULL, `procedimento` text collate utf8_bin NOT NULL, `nome_citta` varchar(40) collate utf8_bin NOT NULL, `nazione` char(3) collate utf8_bin NOT NULL, `utente` varchar(30) collate utf8_bin NOT NULL, PRIMARY KEY (`nome`,`lingua`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; --- Dump dei dati per la tabella `piatto` --- ---------------------------------------------------------- Struttura della tabella `profilo` -CREATE TABLE IF NOT EXISTS `profilo` ( `utente` varchar(30) collate utf8_bin NOT NULL, `messaggio_personale` text collate utf8_bin NOT NULL, `intervista` smallint(4) unsigned NOT NULL, `foto` tinyint(1) unsigned NOT NULL, `stile` tinyint(2) unsigned NOT NULL, Pag. 11 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali PRIMARY KEY (`utente`), KEY `utente` (`utente`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; --- Dump dei dati per la tabella `profilo` --- ---------------------------------------------------------- Struttura della tabella `utente` -CREATE TABLE IF NOT EXISTS `utente` ( `username` varchar(30) collate utf8_bin NOT NULL, `nome` varchar(30) collate utf8_bin NOT NULL, `sesso` enum('M','F') collate utf8_bin NOT NULL, `lingua` char(3) collate utf8_bin NOT NULL, `data_nascita` date NOT NULL, `mail` varchar(40) collate utf8_bin NOT NULL, `nome_citta` varchar(40) collate utf8_bin NOT NULL, `nazione` char(3) collate utf8_bin NOT NULL, PRIMARY KEY (`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; --- Dump dei dati per la tabella `utente` --- ---------------------------------------------------------- Struttura della tabella `valutazione` -CREATE TABLE IF NOT EXISTS `valutazione` ( `ospite` varchar(30) collate utf8_bin NOT NULL, `data` date NOT NULL, `voto` tinyint(2) unsigned NOT NULL, `commento` text collate utf8_bin NOT NULL, `proprietario` varchar(30) collate utf8_bin NOT NULL, `indirizzo` varchar(60) collate utf8_bin NOT NULL, PRIMARY KEY (`ospite`,`data`), KEY `ospite` (`ospite`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; --- Dump dei dati per la tabella `valutazione` -- L'uso di MyISAM è dovuto alla mancanza di InnoDB nel server MySql utilizzato. Per tale motivo i vincoli di integrità referenziale non sono stati riportati. Pag. 12 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3 Implementazione dell'applicativo web È giunto il momento di realizzare la nostra applicazione di accesso e gestione dei dati. Dopo aver costruito la nostra interfaccia grafica procederemo ai vari contenuti dinamici che fanno uso di PHP per la sua semplicità e alta compatibilità soprattutto in campo linux. 3.1 Realizzazione del template grafico L'interfaccia del sito dovrà garantire semplicità e accessibilità, la sua staticità dovrà permettere un veloce riconoscimento delle varie funzioni. Per questo motivo è stato cercato di utilizzare colori conformi allo stile del logo e alla filosofia che tenta di rappresentare. La posizione dei vari oggetti e la scelta delle dimensioni è stata effettuata nel rispetto della tipologia di applicativo web e nelle caratteristiche dei target e del loro bisogno emozionale che stiamo tentando di soddisfare. Secondo la legge di Hick il tempo medio T richiesto all'utente per prendere una decisione tra quelle ugualmente probabili disponibili è dato da una legge logaritmica. Questo perchè si suppone che gli utenti suddividano l'insieme delle alternative in categorie anzichè considerarle separatamente. Ciò comporta un costo logaritmico e non lineare di tale processo. Il numero minimo di possibilità, la presenza di una linearità negli elementi grafici che sono ripetuti quasi al monotono fanno si che l'utente sappia familiarizzare con le varie funzionalità che oltretutto sono più veloci da caricare. Il minor numero di immagini velocizza la trasmissione della pagina e l'utilizzo dei div la rende malleabile e sposta la complessità del codice al foglio di stile permettendone cosi anche una maggiore leggibilità anche in vista di future manutenzioni. Pag. 13 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali <? include($_SERVER['DOCUMENT_ROOT'].'session.php'); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Fri.eu.nd - Your european meeting</title> </head> <link rel="stylesheet" type="text/css" href="http://www.frieund.com/stile.css" /> <link rel="icon" href="http://www.frieund.com/favicon.ico" /> <body> <div id="container"> <div id="header"> <div style="float:left;"> <a href="http://www.frieund.com"> <img src="http://www.frieund.com/images/logo.png" alt="logo" border="0" /> </a> </div> <div style="float:right;"> <form id="form1" name="form1" method="post" action="http://www.frieund.com/bot.php"> <div style="float:left;"> <input name="arg" type="text" class="btn1" id="arg" /> </div> <div style="float:left;"> <select name="for" class="btn1" id="for"> <option value="utente" selected="selected"> User </option> <option value="citta"> City </option> <option value="piatto"> Recipes </option> </select> </div> <div style="float:left;"> <input name="Submit" type="submit" class="btn1" value="Search" /> </div> </form> </div> </div> <div id="menu"> <div id="eu"> <div class="menu_titolo">Eu!</div> <div class="menu"> <a href="http://www.frieund.com/news.php"> News </a> </div> <div class="menu"> <a href="http://www.frieund.com/about.php"> About Europe </a> </div> <div class="menu"> <a href="http://www.frieund.com/lang.php"> The languages </a> </div> <div class="menu"> <a href="http://www.frieund.com/eumap.php"> The countries </a> Pag. 14 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali </div> <div class="divuoto"></div> </div> </div> <div id="canali"> <div class="menu_titolo">Channels</div> <div class="menu"> <a href="http://www.frieund.com/city/europe.php">City</a> </div> <div class="menu"> <a href="http://www.frieund.com/community/">Community</a> </div> <div class="menu"> <a href="http://www.frieund.com/recipes/">Recipes</a> </div> <div class="menu"> <a href="http://www.frieund.com/travelling/">Travelling</a> </div> <div class="menu"> <a href="http://www.frieund.com/wow/index.php">Wow</a> </div> </div> <div id="content"> </div> CONTENUTO CENTRALE <?php if (isset($_POST['username']) && isset($_POST['password']) && isset($_POST['Login'])) { // apro la connessione dal database require_once($_SERVER['DOCUMENT_ROOT'].'conn/xyz.php'); // seleziono il database $db = @mysql_select_db("Sql180545_1", // nome del database $connessione) // nome della connessione or die ("Impossibile selezionare il database."); // eseguo la query $result = mysql_query(sprintf("Select username, privilegio from dati_accesso where username ='%s' AND password = '%s'", mysql_real_escape_string($_POST['username']), sha1(mysql_real_escape_string($_POST['password'])))); // controllo che esista almeno un record if(mysql_num_rows($result) > 0) { // prelevo i risultati $riga = mysql_fetch_row($result); //dichiaro due variabili di sessione a cui assegno il valore della query $_SESSION['username'] = $riga[0]; $_SESSION['privilegio'] = $riga[1]; } else { // l'utente non è autorizzato ad entrare $messaggio = "Access denied!!"; } //libero la memoria utilizzata dal risultato mysql_free_result($result); } else { // chiudo la connessione con il database mysql_close($connessione); if(isset($_POST['Login'])) { Pag. 15 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali } ?> } // non ha inserito tutti i dati $messaggio = "You have to fill all field in the form"; <?php if(isset($_SESSION['username'])) { ?> <div class="login"> <div class="menu_titolo"> <?php echo $_SESSION['username']; ?> </div> <div class="menu"> <a href="http://www.frieund.com/mypage/my.php"> My Page </a> </div> <div class="menu"> <a href="http://www.frieund.com/mypage/edit_content.php"> My Content </a> </div> <div class="menu"> <a href="http://www.frieund.com/mypage/manage.php"> Manage Page </a> </div> <div class="menu"> <a href="http://www.frieund.com/mypage/settings.php"> Account Settings </a> </div> <div class="menu"> <a href="http://www.frieund.com/logout.php"> Log-out </a> </div> </div> <?php if($_SESSION['privilegio'] == 'A') { ?> <div class="menu_admin"> <div class="menu_titolo">Administrator</div> <div class="menu">Languages</div> <div class="menu">Styles</div> <div class="menu">Local</div> </div> <?php } elseif($_SESSION['privilegio'] == 'L') { ?> <div class="menu_admin"> <div class="menu_titolo">Local Administrator</div> <div class="menu">Languages</div> <div class="menu">Styles</div> <div class="menu">Local</div> </div> <?php } ?> <?php } else { ?> <div class="login"> <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" name="login" id="accesso"> <div class="menu_titolo">Login</div> <div style="font-size:10px;">User:</div> <div align="center"> <input name="username" type="text" class="btn1" id="username" size="15" maxlength="30" /> </div> <div style="font-size:10px;">Password:</div> <div align="center"> <input name="password" type="password" class="btn1" id="password" size="15" maxlength="14" /> </div> <div class="divuoto"></div> Pag. 16 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali <?php if(isset($messaggio)) { echo $messaggio; }?> <div align="center"> <input name="Login" type="submit" class="btn1" id="Login" value="Log in" /> </div> <?php } ?> </html> </body> </div> </div> <div class="divuoto"></div> <div class="menu">Remember Password</div> <div class="menu"> <a href="http://www.frieund.com/joinus.php"> Join us for free </a> </div> </form> <div id="footer"> <div id="credits"> <div class="c1"> <a href="http://www.frieund.com/joinus.php"> Join us for free </a> </div> <div class="c1">Help</div> <div class="c1">Contact us</div> <div class="c1"> <a href="http://www.frieund.com/filosofia.php"> Frieund philosophy </a> </div> <div class="c1">Credits</div> </div> <div id="copyright"> © Copyright 2008 - 2009 - N3T_W4RR10R - All rights reserved </div> </div> come vediamo in tutte le pagine si include il file di gestione della sessione. Esso si occupa di avviarla e settare i parametri di funzionamento. In particolare non è possibile utilizzare cookie in alternativa alle sessioni. <?php ini_set('session.use_cookies', 1); ini_set('session.use_only_cookies', 1); session_name('permesso'); session_start(); ?> Utilizzare il template Il template è stato spezzato in due diversi file, il primo comprende la barra superiore e il menu laterale sinistro, il secondo invece comprende il form di login e il footer. Per utilizzare il template costruito basterà importare il file tramite la funzione php include <?php include('temp_up.php'); ?> <!-- contenuti centrali della pagina --> <?php include('temp_down.php'); ?> Pag. 17 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.2 La community Il sito dovrà essere una comunità, una postazione virtuale di scambio e confronto che permetta l'interazione tra culture diverse all'interno dell'unione europea. Vediamone gli sviluppi 3.2.1 La pagina di iscrizione joinus.php La procedura di iscrizione permette a un utente di entrare a far parte del sito, i privilegi dati saranno quelli di utente semplice e sarà possibile modificarli solo da parte dell'amministratore. La prima fase prevede l'accettazione dei termini del trattamento dei dati. Una volta accettate le condizioni si potrà procedere con la scelta dell'username. Con la tecnologia ajax evitiamo il reload della pagina nel susseguirsi dei check. Una volta scelto l'username tra quelli disponibili potremo procedere all'inserimento degli altri dati Pag. 18 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali una volta inseriti tutti i dati non resta che controllare e accettarne l'inserimento Bene siamo stati inseriti nel DB, ora possiamo usufruire dei servizi associati Controllando la nostra mail troveremo un messaggio di benvenuto con i dati di riepilogo dell'avvenuta iscrizione. Implementazione I vari step della procedura di iscrizione sono regolati da una variabile passo che viene valorizzata in base al passo di provenienza e alla correttezza dei valori ogni volta che la pagina è ricaricata. Le variabili del modulo sono riprese dall'array globale POST mentre nel caso del captcha si usa una variabile di sessione in modo che il suo controllo sia più difficilmente aggirabile. Il primo passo effettua un semplice incremento della variabile passo, nel secondo step invece in base al valore scritto invochiamo una funzione javascript che tramite un oggetto XMLHTTP request invia una richiesta asincrona di tipo POST ad una pagina php che effettua una query di selezione al DB. A questo punto in base al risultato è restituita la possibilità di avanzare o meno di passo. Nel passo 3 si ha un semplice form html con controlli javascript sul nome, la mail e la password che avverta l'utente della loro correttezza. Tale controllo è comunque effettuato da lato server all'invio del modulo. Una volta appuratane la correttezza si avanza al passo 4 che riepiloga i dati inseriti e richiede la copia del codice di sicurezza. In caso di scorrettezza la pagina è ricaricata con un codice diverso mantenendo i vari dati, in caso affermativo si passa allo step finale che procede all'invocazione di una stored procedure sul DBMS e all'invio di una mail di conferma (formato html e se non possibile testo) all'indirizzo specificato. Pag. 19 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.2.2 Il modulo di login Visto che il template è riportato in ogni pagina è stato deciso di includere il modulo di accesso all'interno di esso. Sul menu a destra di ogni pagina potremo quindi notare il form di login con i campi text dell'username e della password. Una volta loggati in base ai nostri privilegi (definiti nella tabella dati_accesso) visualizzeremo tipologie di menu diverse local admin simple user Il modulo invia la query alla stessa pagina che effettua una select nel DB in ricerca di un utente con l'username e la password indicati. La password è convertita tramite l'algoritmo sha1 in una forma non leggibile a potenziali malcapitati. Una volta assicurata l'esistenza di un record con quelle caratteristiche si crea una variabile di sessione “username” che è utilizzata per l'autenticazione su tutte le pagine protette. Allo stesso modo il logout distrugge la sessione e le variabili associate utilizzate nell'area riservata e ridireziona alla pagina principale <?php session_name('permesso'); session_start(); unset($_SESSION['Username']); unset($_SESSION['Privilegio']); $_SESSION = array(); session_destroy(); header("Location: http://www.frieund.com/index.php"); ?> Pag. 20 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.2.3 Impostazioni account I dati personali e le impostazioni dell'account sono modificabili nella pagina settings che seleziona i dati della tabella utente e in caso di invio del modulo li modifica con un update. Nel caso venga cliccato su disable account viene abilitato un div assoluto che richiede la conferma di questa delicata operazione; una volta acconsentito si verrà diretti alla pagina remove che provvederà all'invocazione della stored procedure rimuovi passando il semplice username dell'utente. Pag. 21 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.2.4 Gestione dell'aspetto del proprio profilo Ogni profilo ha come detto un proprio stile e un messaggio personale configurabili, nonché un intervista dell'utente che fornisce informazioni aggiuntive che permettono di conoscerlo meglio. Tali informazioni sono configurabili nella pagina manage che seleziona con una query tali dati e una volta premuto il bottone li sottopone di nuovo al DBMS con una update. La foto del contatto è semplicemente inserita e la sua modifica (sostituzione) è effettuabile in una pagina separata. Pag. 22 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.2.5 Il proprio profilo Una volta effettuato l'accesso possiamo accedere direttamente alla nostra pagina che riassumerà i nostri dati e parte dei parametri configurati nel nostro profilo. In alto il messaggio e a sinistra i dati, in basso invece le informazioni aggiuntive. L'implementazione di tale pagina non è che una query di join tra la tabella profilo e utente e la stampa del valore memorizzato nelle variabili identificative dei campi restituiti dal recordset. Pag. 23 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.2.6 Ricerca di profili Dal canale community è possibile impostare i parametri di ricerca geografici che permettono di affinare la ricerca degli utenti iscritti alla community. Tale lista è restituita come tabella html usando la tecnologia Ajax. Inserendo i criteri di ricerca vedremo comparire i risultati senza ricaricare la pagina Pag. 24 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.2.7 Visualizzazione di un utente Ogni utente ha una sua pagina personale, uno spazio che raccoglie alcuni dei suoi dati. In essa possiamo distinguere tre sezioni, una top di intestazione, una laterale che stampa i dati del contatto e una centrale che permette la visualizzazione dei contenuti inseriti dal soggetto. Ogni contatto può scegliere un foglio di stile differente che cambia la tipologia di testo e i colori associati ai diversi oggetti della pagina. É possibile inviare una mail al contatto in questione ma tale servizio è fruibile solo dagli iscritti. La barra inferiore riporta i colori della bandiera della nazione di residenza. Alla pagina è passato l'username con il sistema POST, tale valore una volta recuperato e filtrato da eventuali query injection parametrizza una query di join tra profilo e utente che restituisce i dati utili. Il record restituito è visualizzato nella pagina. Nel caso dell'intervista come abbiamo notato nell'implementazione degli schemi di relazione è costituita da un campo numerico di 4 posizioni. Se convertiamo tale valore decimale in binario possiamo rappresentare fino 16 bit che ci saranno utili per questa funzionalità. Una volta selezionato il campo, le funzioni decbin e bindec ne effettuano la conversione e i valori binari sono messi in un array che ha la stessa lunghezza dell'array delle domande che sono caricate dinamicamente da un file separato (in previsione di un sito multilingua e di espansioni future). Ciò la rende elastica e pronta a qualsiasi lista venga caricata (fino al massimo di 16 domande). Pag. 25 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.3 I canali di frieund.com Oltre alla community frieund fornisce altri servizi quali la possibilità di inserire piatti, abitazioni e fotografie. 3.3.1 Recipes In questa sezione è possibile tramite degli appositi parametri di ricerca selezionare piatti e visualizzarne ingredienti e procedimento. Cliccando su una entry saremo indirizzati alla pagina specifica del piatto su cui visualizzeremo tutte le informazioni associate. 3.3.2 Travelling La sezione travelling raccoglie tutte le abitazioni disponibili per gli scambi tra utenti, anche in questo caso dei parametri di ricerca geografici ci permettono di selezionare risultati conformi alla nostra zona di interesse e visuallizzarne le informazioni associate. Pag. 26 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali 3.3.3 Wow Wow è la sezione dedicata agli scatti fotografici, essa raccoglie e lista le foto presenti nelle cartelle delle varie tipologie di foto. Questo è possibile con un algoritmo dedicato che legge e lista sia le cartelle che i file grafici presenti. Scelta una foto è possibile segnalarla via mail ad un altro contatto o decidere di scaricarla sul proprio pc. Successivamente si dovrà dare possibilità agli utenti di inserire le proprie foto e di posizionarle geograficamente in modo che analogamente a quanto accade per i piatti e le abitazioni siano raggiungibili dalle città. Non entreremo nel merito di tale sezione visto che non è oggetto di relazione. Tutti gli scatti inseriti sono proprietà del webmaster. 3.3.4 Eu! City City è la sezione che sfrutta la tabella città del nostro database, in particolare offre servizi di ricerca di tale entità e le visualizza sulla cartina. Nel nostro caso è stato tentato l'utilizzo delle librerie GD del php che permettono la costruzione di oggetti grafici pur richiedendo molte risorse di sistema. Questa è quindi una via alternativa e provvisoria che tenta semplicemente di testarne le capacità e le metodologie di funzionamento. Per un sistema più pulito si potrebbe pensare di sfruttare le API di google maps. Pag. 27 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali I vantaggi competitivi di frieund Interfaccia grafica Semplice, pulita e in grado di garantire velocità. Il logo riflette in parte lo stile del web 2.0 ma i colori e la disposizione lo rendono accessibile anche a fasce di età più alte. Applicazioni Il sorgente è scritto in modo da garantire le massime performance e la riduzione di codice che in ambienti di rete significa anche minor tempo di caricamento. La validità è stata provata tramite validazione del world wide web consortium (W3C) che ha appurato il rispetto della sintassi xhtml e css per il template. Le applicazioni sono state inoltre protette da query injection, variable injection e XSS tramite dedicate funzioni di escaping e strip dei tag. Database Snello ed ottimizzato in modo da garantire il minor spazio occupato su disco (tramite la scelta dei tipi di dato) e velocizzato da indici costruiti sui criteri di ricerca delle nostre applicazioni. Utilizzo delle procedure per alleggerire le nostre pagine di accesso che sono così più veloci. Funzionalità La procedura di iscrizione permette in 4 semplici passi di entrare a far parte della community, le informazioni inserite non sono sensibili e per tale motivo non è richiesta autorizzazione al garante della privacy per l'attività di trattamento dei dati. Possibilità di ospitare un utente o di essere ospitati. Questo servizio è già presente sul web ma per lo più in club che richiedono una quota annuale per la fruizione. La possibilità di vedere le valutazioni (feedback) degli utenti ospitati e la possibilità di definire un vero e proprio profilo web per la nostra casa è una tipicità di frieund non presente sul mercato. A questo si aggiunge la presenza dell'intervista che sfrutta una sistema di memorizzazione innovativo per ridurre lo spazio occupato. Ogni utente ha poi un profilo stile social network, a questi si differenzia per la possibilità di vedere in modo diretto i contenuti inseriti dall'utente senza dover ricaricare la pagina. Con un clic possiamo visualizzare le sue ricette, i suoi viaggi e le sue case; nonché avere possibilità di dialogare tramite una mail. Ogni utente può selezionare un diverso stile che da un aspetto diverso al suo profilo. La tabella città raccoglie tutte le città e la relativa posizione sulla cartina. Tramite il motore di ricerca è possibile da qualsiasi pagina inserire una località che potremo visualizzare su una mappa e da li avere accesso a piatti, utenti e abitazioni di quella determinata località. In questo modo si incentra il concetto di ente locale e da li si parte verso gli altri canali messi a disposizione. Wow raccoglie molte foto che l'utente potrà decidere di segnalare (stile ecards) ad un amico o di scaricare sul proprio pc. Sarà data in futuro anche la possibilità di caricarne. Pag. 28 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali L'utilizzo dei privilegi di accesso permette la definizione di alcuni amministratori locali. In questo modo si potrà avere la collaborazione di altri utenti per l'inserimento delle città e la traduzione nelle varie lingue europee a costo zero. Frieund rispecchia quindi in modo pieno la filosofia del web 2.0 dove con i minimi costi sono gli utenti a creare contenuti. Una piattaforma il cui scopo primario non è l'utile ma lo scambio di idee. Nuove funzionalità di personalizzazione (rilevanti nell'era del marketing) sono in arrivo e la flessibilità di frieund in previsione del supporto multilingua e dei continui mutamenti dei bisogni e delle mode umane lo rendono adatto ad un continuo stato di transizione. Prezzo Vista la filosofia con cui frieund nasce, sembra chiaro come l'utilizzo del sito sia gratuito. Il codice è di proprietà del webmaster ma nulla vieta che porzioni di esso (che non mettano in pericolo la sicurezza delle applicazioni esistenti) siano rilasciabili sotto la licenza opensource. Tempo Il tempo utile alla realizzazione del sito è di 4 ore per l'interfaccia grafica e di 30 giorni per la parte di programmazione. Alla fase implementativa è preceduta una fase di pianificazione e una di apprendimento e approfondimento dei linguaggi php, html, css, javascript e della tecnologia ajax. Pag. 29 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali Appendice In questa sezione trovano spazio approfondimenti su argomentazioni richiamate in fase di progettazione Sicurezza delle applicazioni Riportiamo in questa breve sezione alcuni dei parametri utilizzati per garantire una sicurezza dei dati memorizzati nella nostra base di dati e delle applicazioni che ne fanno uso ad eventuali accessi non autorizzati. SQL_INJECTION (query injection) La funzioni addslashes è in disuso mentre mysql_escape_string è stata deprecata. Al loro posto si applica la funzione mysql_real_escape_string() che permette di risolvere il problema delle query injection con l'escaping dei caratteri speciali di sql. VARIABLE INJECTION Per evitare questo problema è stato deciso di non utilizzare variabili GET né COOKIE, il passaggio di valori avviene tramite l'array globale POST e l'autenticazione è gestita con il meccanismo delle sessioni cui è stato espressamente indicato di non usare in nessun caso cookie. Le variabili POST non sono mai recuperate dall'array $_REQUEST e su di esse sono effettuati controlli di esistenza e consistenza nonché in determinati casi il casting forzato. XSS (Cross Site Script) Per risolvere il problema dell'inclusione di codice malevolo è stato pensato di filtrare i dati immessi nei nostri campi. strip_tags(stringa) si occupa di eliminare eventuali tag html e php presenti htmlentities(stringa) converte caratteri speciali in testo html L'utilizzo congiunto di queste due funzioni ci permettono una protezione sufficiente a tale problematica Password Per la protezione delle password è stato deciso l'utilizzo della funzione hash sha1. La lunghezza di tale campo è stata vincolata tra 8 e 14 caratteri per garantire una sicurezza minima. Visibilità dei parametri di connessione al DBMS Il file contenente i parametri di connessione, nonché la password in chiaro è stato memorizzato in una cartella protetta da lettura e scrittura. Accesso al DBMS Per la connessione al DBMS è preferibile accedere da un utente non amministratore in modo da poterne limitare i privilegi. Un utente è creabile e gestibile tramite la sintassi GRANT di MySql. Pag. 30 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali Ajax & JSON Riportiamo un esempio di connessione tramite l'oggetto XMLHTTP Request utilizzato per la verifica di disponibilità di un username // Controllo della disponibilità di un username // Andrea Monacchi function createRequestObject() { // se il browser è internet explorer if(navigator.userAgent.indexOf("MSIE") != (-1)) { // istanzio una variabile per diversificare i browser var Classe = "MSxml2.XMLHTTP"; // se il browser è IE 5.5 usiamo una variante if(navigator.appVersion.indexOf("MSIE 5.5") != (-1)) { Classe = "Microsoft.XMLHTTP"; } try { //istanzio un oggetto acriveX XMLHTTP = new ActiveXObject(Classe); XMLHTTP.onreadystatechange = handleResponse; return XMLHTTP; } catch(e) { document.getElementById("risultati").innerHTML = "Error!!"; } } // altrimenti se è un mozilla o simili else { try { XMLHTTP = new XMLHttpRequest(); XMLHTTP.onload = handleResponse; XMLHTTP.onerror = handleResponse; return XMLHTTP; } catch(e) { document.getElementById("risultati").innerHTML = "Your browser is unable to manage this operation"; } } } var http = createRequestObject(); function sndReq() { var action = document.getElementById("usernamecheck").value; var param = "username="+action; //controllo che username sia almeno 5 caratteri if(action.length < 6) { // se la user è troppo corta lo comunico nell'area indicata document.getElementById("risultati").innerHTML = "Username too short"; } else { // pulisco lo spazio nell'area document.getElementById("risultati").innerHTML = "Searching...."; // altrimenti posso controllare se l'username è presente o meno // devo quindi effettuare una richiesta usando il canale istanziato // effettuo la richiesta in modo asincrono e con il metodo post http.open('POST', 'usrex.php', true); Pag. 31 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali //Send the proper header information along with the request http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http.setRequestHeader("Content-length", param.length); http.setRequestHeader("Connection", "close"); //Call a function when the state changes. http.onreadystatechange = handleResponse; // invio di dati alla pagina - in caso di richiesta asincrona è posto a NULL http.send(param); } } function handleResponse() { if(http.readyState == 4){ var response = http.responseText; var update = new Array(); document.getElementById("risultati").innerHTML = http.responseText; } } Per lanciare la richiesta si invoca la funzione sndReq() che si occuperà del recupero dei parametri tramite l'id degli oggetti del DOM e del loro invio tramite POST alla pagina php di controllo. Presentiamo anche la pagina che effettua la query al db <?php $utente = @strip_tags($_POST['username']); // controllo successivamente l'esistenza dell'utente che in certi casi dopo il // filtraggio potrebbe essere diventato una stringa vuota // l'username deve essere compreso tra 5 e 30 caratteri if(isset($utente) && (strlen($utente) < 31) && (strlen($utente) > 4)) { // apro la connessione dal database require_once($_SERVER['DOCUMENT_ROOT'].'conn/xyz.php'); // setto il tipo di documento restituito impostando gli header header("Content-Type: text/plain"); // seleziono il database $db = @mysql_select_db("Sql180545_1", // nome del database $connessione) // nome della connessione or die ("Impossibile selezionare il database."); // eseguo la query $result = @mysql_query("Select $utente."'"); username from dati_accesso where username='". // controllo che esista almeno un record if(mysql_num_rows($result) > 0) { // se esiste un record allora lo username è gia stato usato echo "The username ".$utente." is not available"; } else { // se mysql_num_rows è zero non ci sono record e posso usare lo username echo "The Username ".$utente." is available"; printf("</br> <form id=\"prosegui\" name=\"prosegui\" method=\"post\" action=\"\"> </br> Pag. 32 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali <input name=\"passo\" type=\"hidden\" id=\"passo\" value=\"3\" /> <input name=\"username\" type=\"hidden\" id=\"username\" value=\"%s\" /> <input name=\"send\" class=\"btn1\" type=\"submit\" id=\"send\" value=\"Choose & Next\" /> </form>", $utente); } // chiudo la connessione con il database mysql_close($connessione); } else echo "You have to insert a 5-30 chars-length username"; ?> Nel div risultati il javascript inserisce il codice html restituito dalla pagina di check utente, questo è un modo alternativo e più diretto di usare Ajax che (come dice la sigla) nella comunicazione utilizza un documento XML. Una variante che sentiamo di proporre per future implementazioni è la tecnologia JSON (Javascript Object Notation), essa evita l'invio della pagina html ma propone il solo invio degli oggetti restituiti dal database. Ad esempio invece di restituire una pagina e il suo aspetto che caricherebbe la nostra comunicazione asincrona serializza gli oggetti sotto forma di stringa (il cui formato è riconosciuto e standardizzato a livello internazionale e per più linguaggi). Tale stringa è poi inviata al parser javascript della pagina ricevente tramite la funzione eval() ed è ora possibile ad accedere a tali oggetti come se fossero locali. Ciò risulta più elegante ed intelligente rispetto al semplice file XML. Connessione al database La connessione al DBMS avviene includendo il file esterno xyz (nome meno mnemonico possibile) contenente la funzione connect e le credenziali di accesso. Tale documento è stato posto nella cartella conn che ha privilegi di sola esecuzione. In tal modo si evita la copia e l'accesso al DBMS da utenti non autorizzati. Pag. 33 di 34 La community di frieund.com – Linguaggi e applicazioni multimediali Il captcha (completely automated public Turing test to tell computers and humans apart) Riportiamo il codice php dello script di creazione del codice di sicurezza <?php // faccio partire la sessione include($_SERVER['DOCUMENT_ROOT'].'session.php'); // genero il codice definendo il tipo di dato header('Content-type: image/jpeg'); // definisco le dimensioni $size_x = 150; $size_y = 80; // come codice segreto uso una variabile di sessione in modo che nn sia visibile all'utente $code = $_SESSION['captcha_code']; $space_per_char = $size_x / (strlen($code)+1); // creo l'immagine $img = imagecreatetruecolor($size_x, $size_y); // alloco i colori che mi serviranno // sfondo RGB(230,237,253) $sfondo = imagecolorallocate($img, 230, 237, 253); // bordo RGB(196,211,254) $bordo = imagecolorallocate($img, 196, 211, 254); // genero una palette di colori che mi serviranno alla stampa del testo $colors[] = imagecolorallocate($img,0,58,104); $colors[] = imagecolorallocate($img,0,103,150); $colors[] = imagecolorallocate($img,123,159,221); // riempo lo sfondo disegnando un rettangolo colorato // la funzione riceve l'immagine, le cordinate dell'angolo superiore sinistro // le cordinate dell'angolo inferiore destro e il colore stesso // cioè i punti della diagonale del rettangolo e il colore di riempimento // o nel caso della seconda del colore di bordo imagefilledrectangle($img, 1, 1, $size_x - 2, $size_y - 2, $sfondo); // disegno il bordo disegnando un rettangolo senza riempimento imagerectangle($img, 0, 0, $size_x - 1, $size_y - 1, $bordo); ?> // disegno il testo iterando la stringa di caratteri del codice for ($i=0; $i<strlen($code); $i++){ $color = $colors[$i % count($colors)]; imagettftext($img, 28+rand(0,8), // il parametro riguarda le dimensioni del font che variano da 28 a 36 punti -20 + rand(0,40), // angolo di rotazione del testo ($i + 0.3)* $space_per_char, // posizione x di disegno del carattere 50 + rand(0, 10), // posizione y di base del testo $color, // colore del testo 'arial.ttf', // fonttype da usare $code{$i}); // carattere da stampare } // attivo l'antialiasing sulla immagine in modo da rendere le linee piu morbide imageantialias($img, true); // visualizzo l'immagine in formato jpeg imagejpeg($img, '', 70); // eventualmente essendo un immagine con lineee geometriche potrei optare per png // imagepng($img, '', 75); Ovviamente il font arial dovrà essere incluso nella stessa cartella del file. Una volta che volessimo utilizzare tale sistema non dovremo far altro che inserire un immagine di questo tipo nella nostra pagina <?php // genero un captcha code random e lo passo // il codice generato è una stringa numerica di 6 caratteri $_SESSION['captcha_code'] = rand(0,9).rand(0,9).rand(0,9).rand(0,9).rand(0,9).rand(0,9); ?> <img src="captcha.php" alt="captcha" /> Pag. 34 di 34