Marston Development Studio http://marstonstudio.com Rich Internet Applications Mon, 06 Apr 2015 00:31:50 +0000 en-US hourly 1 http://wordpress.org/?v=4.1.1 http://creativecommons.org/licenses/by-nc-sa/3.0/http://creativecommons.org/licenses/by-nc-sa/3.0/http://creativecommons.org/images/public/somerights20.gifSome Rights Reserved new and exciting security policy settings in flash moviestar http://feedproxy.google.com/~r/marstonstudio/~3/Jg1DbQq1pw8/ http://marstonstudio.com/2007/12/06/new-security-policy-settings-in-flash-moviestar/#comments Fri, 07 Dec 2007 00:23:35 +0000 http://marstonstudio.com/index.php/2007/12/06/new-security-policy-settings-in-flash-player-update/ In addition to all new video capabilities, the recent 9.0.115 release of the Flash Player contains an update to the security policy framework that I haven’t seen much press about. I guess the nickname crossdomain smackdown just wasn’t sexy enough compared to moviestar.

I discovered the new framework by accident when the following message showed up in my Flash debugger log files

Warning: Domain marstonstudio.com does not specify a meta-policy.  Applying default meta-policy 'all'.  This configuration is deprecated.  See http://www.adobe.com/go/strict_policy_files to fix this problem.

Intrigued, I followed up and wound up reading this excellent, thorough, and long article about the new crossdomain file options. In short, Adobe is addressing vulnerabilities that have become apparent with the original crossdomain policy approach. For people in a hurry, here are the highlights.

My old crossdomain.xml file looked like this

<?xml version="1.0" encoding="UTF-8"?>
<DOCTYPE cross-domain-policy SYSTEM "http://adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
    <allow-access-from domain="*.marstonstudio.com" />
</cross-domain-policy>

My new crossdomain.xml file looks like this

<?xml version="1.0" encoding="UTF-8"?>
<cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFile.xsd">
    <allow-access-from domain="*.marstonstudio.com" />
    <site-control permitted-cross-domain-policies="master-only"/>
</cross-domain-policy>

The interesting changes are the use of a schema instead of a DTD, and the new site-control element. My choice of the value master-only means that the only acceptable file name and location for a crossdomain file is the default crossdomain.xml at the site root. There are some other options for this value that permit flexibility, but I’m keeping it simple.

The other change is to my mm.cfg file that controls the Flash Debugger Player logging behavior. There are two new configuration options and a new log file. The new settings are

PolicyFileLog=1     # Enables policy file logging
PolicyFileLogAppend=1   # Optional; do not clear log at startup

These settings control the logging to the new policyfiles.txt log file, which should appear in the same directory as your flashlog.txt file.

That’s the Cliffs Notes version that will help out most people. Read the full Adobe article by Deneb Meketa to learn about socket policies on port 843 along with other new and exciting security policy settings.

]]>
http://marstonstudio.com/2007/12/06/new-security-policy-settings-in-flash-moviestar/feed/ 11 http://marstonstudio.com/2007/12/06/new-security-policy-settings-in-flash-moviestar/
how to impress your friends by taking an image snapshot of a flash movie and automatically uploading the jpg to a server in three easy steps http://feedproxy.google.com/~r/marstonstudio/~3/VcFDvk-B7zw/ http://marstonstudio.com/2007/10/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically-upload-the-jpg-to-a-server-in-three-easy-steps/#comments Fri, 19 Oct 2007 23:31:35 +0000 http://marstonstudio.com/index.php/2007/08/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically-upload-the-jpg-to-a-server-in-three-easy-steps/ The title for this recipe is a little long, but the use case is straightforward: I want to capture the visual appearance of a movieclip, encode it as a jpg, and then upload it to my server without any user interaction

I came to this problem while writing AsUnit tests for my Flash Actionscript 3 application. I wanted to test a feature where a user can select an image file from their desktop and then upload it to the server. My tests run in a harness separate from the rest of the application and they need to run automatically without any clicks required. For various security reasons the powerful FileReference object requires the user to actively select a file before any upload can occur. This restriction prevents unscrupulous RIA developers from using their powers for evil by sucking files off their user’s machines. For my purpose I could get around this limitation by simply creating a jpg within the swf movie itself to use for my upload. Lots of work for a unit test, but the idea of taking a snapshot picture of an application and posting it to a server intrigued me. I can think of several other relevant use cases, for instance handling an application fault by posting a screenshot along with rest of the relevant data to a logging server.

The tricky part turned out to be adding the proper headers to the encoded jpg ByteArray to create something suitable for a UrlRequest. It took some fumbling around but eventually I found my answer. Submitted for your approval: a couple of helpful code snippets and one primo reusable asset.

1) Create a BitmapData snapshot.

Assuming that target is the movieclip that you want to take a picture of

var bitmapData:BitmapData = new BitmapData(target.width, target.height, true, 0xFFFFFF);
var drawingRectangle:Rectangle =  new Rectangle(0, 0, target.width, target.height);
bitmapData.draw(target, new Matrix(), null, null, drawingRectangle, false);

The only insight I have to offer about using BitmapData is that crossdomain.xml may rear it’s ugly head if there are any external video assets involved. You can get around this by setting the checkPolicyFile property of any NetStream objects to true, and making sure that the appropriate policy files are present.

2) Encode a JPG or PNG ByteArray
Could have been a challenge, but thankfully Flash heavyweight Tinic Uro has published all the necessary code. They are distributed as part of Adobe’s AS3 Corelib, available on Google Code. The Corelib is chock full of useful utilities, I highly recommend giving it a look to see if there is anything in it you can use. Here is my usage of the JPGEncoder

import com.adobe.images.JPGEncoder;

var byteArray:ByteArray = new JPGEncoder().encode(bitmapData);

3) Post the ByteArray to the server
Now things get complicated. As I explained in the introduction, the FileReference object which is designed for uploading files to a server requires user interaction. We must POST the data using the UrlRequest and UrlLoader classes, however we run into a limitation of the Flash API. The data property of a UrlRequest can either be a UrlVariables object or a ByteArray object. There is no easy way to send name value pairs along with the JPG byte array. This is a big problem, because most upload applications will require a filename and other headers to accompany the raw file data. I wandered around in the wilderness for a little while, sending random requests and hoping that staring at the contents of the requests using the incredibly useful Charles HTTP monitor tool would magicaly reveal the answer to me. It didn’t.

I was nowhere until I found this blog post by Joa Ebert. Not surprisingly it turns out that there are a whole bunch of precisely formatted headers which must accompany the POST data to tell the server how to interpret the contents. The W3 site has more details. Joa’s code sample showed me how to take an input ByteArray and add all the necessary headers to make a full file upload request. Better yet, it worked on the first try. I modified the code to match my own style, turned it into a separate helper class, and added the ability to submit an arbitrary number of name value pairs.

First, the sample usage of UploadPostHelper

//assumed variable declarations
//var byteArray:ByteArray = jpg byte array created in step 2
//var fileName:String = "desiredfilename.jpg"
//var uploadPath:String = "http://destination.path.on/server"
//var parameters:Object = optional generic object containing name value pairs to accompany the post
//function onComplete(eventObj:Event):void {  handler for succesful loading of request
//function onError(eventObj:ErrorEvent):void {  handler for faulty loading of request

var urlRequest:URLRequest = new URLRequest();
urlRequest.url = uploadPath;
urlRequest.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = UploadPostHelper.getPostData(file, parameters);
urlRequest.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );

var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, onComplete);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
urlLoader.load(urlRequest);

Finally the crown jewel of this blog entry, the UploadPostHelper class. Please use responsibly.

package {

    import flash.events.*;
    import flash.net.*;
    import flash.utils.ByteArray;
    import flash.utils.Endian;

    /**
     * Take a fileName, byteArray, and parameters object as input and return ByteArray post data suitable for a UrlRequest as output
     *
     * @see http://marstonstudio.com/?p=36
     * @see http://www.w3.org/TR/html4/interact/forms.html
     * @see http://www.jooce.com/blog/?p=143
     * @see http://www.jooce.com/blog/wp%2Dcontent/uploads/2007/06/uploadFile.txt
     * @see http://blog.je2050.de/2006/05/01/save-bytearray-to-file-with-php/
     *
     * @author Jonathan Marston
     * @version 2007.08.19
     *
     * This work is licensed under a Creative Commons Attribution NonCommercial ShareAlike 3.0 License.
     * @see http://creativecommons.org/licenses/by-nc-sa/3.0/
     *
     */

    public class UploadPostHelper {

        /**
         * Boundary used to break up different parts of the http POST body
         */

        private static var _boundary:String = "";

        /**
         * Get the boundary for the post.
         * Must be passed as part of the contentType of the UrlRequest
         */

        public static function getBoundary():String {

            if(_boundary.length == 0) {
                for (var i:int = 0; i &lt; 0x20; i++ ) {
                    _boundary += String.fromCharCode( int( 97 + Math.random() * 25 ) );
                }
            }

            return _boundary;
        }

        /**
         * Create post data to send in a UrlRequest
         */

        public static function getPostData(fileName:String, byteArray:ByteArray, parameters:Object = null):ByteArray {

            var i: int;
            var bytes:String;

            var postData:ByteArray = new ByteArray();
            postData.endian = Endian.BIG_ENDIAN;

            //add Filename to parameters
            if(parameters == null) {
                parameters = new Object();
            }
            parameters.Filename = fileName;

            //add parameters to postData
            for(var name:String in parameters) {
                postData = BOUNDARY(postData);
                postData = LINEBREAK(postData);
                bytes = 'Content-Disposition: form-data; name="' + name + '"';
                for ( i = 0; i &lt; bytes.length; i++ ) {
                    postData.writeByte( bytes.charCodeAt(i) );
                }
                postData = LINEBREAK(postData);
                postData = LINEBREAK(postData);
                postData.writeUTFBytes(parameters[name]);
                postData = LINEBREAK(postData);
            }

            //add Filedata to postData
            postData = BOUNDARY(postData);
            postData = LINEBREAK(postData);
            bytes = 'Content-Disposition: form-data; name="Filedata"; filename="';
            for ( i = 0; i &lt; bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData.writeUTFBytes(fileName);
            postData = QUOTATIONMARK(postData);
            postData = LINEBREAK(postData);
            bytes = 'Content-Type: application/octet-stream';
            for ( i = 0; i &lt; bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData = LINEBREAK(postData);
            postData = LINEBREAK(postData);
            postData.writeBytes(byteArray, 0, byteArray.length);
            postData = LINEBREAK(postData);

            //add upload filed to postData
            postData = LINEBREAK(postData);
            postData = BOUNDARY(postData);
            postData = LINEBREAK(postData);
            bytes = 'Content-Disposition: form-data; name="Upload"';
            for ( i = 0; i &lt; bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData = LINEBREAK(postData);
            postData = LINEBREAK(postData);
            bytes = 'Submit Query';
            for ( i = 0; i &lt; bytes.length; i++ ) {
                postData.writeByte( bytes.charCodeAt(i) );
            }
            postData = LINEBREAK(postData);

            //closing boundary
            postData = BOUNDARY(postData);
            postData = DOUBLEDASH(postData);

            return postData;
        }

        /**
         * Add a boundary to the PostData with leading doubledash
         */

        private static function BOUNDARY(p:ByteArray):ByteArray {
            var l:int = UploadPostHelper.getBoundary().length;

            p = DOUBLEDASH(p);
            for (var i:int = 0; i &lt; l; i++ ) {
                p.writeByte( _boundary.charCodeAt( i ) );
            }
            return p;
        }

        /**
         * Add one linebreak
         */

        private static function LINEBREAK(p:ByteArray):ByteArray {
            p.writeShort(0x0d0a);
            return p;
        }

        /**
         * Add quotation mark
         */

        private static function QUOTATIONMARK(p:ByteArray):ByteArray {
            p.writeByte(0x22);
            return p;
        }

        /**
         * Add Double Dash
         */

        private static function DOUBLEDASH(p:ByteArray):ByteArray {
            p.writeShort(0x2d2d);
            return p;
        }

    }
}

Good stuff. Let me know what kind of luck you have trying to make this all work for you.

]]>
http://marstonstudio.com/2007/10/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically-upload-the-jpg-to-a-server-in-three-easy-steps/feed/ 54 http://marstonstudio.com/2007/10/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically-upload-the-jpg-to-a-server-in-three-easy-steps/
extending the flash videoplayer class to load the crossdomain.xml file on demand http://feedproxy.google.com/~r/marstonstudio/~3/RwzWvoSPGT8/ http://marstonstudio.com/2007/09/26/extending-the-flash-videoplayer-class-to-load-the-crossdomainxml-file-on-demand/#comments Thu, 27 Sep 2007 02:26:10 +0000 http://marstonstudio.com/index.php/2007/12/26/extending-the-flash-videoplayer-class-to-load-the-crossdomainxml-file-on-demand/ I’ve been doing lots of Flash video streaming work using ActionScript 3 and I’ve found a nice balance between using the built-in Flash video components and doing my own thing to achieve the exact look and feel that I want. The new as3 version of FLVPlayback has some great features in it, including sophisticated connection management and a well thought out event system. However over the years I’ve learned to avoid to using the standard Flash component set because there is always some sort of customization that my art director wants which the standard set just won’t support. Grant Skinner’s new component architecture in Flash CS3 is a tremendous step forward and I do like the Button and ScrollPane components but I have still found that the options on customizing the skin of something like the Slider are still too limited. At the end of the day, I couldn’t afford to be limited by the options in FLVPlayback. What to do?

In my case, I thanked the architects of the FLVPlayback component for their foresight and used the base fl.video.VideoPlayer class to create my own playback component wrapper. The documentation seems to discourage this as unnecessary,

The VideoPlayer class lets you create a video player with a slightly smaller SWF file than if you used the FLVPlayback component. Unlike the FLVPlayback component, the VideoPlayer class does not let you include a skin or playback controls, and although you cannot find or seek to cue points, the cuePoint events will occur. The FLVPlayback class wraps the VideoPlayer class. Use the FLVPlayback class in almost all cases because there is no functionality in the VideoPlayer class that cannot be accessed using the FLVPlayback class.

In practice I’ve found that the file size reduction of using VideoPlayer instead of FLVPlayback is on the order of 30kb. That’s a nice savings bump, but it’s probably irrelevant compared to the size of the video files. This 30kb savings is achieved by adding the classpath for the video playback package to the .fla file’s classpath instead of just dragging the component icon into the library. For reference, here’s the paths to add (File -> Publish Settings ->Flash -> ActionScript 3.0 Settings)

$(AppConfig)/Component Source/ActionScript 3.0/FLVPlayback
$(AppConfig)/Component Source/ActionScript 3.0/User Interface

So that’s pretty easy, but I found that there was one limitation that was making life complicated for me. I’m making use of all kinds of cool functions (BitmapData.draw, SoundMixer.computeSpectrum, etc) which require that my domain security ducks all be in a row. In this case I want to take Bitmap snapshots of a video as it’s playing back. (FYI: this is an option only for video delivered using http progressive download and not for video delivered by rtsp stream.) In as3 most classes which load remote files offer a means of telling the loader to check against the crossdomain.xml files that have already been loaded and if necessary, try and load the crossdomain.xml file from the new files’ domain. This is handy, because you only request domain files when they are needed and you don’t need to know the domains in advance. To trigger the domain checks Loader uses the LoaderContext class, Sound files use the SoundLoaderContext class, and video files use the checkPolicyFile property on the NetStream class.

So how do you set this flag when using the VideoPlayer or FLVPlayback components? Unfortunately, there is no method to do this in the existing api. VideoPlayer is an excellent wrapper around NetConnection and NetStream, however you cannot set properties directly on the NetStream object from outside the VideoPlayer thus leaving the checkPolicyFile property stuck at the false setting. What to do? Extend the class and set the flag yourself. Here’s my code for a VideoPlayerExtended class:

package {import fl.video.*;

    import flash.events.NetStatusEvent;
    import flash.net.NetStream;

    use namespace flvplayback_internal;

    /**
     * Extended version of fl.video.VideoPlayer class.
     *
     * @see http://marstonstudio.com/?p=45
     *
     * @author Jonathan Marston
     * @version 2007.12.26
     *
     * This work is licensed under a Creative Commons Attribution NonCommercial ShareAlike 3.0 License.
     * @see http://creativecommons.org/licenses/by-nc-sa/3.0/
     *
     */

    public class VideoPlayerExtended extends VideoPlayer {

        /**
         * Override the default means of creating a netstream object
         *
         * Add checkPolicyFile=true to force loading of a crossdomain.xml file
         *
         * @private
         */
        flvplayback_internal override function _createStream():void {
            _ns = null;
            var theNS:NetStream = new NetStream(_ncMgr.netConnection);
            if (_ncMgr.isRTMP) {
                theNS.addEventListener(NetStatusEvent.NET_STATUS, rtmpNetStatus);
            } else {
                theNS.addEventListener(NetStatusEvent.NET_STATUS, httpNetStatus);
            }
            theNS.client = new VideoPlayerClient(this);
            theNS.bufferTime = _bufferTime;
            theNS.soundTransform = soundTransform;
            theNS.checkPolicyFile = true;
            _ns = theNS;
            attachNetStream(_ns);
        }
    }
}

Note that the method is defined in the flvplayback_internal namespace as opposed to the more familiar public or private namespaces.

It probably would be best to make this a property that can be turned on and off from outside the class, but I found I always wanted it to be set to true so I didn’t go that extra step.

]]>
http://marstonstudio.com/2007/09/26/extending-the-flash-videoplayer-class-to-load-the-crossdomainxml-file-on-demand/feed/ 3 http://marstonstudio.com/2007/09/26/extending-the-flash-videoplayer-class-to-load-the-crossdomainxml-file-on-demand/
my new favorite flash event handles the mouse out of stage problem http://feedproxy.google.com/~r/marstonstudio/~3/WT2YnzWsKAg/ http://marstonstudio.com/2007/08/10/my-new-favorite-flasheventsevent-type/#comments Fri, 10 Aug 2007 19:36:54 +0000 http://marstonstudio.com/index.php/2007/08/23/my-new-favorite-flasheventsevent-type/ I don’t want to breed ill will by playing Actionscript favorites, but at the moment I definitely like Event.MOUSE_LEAVE a little more than the rest of the flash.events.Event types.

I’m working on a piece of functionality in my Flash as3 application that involves replacing the mouse cursor with a custom clip and making another clip change it’s position in response to MouseEvent.MOUSE_MOVE. The standard cursor is supposed to return and everything stops dragging on MouseEvent.MOUSE_UP. Standard stuff that any Flash developer has worked with before. What left me unsatisfied was detecting MOUSE_UP when the user has dragged the cursor off of the swf entirely. In this case the dragging action is still active until the user has brought the mouse back to the stage and clicked a couple times. There are all kinds of schemes from as2 for detecting position and watching for when the user leaves the stage, but they tend to break with rapid movements. Generally a hackfest of complex answers.

Enter my favorite new Event type:

stage.addEventListener(Event.MOUSE_LEAVE, onStageMouseLeave);

It took me awhile of hunting around in the API Livedocs to find this gem, in part because I was focused on using MouseEvent for my solution and wasn’t looking at the main Event class. Interestingly enough, it appears in my case that the event is not dispatched until the user lets go of the mouse, so it’s more of a MOUSE_UP while offstage, but that’s the end result I wanted so now I’m satisfied.

]]>
http://marstonstudio.com/2007/08/10/my-new-favorite-flasheventsevent-type/feed/ 5 http://marstonstudio.com/2007/08/10/my-new-favorite-flasheventsevent-type/
asunit testing with flash cs3 and actionscript 3 http://feedproxy.google.com/~r/marstonstudio/~3/DN75HwKhVO8/ http://marstonstudio.com/2007/07/28/asunit-testing-with-flash-cs3-and-actionscript-3/#comments Sat, 28 Jul 2007 22:34:24 +0000 http://marstonstudio.com/index.php/2007/07/28/asunit-testing-with-flash-cs3-and-actionscript-3/ Unit tests are supposed to be the first things you write when following an extreme programming or rapid development methodology, but I seldom found the time to bother until recently. On a Flex Data Services project, we needed to interact with a complex and evolving application programing interface. Our coping strategy was to write flexunit tests for every interaction with our J2EE backend. We were using the Cairngorm framework, which uses value objects and business delegates to abstract communication with a remote service. I wrote a separate test harness application which relied upon the same delegates and value objects as the main application. This approach allowed me to focus on constructing our backend while another team member built out the user interface. We then had a way of detecting any changes in our complex api and adapting quickly. The approach helped us quite a bit and made me a believer.

For more information on the ideas behind unit testing the AsUnit site is a good start, Wikipedia has good definitions of terms, the Extreme Programming site has some good info, or maybe even check out A Guide to Testing the Rails in the Ruby on Rails Manual.

On my current project, I’m using Flash CS3 to write an ActionScript 3 application without using any Flex. It’s important that your testing framework mimic the rest of your application, so I decided to use the asunit framework instead of flexunit. I think asunit is fantastic, however I found that the documentation for as3 is a bit lacking. The best tutorial I found was by Tim Beynart on the FlashCodersNY blog, however it was for as2 and didn’t quite work for me out of the box. So I hacked at it a bit until I got it all to work. It turned out to be pretty straightforward. I offer here an update to Tim Beynart’s original tutorial which should work for Flash as3 applications.

1) Create a directory called AsUnitExample. Download the asunit framework zip file from sourceforge and copy the contents of the as3 directory into your AsUnitExample directory. All of the files we create in the following example will be in the root directory AsUnitExample. At this point the AsUnitExample directory should contain the file AsUnitTestRunner.as and the directories asunit and mx.

2) Open and inspect the file AsUnitExample/AsUnitTestRunner.as. It should contain the following

package {
    import asunit.textui.TestRunner;

    public class AsUnitTestRunner extends TestRunner {

        public function AsUnitTestRunner() {
            start(AllTests, null, TestRunner.SHOW_TRACE);
        }
    }
}

3) Create an .fla file to serve as the test container. In the Flash IDE, File->New->Flash File (Actionscript 3). Save the file as AsUnitExample/AsUnitTestRunner.fla. In the properties window, set the Document class in the properties to be AsUnitTestRunner. Save the file again. This .fla file will remain completely empty except for the link to the Document class. Using the Document class is new for Flash CS3 and replaces the approach of using a static main method as offered in Tim Beynart’s example. We’re doing this to avoid the error

TypeError: Error #1009: Cannot access a property or method of a null object reference. at asunit.textui::TestRunner/asunit.textui:TestRunner::addedHandler()

. The Adobe Design Center has an article titled Migrating for Flash 8 to Flash CS3 which explains the use of the Document class.

4) Create a sample class for us to run tests on. In the Flash IDE, File->New->ActionScript File. Save the file as AsUnitExample/Example.as. Paste in the following:

package {

    public class Example {

        public function add(num1:Number,num2:Number):Number{
            return num1 + num2;
        }
    }
}

5) Create a test for our sample class. Note that a single test class can contain multiple tests. They all share the same setUp and tearDown methods, which are called once for each test. In the Flash IDE, File->New->ActionScript File. Save the file as AsUnitExample/ExampleTest.as. Paste in the following:

package {
    import asunit.framework.TestCase;

    public class ExampleTest extends TestCase {

        private var _instance:Example;

        /**
         * Constructor
         *
         * @param testMethod Name of the method to test
         */
        public function ExampleTest(testMethod:String) {
            super(testMethod);
        }

        /**
         * Prepare for test, create instance of class that we are testing.
         * Invoked by TestCase.runMethod function.
         */
        protected override function setUp():void {
            _instance = new Example();
        }

        /**
         * Clean up after test, delete instance of class that we were testing.
         */
        protected override function tearDown():void {
            _instance = null;
        }

        /**
         * Test of whether or not class properly instantiated
         */
        public function testInstantiated():void {
            assertTrue("Example instantiated", _instance is Example);
        }

        /**
         * Test that is born to lose.
         */
        public function testFail():void {
            assertFalse("failing test", true);
        }

        /**
         * Test the addition method on example
         */
        public function testAddition():void {
            var result:Number = _instance.add(2,3);
            assertEquals("Expected:5 Received:"+result, result, 5);
        }
    }
}

6) Create the test suite. The AsUnit convention is that this class should be called AllTests and should reference each test that you want to run with an addTest call. Note that the parameter in the addTest call is the test class constructor using the test method name as an arguement. In the Flash IDE, File->New->ActionScript File. Save the file as AsUnitExample/AllTests.as. Paste in the following:

package {
    import asunit.framework.TestSuite;

    public class AllTests extends TestSuite {

        public function AllTests() {
            super();
            addTest(new ExampleTest("testInstantiated"));
            addTest(new ExampleTest("testAddition"));
            //addTest(new ExampleTest("testFail"));
        }
    }
}

7) In the Flash IDE, compile AsUnitTestRunner.fla by running Control->Test Movie. You should see the following:

AsUnit Success

8 ) In the file AsUnitExample/AllTests.as uncomment the line

addTest(new ExampleTest("testFail"));

and recompile the movie. This line runs a test which will always fail and you should see the following:

AsUnit Failure

And you are up and running. In the directory AsUnitExample/asunit/framework there are a bunch of examples which demonstrate how to write different types of tests. Nothing I’ve added here is too sophisticated, maybe future releases of asunit could contain these extra files? Just a thought.

I have used AsUnit to build a series of asynchronous tests for my Xml Rest service. Look for a follow up post demonstrating my use of AsUnit to build those services. If you have any trouble with these examples, please leave a comment and I’ll try to help.

]]>
http://marstonstudio.com/2007/07/28/asunit-testing-with-flash-cs3-and-actionscript-3/feed/ 21 http://marstonstudio.com/2007/07/28/asunit-testing-with-flash-cs3-and-actionscript-3/
multiple wordpress widget sidebars http://feedproxy.google.com/~r/marstonstudio/~3/bTQ8m28hNKk/ http://marstonstudio.com/2007/07/17/multiple-wordpress-widget-sidebars/#comments Tue, 17 Jul 2007 04:20:28 +0000 http://marstonstudio.com/index.php/2007/07/17/multiple-wordpress-widget-sidebars/ While customizing my site I decided it would be cool to have different widget sidebars on various pages. I wanted to display navigation on the search/archive pages, related subject info on the post pages, irrelevant itunes info on my life story, and keep a generic sidebar on the rest of the pages. I hunted around on the web but I couldn’t find a brief explanation of the cleanest way to convert a template to have multiple sidebars. The best resource I found was the Automattic Widget API page, but I still had some questions. There are plenty of great themes which implement this feature so I figured it couldn’t be too difficult. In fact it turned out to be pretty easy. Here is how I did it for my WordPress 2.2 site.

1) Create the multiple sidebars.

Sidebars are defined in the file functions.php in your template directory. The sidebar is created with a code segment that looks like either

if ( function_exists('register_sidebar') )
    register_sidebar(array(
    'before_widget' =&gt; '&lt;li id="%1$s" class="widget %2$s"&gt;',
    'after_widget' =&gt; '&lt;/li&gt;',
    'before_title' =&gt; '&lt;h2 class="widgettitle"&gt;',
    'after_title' =&gt; '&lt;/h2&gt;',
));

or

if ( function_exists('register_sidebar') )
    register_sidebar();

or maybe

if ( function_exists('register_sidebars') )
    register_sidebars(1);

Each of these code examples registers a single sidebar. I wanted to register multiple sidebars each with a descriptive title. Here is my replacement code:

if ( function_exists('register_sidebar') ) {
    register_sidebar(array('name' =&gt; '1 - Default'));
    register_sidebar(array('name' =&gt; '2 - Post'));
    register_sidebar(array('name' =&gt; '3 - Archive'));
    register_sidebar(array('name' =&gt; '4 - Life'));
}

Each call to register_sidebar() creates a new sidebar using the parameters passed in through the array. This initialization array can also define unique values for widget formating values for before_widget, after_widget, before_title, and after_title. I just stuck with the defaults. To learn more, check out the register_sidebar() function in the /wp-includes/widget.php file.

2) Using duplicate widgets on multiple sidebars

One challenge with multiple sidebars is the WordPress admin interface. Each widget can only be dragged to a single destination. What if you want to use the same widget in more than one sidebar? The solution to this is to register the same widget twice. For example, I wanted to use the Creative Commons widget on every sidebar. In the file /wp-content/plugins/wpLicense/widget.php I changed the line which registered a single widget

register_sidebar_widget(array('Content License', 'widgets'), 'widget_cc');

To instead register multiple widgets

register_sidebar_widget(array('Content License 1', 'widgets'), 'widget_cc');
register_sidebar_widget(array('Content License 2', 'widgets'), 'widget_cc');
register_sidebar_widget(array('Content License 3', 'widgets'), 'widget_cc');
register_sidebar_widget(array('Content License 4', 'widgets'), 'widget_cc');

In the WordPress admin interface, I now had four identical copies of the Content License which I could drag to each of the sidebars. This step must be taken in the actual code for any widget for which you require multiple instances.

3) Assigning sidebars to pages
Each sidebar that was created is available by passing a numerical index value to the function dynamic_sidebar($index). The index value is based on the order in which the sidebars were registered, where the first sidebar has an index of ‘1’. Typically dynamic_sidebar() is called in the sidebar.php file. Template pages load the sidebar.php file with the function get_sidebar(), which unfortunately takes no parameters. I was able to get around this limitation by making the sidebar.php file smart enough to know which sidebar to display by using a handful of wordpress’ built-in methods. Here is the contents:

<div id="sidebar">
    <ul class="sidebar_list">
    <?php

        //default
        $sidebar_index=1;

        //posts
        if(is_single()) {
            $sidebar_index=2;
        }

        //navigation pages
        if( is_page('archives') || is_search() || is_404() ) < 0) {
            $sidebar_index=3;
        }

        //life story page
        if(is_page('life')) {
            $sidebar_index=4;
        }
        ?>
        <?php if (!function_exists('dynamic_sidebar') || !dynamic_sidebar($sidebar_index)) : ?>
            <li class="widget">
                <h2>Latest Blog Entries</h2>
                <ul>
                    <?php query_posts('showposts=10'); ?>
                    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
                    <li><a href="<?php the_permalink() ?>"><?php the_title() ?></a></li>
                    <?php endwhile; endif; ?>
                </ul>
            </li>
            <li class="widget">
                <h2>Categories</h2>
                <ul>
                    <?php wp_list_categories('title_li=0'); ?>
                </ul>
            </li>
            <?php get_links_list('id'); ?>
            <?php endif; ?>

        </ul>
</div>

The variable $sidebar_index defaults to 1, the index of the default sidebar. The wordpress is_single() function returns true for any single post page. The wordpress is_page($page_slug) function checks whether or not the sidebar is being rendered on a particular user created page. Finally, the wordpress is_search() and is_404() functions check to see if the sidebar is being rendered on a search or a 404 page respectively.

UPDATE:
It looks like this issue will be addressed in WordPress 2.4, scheduled for release in December 2007.

]]>
http://marstonstudio.com/2007/07/17/multiple-wordpress-widget-sidebars/feed/ 50 http://marstonstudio.com/2007/07/17/multiple-wordpress-widget-sidebars/
answer on rest xml and flash as3 http://feedproxy.google.com/~r/marstonstudio/~3/Pp-qIOdez-A/ http://marstonstudio.com/2007/07/12/answer-on-rest-xml-and-flash/#comments Thu, 12 Jul 2007 18:35:15 +0000 http://marstonstudio.com/index.php/2007/07/12/answer-on-rest-xml-and-flash/ Ask and ye shall receive.

Earlier this week I posted a question about REST xml and flash as3. Tony Hillerson of effectiveUI graciously provided an answer. To summarize, I wanted to know best practice on implementing Put and Delete http methods given the limitation that the Actionscript Flash UrlRequest object only supports the Get and Post http methods. It turns out that this problem is not unique to Flash because browsers face the same limitation. To get around this, Ruby on Rails has implemented a standardized hack. To make a Put or a Delete call, simply make a Post with the additional parameter _method=DELETE or _method=POST. The workaround isn’t too obscure and I’m not the first person to ask this question, but I’m new to Rails so consider this my education. :)

I also have to admit that that after buying into the REST vision, I’m a little disappointed that the implementation turns out to just be a hacked action parameter. But no matter, here is my code for a REST service in case it helps anyone with the same questions.

My framework is a custom built collection of design patterns that would be familiar to anyone who has worked with ARP or Cairngorm. I make my REST calls using commands that implement an IResponderCommand interface with execute, onResult, and onFault methods.

Here is the complete Actionscript RestService class as a text file.

The key part of the class is inside the constructor:

/**
 * Constructor. Initialize logger. Initialize UrlLoader the root url of the rest service and the method.
 * Populate the urlVariables with the appropriate _method to support PUT and DELETE operations.
 *
 * @param responderCommand Command that should receive responses from the service
 * @param restMethod Method to use in making request GET, POST, PUT, DELETE
 * @param restPath Begining of address of url to use when making a request.
 * @param restAction Optional end of address of url to use when making a request.
 */
public function RestService(responderCommand:IResponderCommand, restMethod:String, restPath:String, restAction:String = ""):void {
    logger = Logger.buildLogger(this);
    logger.debug("Constructor");

    this._responderCommand = responderCommand;
    this._restMethod = restMethod;
    this._restPath = restPath;
    this._restAction = restAction;

    _urlLoader = new URLLoader();
    _urlLoader.addEventListener(Event.COMPLETE, _responderCommand.onResult);
    _urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
    _urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
    _urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);

    _urlVariables = new URLVariables();

    _urlRequest = new URLRequest();
    switch (_restMethod) {
        case GET:
            _urlRequest.method = URLRequestMethod.GET;
            break;
        case POST:
            _urlRequest.method = URLRequestMethod.POST;
            break;
        case PUT:
            _urlVariables._method = RestService.PUT;
            _urlRequest.method = URLRequestMethod.POST;
            break;
        case DELETE:
            _urlVariables._method = RestService.DELETE;
            _urlRequest.method = URLRequestMethod.POST;
            break;
    }

    //assign data to request
    _urlRequest.data = _urlVariables;
}

This approach hides the hack from any command that will be consuming the service. The service is invoked with the method Get, Post, Put, or Delete. Parameters are added using the service’s addParameter method:

public function addParameter(name:String, value:Object) {
    _urlVariables[name] = value.toString();
}

And the call is made using the service’s load method:

public function load(input:Object):void {
    var requestAddress = _restPath + "/" + input.toString() + ".xml" + _restAction;
    _urlRequest.url = requestAddress;
    _urlLoader.load(_urlRequest);
}

Note that the load method takes in an input object as a parameter to build the url string. Best practice is for this input parameter to be an id. This follows REST conventions with an example url for a Ruby call: /service/5.xml;action. The action matches whatever has been mapped in the Ruby /config/routes.rb file.

The end product is an easy to consume service. Here is an example of an execute method of a command.

public function execute(eventObj:CommandEvent):void {

    //retrieve id from the command event
    var id:String = eventObj.getValueString();

    //create service with method type, path, and action
    service = new RestService(this, RestService.GET, Settings.REST_PATH, Settings.REST_GET_ACTION);

    //load the service
    service.load(id);
}

And finally, the onResult method that uses the service data:

public function onResult(resultObj:Object):void {

    var data:XML = service.data;

    . . . //process the xml here
}

For tips on configuring the Rails side of the REST service, I will defer to other resources on the web. It’s pretty straightforward, but I’m not enough of a Rails expert yet to offer anything particularly insightful on that part of the equation.

Any Rails experts out there, adding useful resource links to the comments would be appreciated.

]]>
http://marstonstudio.com/2007/07/12/answer-on-rest-xml-and-flash/feed/ 2 http://marstonstudio.com/2007/07/12/answer-on-rest-xml-and-flash/
question about rest xml and flash as3 http://feedproxy.google.com/~r/marstonstudio/~3/99_6mqnwQb4/ http://marstonstudio.com/2007/07/09/question-about-rest-and-as3/#comments Mon, 09 Jul 2007 23:54:35 +0000 http://marstonstudio.com/index.php/2007/07/09/question-about-rest-and-as3/ My first project as an independent contractor is a Flash video application that makes some lightweight data calls to a Ruby on Rails backend. We experimented with RubyAMF and implemented a beta version using WebORB Ruby on Rails. Both of these remoting implementations worked well, but in the interests of deployment simplicity we decided to abandon remoting and simply do a REST architecture.

The timing is excellent because I had just been engaging in a debate with my former co-worker Brian Riley about the merits of the Representational State Transfer (REST) approach. Brian’s take was ‘Big deal, it’s xml over http. What’s different about using REST instead of querystring parameters?‘ I didn’t have a great answer for him. I muddled on about how it was a standardized vocabulary of create/update/delete through the GET, PUT, POST, and DELETE http methods. I pointed to framework implementations that make it quick to develop a REST interface which is reusable across different applications. But I didn’t make too good a case because I hadn’t yet built anything on REST and was basing my argument on faith instead of true implementation experience. One source of my faith in particular was a podcast interview I had heard with Tony Hillerson of Effective UI, who had advocated using REST with Rails instead of remoting.

So now that I had the opportunity to implement REST in Actionscript 3 on a project, I dug into it and quickly ran into a problem. The rock solid approach to loading XML into Flash is to use the UrlRequest and UrlLoader classes, however these only implement the GET and POST http methods. This leaves out the DELETE and PUT http methods that round out the REST vocabulary and make the relatively simple approach so powerful.

So I hunted around for the tutorial that would explain how to overcome this shortcoming of implementing REST in Flash Actionscript 3 . . . . and I struck out.

The Flex framework offers the HttpService class, which implements all the http methods:GET, POST, HEAD, OPTIONS, PUT, TRACE and DELETE. However, I’m using Flash and I don’t have the HttpService at my disposal. These are the types of things all those extra kilobytes in Flex applications get you.

I found a tutorial in french. Pourquois Flex? Pourquois ROR? Ou est le code example? This section appears to confirm my suspicions while indicating that the DELETE and PUT methods are unnecessary. However my french is terrible. Do I implement DELETE and PUT using ruby routes mappings? Is this really REST?

HTTP fournit les 4 operations de base du CRUD (POST pour CREATE, GET pour READ, PUT pour UPDATE, DELETE pour DELETE). Chaque operation est auto-suffisante. Utilisation des standards HTML et XML. Ce qu?il faut savoir est que tous nos navigateurs supportent les 2 verbes HTTP seulement : GET et POST. En fait il y en a beaucoup plus. Comme vu precedemment, avec 4 verbes HTTP on se mappe sur un CRUD (persistence en base). RoR va effectuer ce mapping (notamment grace a un mapping ?magique?, associant verbes, formats, headers de requetes). On verra lors de l?exemple, que RoR nous apporte sur un plateau la gestion de deux formats HTML et XML.

I also found the beginings of an open source REST implementation called as3-active-resource that has an interesting approach. It uses a direct socket (SocketLoader.as) to implement PUT and DELETE operations (ActiveResource.as) This looks promising, but I’m a bit wary of implementing a socket approach to support these additional http operations. The project has yet to release any code so I’m guessing it is not ready for primetime at this moment. A socket also defeats the goal of achieving simplicity by using REST.

Here is my question: What is best practice for implementing a full REST architecture with DELETE and PUT using Actionscript 3?

]]>
http://marstonstudio.com/2007/07/09/question-about-rest-and-as3/feed/ 4 http://marstonstudio.com/2007/07/09/question-about-rest-and-as3/
email from a friend http://feedproxy.google.com/~r/marstonstudio/~3/7GY-wa2_qGs/ http://marstonstudio.com/2007/07/09/email-from-a-friend/#comments Mon, 09 Jul 2007 14:12:34 +0000 http://marstonstudio.com/index.php/2007/07/09/email-from-a-friend/ This popped up in my inbox

From: brian_m_riley@
Subject: start blogging…
Date: July 3, 2007 10:52:12 AM EDT
To: jon@

…i know you have the time.

Well, thankfully I haven’t had a lot of time, but that is no excuse. So far my endeavor as an independent contractor has been a roaring success. My first job has been building Flash widgets for a social networking startup based out of Palo Alto, CA. Launch is scheduled for late summer/early fall and I’ve been banging away at a variety of small applications for the website. From a technical sandpoint, I’ve run into a bunch of issues which I think would make for interesting blog posts, so the challenge to me now is putting all that down on this blog in a format that other people will find useful.

  • Using ActionScript 3 and Flash CS3 without the robust Flex Framework.
  • Preloading has changed completely in Flash CS3 especially when using the Document class approach.
  • Ruby on Rails tied with REST, RubyAMF, or WebORB remoting is cool.
  • How to balance robust Design Patterns with timeliness and code that a novice can understand.
  • Using bitmap data for crazy screen effects.
  • Streaming Video from a variety of media servers.

So I have a few things to talk about, I just haven’t carved out the time yet to put it down. Let’s see what I can put down over the next few weeks.

]]>
http://marstonstudio.com/2007/07/09/email-from-a-friend/feed/ 1 http://marstonstudio.com/2007/07/09/email-from-a-friend/
problem using the – character with flash external interface and microsoft internet explorer http://feedproxy.google.com/~r/marstonstudio/~3/c_KuHSDnk9U/ http://marstonstudio.com/2007/06/30/bug-with-flash-externalinterface-and-microsoft-internet-explorer/#comments Sat, 30 Jun 2007 20:20:02 +0000 http://marstonstudio.com/index.php/2007/11/30/bug-with-flash-externalinterface-and-microsoft-internet-explorer/ Here’s an odd bug that I ran into, hopefully this post will save somebody somewhere a little bit of headscratching.

In my current project I’m using swfobject 2.0 to embed our Flash content. I like the syntax and the open source development of the project, and I don’t mind being patient waiting for the fix dealing with the issue of loading a swf in response to a user javascript event. But I found that I was having a weird problem when trying to use ExternalInterface for Flash-Javascript communication. I could successfully call JavaScript functions from Flash using any browser, however registering for callbacks from JavaScript to Flash was failing in Internet Explorer. I hunted for awhile, and suspected that swfobject was to blame. I was wrong, and it appears to actually be a bug with the ExternalInterface code when registering to respond to Javascript calls. For the impatient, don’t use the dash character “-” in the dom id of your flash element. For those of you interested in a blow-by-blow account, read on.

In my Actionscript code, I was registering a callback to a function which allowed the user to change the background color of an element in my flash movie. So I had the code:

ExternalInterface.addCallback("updateBackgroundColor", updateBackgroundColor);

public function updateBackgroundColor(background_color:uint):void {
     Tweener.addTween(backgroundSprite, {_color:background_color});
}

Which uses Tweener’s most excellent ColorShortcut tween, but I digress.

In my page the object was embedded in the page using the following Javascript:

<div class="flashplayer" id="shout-creator_flash" style="width:214px; height:280px;">This website requires <a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash>Flash player</a> 9.0.0 or higher.</div>

<script type="text/javascript">//<![CDATA[

     var flashvars  = {"forwhat": "Test", "is_private": "true"};
     var params     = {"bgcolor": "#FFFFFF", "allowscriptaccess": "always"};
     var attributes = {"name": "shout-creator_swfobject", "id": "shout-creator_swfobject"};

     swfobject.embedSWF('/swfs/shoutcreator/ShoutCreator.swf?1196445820', 'shout-creator_flash', '214', '280', '9.0.0', '/swfs/ExpressInstall.swf?1196229239', flashvars, params, attributes);

//]]></script>

<div id="colortest" onclick="document.getElementById('shoutcreator_swfobject').updateBackgroundColor('0x000000');" style="border: 1px solid black;cursor:pointer;width:214px;">change color to 0x000000</div>

Notice that the name and id of the element is shout-creator_swfobject. Everything was fine and hunky dory in Firefox and Safari, which is great and all, but most of the web audience uses Internet Explorer. My callback wasn’t working in IE and I had one of those tell-tale JS errors showing.

First thing I had to do was configure JS debugging in IE6, which I did by following this excellent tutorial by Jonathan Boutelle. Then in my script debugger console I was seeing the following error:

Microsoft JScript runtime error: 'shout' is undefined

I clicked the ‘Break’ button and could see the following problem line:

__flash__addCallback( shout-creator_swfobject, "updateBackgroundColor");

I removed the - character from the name of the element in my code, changing all references from shout-creator_swfobject to shoutcreator_swfobject and my problem went away.

My theory is that there is some sort of parse error going on somewhere that is breaking up the element id a little too early. We’re using prototype.js and Ruby on Rails, so maybe that has something to do with it. Either way, ditching the - made my problem go away and kept me moving.

]]>
http://marstonstudio.com/2007/06/30/bug-with-flash-externalinterface-and-microsoft-internet-explorer/feed/ 5 http://marstonstudio.com/2007/06/30/bug-with-flash-externalinterface-and-microsoft-internet-explorer/