mercoledì 30 dicembre 2009

Parole, parole, parole

Vi segnalo questa applicazione interattiva pubblicata su Repubblica online che analizza i testi dei discorsi di fine anno di tutti i presidenti della repubblica. È vero che le parole visualizzate in questo modo non rendono giustizia al discorso intero ma è interessante l'approccio "scientifico" e la visualizzazione: la "word cloud" (penso si possa chiamare così) dice anche molte cose implicite e non comprensibili con una lettura lineare. Tecnica da tenere presente anche per altre situazioni. Bella idea. Aggiornamento: Ecco l'applicazione usata per generare i "word cloud" http://www.wordle.net/

mercoledì 25 marzo 2009

Super javascript

In questi giorni ho scoperto una evoluzione, per me nuova, di html e javascript che la dice lunga sulla direzione che sta prendendo questa tecnologia: da semplice sistema per la creazione di ipertesti si sta trasformando sempre più in una vera e propria "piattaforma" per la programmazione di applicazioni che non hanno nulla da invidiare a quelle "classiche" che abbiamo installato sul pc. In particolare ho scoperto che le ultime specifiche dell'HTML5 prevedono la gestione diretta della grafica mediante javascript: in parole semplici è possibile avere una "tela" su cui disegnare quello che si vuole. Il tutto dipende dall'introduzione del tag <canvas> (che significa appunto "tela") e di alcune funzioni javascript per disegnare linee, rettangoli, cerchi, ... ma anche immagini nei formati supportati dal browser. Il tag è supportato, per ora, solo dalle più recenti versioni di Firefox, Safari, Opera e, ovviamente, Chrome. Internet Explorer, anche nella versione 8 (che è uscita recentemente in beta) non lo supporta.

Il funzionamento è procedurale, non dichiarativo; in pratica il disegno viene costruito "dicendo" al browser come deve procedere per farlo: "sposta la matita qui", "traccia una linea da qui a là", "cambia il colore della matita", "fai un cerchio", "riempi il cerchio di colore", ... Non voglio entrare in discussioni (filosofiche) sul fatto se sia meglio un approccio dichiarativo o procedurale ma voglio fare subito alcuni semplici esempi per capire.

Per iniziare c'è bisogno di una semplicissima pagina html con un tag <canvas> al quale associamo un attributo "id" per poterlo identificare semplicemente. Inserirò poi nella pagina una funzione javascript disegna() che viene eseguita al caricamento della pagina stessa (onload) e "disegnerà" nel canvas. Questo è il codice di base della pagina:

<html> <head> <title>Test canvas tag</title> <style type="text/css"> #mycanvas {border-style:solid; border-width:1px; border-color:black;} </style> <script> function disegna() { //Qui inseriremo le istruzioni per fare il disegno } </script> </head> <body onload="disegna();"> <canvas id="mycanvas" width="200" height="200"> Tag &lt;canvas&gt; non supportato da questo browser </canvas> </body> </html>

Notare che qualsiasi contenuto del tag <canvas> non verrà visualizzato se il browser lo supporta: scrivere al suo interno è quindi un ottimo sistema per informare l'utente che sta usando un browser a cui manca questa funzionalità.

Faccio qualche prova di codice javascript nella funzione disegna().

Prima di tutto occorre ottenere l'oggetto che permette di disegnare e metterlo in una variabile:


var foglio = document.getElementById('mycanvas').getContext('2d')


Notare che il metodo getContext() per ora supporta solo il tipo '2d' (disegno bidimensionale) ma in futuro potrebbe anche supportare grafica in uno spazio tridimensionale (3d).

La tela è come un piano cartesiano con le coordinate che hanno origine nell'angolo in alto a sinistra, quindi il punto (0,0) sarà l'angolo in alto a sinistra, il punto (200,200), nel caso di esempio, sarà invece l'angolo in basso a destra.

la funzione moveTo permette di spostare la "matita" senza disegnare

foglio.moveTo(0,150)

La funzione lineTo disegna una linea retta fino al punto indicato

foglio.lineTo(200,150)

La funzione stroke() visualizza le linee fatte

foglio.stroke()

Cambio il colore della matita, ne prendo una rossa:

foglio.strokeStyle = 'red'

Inizio una linea (spezzata)

foglio.beginPath()

Mi sposto (senza disegnare)

foglio.moveTo(50,50)

Faccio due linee...

foglio.lineTo(150,50) foglio.lineTo(100,0)

E "chiudo" la linea spezzata sul punto di partenza:

foglio.closePath() foglio.stroke()

Riprendo la matita nera:

foglio.strokeStyle = 'black'

Disegno un rettangolo (i primi due parametri indicano il punto di partenza (angolo in alto a sinistra) e gli altri due indicano rispettivamente la larghezza e l'altezza del rettangolo

foglio.strokeRect(50,50,100,100)

Imposto il colore per lo riempimento delle figure:

foglio.fillStyle = 'brown'

Disegno un rettangolo colorato:

foglio.fillRect(100,120,20,30)

Il risultato, mettendo tutto insieme, è in questa pagina (visualizzate l'HTML per vedere com'è). Vi sembra banale? Allora guardate questo esempio fatto sfruttando (anche) l'elemento canvas: http://www.chromeexperiments.com/hosted/gravity/index.html

oppure quest'altro:

http://deanm.github.com/pre3d/monster.html

sabato 28 febbraio 2009

Reale e virtuale mescolati

Importanti "rivoluzioni" in campo informatico sono avvenute, in passato, con l'evoluzione delle interfacce tra la macchina e l'uomo. I primi computer comunicavano con schede perforate, poi si è passati a monitor e tastiera con il "prompt dei comandi" (i primi computer che ho usato io erano ancora così); la vera rivoluzione fu però l'avvento del mouse e dei sistemi "a finestre" (Mac, poi Windows, senza entrare in dispute sull'attribuzione dei meriti); attualmente sono già diffusissimi i sistemi "touch screen" (chi ha uno smartphone sicuramente li usa quotidianamente) o addirittura "multitouch" (iPhone) dove viene riconosciuto il tocco di più dita contemporaneamente.
E domani?
Raccolgo qui un po' di notizie già "vecchie" di qualche mese, che secondo me, dipingono bene verso cosa stiamo andando. Alcune sembreranno scomode e inutilizzabili o vi faranno esclamare: "Io una cosa del genere non la userò mai!". Prima di fare questi pensieri, però, provate ad andare indietro con la mente di una decina di anni: com'erano i cellulari, vi ricordate quegli oggetti "enormi" che "ma a cosa serve?, ne posso fare tranquillamente a meno!"? Io ero tra quelli che la rensavano così. Non ne avete forse uno in tasca ora?
Veniamo alle novità. Il denominatore comune sembra quello di mescolare la realtà con il mondo virtuale portando il virtuale nel reale o viceversa. Ma meglio guardare gli esempi: valgono più di mille parole
.
Un bell'esempio di tecnologia multitouch alla Microsoft
Computer "indossabile" costruito al MIT
CamTrax, un software (gratuito!) che permette, tramite la webcam, di usare una cosa qualsiasi per controllare il pc
La "realtà aumentata" che cita Paolo Attivissimo in un suo post
e siamo solo all'inizio!

mercoledì 11 febbraio 2009

Recupero accesso di amministratore

Recupero dell'accesso di amministratore (root) in un sistema linux Ubuntu e riflessione sulla sicurezza dei dati.
Vi racconto un'altra esperienza di "recupero" di un danno dovuto, questa volta, ad un errore umano e non ad un guasto hardware. Non è nulla di particolarmente "innovativo" ma spero possa servire a qualcuno che si dovesse trovare nella stesa situazione. Cercherò di spiegarlo con parole semplici, senza dare nulla per scontato.
Premessa. In un sistema linux esiste un "super utente" che ha la possibilità di vedere e modificare ogni file, si chiama "root". L'utente con cui normalmente si accede al sistema è, invece, generalmente, meno privilegiato e può modificare solo alcuni file. Per le operazioni di configurazione del sistema o l'installazione dei programmi è necessario connettersi con l'utente root.
Veniamo ora ad un altro concetto: i "gruppi". Ogni utente può appartenere a uno o più gruppi. Un gruppo non è altro che un modo per assegnare ad un insieme di utenti i permessi per certi file relativi ad un unico ambito. Esempio: il gruppo "lp" permette di utilizzare tutte le funzionalità relative alla porta parallela: tutti gli utenti che appartengono al gruppo lp possono usare la porta parallela. Mi scusino gli esperti per questa descrizione ultra-semplificata ma è necessaria per capire quanto segue.
Le distribuzioni Ubuntu hanno, per impostazione predefinita, l'utente "root" disabilitato, nel senso che non ha una password impostata per cui non è possibile accedere direttamente al sistema come "root" ma solo con il proprio utente definito in fase di installazione. Come è possibile allora effettuare le operazioni di configurazione ed installazione? Risposta: con il comando sudo (Super User DO). In pratica un utente "normale" può scrivere sul terminale "sudo" seguito da un qualsiasi comando ed esso verrà eseguito come se fosse l'utente root. Sudo prevede generalmente, come misura di sicurezza, il reinserimento della password dell'utente. Anche se non utilizzate il terminale dei comandi in Ubuntu vi sarete certamente imbattuti nella versione "grafica" dello stesso comando che vi richiede la password ogni volta che tentate di eseguire una operazione "riservata". Chi può usare il comando sudo? Certo non chiunque, altrimenti non ci sarebbe la possibilità di impostare dei livelli di sicurezza. Gli utenti che abilitati a sudo sono quelli definiti nel file /etc/sudoers (che ovviamente può essere modificato solo da un utente che possa già, a sua volta, effettuare sudo). In Ubuntu sudo è configurato in modo da dare la possibilità di utilizzarlo a tutti gli utenti del gruppo "admin" e generalmente, in una installazione standard, viene creato un solo utente con il proprio nome e che appartiene anche al gruppo admin (se cè solo un utente non può essere che lui l'amministratore!).
Cosa succederebbe se inavvertitamente (o meglio stupidamente) un utente si auto-eliminasse dal gruppo admin? Ebbene, è proprio quello che ho fatto. Ovviamente è sempre possibile togliersi dal gruppo ma solo un utente amministratore può aggiungere qualcuno allo stesso. Siccome l'unico utente ero io non c'era più (quasi) niente da fare: è stato un po' come chiudersi fuori casa lasciando le chiavi dentro!
La soluzione? La chiavetta USB che ho usato per il recupero dati (vedi post precedente). Avviando Ubuntu "live" dalla chiavetta, il disco rigido è leggibile e scrivibile, quindi è possibile ripristinare i gruppi modificando il file /etc/group (è il file dove vengono salvate tutte le impostazioni dei gruppi). Procedura pratica:
Aprire un terminale
Digitare
sudo mkdir -p /mnt/disco
(crea una directory "disco" dove monteremo l'hard disk; notare che "sudo" funziona perché ora stiamo lavorando nel sistema caricato dalla chiavetta e non su quello installato)
sudo mount /dev/sda1 /mnt/disco
(monta la partizione del disco nella directory appena creata. Attenzione:  sda1 è la prima partizione del primo disco scsi (o SATA), per un disco IDE la prima partizione del primo disco sarà hda1, se il disco è sul secondo canale IDE sarà hdb1, se la partizione non è la prima sarà hda2, hda3, ecc...)
sudo cp /mnt/disco/etc/group- /mnt/disco/etc/group
Ho visto che il vecchio file dei gruppi (contenente la versione in cui il mio utente apparteneva al gruppo admin) è stato salvato in un file con un "-" alla fine. Quindi al posto di modificare il file /etc/group l'ho semplicemente sovrascritto con la versione vecchia.
Riavviare e togliere la chiavetta in modo che parta il sistema dal disco rigido: se tutto è andato bene il problema dovrebbe essere risolto.
Una riflessione finale. Notate come sia semplice leggere dati da un computer anche con un sistema sicuro come linux e protetto da password. Se è impostato il boot da usb (oppure se il BIOS non è protetto da password, quindi chiunque può modificarlo) è sufficiente inserire una chiavetta con Ubuntu, avviare il PC e montare il disco: tutti i dati sono leggibili!
Mettere una password al BIOS potrebbe già essere una sicurezza in più ma è sempre possibile che qualcuno stacchi fisicamente l'hard-disk collegandolo ad un altro PC e montandolo come descritto. Probabilmente la soluzione più sicura sarebbe quella di utilizzare filesystem criptati ma il loro uso al momento è decisamente poco frequente in ambito casalingo.

venerdì 9 gennaio 2009

Recupero di dati da un volume FAT32 corrotto

Racconto di un'esperienza di recupero di dati da una partizione FAT32 con l'intestazione danneggiata
Inizio il nuovo anno con un bel problema. Il "vecchio" pc fisso (un Olidata con processore AMD da 1.8GHz ) non ne vuole più sapere di ripartire: è vero lo stavo usando molto poco negli ultimi mesi, siccome il portatile è molto più comodo, ma non pensavo mi abbandonasse così!
I sintomi sono questi: all'accensione parte il boot loader (uso grub perché ho windows 98, windows XP e Ubuntu linux in multi boot: pessima scelta, ma è un altro discorso), si blocca con "error 17" ancora prima di presentare la lista delle opzioni. Quasi sicuramente il problema è (solo?!) l'hard disk. L'occasione è buona per un esperimento di recupero dei dati.
Occorrente:
  • Un PC con hard disk danneggiato
  • Una chiavetta USB da almeno 1Gb
  • Un hard disk esterno USB con abbastanza spazio libero da contenere i dati da recuperare.
  • Un altro PC funzionante con connessione a internet.

Avvio del sistema

Il primo passo è accedere al PC senza sfruttare l'hard disk: scarico l'immagine ISO dell'ultima versione di Ubuntu (la 8.10, versione desktop), la masterizzo e tento il boot da CD. Purtroppo i guai non vengono mai da soli: il lettore CD aveva già dato segni di cedimento in passato (questo PC è proprio da buttare!) ma questa volta non ne vuole proprio sapere di partire; emette strani suoni e dopo alcuni tentativi falliti decido di tentare un altra strada. Il secondo tentativo ha esiti migliori. Scarico UNetbootin, un software che permette di creare una installazione di una distribuzione linux avviabile da chiavetta USB. L'interfaccia grafica è chiarissima: infilo la chiavetta USB da 1G, seleziono l'immagine ISO appena scaricata e in pochi minuti la mia chiavetta è pronta. Dal BIOS del PC danneggiato imposto la sequenza di avvio in modo che tenti, come prima cosa, l'avvio da chiavetta, resetto ed ecco finalmente Ubuntu Linux. La versione che parte è "live", cioè viene eseguita senza essere installata sull'hard disk, ma le funzionalità presenti dovrebbero essere sufficienti per una verifica dei problemi del disco e per un eventuale recupero dei dati. Il caricamento è piuttosto lento, probabilmente a causa delle porte USB versione 1.1, ma non è la velocità che mi interessa. Durante l'avvio il sistema cerca di montare le partizioni presenti sul disco rigido e infatti vedo scorrere diversi errori: è la conferma che il problema è proprio l'hard disk.

Verifica dei problemi

Una volta avviato il sistema (interfaccia grafica con diverse applicazioni), imposto nel menù System la tastiera italiana (il default è quella americana) e apro un terminale. Il disco viene visto e riconosciuto dal sistema come /dev/sda e l'MBR è leggibile in quanto il comando
sudo fdisk /dev/sda
(seguito poi dall'istruzione 'p') stampa correttamente la tabella delle partizioni.
È una buona notizia.
L'hard disk è suddiviso in diverse partizioni. Mi interessa recuperare i dati di una partizione formattata con FAT32 che si chiama /dev/sda6. Tento di montarla:
sudo mkdir /media/hd
sudo mount -t vfat /dev/sda6 /media/hd
mi risponde:
mount: /dev/sda6: can't read superblock
questa non è una buona notizia.
Provo a eseguire il programma di verifica e riparazione del filesystem FAT32
sudo fsck.vfat -v -l -r /dev/sda6
Risponde:
Read 512 bytes ad 0: Input/output error
Altra brutta notizia: non è possibile nemmeno leggere i primi 512 bytes del volume, quelli dove si trova l'header del filesystem (vedi specifiche FAT32). Voglio capire esattamente quali parti della partizione sono corrotte, uso badblocks, un programma che generalmente viene utilizzato automaticamente dalle varie versioni di fsck quando richiamate con l'opzione -c; in questo caso lo eseguo manualmente impostando una dimensione arbitraria dei blocchi a 512 bytes:
sudo badblocks -s -v -c1 -b 512 -o badblocks.out /dev/sda6
mi restituisce nel file badblocks.out una lista di 32 blocchi danneggiati, precisamente i primi 32. Questa volta c'è una notizia buona e una cattiva: la buona è che il settore contenente i dati è sicuramente oltre il 32mo blocco, cioè i dati sono tutti leggibili; la cattiva notizia è che è illeggibile tutta l'intestazione del filesystem e probabilmente una parte della prima copia della FAT, inoltre, siccome è essenziale per il funzionamento del filesystem e non può essere allocata altrove, il filesystem non è riparabile nel punto in cui si trova.
Riesco a dedurre (come ho fatto lo spiegherò in un altro post altrimenti mi dilungo troppo) che in realtà la prima copia della FAT inizia al 33mo blocco quindi entrambe le copie sono intatte: devo solo ricostruire l'intestazione.

Recupero dei dati

Una grande possibilità dei sistemi linux è quella di montare un file come se fosse una partizione fisica, sfruttando i "loop device". Ho a disposizione un hd esterno usb, completamente formattato con NTFS, con 30 Gb liberi, a me ne bastano 20 (la dimensione del volume danneggiato). L'hd viene riconosciuto automaticamente da Ubuntu ed è subito disponibile. Prima di tutto travaso tutto il contenuto del volume in un file sostituendo la parte illeggibile con degli zeri:
dd ibs=512 obs=512 skip=32 seek=32 if=/dev/sda6 of=sda6.data
(ci vuole un bel po' di tempo, probabilmente sempre a causa dell'USB1.1)
Poi creo su questo file un filesystem di tipo FAT32:
mkfs.vfat -F 32 -s 32 -S 512 -v sda6.data
una spiegazione dei parametri:
-F 32 indica di creare un fs di tipo FAT32 (esiste anche FAT16 FAT12)
-S 512 indica di considerare settori da 512 byte
-s 32 indica che ogni cluster (unità di allocazione minima di un file) è composto da 32 settori (cioè 512 * 32 = 16Kb). Il fatto che i clusters debbano essere di 16 Kb l'ho ricavato da considerazioni sui dati che spiegherò in un altro post.
-v è solo per avere un output più prolisso
Fatto questo provo a montare il file, solo per vedere se è corretto; non vedrò ancora i miei dati ma solo un filesystem vuoto siccome le FAT sono state sovrascritte da mkfs:
sudo mount -o loop -tvfat sda6.data /media/hd
Bene funziona. Lo smonto di nuovo.
sudo umount /media/hd
Ora che ho in sda6.data un filesystem vuoto con un header corretto provo a sostituire le due copie delle FAT vuote con quelle piene presenti nella partizione originale e, come abbiamo visto, integre.
La dimensione di una FAT del mio volume è di 5118 Kb (come faccio a saperlo lo spiego nell'altro post che farò), le due copie occupano dunque 10236 Kb e partono dopo 16 Kb dall'inizio del volume (32 blocchi da 512 byte di header danneggiati). In realtà oltre a copiare le FAT devo anche copiare i cluster contenenti la root directory che sono stati sovrascritti quando ho generato il filesystem. La root directory è verosimilmente contenuta nei primi clusters dopo le FAT (essendo la prima creata) quindi abbondo un po' e prendo 30000 Kb. Notare che avrei potuto ricopiare nuovamente tutto il volume per maggior sicurezza, ma siccome ci vuole molto tempo evito di farlo.
Le estraggo in un file:
sudo dd bs=1024 count=30000 skip=16 if=/dev/sda6 of=sda6.fat
e inserisco il file nel punto corretto all'interno di sda6.data.
Per fare questo non sono riuscito a trovare un comando unix (se qualcuno lo conosce mi "faccia un fischio"), ma ho usato uno script python di poche righe (la versione live di Ubuntu comprende anche l'interprete python)
f=open('sda6.fat')
fat=f.read()
f.close()
f = open('sda6.data', 'r+')
f.seek(16384) #inizio a scrivere dopo i primi 16 Kb
f.write(fat)
f.close()
ora monto nuovamente il volume
sudo mount -o loop -tvfat sda6.data /media/hd
ls /media/hd
e...
EUREKA!
ecco tutti i miei dati: non mi resta che copiarmeli e sono salvi.