AS3 functions and accessing variables - actionscript-3

I'm trying to create a JW player plugin, a part of the source code is shown below:
public function initPlugin(player:IPlayer, config:PluginConfig):void {
api = player;
var streamUrl:String = 'xxx';
var streamSecret:String = 'xxx';
var xid:String = config['xid'];
var request:URLRequest = new URLRequest("xxx"+xid);
request.method = URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.addEventListener(Event.COMPLETE, completeHandler);
loader.load(request);
var fileName:String, drive:String, userFolder:String, t_hex:String, linkType:String
function completeHandler(evt:Event) {
linkType = evt.target.data.linkType;
fileName = evt.target.data.filename;
drive = evt.target.data.drive;
userFolder = evt.target.data.userFolder;
t_hex = evt.target.data.t_hex;
if (linkType == "1")
{
/*
PHP will generate these variables for the plugin.
fileName, drive, userFolder, t_hex
*/
var relPath:String = "/"+drive+"/"+userFolder+"/"+fileName;
var md5Hash = MD5.encrypt (streamSecret+relPath+t_hex);
var link:String = streamUrl+md5Hash+"/"+t_hex+relPath;
} else
{
}
api.load('http://music-stream.burst-dev.com/test.flv');
api.play();
}
I'm currently stuck on getting api.load('') to actually load the file. I've tested through anthropod and the variables getting added in are a-okay and the link generates perfectly.
I think my error is trying to get api = player to be accessed by function completeHandler, but it is not able to. Anyone got any ideas?

The code above worked, using Anthropod, I found out that it still was a crossdomain issue. I solved it by loading all files under the same URL basename. For example, xxx.burst-dev.com. api.load however can load files abroad, despite the crossdomain need in AS3 files.

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.

AS3 won't send POST data to browser - wrong URLRequestHeader content type?

I have the following code in my AS3 Flash code that takes a screenshot within the swf using JPGEncoder and sends it to the url where i write it to a file in PHP.
I did run into the Google Chrome Pepperflash issue recently where the function just stops and the page fails to redirect. Nothing gets sent to save.php. By changing
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "application/octet-stream");
to
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "text/plain");
That seemed to do the trick. As of today though this works in internet Explorer but no longer in Chrome, Safari, Firefox. I saw that Adobe put out an update/patch to flash and flash player yesterday - could that have anything to do with it?
If i remove the following:
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "text/plain");
jpgURLRequest.requestHeaders.push(header);
Then the page successfully redirects but $GLOBALS['HTTP_RAW_POST_DATA'] is then empty so no image file can be created.
Is there an alternative header i can put that will solve this?
My code is:
AS3:
function createJPG(m:MovieClip, q:Number, fileName:String) {
var jpgSource:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
jpgSource.draw(stage);
var jpgScreenshot: BitmapData = new BitmapData(362, 310);
jpgScreenshot.copyPixels(jpgSource, new Rectangle(288, 89, 362, 310), new Point(0, 0));
var jpgEncoder:JPGEncoder = new JPGEncoder(q);
var jpgStream:ByteArray = jpgEncoder.encode(jpgScreenshot);
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "text/plain");
var jpgURLRequest:URLRequest = new URLRequest ("http://www.url.com/save.php");
jpgURLRequest.requestHeaders.push(header);
jpgURLRequest.method = URLRequestMethod.POST;
jpgURLRequest.data = jpgStream;
var jpgURLLoader:URLLoader = new URLLoader();
navigateToURL(jpgURLRequest, "_self");
}
save.php
$imagefile=''.$imageURL.'';
$fp = fopen($imagefile, 'wb');
fwrite($fp, $GLOBALS['HTTP_RAW_POST_DATA']);
fclose($fp);
header('Location: https://www.url.com/your-image.php');
Managed to get this working now with the following code. Liam was correct on the Flash Player issue. Working now by separating saving the image and navigating to the url into 2 differents function:
function createJPG(m:MovieClip, q:Number, fileName:String) {
var jpgSource:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
jpgSource.draw(stage);
var jpgScreenshot: BitmapData = new BitmapData(362, 310);
jpgScreenshot.copyPixels(jpgSource, new Rectangle(288, 89, 362, 310), new Point(0, 0));
var jpgEncoder:JPGEncoder = new JPGEncoder(q);
var jpgStream:ByteArray = jpgEncoder.encode(jpgScreenshot);
var urlLoader:URLLoader = new URLLoader();
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
var saveJPG:URLRequest = new URLRequest('http://www.url.com/save_image.php?name=filename';
saveJPG.requestHeaders.push(header);
saveJPG.method = URLRequestMethod.POST;
saveJPG.data = jpgStream;
urlLoader.addEventListener(Event.COMPLETE, goToCheckout);
urlLoader.load(saveJPG);
}
function goToCheckout(e:Event):void{
var url:String = 'http://www.url.com/show_image.php';
var request:URLRequest = new URLRequest(url);
try {
navigateToURL(request, '_self');
} catch (e:Error) {
trace("Error occurred!:");
}
}
save_image.php:
if(isset($GLOBALS["HTTP_RAW_POST_DATA"])){
$jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
$path = "";
$id = $_GET["name"];
$file = $id;
file_put_contents($path.$file, $jpg);
echo "complete";
} else{
// error
}
Flash Player version 13.0.0.214 introduces some key security fixes. Unfortunately it also breaks navigateToUrl() by forbidding the changing of any headers in the request given to navigateToUrl(). This breaks POST requests that need to pass in security/session token headers, or to even change the Content-Type, e.g. to text/xml, etc. as you have done in your example.
Right now, as much as it sucks, our best known workaround is to downgrade clients to 13.0.0.206
Adobe proposes using external interface call as described here: https://forums.adobe.com/message/6396080
it uses JavaScript to replace the POST method
The solution proposed by odd_duck seems simpler though - would be great to see the php code as well.

Imdb api with flash - as3 - flex

I am trying to use the imdb API, in this case: http://imdbapi.org/
I need to search for a movie by name and get a json, then load an image with the poster obtained.
I'll be using as3 - flex to generate an Air package.
I tried this example, but can't seem to get it right.
import flash.net.*;
var url:String = "http://imdbapi.org/";
var request:URLRequest = new URLRequest(url);
request.method = URLRequestMethod.GET;
var variables:URLVariables = new URLVariables();
variables.name = "Pulp fiction";
request.data = variables;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onComplete);
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.load(request);
function onComplete (event:Event):void {
trace(event.target.data);
}
Perhaps you could enlight me with an example of connecting to the api and retrieving that json so that I can load an image with the poster and generate my air package.
Many thanks!
The API seems to want the movie in the q param so change this
variables.name = "Pulp fiction";
to :
variables.q = "Pulp fiction";
To verify : http://imdbapi.org/?q=Pulp%20Fiction
From there getting the poster URL is just a matter of reading the correct property from the JSON string.
private function onComplete (event:Event):void {
var data:Array = JSON.parse(event.target.data);
if(data && data.length)
{
var movie:Object = data[0];
trace(movie.poster);
}
}

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

How can I use addEventListener and return something that's changed from it in Actionscript?

private function getTitle(src:String):String{
var urlLoader:URLLoader = new URLLoader();
var rssURLRequest:URLRequest = new URLRequest(src);
var rss:XML = new XML;
var t:String = src;
urlLoader.addEventListener(Event.COMPLETE,
function(event:Event):void{
rss = XML(urlLoader.data);
t = rss.channel.title.toString();
});
return t;
}
I'm aware that this code doesn't work because the anonymous function doesn't work until after t is returned. How would I make it so that it works?
You won't be able to return the loaded data from this method. The reason for this is because the loading is asynchronous and doesn't not block the execution of subsequent code. Your best option is to move the vars out of the scope of the function and to write a second function to handle the COMPLETE event.
Something like the following should work:
var rss:XML;
var t:String;
var path:String = "some path";
var urlLoader:URLLoader = new URLLoader();
private function getTitle(src:String):String
{
urlLoader.load( new URLRequest( src ) );
urlLoader.addEventListener(Event.COMPLETE, onComplete );
}
private function onComplete(event:Event):void
{
rss = XML(urlLoader.data);
t = path + rss.channel.title.toString();
}
I realize that this doesn't really answer the question directly, though it is the best practice for handling data loading. If you really want to stop any code from executing before the data is loaded, it may be possible use a while loop after the addEventListener line to halt the player from until the data is loaded. This should probably be considered a not so elegant hack though.
private function getTitle(src:String):String
{
var urlLoader:URLLoader = new URLLoader();
var rssURLRequest:URLRequest = new URLRequest(src);
var rss:XML = new XML;
var t:String = src;
var complete:Boolean;
urlLoader.addEventListener(Event.COMPLETE,
function(event:Event):void
{
rss = XML(urlLoader.data);
t = rss.channel.title.toString();
complete = true;
});
while( !complete ) { /* sleep hack */ }
return t;
}
I haven't tested this, but it seems like it could work. The first example is recommended.