Home > OS >  Trying to send a compressed base64 encoded string from JS to AS3 via Websocket. Problem with uncompr
Trying to send a compressed base64 encoded string from JS to AS3 via Websocket. Problem with uncompr

Time:09-17

Hello and to a very happy and more healthy 2021!

I am setting up a small communication interface between a JS client and a AS3 Server based on the Websockets protocol. For various reasons I need to compress and base64 encode the payloads. From AS3 to JS everything works like this (using https://github.com/blooddy/blooddy_crypto to handle the Base64 en/decryption ) :

function encodeMessage(message:String):String{
    var rawData:ByteArray=new ByteArray()
    rawData.writeUTFBytes( encodeURIComponent(message) );
    rawData.compress();
    var b64 = Base64.encode(rawData);
    return b64;
};

decoding in JS with pako for inflation (https://github.com/nodeca/pako):

decodePayload(payload){
    let rawfile = (atob(payload));
    var bytes = [];
    for (var fileidx = 0; fileidx < rawfile.length; fileidx  ) {
        var abyte = rawfile.charCodeAt(fileidx) & 0xff;
        bytes.push(abyte);
    }
    var plain = pako.inflate(bytes);
    var enc = "";
    for (var i = 0; i < plain.length; i  ) {         
         enc  = String.fromCharCode(plain[i]);
    }
    return decodeURIComponent(enc);
}

now the other direction creates some problems: in JS I use:

encodeMessage(message){
    let enc = encodeURIComponent(message)
    let zlib = pako.deflate(enc)
    let b64 = btoa(zlib);
    return b64;
}

but then I am running into issues on the AS3 side:

function decodePayload(payload:String){
    var ba:ByteArray = Base64.decode(payload);
    //this is where the error happens
    ba.uncompress();
   
}

the error is a "Error: Error #2058: There was an error decompressing the data." I suspect that the bytearry i receive from pako.deflate is different from what AS3 is using?

Any pointers welcome!

CodePudding user response:

here is the solution - a stupid little oversight of course ;)

in the encode function in JS the Uint8Array needs to be converted into a BinaryString before it gets Base64 encoded:

function encodeMessage(message){
    let enc = encodeURIComponent(message);
    let zlib = pako.deflate(enc);
    let binstring = convertUint8ArrayToBinaryString(zlib); 
    let b64 = btoa(binstring);
    return b64;
};
function convertUint8ArrayToBinaryString(u8Array) {
    
    var i, len = u8Array.length, b_str = "";
    for (i=0; i<len; i  ) {
        b_str  = String.fromCharCode(u8Array[i]);
    }
    return b_str;
}

Then all is well in Roswell.

CodePudding user response:

It's not obvious if your AS3 code is used in just an SWF file or you have an AIR project.

  • If making an AIR project:

Try using uncompress.apply... (code not yet tested).

//# this is where the error happens
//ba.uncompress();

//# try this..
ba.uncompress.apply(ba, ["deflate"]);
  • If making an SWF project:

When I needed Deflate algorithm inside an SWF running on browser I used a port of Zlib.

Get as3zlib at: https://github.com/BenV/as3zlib (is a port of Zlib for Java).

note: While in JS it's better to make local vars rather than global, this a quirk of JavaScript and actually in most C-like languages (Java, C#, AS3, etc) this is opposite, a global variable is less expensive than constantly making local vars every time the function is called.

Here is a usage example:

//# import Zlib Class
import Zlib;

//# setup global vars
var zlibdecomp :Zlib;
var ba :ByteArray = new ByteArray;
var decoded_BA :ByteArray = new ByteArray;

//# try Deflate algo...
function decodePayload(payload:String)
{
    zlibdecomp = new Zlib;
    ba.clear(); //in case it already has data from a prev decode
    
    //# all code below can be done in this one line
    //ba = zlibdecomp.uncompress( Base64.decode(payload) );
    
    ba = Base64.decode(payload);
    
    //# this is where the error happens...
    //ba.uncompress();
    
    //# try this...
    decoded_BA = zlibdecomp.uncompress( ba ); //inflate to original big from small/compressed
    //ba = decoded_BA; //if this way of updating is needed
}
  • Related