AS3 Saving Local File under iOS - actionscript-3

I am opening and testing data using the FileStream class which is supposed to avoid file security issues. It works fine until I try to save to a local file. When I test under adl I get a security error which I though was ok (at least it was attempting to save) until the app was packaged and tested on a device, but the file fails to save. Any ideas?
public class FilesApp extends MovieClip {
var file:File;
var xmldata:XML;
public function FilesApp() {
// constructor code
LoadButton.addEventListener(MouseEvent.MOUSE_DOWN,xml_load);
ParseButton.addEventListener(MouseEvent.MOUSE_DOWN,xml_parse);
SaveButton.addEventListener(MouseEvent.MOUSE_DOWN,xml_save);
}
public function xml_load (e:MouseEvent):void
{
file = File.applicationDirectory;
file = file.resolvePath("./Data/data.xml");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var str:String = fileStream.readMultiByte(file.size, File.systemCharset);
fileStream.close();
DataText.text = str;
xmldata = XML(str);
trace('xml file loaded');
}
public function xml_save (e:MouseEvent):void
{
var writeStream:FileStream = new FileStream();
writeStream.open(file, FileMode.WRITE);
writeStream.writeUTF("<xml><name>Changed</name><score>5000</score></xml>");
writeStream.close();
trace('xml file saved');
}
public function xml_parse (e:MouseEvent):void
{
trace('xml file saved');
DataText.text = "Your name is:"+xmldata.name+" Your best score is:"+xmldata.score;
}
}

You cannot save data in File.applicationDirectory, it is meant to be immutable. Store it in File.applicationStorageDirectory instead. There is also File.documentsDirectory - current user documents directory, if you are sure you need to litter it with your files :)

For me, switching to readUTF() worked.
Also, the two lines initializing "file" should be in the constructor, else you cannot call "xml_save" (you'll have to do "xml_load" first).
Thanks

did you try Filereference.save()?

It fails because you are using writeUTF to do the write and readMultiByte to do the read.
If you switch to readUTF it will work.

Related

FLEX/AS3 How to open docx/odt file

I have function that create docx or odt file. I need automaticly to open this file in microsoft/libre office, right after creation complete. How to coding this in flex/as3 ?
protected function create003(docType:String, patientID:String):void
{
create003Result.token = nhealthReports.create003(docType, patientID);
}
protected function getFormModuleDataResult_resultHandler(event:ResultEvent):void
{
var pathToFile:String;
pathToFile=create003Result.lastResult; // this is path to created file
// here i need some code from you
}
<nhealthreports:NhealthReports id="nhealthReports"
showBusyCursor="true"/>
<s:CallResponder id="create003Result" result="getFormModuleDataResult_resultHandler(event)"/>
So you'd need to first download the file to the user's machine and then open it. Something like this should do it (copy pasted stuff from my projects so you might need to adjust it a bit).
Also your server might need a crossdomain file so your app can load files from it.
private function getFormModuleDataResult_resultHandler(event:ResultEvent):void
{
// load file
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onLoadingComplete);
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.load(new URLRequest(pathToFile));
}
private function onLoadingComplete(event:Event):void
{
// get the data as bytearray
var data:ByteArray = event.target.data;
// you will probably need to figure this out from your server path or define your own here
var fileName:String = "MyFilename.doc";
// create a file under the application storage directory (C:\Users\YOURUSERHERE\AppData\Roaming\RateBook\Local Store)
// you can store the file anywhere but it is recommended to do it here
// as users with restricted access on their machines (non-admin users) might have trouble saving the files elsewhere
var file:File = File.applicationStorageDirectory.resolvePath(fileName);
//create a file stream to be able to write the content of the file
var fileStream:FileStream = new FileStream();
//open the file stream and set for Write
fileStream.open(file, FileMode.WRITE);
//writes the bytes
fileStream.writeBytes(data, 0, data.length);
//close the stream
fileStream.close();
// by now the file should be saved to disk, let's open it
// Naturally this assumes that the user have the file extension (like .doc) associated with the correct program (MS Word)
file.openWithDefaultApplication();
}

It's possible to write a sharedobject when allowscriptaccess is = "never"?

I will try to write a sharedObject item using my swf embeded into an html page.
"allowscriptaccess" is setted to "never". I can't write sharedObject!
However if I set allowscriptaccess to "always", write action work well...
If I can't use sharedObject with allowscriptaccess setted to never, exist alternative for saving data?
I write a little and stupid example:
public class Main extends Sprite {
private var SHARED_NAME:String = "__SO__";
private var so:SharedObject;
Security.allowDomain("*");
Security.allowInsecureDomain("*");
public function Main() {
this.so = SharedObject.getLocal(this.SHARED_NAME, "/");
this.setSharedObj("YEAHHHHHHHH");
this.getSharedObj();
}
public function getSharedObj(clientId:String = null):Object {
var url:String = "http://localhost:8080?so=" + this.so.data.test;
var request:URLRequest = new URLRequest(url);
var loader:URLLoader = new URLLoader();
loader.load(request);
return this.so.data;
}
public function setSharedObj(setValue:String):void {
this.so.data.test = setValue;
this.so.flush();
}
}
When embed the compiled swf using AllowScriptAccess: "never", get Request never have setted the queryparam so.
If set AllowScriptAccess to "always" queryparam will be correctly setted
#akmozo is right, the problem was not related by AllowScriptAccess, but from my way of testing.
The problem is:
Using firefox in anonymous mode, every time you reload the page, shared object are deleted.
I thought for anonymous session are saved, it is not so!

as3 loaded swf accessing variables

I have some questions with sharing/using/accessing variables/functions between loaded swf files.
my prj consists of main.swf file and 2 swf's which I load on first init of the main.swf.
my questions are:
1.how can I use variables from 1.swf in 2.swf (function is running in 2.swf)
2.how can I call a function from 2.swf in 1.swf
here is the code I'm using to load the swf's:
var playerMc:MovieClip = new MovieClip();
var dbMc:MovieClip = new MovieClip();
var m2Loader:Loader = new Loader();
var mLoader:Loader = new Loader();
startLoad();
function startLoad()
{
//var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest("./_player/player.swf");
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadMc);
mLoader.load(mRequest);
addChild(mLoader);
//var m2Loader:Loader = new Loader();
var m2Request = new URLRequest("./_db/db.swf");
m2Loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadMc2);
m2Loader.load(m2Request);
addChild(m2Loader);
}
function loadMc(event:Event):void
{
if (! event.target)
{
return;
}
playerMc = event.target.content as MovieClip;
mLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadMc);
}
function loadMc2(event:Event):void
{
if (! event.target)
{
return;
}
dbMc = event.target.content as MovieClip;
dbMc.x = -400;
m2Loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadMc2);
}
You have to stick with application domain.
In most cases you should load another swf in another application domain, but it's not really related to your question.
From loader, you must access to applicationDomain and then getDefinition. From there, you can get classes and use them in your main swf. Yes, you can read static properties.
If you need instances you should access loader#content. It is pointing to a root of loaded SWF. Root of loaded is SWF – is the instance of main class of the loaded swf.
Create a variable with no definition such as
public var MyClass;
as you can see i didnt add
public var MyClass:Class;
then in another function write
this.MyClass = this.mLoader.contentLoaderInfo.applicationDomain.getDefinition("NameOfClass") as Class;
i dont know much about this myself.. im having problems figuring out if you can only access Public static variables or if its possible to access normal public variables and possibly private variables because it is creating a new instance of the same class or however you want to word it..?
also after your write the above code .. when you want to change a varaibles this usually works for me
this.MyClass.RandomVariableName = this.MyClass.RandomVariableName + 1;
something like that..

Image path issue on as3

I'm trying to create a screensaver for one our of our display we have at work. Images will be uploaded to an external server, from that server I will have pull the images and xml file. so my flash app and my content will be in two different places. I'm getting an error "SecurityError: Error #2000: No active security context". how do I override error and get the images to my stage.
var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML;
var imageList:XMLList;
var imageLoader:Loader = new Loader();
var timer:Timer =new Timer(5000);
var imageIndex:uint = 0;
var child:DisplayObject;
var path:String="http://bgxserv03.mgmmirage.org/interactivemedia/mmhub01/test/mb/edit_bay/hr/infoscreen/servamb/";
xmlLoader.load(new URLRequest(path +"output.xml"));
xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
timer.addEventListener(TimerEvent.TIMER, tick);
function xmlLoaded(e:Event) {
xmlData = new XML ( e.target.data);
imageList = xmlData.image.name;
timer.start();
loadImage(imageList[0]);
}
function imageLoaded(e:Event){
if (child){
myImageHolder.removeChild(child);
}
child = myImageHolder.addChild(imageLoader);
Tweener.addTween(child, {alpha:0, time:1, delay:4});
Tweener.addTween(child, {alpha:1, time:1, delay:5});
}
function loadImage(path:String){
imageLoader.load(new URLRequest( path +"photos/"));
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageLoaded);
}
Any help would be deeply appreciate. Thank you.
You need to put the "Crossdomain.XML" on the server's root directory. This will allow your flash file to access the data (image in your case) from that server. You can get a sample xml from the following URL, customize it for your server:
Sample CrossDomain.XML
What you are missing is probably a crossdomain.xml policy file at the domain of your image/xml files.
Use this link to create a crossdomain.xml file and add it to the root of your image/xml domain like so : "http://bgxserv03.mgmmirage.org/crossdomain.xml"
The URLLoader load() function automatically checks for the crossdomain.xml. Loader class requires you specify that you are interested in checking for a policy file in a LoaderContext object sent to the load() function.
In your code, it looks like the error should be coming from the URLLoader xml file request, since it doesn't look like you are trying to access the bitmap data of your images in any way, which is normally what would throw a security error for image files. If it is a problem with the image loading part, then complete the following instructions and you should be set to go:
In your loadImage function, add a LoaderContext parameter to your load method call:
function loadImage(path:String){
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.checkPolicyFile = true;
imageLoader.load(new URLRequest( path +"photos/"), loaderContext);
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,imageLoaded);
}
Check out the spec for more info on how to use the Loader class.
If you run into any trouble, this thread may be helpful.

Cross domain problems in Flash

I have two swf files hosted on different domains aaa.com/a.swf and bbb.com/b.swf. a.swf is loading b.swf and trying to cast it to some interface. When both of these swf files are under the same domain everything works fine. But when they are under different domains I'm getting null after casting b.swf to the implemented interface IComponent. Both of these swfs are compiled with use-network=true and with the same IComponent.as.
public class Wrapper extends Sprite
{
public function Wrapper()
{
super();
var request:URLRequest = new URLRequest("http://aaa.com/Component.swf");
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.applicationDomain = ApplicationDomain.currentDomain;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadingComplete);
loader.load(request,loaderContext);
addChild(loader);
}
private function onLoadingComplete(event:Event):void
{
var target:LoaderInfo = event.target as LoaderInfo;
var component:IComponent = target.content as IComponent;
component.init({"s":1});
component.run();
}
}
public class Component extends Sprite implements IComponent
{
public function Component()
{
super();
Security.allowInsecureDomain("*");
}
public function init(params:Object):void
{
//some actions
}
public function run():void
{
//some actions
}
}
Try this:
//Assuming you've set a crossdomain policy file
var loaderContext:LoaderContext =
new LoaderContext( true , ApplicationDomain.currentDomain )
It seems that the reason why it's not working has to do with the fact that either IComponent is not recognized or that there's a definition conflict. I would have thought that with ApplicationDomain set to currentDomain, a definition conflict should have been avoided... but it may be worth trying to leave each SWF within their own domain.
//Assuming you've set a crossdomain policy file
var loaderContext:LoaderContext =
new LoaderContext( true );
You could also check if IComponent "exists" before loading the other SWF. This could help in diagnosing what's going on...
var ClassName:Object = getDefinitionByName('IComponent');
trace( ClassName );
Maybe you have to set cross-domain security policy by crossdomain.xml file
http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html
For example:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy
SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*.example.com" />
</cross-domain-policy>
Thanks all for answers, I've found a working solution today.
Instead of casting loaded content to IComponent I'm casting it to object
var component:Object = (event.target as LoaderInfo).content as Object;
component["init"](null);
component["run"]();
I's confimed from testing that even when we are using shared class with static fields and methods it doesn't work. Both of wrapper and component are instantiating their own instances of shared class. It's really strange.
If you have the same problems please ensure that your wrapper/component classes have Security.allowDomain calls
This is a bug in the player:
http://bugs.adobe.com/jira/browse/ASC-3529
It happens when you try to "share" an interface between swfs that were loaded from different domains. This should work provided that you put both swfs under the same app domain (as you have).
Using an Object works, but kind of defeats the purpose of using an interface in the first place.
Here's a workaround that basically loads the swf as a binary and then uses Loader::loadBytes to actually load the swf into memory:
http://blog.aleksandarandreev.com/?p=42
my idea about syntax errors was pointless, here's an edit:
this code:
private function ololo():void{
var request:URLRequest = new URLRequest("http://domain/file.swf");
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.applicationDomain = ApplicationDomain.currentDomain;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadingComplete);
loader.load(request,loaderContext);
}
private function onLoadingComplete(e:Event):void {
var target:LoaderInfo = e.target as LoaderInfo;
addChild(target.content as Sprite);
}
works well even if files are on completely different domains.
does it work if you treat your IComponent as Sprite?