Introduzione al progetto Ninive
|
Studio sull'interazione di filmati Macromedia Flash con eseguibili esterni |
a cura del Ninive Project Team ( ninive(at)iunknown(dot)org ) |
|
Introduzione
Macromedia Flash consente di creare filmati ad alto valore grafico che hanno un ambiente target ben definito: il mondo Internet. Come tale assioma impone, il set di funzionalità messe a disposizione dall'ambiente di sviluppo di filmati Flash deve essere necessariamente incapsulato all'interno di un contenitore protetto, che non può e non deve permettere ( facilmente ):
-
una facile interazione con l'ambiente esterno, intesa come reperimento dati mediante socket, pipe, e IPC similari.
-
l'accesso a segmenti sensibili, come ogni tipo di memoria disponibile.
Ogni applicazione scritta in questo ambiente di sviluppo, sia essa un filmato o un proiettore eseguibile, eredita queste limitazioni, e non permette quella versatilità che una applicazione nativa porta con sè senza sforzi: l'interazione con il file system, la gestione diretta e a basso livello di socket, ecc.
Il problema è dunque: come fare in modo che un generico filmato Flash funzioni come una applicazione completa pur essendo sviluppata in un ambiente che non è general purpose?
In questo documento si intende presentare una possibile soluzione al problema.
Ambiente di sviluppo e test
L'ambiente di sviluppo e testing della soluzione proposta si articola in questo modo:
- Microsoft Windows XP Home
- Macromedia Flash MX Professional 2004
- Compilatore GNU C gcc versione 3.3.1 ( mingw special 20030804-1 )
I dettagli dei test effettuati
Sulla base delle attuali conoscenze del gruppo di testing sono stati testate inizialmente due possibilità di interazione di un filmato Flash con il mondo esterno:
- attraverso l'oggetto ActionScript loadVars
- attraverso la funzione ActionScript fscommand
L'oggetto ActionScript loadVars permette di interagire con un URL e acquisire da esso, o inviare ad esso, variabili in formato MIME, vale a dire nella forma var1=value1[&var2=value2....]. A seguito di una corretta esecuzione del metodo load, Macromedia ci dice che all'interno dell'instanza invocante vengono generate le n variabili contenute nella stringa MIME inizializzate ai loro valori.
Dato che l'URL, come dice la pagina di help di loadVariables, può essere
[..]
such as a text file or text generated by a CGI script, Active Server Pages (ASP), or PHP, or Perl script
[..]
è stato generato un semplice eseguibile chiamato prova.exe, che emette in output una stringa MIME, e nel filmato Flash utilizzato come container del test è stato inserito questo codice:
my_var=new LoadVars();
status=my_var.load("prova.exe");
Pubblicando questo primo esempio ed eseguendolo non abbiamo avuto il risultato sperato, ed il motivo è chiaro: Flash non invoca di per sè stesso CGI script, perchè rivolgendosi ad un URL assume che siano i motori interni dell'URL invocato ad eseguire il CGI script.
Quindi è stata fatta una seconda prova: invece di invocare il CGI script, si è cercato di leggere l'output da esso prodotto scaricato su un file di testo:
my_var=new LoadVars();
status=my_var.load("test.log");
Ma nemmeno questo esempio ha funzionato, per un motivo altrettanto chiaro: il metodo load intercetta lo standard output dello script eseguito nell'URL richiesto, mentre un file di testo può contenere i dati MIME, ma non può esporli automaticamente sullo standard output.
A questo punto, si è arrivati ad utilizzare l'unica interfaccia Flash disponibile ad interagire con eseguibili esterni, cioè la funzione fscommand. L'invocazione di eseguibili esterni ha però delle forti limitazioni, peraltro necessarie ai fini della sicurezza:
- gli eseguibili invocati devono risiedere in una sottodirectory rispetto al percorso del filmato Flash invocante, chiamata fscommand.
- non è possibile passare parametri in riga di comando agli eseguibili invocati, inserendoli nella stringa di impostazione del nome dell'eseguibile.
- non è possibile intercettare lo standard output emesso dagli eseguibili invocati.
Per prima cosa, è stata testata la corretta esecuzione di un eseguibile esterno; il file prova.exe è stato corredato di un'emissione di un semplice log di esecuzione su file di testo ed è stato spostato nella sottodirectory indicata; nel filmato Flash è stato quindi introdotto il codice:
fscommand("exec","prova.exe");
che è la forma ( unica possibile ) con cui invocare eseguibili esterni. Il comando è risultato correttamente eseguito, ma è importante segnalare che il test del movie Flash attivato con CTRL+ENTER non ha attivato l'eseguibile, mentre la pubblicazione del movie stesso e la sua successiva esecuzione come proiettore ha funzionato correttamente. Questo elemento è molto importante in quanto si sono riscontrate delle forti differenze fra il comportamento di un filmato Flash eseguito in test e un filmato Flash pubblicato.
A questo punto, abbiamo scoperto che possiamo invocare eseguibili da un filmato Flash, ma non possiamo intercettare direttamente in alcun modo il loro operato. Per questo motivo possiamo avvalerci dell'unica interfaccia di colloquio fra applicazioni sicura per definizione, solida e standard: il formato XML.
Il file prova.exe è stato per l'ennesima volta modificato: è stata aggiunta la creazione di un piccolo file XML nella directory di invocazione, chiamato test.xml, e il filmato Flash è stato modificato come segue:
fscommand("exec","prova.exe");
doc = new XML();
doc.onLoad = function (success) {
testo_file.text=doc.getBytesTotal(); // testo_file è un dynamic text
}
doc.load ("fscommand/test.xml");
Nel codice è stata dunque aggiunta una semplice e dimostrativa istanza dell'oggetto Flash XML, che consente la gestione di buffer XML internamente ai filmati Flash.
L'esecuzione del filmato ha permesso di caricare correttamente il file XML generato dall'eseguibile prova.exe.
Chiaramente, questo è ancora insufficiente; sebbene sia possibile comunicare con una applicazione Flash, il fatto che una applicazione Flash non possa pilotare in alcun modo applicazioni esterne non è accettabile, perchè per generare un insieme di soluzioni a possibili necessità del filmato dovremmo realizzare un numero infinito di applicazioni troppo verticalizzate su microsoluzioni, piuttosto che un codice unico e general purpose.
Andiamo avanti.
Uno dei modi che Flash mette a disposizione per aprire un canale full duplex con il mondo esterno è attraverso l'utilizzo dell'oggetto XMLSocket; tale oggetto apre una connessione TCP full duplex con un server operante nel medesimo dominio dell'applicazione Flash, con la quale
[..]
An unlimited number of XML messages can be sent and received over a single XMLSocket connection.
[..]
Il file prova.exe è divenuto quindi un server TCP, e il codice del filmato Flash è diventato:
fscommand("exec","prova.exe");
doc = new XML();
doc.onLoad = function (success) {
testo_file.text=doc.getBytesTotal(); // testo_file è un dynamic text
}
doc.load ("fscommand/test.xml");
function myOnConnect(success) // funzione eseguita in caso di connessione OK
{
if(success)
{
trace("Connection succeeded!");
socket.send(doc); // prova di invio dell'XML letto precedentemente
}
else
{
trace("Connection failed!");
}
}
socket = new XMLSocket();
socket.onConnect = myOnConnect;
if(!socket.connect("localhost", 1999)) // connessione di prova porta 1999
{
trace("Non riesco a connettermi");
}
else
{
trace ("Prima connect OK");
}
socket.onXML = myOnXML;
function myOnXML(client)
{
testo_file.text=client.toString();
}
In pratica il buffer XML precedentemente caricato dal file fscommand/test.xml viene inviato al server TCP in ascolto sulla porta 1999 e operante nella stessa macchina in cui opera il filmato Flash; a sua volta, per verificare l'handshake, il server TCP risponde con un suo buffer XML, intercettato dal metodo myOnXML e mostrato in una dynamic string testo_file di appoggio all'interno del filmato vero e proprio.
L'esecuzione del filmato ha permesso di osservare un simpatico scambio XML tra Flash ed il nostro server TCP, scritto in C utilizzando il compilatore GNU indicato nel paragrafo 'Ambiente di sviluppo e test'.
Una soluzione al problema
Da queste prove, si evince che una possibile soluzione al problema è quella di realizzare un server TCP esterno, utilizzando ad esempio il linguaggio C, che operi in ascolto su una porta specifica, esegua le richieste inoltrate attraverso il canale TCP in formato XML dal filmato Flash e invii le eventuali risposte, sempre su canale TCP e sempre nel formato XML, al filmato stesso.
Tale soluzione è stata realizzata attraverso il Progetto Ninive, un progetto Open Source di iUnknown.org. Si rimanda alle pagine del progetto per i dettagli sulla implementazione e per leggere e scaricare documentazione e codici.
|