Declarative and programmatic SWFLoaders - apache-flex

What's the difference in terms of security between declarative and programmatic SWFLoaders? In the ff. code, loader1 throws a security exception while loader2 does not.
public someFunction(source:String):void
{
var loader1:SWFLoader = new SWFLoader();
loader1.load(source);
loader2.source = source;
}
...
<mx:SWFLoader id="loader2"/>

I don't think there is any difference in terms of security. Remember, MXML gets converted to ActionScript by the mxmlc compiler before the actual compilation commences, so a declarative SWFLoader (or any other declarative element, for that matter) is just a short-hand way of creating something instead of coding it by hand. You can use the -compiler.keep-generated-actionscript mxmlc argument to see what kind of code gets generated from your MXML.
And the reason you're not seeing a runtime error from the loader2.source = source; line in that example is that since the previous line of code invokes an error, the execution of that function stops there. Try commenting out the line where you call loader1.load(source) and you'll see the next line throw this kind of a SecurityError:
SecurityError: Error #2148: SWF file http://example.com/test.swf cannot access local resource file:///Users/username/Desktop/picture.jpg. Only local-with-filesystem and trusted local SWF files may access local resources.
at flash.display::Loader/_load()
at flash.display::Loader/load()
at mx.controls::SWFLoader/loadContent()
at mx.controls::SWFLoader/load()
at mx.controls::SWFLoader/commitProperties()
at mx.core::UIComponent/validateProperties()
at mx.managers::LayoutManager/validateProperties()
at mx.managers::LayoutManager/doPhasedInstantiation()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()
at mx.core::UIComponent/callLaterDispatcher()

Related

setting CilBody.KeepOldMaxStack or MetadataOptions.Flags

While decompiling .net assembly using de4dot I am getting following message in console:
Error calculating max stack value. If the method's obfuscated, set CilBody.KeepOldMaxStack or MetadataOptions.Flags (KeepOldMaxStack, global option) to ignore this error
How do I set CilBody.KeepOldMaxStack or MetadataOptions.Flags?
Maybe a bit late, but I ran into the same problem today, finding your open question while looking for a solution, and this is how I solved it - I hope it works for you, too:
// Working with an assembly definition
var ass = AssemblyDef.Load("filename.dll");
// Do whatever you want to do with dnLib here
// Create global module writer options
var options = new ModuleWriterOptions(ass.Modules[0]);
options.MetadataOptions.Flags |= MetadataFlags.KeepOldMaxStack;
// Write the new assembly using the global writer options
ass.Write("newfilename.dll", options);
If you want to set the flag only for a selection of methods that produce the problem before writing, just for example:
// Find the type in the first module, then find the method to set the flag for
ass.Modules[0]
.Types.First((type) => type.Name == nameof(TypeToFind))
.FindMethod(nameof(MethodToFind))
.KeepOldMaxStack = true;
CilBody is maybe a bit confusing, if you're not too deep into the internal .NET assembly structures: It simply means the body object of the method that produces the problem, when writing the modified assembly. Obfuscators often try to confuse disassemblers by producing invalid structures, what may cause a problem when calculating the maxstack value before writing the assembly with dnLib. By keeping the original maxstack value, you can step over those invalid method structures.
In the context of de4dot it seems to be a bug, or the application is simply not designed to solve invalid method structures of obfuscated assemblies - in this case there's no solution for you, if the de4net developer won't fix/implement it, and you don't want to write a patch using the source code from GitHub.

"Cannot access a property or method of a null object reference." without any meaningfull stack trace

Regularly during my application run, I get
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.managers::SystemManager/stageEventHandler()[C:\autobuild\3.4.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:5649]
This is the full stack trace. Obviously, I guess there is something wrong, but I can't understand what.
Is there any way for me to find the origin of that bad behaviour ?
EDIT
Having added my SDK sources to my debugger, I can now say precisely which line it is :
private function stageEventHandler(event:Event):void
{
if (event.target is Stage)
mouseCatcher.dispatchEvent(event); // This is line 5649
}
mouseCatcher is indeed null. The current event target is indeed a Stage object, and event type contains the "deactivate" String. As event occurs at application startup (before I try to do any kind of user interaction), I guess it's a kind of initialization bug, but where ? and why ?
Look at the source code, this is always your best option. The 3.4 SDK is open source (datavisualization and the flash player itself aside) and you probably already have the source for it in your FlashBuilder/FlexBuilder install/sdks folder. Use grep or windows grep to find the file in question (or find, whatever floats your boat). Open the SystemManager file and check what's happening at that line, check for calls to the method (if it's public use grep again, if it's private you just need to look within the SystemManager). Try to understand why it gets to this point, as pointed out by some others it's likely a timing related issue where you're trying to access something before it has been assigned, in this case the SystemManager, you probably need to defer whatever action you're taking that is causing the error to a later part of the life-cycle (if you're using initialize event or pre-initialize try on creationComplete instead since that will be dispatched after the createChildren method is called).
Note: Mine is located here
C:\CleanFS\SDKs\flex\3.4.0.9271\frameworks\projects\framework\src\mx\managers
In my copy of SystemManager with the version of the SDK I have that line number doesn't make any sense since it's a block closure not an executable line so you'll have to look at your specific version.
It looks like you are using the Flex 3.4 SDK. Are you listening for the ADDED_TO_STAGE event when the application loads? Or doing anything with the Stage object on load? If so, you might be hitting a bug specific to the 3.4 SDK:
http://bugs.adobe.com/jira/browse/SDK-23332
The most obvious solution is to swap out the 3.4 SDK for a later version (3.4A, 3.5 or 3.6). You can do that here: http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+3
All of your code should be backwards compatable with the newer Flex 3 SDKs.

Flex library projects: `undefined` is "unknown or not a compile-time constant"?

I'm in the process of refactoring a Flex application into a "library project", and one of the, err, interesting errors I've come across involves a function like this:
function spam(eggs:*=undefined):void {
...
}
While it was a "Flex application", this function compiled without issue… But when I try to build it as a "library project", the compiler gives me the error:
1047: Parameter initializer unknown or is not a compile-time constant.
So, uuhh… Why? And is there anything I can do to fix that?
There's a bug in jira (link) that says mxmlc and the flash compiler behave differently when working with parameter initializers. As the library projects are compiled using a different compiler (compc in place of mxmlc) I suspect it might be the same issue.
You can probably change the function to something like this, if you need it to be undefined:
function spam(eggs:*=null):void {
if (eggs is null) eggs = undefined;
}
Is the class with this code being used at all? A Flex Project may have optimized it out of the project if it's never used; thus not throwing an error. A library project would not do that.
I would recommend using null as the default value instead of undefined. Isn't there a bit of a paradox to initialize a value as 'undefined' ?

How can you get NVelocity to initialize correctly?

I can't get NVelocity to initialize. I'm not trying to do anything complicated, so it's just fine if it initializes at the defaults, but it won't even do that.
This:
VelocityEngine velocity = new VelocityEngine();
ExtendedProperties props = new ExtendedProperties();
velocity.Init(props);
Results in: "It appears that no class was specified as the ResourceManager..."
So does this:
VelocityEngine velocity = new VelocityEngine();
velocity.Init();
I can find precious little documentation on what the properties should be, nor how to get it to initialize with the simple defaults. Can anyone point to a resource?
A lot of pages point back to this page:
http://www.castleproject.org/others/nvelocity/usingit.html
But this page skips over the (seemingly) most important point -- how to set the properties and what to set them to.
I just want to load a simple template from a file.
Here's what I found out --
I was using the original NVelocity library, which hasn't had an update since 2003. I think it's a dead project.
I switched to the Castle Project version, and it's much easier -- in fact, it runs much like the examples on the page I linked to. It seems to set intelligent defaults for properties. I can initialize it without any properties set, but the template directory defaults to ".", so I generally set that one (do it before running "init").
To get the correct DLL, you need to download the latest NVelocity release (as of this writing it's 1.1).
Castle Project Download Page
You need to include the following files in your assembly, and make sure that their type is set to "Resource"
src\Runtime\Defaults\directive.properties
src\Runtime\Defaults\nvelocity.properties
These will then be found by ResourceLocator
src\Runtime\Resource\Loader\ResourceLocator.cs
If you get an exception on GetManifestResourceNames() as I did when trying to run Dvsl, then try modifying the ResourceLocator constructor to catch and ignore the error since the required files are in your local assembly (if you included them above) and the exception is only thrown by external assemblies (no idea why).
foreach(Assembly a in assemblies) {
String prefix = a.FullName.Substring(0,a.FullName.IndexOf(",")).ToLower();
try
{
String[] names = a.GetManifestResourceNames();
foreach (String s in names)
{
if (s.ToLower().Equals(fn) || s.ToLower().Equals(prefix + "." + fn))
{
this.filename = s;
assembly = a;
isResource = true;
}
}
} catch {
}
}

How to handle errors loading with the Flex Sound class

I am seeing strange behaviour with the flash.media.Sound class in Flex 3.
var sound:Sound = new Sound();
try{
sound.load(new URLRequest("directory/file.mp3"))
} catch(e:IOError){
...
}
However this isn't helping. I'm getting a stream error, and it actually sees to be in the Sound constructor.
Error #2044: Unhandled IOErrorEvent:.
text=Error #2032: Stream Error. at... ]
I saw one example in the Flex docs where they add an event listener for IOErrorEvent, SURELY I don't have to do this, and can simply use try-catch? Can I set a null event listener?
IOError = target file cannot be found (or for some other reason cannot be read). Check your file's path.
Edit: I just realized this may not be your problem, you're just trying to catch the IO error? If so, you can do this:
var sound:Sound = new Sound();
sound.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
sound.load(new URLRequest("directory/file.mp3"));
function ioErrorHandler(event:IOErrorEvent):void {
trace("IO error occurred");
}
You will need to add a listener since the URLRequest is not instantaneous. It will be very fast if you're loading from disk, but you will still need the Event-listener.
There's a good example of how to set this up (Complete with IOErrorEvent handling) in the livedocs.
try...catch only applies for errors that are thrown when that function is called. Any kind of method that involves loading stuff from the network, disk, etc will be asynchronous, that is it doesn't execute right when you call it, but instead it happens sometime shortly after you call it. In that case you DO need the addEventListener in order to catch any errors or events or to know when it's finished loading.

Resources