Lets say you have swf which (for the sake of our example) simply has 1 line of code:
PHP Code:
var testing="1234567890";
Of course the file may contain pretty much anything, functions, graphics etc like any other swf. Small file allows just to list code better here.
The swf is then exported under name "loadedswf.swf". Now instead of loading it directly, we will convert it into byteArray object to be used in our larger project.
PHP Code:
bytes = new ByteArray ();
var ldr:URLLoader = new URLLoader();
ldr.dataFormat = URLLoaderDataFormat.BINARY;
var req:URLRequest = new URLRequest("loadedswf.swf");
ldr.addEventListener(Event.COMPLETE, completeHandler);
ldr.load(req);
function completeHandler(e:Event):void {
bytes=ldr.data;
var s:String="";
for (var j : int = 0; j < bytes.length; j++){
var n:String=bytes.readUnsignedByte().toString(16);
if(n.length<2){
n="0"+n;
}
s+=n;
}
trace(s);
}
This code loads file "loadedswf.swf" and traces its bytes. You now need to copy/paste the data from trace window and save it. I have attached file ba.txt containing the traced data.
Now you need to load byteArray from text file and convert it into usable swf file again in your main movie:
PHP Code:
var ldr1:URLLoader = new URLLoader();
var req:URLRequest = new URLRequest("ba.txt");
ldr1.addEventListener(Event.COMPLETE, completeHandler1);
ldr1.load(req);
function completeHandler1(e:Event):void {
var bA =new ByteArray ();
var data1:Array=ldr1.data.split("");
var data2:Array=[];
for (var i : int = 0; i < data1.length; i +=2){
data2.push("0x"+data1 [i]+data1[i+1]);
}
for (var j : int = 0; j < data2.length; j ++){
bA[j] = data2[j];
}
ldr = new Loader ();
ldr.contentLoaderInfo.addEventListener (Event.COMPLETE, completeHandler);
ldr.loadBytes (bA);
}
function completeHandler(e:Event):void {
trace(ldr.content.testing);
}
This code first loads txt file, once its loaded the data is converted into byteArra object and Loader object is used to load swf from byteArray. The example finally traces value of variable "testing" from loaded swf ("1234567890").
Instead of loading byteArra from external file, you could also include it straight into main file:
PHP Code:
var loadData:String="(please copy the data from txt file)";
bytes = new ByteArray ();
var data1:Array=loadData.split("");
var data2:Array=[];
for (var i : int = 0; i < data1.length; i +=2){
data2.push("0x"+data1 [i]+data1[i+1]);
}
for (var j : int = 0; j < data2.length; j ++){
bytes[j] = data2[j];
}
ldr = new Loader ();
ldr.contentLoaderInfo.addEventListener (Event.COMPLETE, completeHandler);
ldr.loadBytes (bytes);
function completeHandler(e:Event):void {
trace(ldr.content.testing);
}
Here the variable "loadData" holds exactly same data as saved in text file in previous example. Because the string is so long, FK wont display it properly so copy/paste the data from attached file into code example. The Loader object and loadBytes method is used same way.
For anyone decompiling the main swf or looking at the loaded text file, the content of loaded.swf remains only visible as bunch of unhelpful bytes.
Sorry for not using proper classes and FCS3 here, examples are made with F9Alpha, you can simply copy/paste the code into Flash and test the movie.
I somehow miss a summary,- for wich fields is this technique usefull- can you give us/ me some samples ? You directly get to the practice- but I am not yet sure what it is for.
Very nice Tonypa. I've been playing around with some of this too. One suggestion, before you convert your byte array to a hex string, you should compress it using the compress() command and then use uncompress() right before you pass the byte array to the loader. This will cut the output size a great deal as zlib is pretty effective.
It will be slow. The loops would surely take time and you need to spread them over many steps. I have not tried to optimise code in any way, most likely it can be done faster and better.
Originally Posted by renderhjs
I somehow miss a summary,- for wich fields is this technique usefull- can you give us/ me some samples ? You directly get to the practice- but I am not yet sure what it is for.
I thought this could be useful in ways:
*to make it harder for every kid poking around in your swf code. I believe there is already too many tutorials and application for cheaters and thieves so taking extra steps to avoid cheating/stealing can only be good thing. I am not claiming this is some magical way to get rid of every bad guy, it is one possible step among others.
*this can be used to cut down bandwidth on your host and speed up loading of game. Lets say you game is 5 MB, every time someone loads the game your host sends 5 MB out again, even when the player returns next day. swf files are rarely used from browsers cache (I could be wrong about that, but I dont see cached swfs being used much). Now if you have 50kB loader swf and 5MB main swf loaded as byteArray, you can save the 5MB in users computer using ShareObject. Next time someone from same computer plays the game, you only need to send the small loader swf, check the version saved in SharedObject and load main file straight from there. Not only does it save your bandwidth, but it also loads much faster for visitor (making them happy).
Originally Posted by webgeek
One suggestion, before you convert your byte array to a hex string, you should compress it using the compress() command and then use uncompress() right before you pass the byte array to the loader. This will cut the output size a great deal as zlib is pretty effective.
Yes, I tried that. However, maybe because the "loadedswf.swf" itself is exported as compressed file (I thought the swf is also compressed with GZLib) or because the file used in the example was very small, I did not see improvement in compressing the byteArray. May need to do some more tests with it.
*this can be used to cut down bandwidth on your host and speed up loading of game. Lets say you game is 5 MB, every time someone loads the game your host sends 5 MB out again, even when the player returns next day. swf files are rarely used from browsers cache (I could be wrong about that, but I dont see cached swfs being used much).
mmm... swf files are definitely cached by all major browsers (IE, FF, Safari)
The next time you load the same swf, the browser will use the locally cached file. (Quick test: check this game -> http://www.gotoandplay.it/_games/playGame.php?g=190 then close your browser, reopen it and go back to that page. Unless you have turned off your browser cache you'll notice that the game gets loaded instantly)
Yeah one of the projects I'm working on is a 100% dependant on using the cache to preload assets ( Not sure how much I trust it myself, but the coders who have put that part of it together are confident so I'll take their word for it ).
Nice example T, it's little things like this are making me itch to get all down and dirty with AS3.
The cache settings in browsers can be changed by user (turn it off completely, clear it all on exit, clear it when trash is deleted, amount of space given to cached files etc). i also think in case of swf files it depends how you embed them in page (which again I have not tested).
The files that get cached are also easily decompiled. The common route to decompile swf is to get it from browsers cache, I dont see any harm providing alternative way to achieve same thing. The sharedObject itself is of course readable too, but converting it back into original swf requires more work. Good thing about byteArray is that is simply bunch of bytes. You could split it up into multiple files, you could remove header and footer from your swf and include them again in main swf, you could scramble the byteArray, write it backwards.. whatever your imagination can come up with
Nice method. Its always good to have multiple sets of proofing on your projects, to put off people trying to view your code. Has anyone tested large files with this method, specifically the reconstruction speed?
Is there a way you could use JavaScript or some other language to trigger a browser cache clear. Like ctrl + f5?
EDIT: Never mind, I figured it out. Just in case anyone else stumbles upon this with the same problem, I just added the ldr.content to the display list and it worked
sorry for resurrecting this old thread, but it was just what I was looking for in terms of using an swf's bytes. So I did this, and created a simple animation of a box moving:
PHP Code:
var cow:Cow = new Cow();//makes a box come on the screen cow.addEventListener(Event.ENTER_FRAME,onLoop); function onLoop(evt:Event){ cow.x++; if(cow.x>550){ cow.x = 0; } }
This works great in the original file, but when I load this as a byte array, I can't figure out how to make this "play." I want it to run just like the original file. Any ideas?