How to handle the SecurityError #2070 and #2000 in Loader.load() - actionscript-3

I have a AIR project that loads a any swf. But when the loaded swf dispatches a SecurityError, I can't handle this error! My code is bellow:
var loader:Loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfComplete);
_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, swfErrors);
_loader.contentLoaderInfo.addEventListener(Event.INIT, swfInit);
_loader.contentLoaderInfo.addEventListener(Event.OPEN, swfOpen);
_loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatus);
_loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, swfSecurityError);
_loader.contentLoaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrors);
try {
_loader.load(new URLRequest('path.swf'));
}
catch(e:SecurityError) {
trace("trying handle error!");
}
function swfComplete(e:Event):void {
trace("complete");
}
function swfErrors(e:IOErrorEvent):void {
trace("swf error: " + e.toString() );
}
function swfInit(e:Event):void {
trace("swf init");
}
function swfOpen(e:Event):void {
trace("swf open. this listener dispatch!");
}
function httpStatus(e:HTTPStatusEvent):void {
trace("http status: " + e.toString() );
}
function swfSecurityError(e:SecurityErrorEvent):void {
trace("trying handle security error. :(");
}
function uncaughtErrorEvent(e:UncaughtErrorEvent):void {
trace("uncaught error: " + e.toString() );
}
The exceptions from FlashDevelop:
[Fault] exception, information=SecurityError: Error #2070: Security sandbox violation: caller file.swf cannot access Stage owned by app:/myApp.swf.
[Fault] exception, information=SecurityError: Error #2000: No active security context.
The problem is that my program quits and I can not catch these security errors. How can I prevent my program from closing?

You code cannot handle this exception because it is not a loading routine violation. It happens when the loaded content tries to access the stage (and does not have right to access it due to sandbox policy).
You can (probably) solve it in several ways:
Load your file as binary data via URLLoader and then Loader.loadBytes it. Thus your content will be taken as internal within the same sandbox and it will have full access to your whole application.
Handle the exception: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/UncaughtErrorEvent.html
Add that SWF as additional file to your app so it is in the same folder as main SWF and will be loaded into the same sandbox too. Cannot say for sure for I never published AIR apps from FD.

Related

How to catch and exception in a loaded SWF's global$init?

My Flash program's loading a SWF that contains user code which has been compiled in real time. Because it's user code, it may throw exceptions. Unfortunately, I can't seem to catch the exceptions. This code doesn't work:
this._loader = new Loader();
this._loader.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
this._loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfCompleteHandler);
this._loader.loadBytes(swfByteArray, loaderContext);
However, the debug player shows this in the unhandled exception dialog:
[Fault] exception, information=Error: Test error message
at global$init() [User_Code:3]
How do I catch an exception in global$init() of a loaded SWF? I've tried adding UNCAUGHT_ERROR event listeners to every loader and loaderInfo I can find... but none of them trigger when the exception is thrown from the loaded SWF's global$init(). Thanks in advance.
In cases where I could, I injected a try/catch into the user's code. For example, if the user code is simply:
trace("Hello");
My program modifies the code string to be:
try {
trace("Hello");
catch (Error error) { DoSomething(); }
However, this doesn't always work. For example, if the users' code is:
function output():void
{
throw new Error("Error!");
}
output();
Then the trick above doesn't work. Instead, I inject code like so:
startUserCode();
function output():void
{
throw new Error("Error!");
}
output();
endUserCode();
If endUserCode() doesn't get hit, I assume that an exception was thrown. I just don't know what exception. A nasty user could insert a random "return" into their code and endUserCode won't get hit but that's an edge case I decided to simply not handle.

NetConnection unhandled NetStatusEvent

Occasionally I'm getting an unhanded NetStatusEvent when using NetConnection to connect to a Red5 server:
Error #2044: Unhandled NetStatusEvent:. level=error, code=NetConnection.Call.Failed
This is how I am connecting (the only place where NetConnection.connect() is called):
public function Connect(callBack:Function = null):void
{
if (IsConnected())
{
if (callBack != null)
{
callBack.call();
}
}
else // Not connected
{
netConnect.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void
{
// OnConnect called whenever there is a net status event
OnConnect(e, callBack);
netConnect.removeEventListener(NetStatusEvent.NET_STATUS, arguments.callee);
});
try
{
// Attempt to connect to Media Server
netConnect.connect(MEDIA_SERVER_URI, true);
}
catch(error:Error)
{
logger.LogError("NetConnection.connect threw an exception.", error);
}
}
}
I am adding an event listener for NetStatusEvent.NET_STATUS. How is it possible that sometimes my listener called?
You're removing your listener in your NetStatusEvent handler. You should keep it until the connection is closed. This is why NetStatusEvent is only handled once before its listener is removed. Any other than first event will throw that error.
So remove netConnect.removeEventListener(NetStatusEvent.NET_STATUS, arguments.callee);
NetConnection dispatches that event quite a lot, depending on what is happening. You have to handle the event until every time. For a list of possible values of the info property visit this Link. There's also a little example of how to handle the event at the end of the page.
You may see this if your client does not handle the onBWCheck or onBWDone methods. This will also happen if you have bandwidth detection turned on; turn it off on the server by changing this parameter in the red5.properties file and restart the server.
rtmp.bandwidth_detection=false
Blockquote
Just an additional piece of information. Dispatching NetStatusEvent objects with info.level = "error" will always throw an Unhandled Exception. Its a special use case. I, for example, wrap all of this functionality and change the level to "info" before re-dispatching the event.

How to handle security error and time out error of UrlLoader.load() in actionscript3?

I use UrlLoader.load() in my flash app.
And I'm handling UncaughtErrorEvent.UNCAUGHT_ERROR to stop the app when an uncaught exception occured.
UrlLoader.load() works when you are connecting the internet normally.
But if the connection to the internet was lost after your browser loaded the app,
SecurityError happens when UrlLoader.load() is called.
I can not catch the SecurityError by using try catch and UNCAUGHT_ERROR happens and it stops my app.
I don't want to stop the app when UrlLoader.load() failed because I'm just using UrlLoader.load() to log some unimportant information.
And I think timeout error also can be ocurred if it takes a long time to load.
And I also don't want to stop my app due to the time out error.
How can I solve those problems?
And are there more other type of errors which can be ocurred and stop my app?
The SecurityError exception is thrown when some type of security violation takes place.
Examples of security errors:
An unauthorized property access or method call is made across a security sandbox boundary.
An attempt was made to access a URL not permitted by the security sandbox.
A socket connection was attempted to an unauthorized port number, e.g. a port above 65535.
An attempt was made to access the user’s camera or microphone, and the request to access the device was denied by the user.
Lets say we have to load an swf from any external URL then:
// URL of the external movie content
var myRequest:URLRequest=new URLRequest("glow2.swf");
// Create a new Loader to load the swf files
var myLoader:Loader=new Loader();
// 1st level IO_ERROR input and output error checking
// Listen error events for the loading process
myLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
function ioError(event:ErrorEvent):void
{
// Display error message to user in case of loading error.
output_txt.text = "Sorry that there is an IO error during the loading of an
external movie. The error is:" + "\n" + event;
}
function checkComplete(evt:MouseEvent)
{
// 2nd level SecurityError error checking
// Use the try-catch block
try
{
// Load the external movie into the Loader
myLoader.load(myRequest);
}
catch (error:SecurityError)
{
// catch the error here if any
// Display error message to user in case of loading error.
output_txt.text = "Sorry that there is a Security error during the
loading of an external movie. The error is:" + "\n" +
error;
}
}
movie1_btn.addEventListener(MouseEvent.CLICK, checkComplete);
// Listen when the loading of movie (glow.swf) is completed
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadMovie1);
function loadMovie1(myEvent:Event):void
{
// Display the Loader on the MainTimeline when the loading is completed
addChild(myLoader);
// Set display location of the Loader
myLoader.x = 200;
myLoader.y = 80;
}
Hope this will work for you.

Socket error - sometimes?

so - I have this Socket (not XMLSocket, just Socket) client. I also have a custom PHP script on my server, that listens on port X. My client tries to connect to it.
Everything works fine, the security and communication, sync and whatever else. But - the Flash Player (AIR runtime actually) shoots an error when trying to connect, but ONLY when the server is not running... What? It is really weird - the error is actually handled by try catch (IOError), and even weirder, the line that is specified in the output as the error line is the line where I just CREATE the Socket...?
Hm...
Output:
Error #2044: Unhandled IOErrorEvent:. text=Error #2031: Socket Error.
at ---.server::Client()[---/server/Client.as:167]
at Function/<anonymous>()[---_fla.MainTimeline::frame1:430]
at Function/<anonymous>()
at Function/<anonymous>()[---_fla.MainTimeline::frame1:375]
Code:
try {
Sock = new Socket(); // THIS is line 167
} catch (e:IOError){
log("Could not connect!");
status = "disconnected";
}
It does not really matter - the server is supposed to be still online, the errors won't show up... But ignoring an error is not good.
One more thing: when I comment out the line where I actually connect using Sock.connect(...) - it does not throw the error, but it obviously does not work... Also, the connect part is also in try catch (IOError) block...
WHY does Flash say the problem is on line 167 when it is obviously elsewhere? And / or what can be the problem?
This might not seem obvious if you had not worked with Flash previously, but many Errors in the net api are asynchronous. Meaning, you cannot catch them with a catch block, because the error is not thrown when you execute the connect method, but at a later point.
In fact, the error message says you have an uncaught IOErrorEvent not an IOError.
This is covered here:
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/net/Socket.html#connect()
Basically, you have to add a handler for the IOErrorEvent (adding one for SecurityErrorEvent is a good idea as well). Something like this:
private function connect():void {
socket = new Socket(host,port);
// handle asynchronous errors in these handlers
socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
try {
socket.connect();
} catch(ioError:IOError) {
// handle synchronous errors here
} catch(secError:SecurityError) {
// and here
}
}
private function ioErrorHandler(event:IOErrorEvent):void {
trace("ioErrorHandler: " + event);
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
trace("securityErrorHandler: " + event);
}
I came across a similar error. It was occurring because I had removed the handler ioErrorHandler (removeEventListener) before issuing a sock.close(). sock.close() can throw an IoErrorEvent.
Even though the ioErrorEvent was thrown by sock.close(), the debugger showed it as unhandled error at the line where the socket constructor was called.
Calling the removeEventListener() after the sock.close() solved the problem.
Hope this helps.
I got the error in the same situation with wizard, and fixed it by change the order of close and remove event listener.

Unhandled Socket securityError even when (seemingly) handling it

I Have a problem where I occasionally (i.e. not always) see the below error popup from the Debug Flash Player after launching my app:
Error #2044: Unhandled securityError:. text=Error #2048: Security sandbox violation: http://example.com/myApp.swf cannot load data from localhost:4499.
at org.mydomain.mypackage::MyClassUsingSocket()
at MyMainApplicationClass$cinit()
at global$init()
at global$init()
at flash.system::ApplicationDomain/hasDefinition()
at mx.managers::SystemManager/getDefinitionByName()
at _MyMainApplicationClass_mx_managers_SystemManager/create()
at mx.managers::SystemManager/initializeTopLevelWindow()
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::docFrameHandler()
I have some code in this app that tries to connect to localhost:4499 via a Socket, and this error occurs when the socket server is not running and listening for the connections, which is to be expected. What I don't understand, however, is why Flash Player is complaining about unhandled securityErrors when I have try/catch blocks to catch the SecurityErrors when trying to connect the socket (as well as listeners for the SecurityErrorEvents, which this error message doesn't seem to point to, though).
The constructor of the relevant class is below:
/**
* Constructor.
*/
public function MyClassUsingSocket(aHost:String = null, aPort:int = -1):void
{
super();
var hostToConnectTo:String = (aHost != null) ? aHost : DEFAULT_HOST;
var portToConnectTo:int = (aPort != -1) ? aPort : DEFAULT_PORT;
try
{
_out_socket = new Socket();
// note: the event handlers used below are private functions within the same class
_out_socket.addEventListener(Event.CONNECT, _socketConnectEventHandler, false,0,true);
_out_socket.addEventListener(IOErrorEvent.IO_ERROR, _socketIOErrorEventHandler, false,0,true);
_out_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _socketSecurityErrorEventHandler, false,0,true);
_out_socket.connect(hostToConnectTo, portToConnectTo);
}
catch(e:IOError)
{
enabled = false;
}
catch(e:SecurityError)
{
enabled = false;
}
}
Any ideas on why this might be occurring? What am I missing?
I too struggled with this for a couple of hours. The solution is to listen for SecurityErrorEvent.SECURITY_ERROR. Apparently the SecurityError is only raised if there isn't such an event handler.
I don't think the errors that show in the dialog box are synchronous. I'm almost certain that they are thrown outside of your code path (during an async network event), so catching them with a try-catch is impossible.
So you'd think that listening for the right event on the right dispatcher would catch the error? I've tried listening to the stage, root, the object (the socket), but nothing suppresses the error.
Yep, it's pretty horrendous. I've been looking for a way to catch these little critters for a while now. The only consolation is that I think it is suppressed in the release version of the player. Still, it's cryptic huh? Not much documentation either (that I've found).
This isn't really an answer. Sorry.
This may not be the issue but you're catching SecurityError and its throwing securityError. Maybe try lowercasing the s.
Shot in the dark: try catching a generic Error?
try
{
_out_socket = new Socket();
// note: the event handlers used below are private functions within the same class
_out_socket.addEventListener(Event.CONNECT, _socketConnectEventHandler, false,0,true);
_out_socket.addEventListener(IOErrorEvent.IO_ERROR, _socketIOErrorEventHandler, false,0,true);
_out_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _socketSecurityErrorEventHandler, false,0,true);
_out_socket.connect(hostToConnectTo, portToConnectTo);
}
catch(e:IOError)
{
enabled = false;
}
catch(e:SecurityError)
{
enabled = false;
}
catch( e:Error )
{
trace( e );
}