SWF cannot load local XML file in browser - actionscript-3

I need a local SWF to load a local XML file when running in a browser. The SWF and XML are placed locally on my HD in the same directory, which - as far as I understand - should be OK? But in a browser the XML does not load - output reads "begin" and I cannot get any of the events to trigger. Whereas when running directly from Animate or in the Flash player it works and the output reads "success".
package {
import flash.display.MovieClip;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.events.SecurityErrorEvent;
import flash.events.HTTPStatusEvent;
public class main extends MovieClip {
private var output:TextField;
public function main() {
output = new TextField();
output.width = 600;
output.text = "begin";
addChild(output);
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, function(e:Event){
output.text = "success";
});
urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, function(e:Event) {
output.text = "http status event";
});
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event) {
output.text = "io error";
});
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(e:SecurityErrorEvent) {
output.text = "security error";
});
urlLoader.load(new URLRequest("test.xml"));
}
}
}
As suggested in the comments, I have tried to set the "Global Security Settings Panel" to "Always allow" but it does not make a difference.

Local-with-filesystem setup is tricky, the easiest way is to go to Flash Player Global Security Settings and add the folder you are debugging in to the list of always trusted locations. Checking the "Always Allow" option might not work, no idea why, as I said - tricky.

Related

Decompiling a Bin File Inside the SWF file

I decompiled a swf file using JPEXS Free Flash Decompiler v.10.0.0 , When i decompile the swf file I only see 2 scripts:
AppLoader
$gamename-web_sec$aba37a......
In the binaryData folder, there's a thing named:
DefineBinaryData(1:gamename-web_sec$aba37a........
Here's the tree of the decompiled swf:
gamename.swf
Headers
BinaryData
DefineBinaryData(1:gamename-websec$aba37a...
Frames
Scripts
AppLoader
$gamename-web_sec$aba37a...
inside the appLoader, here's the script:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.utils.ByteArray;
public class AppLoader extends Sprite
{
private var content:Class;
public function AppLoader()
{
content = §gamename-web_sec$aba37a95a98fb59f905d8915dbd77871-2007405621§;
super();
var loader:Loader = new Loader();
addChild(loader);
var ba:ByteArray = new content();
var bamod:ByteArray = new ByteArray();
bamod.writeBytes(ba,1,ba.length - 1);
loader.loadBytes(bamod,new LoaderContext(false,new ApplicationDomain()));
}
}
}
$gamename-web_sec$aba37a... actionscript:
package
{
import flash.utils.ByteArray;
public class §gamename-web_sec$aba37a95a98fb59f905d8915dbd77871-2007405621§ extends ByteArray
{
public function §chitchatcity-web_sec$aba37a95a98fb59f905d8915dbd77871-2007405621§()
{
super();
}
}
}
I see that It's loading the swf game with that BinaryData. When i try to export the bin file and try to load it again using JPEXS Flash Decompiler again. This what it shows,
[2744232]
header
shapes
sprites
binaryData
DefineBinaryData (51763)
DefineBinaryData (11730)
frames
others
ErrorTag
Unknown (ID=377)
Unknown (ID=909)
Unknown (ID=544)
...
Unknown (ID=879)
ErrorTag
Unknown (ID=777)
....
scripts
frame1
DoAction
It show's so many unknown objects in others folder.
Do P-code source: (because the actionscript source is blank)
Jump loc0005
loc0005:
Do you guys have an idea how will i able to decompile the swf file? I have a permission of the owner, and he wants me to decompile it, so we can better secure the game more.

fileReference.save; works in swf but doesn't work when the swf embeded in the html

This code works properly when published by Flash CS 5.5 as .swf (it prompts to browse where to save the file). However, when it is published to HTML, it doesn't work (doesn't prompt to browse the destination). Is it security issue or other problem?
import flash.display.Sprite;
import flash.media.Microphone;
import flash.system.SecurityDomain;
import org.bytearray.micrecorder.*;
import org.bytearray.micrecorder.events.RecordingEvent;
import org.bytearray.micrecorder.encoder.WaveEncoder;
import flash.events.Event;
import flash.net.FileReference;
import flash.utils.setTimeout;
var mic:Microphone;
var waveEncoder:WaveEncoder = new WaveEncoder();
var recorder:MicRecorder = new MicRecorder(waveEncoder);
var fileReference:FileReference = new FileReference();
mic = Microphone.getMicrophone();
mic.setSilenceLevel(0);
mic.gain = 100;
mic.setLoopBack(true);
mic.setUseEchoSuppression(true);
Security.showSettings("2");
addListeners();
function addListeners():void
{
setTimeout(startIntroTime,3000);
function startIntroTime():void
{
startRecording();
setTimeout(stopRecording,5000);
}
recorder.addEventListener(Event.COMPLETE, recordComplete);
}
function startRecording():void
{
if (mic != null)
{
recorder.record();
}
}
function stopRecording():void
{
recorder.stop();
mic.setLoopBack(false);
}
function recordComplete(e:Event):void
{
fileReference.save(recorder.output, "recording.wav");
}
Have a look at the documentation: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#save()
It says :
In Flash Player, you can only call this method successfully in response to a user event (for example, in an event handler for a mouse click or keypress event). Otherwise, calling this method results in Flash Player throwing an Error exception. This limitation does not apply to AIR content in the application sandbox.
So it is not possible and probably a security thing.

Workaround for Security.allowDomain

I have number of SWF files which should be accessed from external server. To be able to do this I need to have Security.allowDomain in each SWF file. The problem here is that I don't have FLA for those files and there are thousands of SWFs.
If there a better way to configure those files to be accessible from other domain?
Like having some kind of config file or so.
Yes, there is one workaround, but I think it's a security hole, so it can be fixed in any release of flash player. Meanwhile it works now so here is solution - use URLLoader with BINARY dataFormat as preloader for swf bytes:
swf without Security permissions for it scripting:
package
{
import flash.display.MovieClip;
public class astest extends MovieClip
{
public function astest()
{
}
public function externalCheck():void
{
graphics.beginFill(0xFF0000);
graphics.drawCircle(100, 100, 100);
}
}
}
Loader swf that wants to load previous swf and call the externalCheck method:
package
{
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
public class astest2 extends MovieClip
{
private var loader:Loader;
private var urlLoader:URLLoader;
public function astest2()
{
init();
}
//this method works fine
protected function init():void
{
urlLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.load(new URLRequest("http://domain_with_your_swfs/astest.swf"));
urlLoader.addEventListener(Event.COMPLETE, function(event:Event):void
{
addChild(loader = new Loader());
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoader);
loader.loadBytes(urlLoader.data as ByteArray);
});
}
//this method will fire SecurityError when calling the 'externalCheck' method
protected function init2(event:Event = null):void
{
addChild(loader = new Loader());
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoader);
loader.load(new URLRequest("http://domain_with_your_swfs/astest.swf"));
}
protected function onLoader(event:Event = null):void
{
var swf:Object = loader.content;
swf.externalCheck();
}
}
}
Don't forget to place the crossdomain.xml file to the root of your server with swf files to load, without it URLLoader will not able to load the bytes, it's the only security requirement.

as3 Adobe Air access iPad device camera

Is there a way you can use as3 to access iPad's camera?
I mean start the Camera within the app itself
have ability take a shoot and save the image to byteArray and applying the image to the background or doing some manipulation
I have done some research most of them just showing how to access the android devices.
Thanks for any suggestion or help.
Yes, you can absolutely do this. The beauty of Flash is that the code to do it is the same that you would use on Android or a PC.
Literally, you can do this to connect the camera to a Video object:
var camera:Camera = Camera.getCamera();
var video=new Video();
video.attachCamera(camera);
this.addChild(video); // 'this' would be a Sprite or UIComponent, etc...
There's a lot more to do if you want to do something useful, but it's fairly straight forward once you get started :)
bluebill1049, I'm not certain from the thread if you got what you were looking for, but I did see your request for the whole class. I found the same information (that Jason Sturges posted in his answer) in this post.
take photo using Adobe Builder (flex) for iOS
Unlike his reply here, his reply to that post had had a link to a great tutorial on building a mobile app and it was from that tutorial that this code was lifted/quoted. It requires an event class (event.CameraEvent - only a few lines) that's contained in that project/tutorial so it's important to be able to go back to the source, as it were. That source is located here:
http://devgirl.org/files/RIAUnleashed/
My thanks to Jason. Just so you don't have to dig, here's the event class that's missing from the quote:
package events
{
import flash.events.Event;
import flash.filesystem.File;
public class CameraEvent extends Event
{
public static const FILE_READY:String = "fileReady";
public var file:File;
public function CameraEvent(type:String, file:File=null, bubbles:Boolean = true, cancelable:Boolean = true)
{
super(type, bubbles, cancelable);
this.file = file;
}
}
}
Hope that helps!
Using the loader is not the only way to access the image bytes on iOS. It turns out the data is already in JPEG format to begin with, so encoding it again is not necessary.
Just do a mediaPromise.open() to get at the bytes and save them directly instead.
XpenseIt example code offers this camera implementation:
Class: CameraUtil:
package utils
{
import events.CameraEvent;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MediaEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.media.CameraRoll;
import flash.media.CameraUI;
import flash.media.MediaPromise;
import flash.media.MediaType;
import flash.utils.ByteArray;
import mx.events.DynamicEvent;
import mx.graphics.codec.JPEGEncoder;
[Event(name = "fileReady", type = "events.CameraEvent")]
public class CameraUtil extends EventDispatcher
{
protected var camera:CameraUI;
protected var loader:Loader;
public var file:File;
public function CameraUtil()
{
if (CameraUI.isSupported)
{
camera = new CameraUI();
camera.addEventListener(MediaEvent.COMPLETE, mediaEventComplete);
}
}
public function takePicture():void
{
if (camera)
camera.launch(MediaType.IMAGE);
}
protected function mediaEventComplete(event:MediaEvent):void
{
var mediaPromise:MediaPromise = event.data;
if (mediaPromise.file == null)
{
// For iOS we need to load with a Loader first
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleted);
loader.loadFilePromise(mediaPromise);
return;
}
else
{
// Android we can just dispatch the event that it's complete
file = new File(mediaPromise.file.url);
dispatchEvent(new CameraEvent(CameraEvent.FILE_READY, file));
}
}
protected function loaderCompleted(event:Event):void
{
var loaderInfo:LoaderInfo = event.target as LoaderInfo;
if (CameraRoll.supportsAddBitmapData)
{
var bitmapData:BitmapData = new BitmapData(loaderInfo.width, loaderInfo.height);
bitmapData.draw(loaderInfo.loader);
file = File.applicationStorageDirectory.resolvePath("receipt" + new Date().time + ".jpg");
var stream:FileStream = new FileStream()
stream.open(file, FileMode.WRITE);
var j:JPEGEncoder = new JPEGEncoder();
var bytes:ByteArray = j.encode(bitmapData);
stream.writeBytes(bytes, 0, bytes.bytesAvailable);
stream.close();
trace(file.url);
dispatchEvent(new CameraEvent(CameraEvent.FILE_READY, file));
}
}
}
}

Security: Restrict plugin access to file system and network

In a plugin context (a swf loaded by an another swf), is there any way to restrict access to file system and network in the same time to the loaded swf ?
Compiler option "-use-network=true|false" does not fit because you cannot restrict both file/network.
Code example :
Air App :
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.filesystem.File;
import flash.net.URLRequest;
public class TestContentSecurity extends Sprite
{
private var l :Loader = new Loader;
public function TestContentSecurity()
{
addChild(l);
l.load(new URLRequest(File.documentsDirectory.nativePath + "/Content.swf"));
}
}
}
Loaded swf :
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.text.TextField;
public class Content extends Sprite
{
private var _log : TextField = new TextField;
private var l: URLLoader;
public function Content()
{
addChild(_log)
_log.multiline = true;
_log.width = 500;
_log.height = 500;
l = new URLLoader();
l.addEventListener(Event.COMPLETE, onLoad);
l.addEventListener(IOErrorEvent.IO_ERROR, onError);
l.load(new URLRequest("c:/Windows/regedit.exe"))
}
public function onLoad(e:Event) : void{
_log.text += "SUCCESS\n" ;
}
public function onError(e:IOErrorEvent) : void{
_log.text += "ERROR\n";
}
}
}
The loaded swf is in user's document folder, outside Air app folder. Currently, the loaded swf is abble to load "c:/Windows/regedit.exe" and I don't want it (neither sending informations on the network).
I've found one solution in AIR, I don't like it but it works. The idea is to have a mini http server and to load content from this server.
I load targeted file with :
new URLRequest("http://localhost:1111/Content.swf")
By doing this, flash will load "Content.swf" as a remote file and place it in a REMOTE security sandbox. Loaded swf won't be able to access to any local files neither to network.
If anyone have a cleaner solution to get this REMOTE security sand box, I will be happy.
/**
* HTTP server original idea :
* http://coenraets.org/blog/2009/12/air-2-0-web-server-using-the-new-server-socket-api/
*/
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.ServerSocketConnectEvent;
import flash.net.ServerSocket;
import flash.net.Socket;
import flash.utils.ByteArray;
public class TestContentSecurity extends Sprite
{
private var l :Loader = new Loader;
private var serverSocket:ServerSocket;
public function TestContentSecurity()
{
init();
l.load(new URLRequest("http://localhost:1111/Content.swf"));
}
private function init():void
{
// Initialize the web server directory (in applicationStorageDirectory) with sample files
listen(1111);
}
private function listen(port : uint):void
{
try
{
serverSocket = new ServerSocket();
serverSocket.addEventListener(Event.CONNECT, socketConnectHandler);
serverSocket.bind(port, "127.0.0.1");
serverSocket.listen();
trace("Listening on port " + port + "...\n");
}
catch (error:Error)
{
trace("Port " + port +
" may be in use. Enter another port number and try again.\n(" +
error.message +")", "Error");
}
}
private function socketConnectHandler(event:ServerSocketConnectEvent):void
{
var socket:Socket = event.socket;
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
}
private function socketDataHandler(event:ProgressEvent):void
{
try
{
var socket:Socket = event.target as Socket;
var bytes:ByteArray = new ByteArray();
socket.readBytes(bytes);
var request:String = "" + bytes;
var filePath:String = request.substring(5, request.indexOf("HTTP/") - 1);
var file:File = File.applicationDirectory.resolvePath(filePath);
if (file.exists && !file.isDirectory)
{
var stream:FileStream = new FileStream();
stream.open( file, FileMode.READ );
var content:ByteArray = new ByteArray();
stream.readBytes(content);
stream.close();
socket.writeUTFBytes("HTTP/1.1 200 OK\n");
socket.writeUTFBytes("Content-Type: application/x-shockwave-flash\n\n");
socket.writeBytes(content);
}
else
{
socket.writeUTFBytes("HTTP/1.1 404 Not Found\n");
socket.writeUTFBytes("Content-Type: text/html\n\n");
socket.writeUTFBytes("<html><body><h2>Page Not Found</h2></body></html>");
}
socket.flush();
socket.close();
}
catch (error:Error)
{
trace("Error");
}
}
}
}
Not unless you deploy as an AIR application.
You can, however, store some data in a SharedObject, even when you deploy with -use-network=true. This should work for storing game state and such.
Edit:
In AIR, security between content from different domains is regulated by using AIR sandbox bridges. This should give you all the leverage you need.