AS3 ByteArray " The supplied index is out of bounds" Error - actionscript-3

I'm working on an application and I need to save an AS3 object to a db.
Here's what I'm doing:
private function getComplete(e:Event)
{
var getVars:URLVariables = new URLVariables(unescape(e.target.data));
var _saveData_obj = readObjectFromStringBytes( getVars.saveData);
// do something with the save data....
}
public function SaveGame() {
var _save_data:Object = _puzzle.dataForSaving;
var _serialized_string = escape(serializeToString(_save_data));
var _round_time = Math.round( _elapsed_time);
var _token = MD5.hash( _id +
_difficulty +
"mysomewhatsecretstringhere" +
_round_time );
var request:URLRequest =
new URLRequest( _home + 'savegame.php' );
request.method = URLRequestMethod.POST;
var variables:URLVariables = new URLVariables();
variables.saveData = _serialized_string;
variables.time = _round_time;
variables.id = _id;
variables.dif = _difficulty;
variables.token = _token;
request.data = variables;
var loader:URLLoader = new URLLoader (request);
loader.addEventListener(Event.COMPLETE, postComplete);
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.load(request);
}
public function LoadGame() {
var request:URLRequest =
new URLRequest( _home + 'loadgame.php?id='+_id+"&dif="+_difficulty);
request.method = URLRequestMethod.GET;
var loader:URLLoader = new URLLoader (request);
loader.addEventListener(Event.COMPLETE, getComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, netError);
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.load(request);
}
public static function serializeToString(value:Object):String{
if(value==null){
throw new Error("null isn't a legal serialization candidate");
}
var bytes:ByteArray = new ByteArray();
bytes.writeObject(value);
bytes.position = 0;
trace ("Saved: "+bytes.length);
var be:String = Base64.encodeByteArray(bytes);
return be;
}
public static function readObjectFromStringBytes(value:String):Object {
var result:ByteArray=Base64.decodeToByteArray( value) as ByteArray;
result.position = 0;
var the_obj:Object = result.readObject();
return the_obj
}
The problem is that I keep getting a "The supplied index is out of bounds" error when I try to read the object from the Base64 string.... I checked if the saved string and the loaded string are the same. Tried to save the Base64 string to a shared object and retrieve it - that works fine ... the only problem is when I save and load to/from the server.
Can you guys help me? What am I doing wrong?
Thanks.

try using ba.writeMultiByte(string, 'utf-8') and ba.readMultiByte(ba.bytesAvailable, 'utf-8') without converting to object

Ok, so it looks like we've come to a series of steps you can take to debug what's going on.
(In save game) make sure that unescape( variables ).saveData == _puzzle.dataForSaving. If this does not work, then your issue is with either escape or unescape. I have to admit
I am suspicious here, you should never need to escape data for a POST once it has been Base64 encoded (as3crypto's Base 64 encoding will return only one of these characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=. Those are all legit in a POST) and your URLLoader should take care of making it a legit request, so I have difficulty seeing the need.
It is more consistent (and more expected) to have escape and unescape both accept strings as parameters and return strings.
Instead of storing to the database and then retrieving, store to $_SESSION (or, if possible, just echo the value back). This will eliminate PHP as a possible culprit.
In PHP, make sure that $_POST['saveData'] == /* whatever you echo */. If it isn't, then you have a DB encoding issue. You need to make sure that whatever encoding is used in MySQL is the same as the one used in AS.
As an aside, when working with AS, you'll often find it easier to use $_REQUEST instead of $_POST or $_GET. Since the requests are more or less abstracted, the URLRequests of AS don't really need to worry about being RESTful, and it is a heck of a lot easier to work with than exclusively using POSTs.

Related

getting POST using URLRequest + if statement syntax issue

I'm trying to get the reply from the address specified in var url:String, which is either 0 or 1. If the reply is 1 then it must set currentState = CallFailed (as seen below). The client compiles without error (using Adobe Flash Builder 4.6) and seems to successfully reach var url:String, but doesn't seem to be getting the response\and or my if statement is incorrect.
Actionscript:
// check to see if block.php replies 0 or 1
var url:String = "https://domain.com/block.php?postid=" + calleeInput.text + "";
var request:URLRequest = new URLRequest(url);
var variables:URLVariables = new URLVariables();
request.data = variables;
request.method = URLRequestMethod.POST;
navigateToURL(request);
if (request.data == 1)
{
// if reply is 1 then cancel the call
currentState = CallFailed;
return;
}
PHP:
PHP will echo 0 or 1 when block.php is loaded. It's not encoded in any format such as JSON\AJAX.
It seems you want data from the server. Perhaps the URLLoader class would be better?
var url:String = "https://domain.com/block.php?postid=" + calleeInput.text + "";
var request:URLRequest = new URLRequest(url);
var variables:URLVariables = new URLVariables();
request.data = variables;
request.method = URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener( Event.COMPLETE,
function( e:Event ) : void
{
// your response data will be here
// you'll have to verify the format
trace( e.target.data );
}
)
loader.load( request );
Put a breakpoint at the trace statement and check out the contents of e.target.data, and go from there
The purpose of navigateToURL() is to open the webbrowser, as stated in its documentation:
Opens or replaces a window in the application that contains the Flash Player container (usually a browser). In Adobe AIR, the function opens a URL in the default system web browser
In order to perform an request (without opening a browser, just the HTTP communication) you should use URLLoader.
The URLLoader class downloads data from a URL as text, binary data, or URL-encoded variables.
On a related note: your logic is not valid. The call to a server is asynchronous. You have to wait for the response to be returned before reasoning about the result.
The URLLoader class dispatches a number of Events that help you decide when the result of a request is returned or if there's a problem with it.

Running-order of nested function-calls delayed/altered due to URLloader in AS3?

First of all: English is not my first language. ;-)
I am compiling the following code:
var sqldata:String;
function sql(saveorload,sqlstring) {
var sqlloader = new URLLoader();
var sqlrequest = new URLRequest("http://***/sql.php");
sqlrequest.method = URLRequestMethod.POST;
sqlloader.addEventListener(Event.COMPLETE, sqldonetrace);
var variables:URLVariables = new URLVariables();
variables.sqlm = saveorload;
variables.sqlq = sqlstring;
sqlrequest.data = variables;
sqlloader.load(sqlrequest);
}
function sqldonetrace(e:Event) {
sqldata = e.target.data;
}
sql("1","SELECT * FROM songs WHERE `flag2` LIKE '0'");
trace (sqldata);
So, here comes the problem:
"sqldata" is traced as "null". AS3 seems to run "sql", then "trace" and then "sqldone", but i would need sql -> sqldone -> trace...
I can't put the trace-command in the sqldone-function because it is stored as *.as and loaded at different points in my .swf and not always followed by only a trace-command.
Any Ideas/hints/flaws in script?
Actionscript is, by design, an event driven language. It also guarantees that the code executes in a single thread i.e. if a function call starts, no other(new call) actionscript code would execute until the first call finishes.
That being said, what you should have is to pass a complete handler to sql(...).
function sql(saveorload:String, sqlstring:String, completeHandler:Function):void
{
var sqlloader = new URLLoader();
var sqlrequest = new URLRequest("http://***/sql.php");
sqlrequest.method = URLRequestMethod.POST;
sqlloader.addEventListener(Event.COMPLETE, completeHandler);//tell urlloader to use the complete handler passed in parameters
var variables:URLVariables = new URLVariables();
variables.sqlm = saveorload;
variables.sqlq = sqlstring;
sqlrequest.data = variables;
sqlloader.load(sqlrequest);
}
And then use it from some other place like:
sql("1","SELECT * FROM songs WHERE `flag2` LIKE '0'", sqldonetrace);
function sqldonetrace(e:Event)
{
var sqldata:String = e.target.data;
trace (sqldata);
}
Also, I think you should check for error events from urlloader. Pass another parameter to sql as errorHandler

AS3 AIR URLLoader POST

I am developing my first AIR app (moving over from PHP/Javascript) and am at a stage where I want to send some data from the app back to a PHP script on my server. I have the following:
var url:String = "PHP URL HERE";
var request:URLRequest = new URLRequest(url);
var requestVars:URLVariables = new URLVariables();
requestVars.test = "1234";
request.data = requestVars;
request.method = URLRequestMethod.POST;
request.contentType = "application/xml;charset=utf-8";
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlLoader.addEventListener(Event.COMPLETE, processSERPS, false, 0, true);
urlLoader.load(request);
I did have something else in the server side PHP script originally but for debugging I just changed it to dump the REQUEST array.
With the code above it will simply return nothing:
Array
(
)
But if I change the request method to Get:
request.method = URLRequestMethod.GET;
I receive:
Array
(
[test] => 1234
)
Which tells me that the code is correct, it just isn't sending the post parameters for some reason.
I would just alter the code to use GET variables but unfortunately the data I need to send is too large hence the need for POST.
Any help appreciated!
For URLRequest.contentType:
If the value of the data property is a URLVariables object, the value
of contentType must be application/x-www-form-urlencoded.
This is the default value, so just removing your assignment should do it.

How do you read and write http headers in ActionScript?

Is it even possible to both read and write http headers in actionscript?
Hmm... ok setting them doesn't seem to be a problem.
Pretty straight forward, you just add and array of URLRequestHeader objects to the URLRequest object.
var req:URLRequest = new URLRequest();
var someheader:URLRequestHeader = new URLRequestHeader( "Connection", "OK" );
req.requestHeaders = [someheader];
However, you can't read them in the regular FlashPlayer. This can be done in AIR and Flash Lite on using the requestHeader property on the HTTPStatusEvent.
var loader:URLLoader = new URLLoader();
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, onStatus);
private function onStatus( e:HTTPStatusEvent ) : void
{
var headers:Array = e.requestHeaders; // only available in FlashLite and AIR
}
This is kinda weird.

how to read the data from the JSP in a MXML through actionscript?

We are collecting the data at run time in Collection object in JSP page. We want to read this data from the JSP in a MXML through actionscript.
pls share the sample if you have.
thanks,
Sudarshan
function loadData():void
{
var ldr:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest("page.jsp");
ldr.addEventListener(Event.COMPLETE, onLoad);
ldr.load(request);
}
private function onLoad(e:Event):void
{
var ldr:URLLoader = URLLoader(e.target);
trace(ldr.data);//traces the loaded string
//if the data is xml
/*
var myxml:XML = new XML(ldr.data);
trace(myxml.toXMLString());
*/
//update: answer to the comment:
//If the input string just lacks a root tag from being valid xml,
//you can introduce a dummy root tag.
var myxml:XML = new XML("<root>" + ldr.data + "</root>");
trace(myxml.data.toString()); //Hello
trace(myxml.value.toString()); //Hi
}
page.jsp should serialize the collection to appropriate format (xml/json/whatever) and return it.