import com.infrared5.application.command.AddUserCommand;
import com.infrared5.application.model.Session;
import com.infrared5.application.model.User;
import com.infrared5.application.service.UserService;

import flash.events.Event;
import flash.net.URLLoader;

import mockolate.stub;

import org.jasmineflex.global.*;

import support.Prepare;

describe("Add User", function():void {

	var user:User;
	var session:Session;
	var command:AddUserCommand;
	var userService:UserService;
	var dispatcher:URLLoader = new URLLoader();
	const USER_ID:String = new Date().time.toString();

	beforeEach(function():void {
		user = new User(USER_ID);
		session = new Session();
		command = new AddUserCommand();
		Prepare.UserServicePrep(function(mockService:UserService):void {
			userService = mockService;

			command.session = session;
			command.userService = userService;
			command.setUser(user);

			stub(userService).method('addUser').returns(dispatcher);
		});
	});
	afterEach(function():void {
		user = null;
		session = null;
	});

	describe("add previously non-existant user", function():void {

		it("should return user on success", function():void {
			var responseUser:User;
			command.execute(function(response:Object):void {
				responseUser = response as User;
			}, null);
			dispatcher.dispatchEvent(new Event(Event.COMPLETE));

			waitsFor(function():* {
				return responseUser != null;
			}, "Could not properly test add user. Timeout.", 500);

			runs(function():void {
				expect(responseUser).toEqual(user);
			});
		});

	});
});

import com.infrared5.application.command.AddUserCommand;
import com.infrared5.application.model.Session;
import com.infrared5.application.model.User;
import com.infrared5.application.service.UserService;

import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;

import mockolate.stub;

import org.jasmineflex.global.*;

import support.Prepare;

describe("Add User", function():void {

	var user:User;
	var session:Session;
	var command:AddUserCommand;
	var userService:UserService;
	var dispatcher:URLLoader = new URLLoader();
	const USER_ID:String = new Date().time.toString();

	beforeEach(function():void {
		user = new User(USER_ID);
		session = new Session();
		command = new AddUserCommand();
		Prepare.UserServicePrep(function(mockService:UserService):void {
			userService = mockService;

			command.session = session;
			command.userService = userService;
			command.setUser(user);

			stub(userService).method('addUser').returns(dispatcher);
		});
	});
	afterEach(function():void {
		user = null;
		session = null;
	});

	describe("add previously non-existant user", function():void {

		it("should return user on success", function():void {
			var responseUser:User;
			command.execute(function(response:Object):void {
				responseUser = response as User;
			}, null);
			dispatcher.dispatchEvent(new Event(Event.COMPLETE));

			waitsFor(function():* {
				return responseUser != null;
			}, "Could not properly test add user. Timeout.", 500);

			runs(function():void {
				expect(responseUser).toEqual(user);
			});
		});

		it("should append previously non-existant user to session listing.", function():void {
			var responseUser:User;
			command.execute(function(response:Object):void {
				responseUser = response as User;
			}, null);
			dispatcher.dispatchEvent(new Event(Event.COMPLETE));

			waitsFor(function():* {
				return responseUser != null;
			}, "Could not properly test add user. Timeout.", 500);

			runs(function():void {
				expect(session.users.length).toEqual(1);
				expect(session.users[0]).toEqual(user);
			});
		});

	});

	describe("add previously existant user", function():void {

		it("should respond on fault if user not added", function():void {
			var responseMessage:String;
			command.execute(null, function(response:Object):void {
				responseMessage = response as String;
			});
			dispatcher.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));

			waitsFor(function():* {
				return responseMessage != null;
			}, "Could not properly test add user. Timeout.", 500);

			runs(function():void {
				expect(responseMessage as String).not.toBeNull();
			});
		});

		it("should not affect session user list on fault", function():void {
			var responseMessage:String;
			var previousSessionUserLength:int = session.users.length;
			command.execute(null, function(response:Object):void {
				responseMessage = response as String;
			});
			dispatcher.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));

			waitsFor(function():* {
				return responseMessage != null;
			}, "Could not properly test add user. Timeout.", 500);

			runs(function():void {
				expect(session.users.length).toEqual(previousSessionUserLength);
			});
		});

	});
});

add user specs for jasmine-flex

add user specs for jasmine-flex


/*
 * Copyright (c) 2009 the original author or authors
 *
 * Permission is hereby granted to use, modify, and distribute this file
 * in accordance with the terms of the license agreement accompanying it.
 */

package org.robotlegs.mvcs
{
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.system.ApplicationDomain;

	import org.robotlegs.adapters.SwiftSuspendersInjector;
	import org.robotlegs.adapters.SwiftSuspendersReflector;
	import org.robotlegs.base.CommandMap;
	import org.robotlegs.base.ContextBase;
	import org.robotlegs.base.ContextEvent;
	import org.robotlegs.base.EventMap;
	import org.robotlegs.base.MediatorMap;
	import org.robotlegs.base.ViewMap;
	import org.robotlegs.core.ICommandMap;
	import org.robotlegs.core.IContext;
	import org.robotlegs.core.IEventMap;
	import org.robotlegs.core.IInjector;
	import org.robotlegs.core.IMediatorMap;
	import org.robotlegs.core.IReflector;
	import org.robotlegs.core.IViewMap;

	/**
	 * Abstract MVCS IContext implementation
	 */
	public class Context extends ContextBase implements IContext
	{

		/**
		 * @private
		 */
		protected var _injector:IInjector;

		/**
		 * @private
		 */
		protected var _reflector:IReflector;

		/**
		 * @private
		 */
		protected var _autoStartup:Boolean;

		/**
		 * @private
		 */
		protected var _contextView:DisplayObjectContainer;

		/**
		 * @private
		 */
		protected var _commandMap:ICommandMap;

		/**
		 * @private
		 */
		protected var _mediatorMap:IMediatorMap;

		/**
		 * @private
		 */
		protected var _viewMap:IViewMap;

		//---------------------------------------------------------------------
		//  Constructor
		//---------------------------------------------------------------------

		/**
		 * Abstract Context Implementation
		 *
		 *
Extend this class to create a Framework or Application context

		 *
		 * @param contextView The root view node of the context. The context will listen for ADDED_TO_STAGE events on this node
		 * @param autoStartup Should this context automatically invoke it's startup method when it's contextView arrives on Stage?
		 */
		public function Context(contextView:DisplayObjectContainer = null, autoStartup:Boolean = true)
		{
			super();
			_contextView = contextView;
			_autoStartup = autoStartup;
			mapInjections();
			checkAutoStartup();
		}

		//---------------------------------------------------------------------
		//  API
		//---------------------------------------------------------------------

		/**
		 * The Startup Hook
		 *
		 *
Override this in your Application context

		 */
		public function startup():void
		{
			dispatchEvent(new ContextEvent(ContextEvent.STARTUP_COMPLETE));
		}

		/**
		 * The Startup Hook
		 *
		 *
Override this in your Application context

		 */
		public function shutdown():void
		{
			dispatchEvent(new ContextEvent(ContextEvent.SHUTDOWN_COMPLETE));
		}

		/**
		 * The DisplayObjectContainer that scopes this IContext
		 */
		public function get contextView():DisplayObjectContainer
		{
			return _contextView;
		}

		/**
		 * @private
		 */
		public function set contextView(value:DisplayObjectContainer):void
		{
			if (_contextView != value)
			{
				_contextView = value;
				// Hack: We have to clear these out and re-map them
				_injector.applicationDomain = getApplicationDomainFromContextView();
				_commandMap = null;
				_mediatorMap = null;
				_viewMap = null;
				mapInjections();
				checkAutoStartup();
			}
		}

		//---------------------------------------------------------------------
		//  Protected, Lazy Getters and Setters
		//---------------------------------------------------------------------

		/**
		 * The IInjector for this IContext
		 */
		protected function get injector():IInjector
		{
			return _injector ||= createInjector();
		}

		/**
		 * @private
		 */
		protected function set injector(value:IInjector):void
		{
			_injector = value;
		}

		/**
		 * The IReflector for this IContext
		 */
		protected function get reflector():IReflector
		{
			return _reflector ||= new SwiftSuspendersReflector();
		}

		/**
		 * @private
		 */
		protected function set reflector(value:IReflector):void
		{
			_reflector = value;
		}

		/**
		 * The ICommandMap for this IContext
		 */
		protected function get commandMap():ICommandMap
		{
			return _commandMap ||= new CommandMap(eventDispatcher, createChildInjector(), reflector);
		}

		/**
		 * @private
		 */
		protected function set commandMap(value:ICommandMap):void
		{
			_commandMap = value;
		}

		/**
		 * The IMediatorMap for this IContext
		 */
		protected function get mediatorMap():IMediatorMap
		{
			return _mediatorMap ||= new MediatorMap(contextView, createChildInjector(), reflector);
		}

		/**
		 * @private
		 */
		protected function set mediatorMap(value:IMediatorMap):void
		{
			_mediatorMap = value;
		}

		/**
		 * The IViewMap for this IContext
		 */
		protected function get viewMap():IViewMap
		{
			return _viewMap ||= new ViewMap(contextView, injector);
		}

		/**
		 * @private
		 */
		protected function set viewMap(value:IViewMap):void
		{
			_viewMap = value;
		}

		//---------------------------------------------------------------------
		//  Framework Hooks
		//---------------------------------------------------------------------

		/**
		 * Injection Mapping Hook
		 *
		 *
Override this in your Framework context to change the default configuration

		 *
		 *
Beware of collisions in your container

		 */
		protected function mapInjections():void
		{
			injector.mapValue(IReflector, reflector);
			injector.mapValue(IInjector, injector);
			injector.mapValue(IEventDispatcher, eventDispatcher);
			injector.mapValue(DisplayObjectContainer, contextView);
			injector.mapValue(ICommandMap, commandMap);
			injector.mapValue(IMediatorMap, mediatorMap);
			injector.mapValue(IViewMap, viewMap);
			injector.mapClass(IEventMap, EventMap);
		}

		//---------------------------------------------------------------------
		//  Internal
		//---------------------------------------------------------------------

		/**
		 * @private
		 */
		protected function checkAutoStartup():void
		{
			if (_autoStartup && contextView)
			{
				contextView.stage ? startup() : contextView.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
			}
		}

		/**
		 * @private
		 */
		protected function onAddedToStage(e:Event):void
		{
			contextView.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			startup();
		}

		/**
		 * @private
		 */
		protected function createInjector():IInjector
		{
			var injector:IInjector = new SwiftSuspendersInjector();
			injector.applicationDomain = getApplicationDomainFromContextView();
			return injector;
		}

		/**
		 * @private
		 */
		protected function createChildInjector():IInjector
		{
			return injector.createChild(getApplicationDomainFromContextView());
		}

		/**
		 * @private
		 */
		protected function getApplicationDomainFromContextView():ApplicationDomain
		{
			if (contextView && contextView.loaderInfo)
				return contextView.loaderInfo.applicationDomain;
			return ApplicationDomain.currentDomain;
		}

	}
}

/*
 * Copyright (c) 2009 the original author or authors
 *
 * Permission is hereby granted to use, modify, and distribute this file
 * in accordance with the terms of the license agreement accompanying it.
 */

package org.robotlegs.mvcs
{
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.system.ApplicationDomain;

	import org.robotlegs.adapters.SwiftSuspendersInjector;
	import org.robotlegs.adapters.SwiftSuspendersReflector;
	import org.robotlegs.base.CommandMap;
	import org.robotlegs.base.ContextBase;
	import org.robotlegs.base.ContextEvent;
	import org.robotlegs.base.EventMap;
	import org.robotlegs.base.MediatorMap;
	import org.robotlegs.base.ViewMap;
	import org.robotlegs.core.ICommandMap;
	import org.robotlegs.core.IContext;
	import org.robotlegs.core.IEventMap;
	import org.robotlegs.core.IInjector;
	import org.robotlegs.core.IMediatorMap;
	import org.robotlegs.core.IReflector;
	import org.robotlegs.core.IViewMap;

	/**
	 * Dispatched by the startup() method when it finishes
	 * executing.
	 *
	 *
One common pattern for application startup/bootstrapping makes use
	 * of the startupComplete event. In this pattern, you do the
	 * following:

	 *

	 *
Override the startup() method in your Context
	 *       subclass and set up application mappings in your
	 *       startup() override as you always do in Robotlegs.

	 *
Create commands that perform startup/bootstrapping operations
	 *       such as loading the initial data, checking for application updates,
	 *       etc.

	 *

Map those commands to the ContextEvent.STARTUP_COMPLETE
	 *       event:

	 *       <listing>commandMap.mapEvent(ContextEvent.STARTUP_COMPLETE, LoadInitialDataCommand, ContextEvent, true):</listing>
	 *

	 *
Dispatch the startupComplete (ContextEvent.STARTUP_COMPLETE)
	 *       event from your startup() override. You can do this
	 *       in one of two ways: dispatch the event yourself, or call
	 *       super.startup(). (The Context class's
	 *       startup() method dispatches the
	 *       startupComplete event.)

	 *

	 *
	 * @eventType org.robotlegs.base.ContextEvent.STARTUP_COMPLETE
	 *
	 * @see #startup()
	 */
	[Event(name="startupComplete", type="org.robotlegs.base.ContextEvent")]

	/**
	 * Abstract MVCS IContext implementation
	 */
	public class Context extends ContextBase implements IContext
	{

		/**
		 * @private
		 */
		protected var _injector:IInjector;

		/**
		 * @private
		 */
		protected var _reflector:IReflector;

		/**
		 * @private
		 */
		protected var _autoStartup:Boolean;

		/**
		 * @private
		 */
		protected var _contextView:DisplayObjectContainer;

		/**
		 * @private
		 */
		protected var _commandMap:ICommandMap;

		/**
		 * @private
		 */
		protected var _mediatorMap:IMediatorMap;

		/**
		 * @private
		 */
		protected var _viewMap:IViewMap;

		//---------------------------------------------------------------------
		//  Constructor
		//---------------------------------------------------------------------

		/**
		 * Abstract Context Implementation
		 *
		 *
Extend this class to create a Framework or Application context

		 *
		 * @param contextView The root view node of the context. The context will listen for ADDED_TO_STAGE events on this node
		 * @param autoStartup Should this context automatically invoke it's startup method when it's contextView arrives on Stage?
		 */
		public function Context(contextView:DisplayObjectContainer = null, autoStartup:Boolean = true)
		{
			super();
			_contextView = contextView;
			_autoStartup = autoStartup;
			mapInjections();
			checkAutoStartup();
		}

		//---------------------------------------------------------------------
		//  API
		//---------------------------------------------------------------------

		/**
		 * The Startup Hook
		 *
		 *
Override this in your Application context

		 *
		 * @event startupComplete ContextEvent.STARTUP_COMPLETE Dispatched at the end of the
		 *                        startup() method's execution. This
		 *                        is often used to trigger startup/bootstrapping
		 *                        commands by wiring them to this event and
		 *                        calling super.startup() in the
		 *                        last line of your startup()
		 *                        override.
		 */
		public function startup():void
		{
			dispatchEvent(new ContextEvent(ContextEvent.STARTUP_COMPLETE));
		}

		/**
		 * The Startup Hook
		 *
		 *
Override this in your Application context

		 */
		public function shutdown():void
		{
			dispatchEvent(new ContextEvent(ContextEvent.SHUTDOWN_COMPLETE));
		}

		/**
		 * The DisplayObjectContainer that scopes this IContext
		 */
		public function get contextView():DisplayObjectContainer
		{
			return _contextView;
		}

		/**
		 * @private
		 */
		public function set contextView(value:DisplayObjectContainer):void
		{
			if (_contextView != value)
			{
				_contextView = value;
				// Hack: We have to clear these out and re-map them
				_injector.applicationDomain = getApplicationDomainFromContextView();
				_commandMap = null;
				_mediatorMap = null;
				_viewMap = null;
				mapInjections();
				checkAutoStartup();
			}
		}

		//---------------------------------------------------------------------
		//  Protected, Lazy Getters and Setters
		//---------------------------------------------------------------------

		/**
		 * The IInjector for this IContext
		 */
		protected function get injector():IInjector
		{
			return _injector ||= createInjector();
		}

		/**
		 * @private
		 */
		protected function set injector(value:IInjector):void
		{
			_injector = value;
		}

		/**
		 * The IReflector for this IContext
		 */
		protected function get reflector():IReflector
		{
			return _reflector ||= new SwiftSuspendersReflector();
		}

		/**
		 * @private
		 */
		protected function set reflector(value:IReflector):void
		{
			_reflector = value;
		}

		/**
		 * The ICommandMap for this IContext
		 */
		protected function get commandMap():ICommandMap
		{
			return _commandMap ||= new CommandMap(eventDispatcher, createChildInjector(), reflector);
		}

		/**
		 * @private
		 */
		protected function set commandMap(value:ICommandMap):void
		{
			_commandMap = value;
		}

		/**
		 * The IMediatorMap for this IContext
		 */
		protected function get mediatorMap():IMediatorMap
		{
			return _mediatorMap ||= new MediatorMap(contextView, createChildInjector(), reflector);
		}

		/**
		 * @private
		 */
		protected function set mediatorMap(value:IMediatorMap):void
		{
			_mediatorMap = value;
		}

		/**
		 * The IViewMap for this IContext
		 */
		protected function get viewMap():IViewMap
		{
			return _viewMap ||= new ViewMap(contextView, injector);
		}

		/**
		 * @private
		 */
		protected function set viewMap(value:IViewMap):void
		{
			_viewMap = value;
		}

		//---------------------------------------------------------------------
		//  Framework Hooks
		//---------------------------------------------------------------------

		/**
		 * Injection Mapping Hook
		 *
		 *
Override this in your Framework context to change the default configuration

		 *
		 *
Beware of collisions in your container

		 */
		protected function mapInjections():void
		{
			injector.mapValue(IReflector, reflector);
			injector.mapValue(IInjector, injector);
			injector.mapValue(IEventDispatcher, eventDispatcher);
			injector.mapValue(DisplayObjectContainer, contextView);
			injector.mapValue(ICommandMap, commandMap);
			injector.mapValue(IMediatorMap, mediatorMap);
			injector.mapValue(IViewMap, viewMap);
			injector.mapClass(IEventMap, EventMap);
		}

		//---------------------------------------------------------------------
		//  Internal
		//---------------------------------------------------------------------

		/**
		 * @private
		 */
		protected function checkAutoStartup():void
		{
			if (_autoStartup && contextView)
			{
				contextView.stage ? startup() : contextView.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
			}
		}

		/**
		 * @private
		 */
		protected function onAddedToStage(e:Event):void
		{
			contextView.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			startup();
		}

		/**
		 * @private
		 */
		protected function createInjector():IInjector
		{
			var injector:IInjector = new SwiftSuspendersInjector();
			injector.applicationDomain = getApplicationDomainFromContextView();
			return injector;
		}

		/**
		 * @private
		 */
		protected function createChildInjector():IInjector
		{
			return injector.createChild(getApplicationDomainFromContextView());
		}

		/**
		 * @private
		 */
		protected function getApplicationDomainFromContextView():ApplicationDomain
		{
			if (contextView && contextView.loaderInfo)
				return contextView.loaderInfo.applicationDomain;
			return ApplicationDomain.currentDomain;
		}

	}
}

Add documentation for the startupComplete event dispatched by the Context.startup() method. The docs describe a common pattern for using the startupComplete event to trigger traditional "app entrypoint" bootstrapping operations.


////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.html
{
    import org.apache.flex.core.ISelectionModel;

    COMPILE::JS
    {
        import goog.events;
        import org.apache.flex.core.WrappedHTMLElement;
        import org.apache.flex.html.beads.models.ArraySelectionModel;
    }

    //--------------------------------------
    //  Events
    //--------------------------------------

    /**
     *  Dispatched when the user selects an item.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="change", type="org.apache.flex.events.Event")]

    /**
     *  The DropDownList class implements the basic equivalent of
     *  the <select> tag in HTML.
     *  The default implementation only lets the user see and
     *  choose from an array of strings.  More complex controls
     *  would display icons as well as strings, or colors instead
     *  of strings or just about anything.
     *
     *  The default behavior only lets the user choose one and
     *  only one item.  More complex controls would allow
     *  mutiple selection by not dismissing the dropdown as soon
     *  as a selection is made.
     *
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class DropDownList extends Button
	{
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function DropDownList()
		{
            COMPILE::JS
            {
                model = new ArraySelectionModel();
            }
		}

        /**
         *  The data set to be displayed.  Usually a simple
         *  array of strings.  A more complex component
         *  would allow more complex data and data sets.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get dataProvider():Object
        {
            return ISelectionModel(model).dataProvider;
        }

        /**
         *  @private
         *  @flexjsignorecoercion HTMLOptionElement
         *  @flexjsignorecoercion HTMLSelectElement
         */
        public function set dataProvider(value:Object):void
        {
            ISelectionModel(model).dataProvider = value;
            COMPILE::JS
            {
                var dp:HTMLOptionsCollection;
                var i:int;
                var n:int;
                var opt:HTMLOptionElement;
                var dd:HTMLSelectElement = element as HTMLSelectElement;

                model.dataProvider = value;
                dp = dd.options;
                n = dp.length;
                for (i = 0; i < n; i++) {
                    dd.remove(0);
                }

                var lf:String = labelField;
                n = value.length;
                for (i = 0; i < n; i++) {
                    opt = document.createElement('option') as HTMLOptionElement;
                    if (lf)
                        opt.text = value[i][lf];
                    else
                        opt.text = value[i];
                    dd.add(opt, null);
                }

            }
        }

        [Bindable("change")]
        /**
         *  @copy org.apache.flex.core.ISelectionModel#selectedIndex
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get selectedIndex():int
        {
            return ISelectionModel(model).selectedIndex;
        }

        /**
         *  @private
         */
        public function set selectedIndex(value:int):void
        {
            ISelectionModel(model).selectedIndex = value;
        }

        [Bindable("change")]
        /**
         *  @copy org.apache.flex.core.ISelectionModel#selectedItem
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get selectedItem():Object
        {
            return ISelectionModel(model).selectedItem;
        }

        /**
         *  @private
         */
        public function set selectedItem(value:Object):void
        {
            ISelectionModel(model).selectedItem = value;
        }

        /**
         *  The name of field within the data used for display. Each item of the
         *  data should have a property with this name.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get labelField():String
        {
            return ISelectionModel(model).labelField;
        }
        public function set labelField(value:String):void
        {
            ISelectionModel(model).labelField = value;
        }

        /**
         * @flexjsignorecoercion org.apache.flex.core.WrappedHTMLElement
         * @flexjsignorecoercion HTMLSelectElement
         */
        COMPILE::JS
        override protected function createElement():WrappedHTMLElement
        {
            element = document.createElement('select') as WrappedHTMLElement;
            (element as HTMLSelectElement).size = 1;
            goog.events.listen(element, 'change',
                changeHandler);

            positioner = element;
            positioner.style.position = 'relative';

            element.flexjs_wrapper = this;

            return element;
        }

        /**
         * @flexjsignorecoercion HTMLSelectElement
         */
        COMPILE::JS
        protected function changeHandler(event:Event):void
        {
            model.selectedIndex = (element as HTMLSelectElement).selectedIndex;
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.html
{
    import org.apache.flex.core.ISelectionModel;

    COMPILE::JS
    {
        import goog.events;
        import org.apache.flex.core.WrappedHTMLElement;
        import org.apache.flex.html.beads.models.ArraySelectionModel;
    }

    //--------------------------------------
    //  Events
    //--------------------------------------

    /**
     *  Dispatched when the user selects an item.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="change", type="org.apache.flex.events.Event")]

    /**
     *  The DropDownList class implements the basic equivalent of
     *  the <select> tag in HTML.
     *  The default implementation only lets the user see and
     *  choose from an array of strings.  More complex controls
     *  would display icons as well as strings, or colors instead
     *  of strings or just about anything.
     *
     *  The default behavior only lets the user choose one and
     *  only one item.  More complex controls would allow
     *  mutiple selection by not dismissing the dropdown as soon
     *  as a selection is made.
     *
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class DropDownList extends Button
	{
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		public function DropDownList()
		{
            COMPILE::JS
            {
                model = new ArraySelectionModel();
            }
		}

        /**
         *  The data set to be displayed.  Usually a simple
         *  array of strings.  A more complex component
         *  would allow more complex data and data sets.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get dataProvider():Object
        {
            return ISelectionModel(model).dataProvider;
        }

        /**
         *  @private
         *  @flexjsignorecoercion HTMLOptionElement
         *  @flexjsignorecoercion HTMLSelectElement
         */
        public function set dataProvider(value:Object):void
        {
            ISelectionModel(model).dataProvider = value;
            COMPILE::JS
            {
                var dp:HTMLOptionsCollection;
                var i:int;
                var n:int;
                var opt:HTMLOptionElement;
                var dd:HTMLSelectElement = element as HTMLSelectElement;

                model.dataProvider = value;
                dp = dd.options;
                n = dp.length;
                for (i = 0; i < n; i++) {
                    dd.remove(0);
                }

                var lf:String = labelField;
                n = value.length;
                for (i = 0; i < n; i++) {
                    opt = document.createElement('option') as HTMLOptionElement;
                    if (lf)
                        opt.text = value[i][lf];
                    else
                        opt.text = value[i];
                    dd.add(opt, null);
                }

            }
        }

        [Bindable("change")]
        /**
         *  @copy org.apache.flex.core.ISelectionModel#selectedIndex
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get selectedIndex():int
        {
            return ISelectionModel(model).selectedIndex;
        }

        /**
         *  @private
         *  @flexjsignorecoercion HTMLSelectElement
         */
        public function set selectedIndex(value:int):void
        {
            ISelectionModel(model).selectedIndex = value;
            COMPILE::JS
            {
                (element as HTMLSelectElement).selectedIndex = ISelectionModel(model).selectedIndex;
            }
        }

        [Bindable("change")]
        /**
         *  @copy org.apache.flex.core.ISelectionModel#selectedItem
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get selectedItem():Object
        {
            return ISelectionModel(model).selectedItem;
        }

        /**
         *  @private
         *  @flexjsignorecoercion HTMLSelectElement
         */
        public function set selectedItem(value:Object):void
        {
            ISelectionModel(model).selectedItem = value;
            COMPILE::JS
            {
                (element as HTMLSelectElement).selectedIndex = ISelectionModel(model).selectedIndex;
            }
        }

        /**
         *  The name of field within the data used for display. Each item of the
         *  data should have a property with this name.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get labelField():String
        {
            return ISelectionModel(model).labelField;
        }
        public function set labelField(value:String):void
        {
            ISelectionModel(model).labelField = value;
        }

        /**
         * @flexjsignorecoercion org.apache.flex.core.WrappedHTMLElement
         * @flexjsignorecoercion HTMLSelectElement
         */
        COMPILE::JS
        override protected function createElement():WrappedHTMLElement
        {
            element = document.createElement('select') as WrappedHTMLElement;
            (element as HTMLSelectElement).size = 1;
            goog.events.listen(element, 'change',
                changeHandler);

            positioner = element;
            positioner.style.position = 'relative';

            element.flexjs_wrapper = this;

            return element;
        }

        /**
         * @flexjsignorecoercion HTMLSelectElement
         */
        COMPILE::JS
        protected function changeHandler(event:Event):void
        {
            model.selectedIndex = (element as HTMLSelectElement).selectedIndex;
        }
    }
}

Fix dropdownlist selection

Fix dropdownlist selection


/*
 *  ISteamWorks.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by Ventero <http://github.com/Ventero> on 2013-08-28
 *  Copyright (c) 2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam {
	import flash.display.DisplayObjectContainer;
	import flash.events.IEventDispatcher;
	import flash.utils.ByteArray;

	public interface ISteamWorks extends IEventDispatcher {
		[Event(name="steamResponse", type="com.amanitadesign.steam.SteamEvent")]
		function ISteamWorks(target:IEventDispatcher = null);

		function init():Boolean;
		function dispose():void;

		function addOverlayWorkaround(container:DisplayObjectContainer,
			alwaysVisible:Boolean = false, color:uint = 0x000000):void;

		function runCallbacks():Boolean;
		function getUserID():String;
		function getAppID():uint;
		function getPersonaName():String;
		function useCrashHandler(appID:uint, version:String, date:String, time:String):Boolean;
		/* stats/achievements */
		function requestStats():Boolean;
		function setAchievement(name:String):Boolean;
		function clearAchievement(name:String):Boolean;
		function isAchievement(name:String):Boolean;
		function getStatInt(name:String):int;
		function getStatFloat(name:String):Number;
		function setStatInt(name:String, value:int):Boolean;
		function setStatFloat(name:String, value:Number):Boolean;
		function storeStats():Boolean;
		function resetAllStats(achievementsToo:Boolean):Boolean;
		/* cloud */
		function getFileCount():int;
		function getFileSize(name:String):int;
		function fileExists(name:String):Boolean;
		function fileWrite(name:String, data:ByteArray):Boolean;
		function fileRead(name:String, data:ByteArray):Boolean;
		function fileDelete(name:String):Boolean;
		function fileShare(name:String):Boolean;
		function fileShareResult():String;
		function isCloudEnabledForApp():Boolean;
		function setCloudEnabledForApp(enabled:Boolean):Boolean;
		function getQuota():Array;
		/* ugc/workshop */
		function UGCDownload(handle:String, priority:int):Boolean;
		function UGCRead(handle:String, size:int, offset:uint, data:ByteArray):Boolean;
		function getUGCDownloadProgress(handle:String):Array;
		function getUGCDownloadResult(handle:String):DownloadUGCResult;
		function publishWorkshopFile(name:String, preview:String, appId:uint, title:String, description:String, visibility:uint, tags:Array, fileType:uint):Boolean;
		function publishWorkshopFileResult():String;
		function deletePublishedFile(file:String):Boolean;
		function getPublishedFileDetails(file:String, maxAge:int):Boolean;
		function getPublishedFileDetailsResult(file:String):FileDetailsResult;
		function enumerateUserPublishedFiles(startIndex:uint):Boolean;
		function enumerateUserPublishedFilesResult():UserFilesResult;
		function enumeratePublishedWorkshopFiles(type:uint, start:uint, count:uint, days:uint, tags:Array, userTags:Array):Boolean;
		function enumeratePublishedWorkshopFilesResult():WorkshopFilesResult;
		function enumerateUserSubscribedFiles(startIndex:uint):Boolean;
		function enumerateUserSubscribedFilesResult():SubscribedFilesResult;
		function enumerateUserSharedWorkshopFiles(steamID:String, start:uint, required:Array, excluded:Array):Boolean;
		function enumerateUserSharedWorkshopFilesResult():UserFilesResult;
		function enumeratePublishedFilesByUserAction(action:uint, startIndex:uint):Boolean;
		function enumeratePublishedFilesByUserActionResult():FilesByUserActionResult;
		function subscribePublishedFile(file:String):Boolean;
		function unsubscribePublishedFile(file:String):Boolean;
		function createPublishedFileUpdateRequest(file:String):String;
		function updatePublishedFileFile(handle:String, file:String):Boolean;
		function updatePublishedFilePreviewFile(handle:String, preview:String):Boolean;
		function updatePublishedFileTitle(handle:String, title:String):Boolean;
		function updatePublishedFileDescription(handle:String, description:String):Boolean;
		function updatePublishedFileSetChangeDescription(handle:String, changeDesc:String):Boolean;
		function updatePublishedFileVisibility(handle:String, visibility:uint):Boolean;
		function updatePublishedFileTags(handle:String, tags:Array):Boolean;
		function commitPublishedFileUpdate(handle:String):Boolean;
		function getPublishedItemVoteDetails(file:String):Boolean;
		function getPublishedItemVoteDetailsResult():ItemVoteDetailsResult;
		function getUserPublishedItemVoteDetails(file:String):Boolean;
		function getUserPublishedItemVoteDetailsResult():UserVoteDetails;
		function updateUserPublishedItemVote(file:String, upvote:Boolean):Boolean;
		function setUserPublishedFileAction(file:String, action:uint):Boolean;
		/* overlay */
		function activateGameOverlay(dialog:String):Boolean;
		function activateGameOverlayToUser(dialog:String, steamId:String):Boolean;
		function activateGameOverlayToWebPage(url:String):Boolean;
		function activateGameOverlayToStore(appId:uint, flag:uint):Boolean;
		function activateGameOverlayInviteDialog(steamIdLobby:String):Boolean;
		function isOverlayEnabled():Boolean;
		/* DLC / subscriptions */
		function isSubscribedApp(appId:uint):Boolean;
		function isDLCInstalled(appId:uint):Boolean;
		function getDLCCount():int;
		function installDLC(appId:uint):Boolean;
		function uninstallDLC(appId:uint):Boolean;
		function DLCInstalledResult():uint;
	}
}

/*
 *  ISteamWorks.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by Ventero <http://github.com/Ventero> on 2013-08-28
 *  Copyright (c) 2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam {
	import flash.display.DisplayObjectContainer;
	import flash.events.IEventDispatcher;
	import flash.utils.ByteArray;

	public interface ISteamWorks extends IEventDispatcher {
		[Event(name="steamResponse", type="com.amanitadesign.steam.SteamEvent")]
		function ISteamWorks(target:IEventDispatcher = null);

		function init():Boolean;
		function dispose():void;

		function addOverlayWorkaround(container:DisplayObjectContainer,
			alwaysVisible:Boolean = false, color:uint = 0x000000):void;

		function runCallbacks():Boolean
		function getUserID():String
		function getAppID():uint
		function getPersonaName():String
		function useCrashHandler(appID:uint, version:String, date:String, time:String):Boolean
		/* stats/achievements */
		function requestStats():Boolean
		function setAchievement(name:String):Boolean
		function clearAchievement(name:String):Boolean
		function isAchievement(name:String):Boolean
		function getStatInt(name:String):int
		function getStatFloat(name:String):Number
		function setStatInt(name:String, value:int):Boolean
		function setStatFloat(name:String, value:Number):Boolean
		function storeStats():Boolean
		function resetAllStats(achievementsToo:Boolean):Boolean
		/* cloud */
		function getFileCount():int
		function getFileSize(name:String):int
		function fileExists(name:String):Boolean
		function fileWrite(name:String, data:ByteArray):Boolean
		function fileRead(name:String, data:ByteArray):Boolean
		function fileDelete(name:String):Boolean
		function fileShare(name:String):Boolean
		function fileShareResult():String
		function isCloudEnabledForApp():Boolean
		function setCloudEnabledForApp(enabled:Boolean):Boolean
		function getQuota():Array
		/* ugc/workshop */
		function UGCDownload(handle:String, priority:int):Boolean
		function UGCRead(handle:String, size:int, offset:uint, data:ByteArray):Boolean
		function getUGCDownloadProgress(handle:String):Array
		function getUGCDownloadResult(handle:String):DownloadUGCResult
		function publishWorkshopFile(name:String, preview:String, appId:uint, title:String, description:String, visibility:uint, tags:Array, fileType:uint):Boolean
		function publishWorkshopFileResult():String
		function deletePublishedFile(file:String):Boolean
		function getPublishedFileDetails(file:String, maxAge:int = 0):Boolean
		function getPublishedFileDetailsResult(file:String):FileDetailsResult
		function enumerateUserPublishedFiles(startIndex:uint):Boolean
		function enumerateUserPublishedFilesResult():UserFilesResult
		function enumeratePublishedWorkshopFiles(type:uint, start:uint, count:uint, days:uint, tags:Array, userTags:Array):Boolean
		function enumeratePublishedWorkshopFilesResult():WorkshopFilesResult
		function enumerateUserSubscribedFiles(startIndex:uint):Boolean
		function enumerateUserSubscribedFilesResult():SubscribedFilesResult
		function enumerateUserSharedWorkshopFiles(steamID:String, start:uint, required:Array, excluded:Array):Boolean
		function enumerateUserSharedWorkshopFilesResult():UserFilesResult
		function enumeratePublishedFilesByUserAction(action:uint, startIndex:uint):Boolean
		function enumeratePublishedFilesByUserActionResult():FilesByUserActionResult
		function subscribePublishedFile(file:String):Boolean
		function unsubscribePublishedFile(file:String):Boolean
		function createPublishedFileUpdateRequest(file:String):String
		function updatePublishedFileFile(handle:String, file:String):Boolean
		function updatePublishedFilePreviewFile(handle:String, preview:String):Boolean
		function updatePublishedFileTitle(handle:String, title:String):Boolean
		function updatePublishedFileDescription(handle:String, description:String):Boolean
		function updatePublishedFileSetChangeDescription(handle:String, changeDesc:String):Boolean
		function updatePublishedFileVisibility(handle:String, visibility:uint):Boolean
		function updatePublishedFileTags(handle:String, tags:Array):Boolean
		function commitPublishedFileUpdate(handle:String):Boolean
		function getPublishedItemVoteDetails(file:String):Boolean
		function getPublishedItemVoteDetailsResult():ItemVoteDetailsResult
		function getUserPublishedItemVoteDetails(file:String):Boolean
		function getUserPublishedItemVoteDetailsResult():UserVoteDetails
		function updateUserPublishedItemVote(file:String, upvote:Boolean):Boolean
		function setUserPublishedFileAction(file:String, action:uint):Boolean
		/* overlay */
		function activateGameOverlay(dialog:String):Boolean
		function activateGameOverlayToUser(dialog:String, steamId:String):Boolean
		function activateGameOverlayToWebPage(url:String):Boolean
		function activateGameOverlayToStore(appId:uint, flag:uint):Boolean
		function activateGameOverlayInviteDialog(steamIdLobby:String):Boolean
		function isOverlayEnabled():Boolean
		/* DLC / subscriptions */
		function isSubscribedApp(appId:uint):Boolean
		function isDLCInstalled(appId:uint):Boolean
		function getDLCCount():int
		function installDLC(appId:uint):Boolean
		function uninstallDLC(appId:uint):Boolean
		function DLCInstalledResult():uint
	}
}

Remove unnecessary semicolons.

Remove unnecessary semicolons.


/*
 * FLINT PARTICLE SYSTEM
 * .....................
 *
 * Author: Richard Lord
 * Copyright (c) Richard Lord 2008-2010
 * http://flintparticles.org
 *
 *
 * Licence Agreement
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.flintparticles.common.events
{
	import flash.events.Event;

	/**
	 * The class for particle related events dispatched by classes in the Flint project.
	 */
	public class UpdateEvent extends Event
	{
		/**
		 * The event dispatched on the enter frame
		 */
		public static var UPDATE:String = "update";

		/**
		 * The particle to which the event relates.
		 */
		public var time:Number;

		/**
		 * The constructor creates a ParticleEvent object.
		 *
		 * @param type The type of the event, accessible as Event.type.
		 * @param particle The particle to which teh event relates.
		 * @param bubbles Determines whether the Event object participates
		 * in the bubbling stage of the event flow. The default value is false.
		 * @param cancelable Determines whether the Event object can be
		 * canceled. The default values is false.
		 */
		public function UpdateEvent( type : String, time:Number = NaN, bubbles : Boolean = false, cancelable : Boolean = false )
		{
			super(type, bubbles, cancelable);
			this.time = time;
		}

		/**
		 * Creates a copy of this event.
		 *
		 * @return The copy of this event.
		 */
		override public function clone():Event
		{
			return new UpdateEvent( type, time, bubbles, cancelable );
		}
	}
}

/*
 * FLINT PARTICLE SYSTEM
 * .....................
 *
 * Author: Richard Lord
 * Copyright (c) Richard Lord 2008-2010
 * http://flintparticles.org
 *
 *
 * Licence Agreement
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.flintparticles.common.events
{
	import flash.events.Event;

	/**
	 * The UpdateEvent is dispatched from the FrameUpdater utility every frame, to all emitters that are
	 * being updated by Flint, to trigger the update cycle on each emitter.
	 */
	public class UpdateEvent extends Event
	{
		/**
		 * The event dispatched on the enter frame
		 */
		public static var UPDATE:String = "update";

		/**
		 * The particle to which the event relates.
		 */
		public var time:Number;

		/**
		 * The constructor creates a ParticleEvent object.
		 *
		 * @param type The type of the event, accessible as Event.type.
		 * @param particle The particle to which teh event relates.
		 * @param bubbles Determines whether the Event object participates
		 * in the bubbling stage of the event flow. The default value is false.
		 * @param cancelable Determines whether the Event object can be
		 * canceled. The default values is false.
		 */
		public function UpdateEvent( type : String, time:Number = NaN, bubbles : Boolean = false, cancelable : Boolean = false )
		{
			super(type, bubbles, cancelable);
			this.time = time;
		}

		/**
		 * Creates a copy of this event.
		 *
		 * @return The copy of this event.
		 */
		override public function clone():Event
		{
			return new UpdateEvent( type, time, bubbles, cancelable );
		}
	}
}

Fix documentation on UpdateEvent class

Fix documentation on UpdateEvent class


package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.external.ExternalInterface;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.net.Socket;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;
    import flash.net.URLVariables;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.setTimeout;

    public class swfcat extends Sprite
    {
        private const RTMFP_URL:String = "rtmfp://tor-facilitator.bamsoftware.com";

        private const DEFAULT_FACILITATOR_ADDR:Object = {
            host: "tor-facilitator.bamsoftware.com",
            port: 9002
        };

        /* Local Tor client to use in case of RTMFP connection. */
        private const DEFAULT_LOCAL_TOR_CLIENT_ADDR:Object = {
            host: "127.0.0.1",
            port: 9002
        };

        private const MAX_NUM_PROXY_PAIRS:uint = 100;

        // Milliseconds.
        private const FACILITATOR_POLL_INTERVAL:int = 10000;

        // Bytes per second. Set to undefined to disable limit.
        public static const RATE_LIMIT:Number = undefined;
        // Seconds.
        private static const RATE_LIMIT_HISTORY:Number = 5.0;

        /* TextField for debug output. */
        private var output_text:TextField;

        /* UI shown when debug is off. */
        private var badge:Badge;

        /* Proxy pairs currently connected (up to MAX_NUM_PROXY_PAIRS). */
        private var proxy_pairs:Array;

        private var fac_addr:Object;

        private var local_addr:Object;

        public var debug:Boolean;

        public var rate_limit:RateLimit;

        public function puts(s:String):void
        {
            if (output_text) {
                output_text.appendText(s + "\n");
                output_text.scrollV = output_text.maxScrollV;
            }
        }

        public function swfcat()
        {
            // Absolute positioning.
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            badge = new Badge();

            proxy_pairs = [];

            if (RATE_LIMIT)
                rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
            else
                rate_limit = new RateUnlimit();

            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            debug = this.loaderInfo.parameters["debug"];

            if (debug || this.loaderInfo.parameters["client"]) {
                output_text = new TextField();
                output_text.width = stage.stageWidth;
                output_text.height = stage.stageHeight;
                output_text.background = true;
                output_text.backgroundColor = 0x001f0f;
                output_text.textColor = 0x44cc44;
                addChild(output_text);
            } else {
                addChild(badge);
            }

            puts("Parameters loaded.");

            fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
            if (!fac_addr) {
                puts("Error: Facilitator spec must be in the form \"host:port\".");
                return;
            }

            local_addr = get_param_addr("local", DEFAULT_LOCAL_TOR_CLIENT_ADDR);
            if (!local_addr) {
                puts("Error: Local spec must be in the form \"host:port\".");
                return;
            }

            if (this.loaderInfo.parameters["client"])
                client_main();
            else
                proxy_main();
        }

        /* Get an address structure from the given movie parameter, or the given
           default. Returns null on error. */
        private function get_param_addr(param:String, default_addr:Object):Object
        {
            var spec:String;

            spec = this.loaderInfo.parameters[param];
            if (spec)
                return parse_addr_spec(spec);
            else
                return default_addr;
        }

        /* The main logic begins here, after start-up issues are taken care of. */
        private function proxy_main():void
        {
            var fac_url:String;
            var loader:URLLoader;

            if (proxy_pairs.length >= MAX_NUM_PROXY_PAIRS) {
                setTimeout(proxy_main, FACILITATOR_POLL_INTERVAL);
                return;
            }

            loader = new URLLoader();
            /* Get the x-www-form-urlencoded values. */
            loader.dataFormat = URLLoaderDataFormat.VARIABLES;
            loader.addEventListener(Event.COMPLETE, fac_complete);
            loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            fac_url = "http://" + encodeURIComponent(fac_addr.host)
                + ":" + encodeURIComponent(fac_addr.port) + "/";
            puts("Facilitator: connecting to " + fac_url + ".");
            loader.load(new URLRequest(fac_url));
        }

        private function fac_complete(e:Event):void
        {
            var loader:URLLoader;
            var client_spec:String;
            var relay_spec:String;
            var proxy_pair:Object;

            setTimeout(proxy_main, FACILITATOR_POLL_INTERVAL);

            loader = e.target as URLLoader;
            client_spec = loader.data.client;
            if (client_spec == "") {
                puts("No clients.");
                return;
            } else if (!client_spec) {
                puts("Error: missing \"client\" in response.");
                return;
            }
            relay_spec = loader.data.relay;
            if (!relay_spec) {
                puts("Error: missing \"relay\" in response.");
                return;
            }
            puts("Facilitator: got client:\"" + client_spec + "\" "
                + "relay:\"" + relay_spec + "\".");

            try {
                proxy_pair = make_proxy_pair(client_spec, relay_spec);
            } catch (e:ArgumentError) {
                puts("Error: " + e);
                return;
            }
            proxy_pairs.push(proxy_pair);
            proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
                proxy_pair.log("Complete.");
                /* Delete from the list of active proxy pairs. */
                proxy_pairs.splice(proxy_pairs.indexOf(proxy_pair), 1);
                badge.proxy_end();
            });
            proxy_pair.connect();

            badge.proxy_begin();
        }

        private function client_main():void
        {
            var rs:RTMFPSocket;

            puts("Making RTMFP socket.");
            rs = new RTMFPSocket(RTMFP_URL);
            rs.addEventListener(Event.COMPLETE, function (e:Event):void {
                puts("Got RTMFP id " + rs.id);
                register(rs);
            });
            rs.addEventListener(RTMFPSocket.ACCEPT_EVENT, client_accept);

            rs.listen();
        }

        private function client_accept(e:Event):void {
            var rs:RTMFPSocket;
            var s_t:Socket;
            var proxy_pair:ProxyPair;

            rs = e.target as RTMFPSocket;
            s_t = new Socket();

            puts("Got RTMFP connection from " + rs.peer_id);

            proxy_pair = new ProxyPair(this, rs, function ():void {
                /* Do nothing; already connected. */
            }, s_t, function ():void {
                s_t.connect(local_addr.host, local_addr.port);
            });
            proxy_pair.connect();
        }

        private function register(rs:RTMFPSocket):void {
            var fac_url:String;
            var loader:URLLoader;
            var request:URLRequest;

            loader = new URLLoader();
            loader.addEventListener(Event.COMPLETE, function (e:Event):void {
                puts("Facilitator: registered.");
            });
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
                rs.close();
            });
            loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
                rs.close();
            });

            fac_url = "http://" + encodeURIComponent(fac_addr.host)
                + ":" + encodeURIComponent(fac_addr.port) + "/";
            request = new URLRequest(fac_url);
            request.method = URLRequestMethod.POST;
            request.data = new URLVariables();
            request.data["client"] = rs.id;

            puts("Facilitator: connecting to " + fac_url + ".");
            loader.load(request);
        }

        private function make_proxy_pair(client_spec:String, relay_spec:String):ProxyPair
        {
            var proxy_pair:ProxyPair;
            var addr_c:Object;
            var addr_r:Object;
            var s_c:*;
            var s_r:Socket;

            addr_r = swfcat.parse_addr_spec(relay_spec);
            if (!addr_r)
                throw new ArgumentError("Relay spec must be in the form \"host:port\".");

            addr_c = swfcat.parse_addr_spec(client_spec);
            if (addr_c) {
                s_c = new Socket();
                s_r = new Socket();
                proxy_pair = new ProxyPair(this, s_c, function ():void {
                    s_c.connect(addr_c.host, addr_c.port);
                }, s_r, function ():void {
                    s_r.connect(addr_r.host, addr_r.port);
                });
                proxy_pair.set_name("<" + addr_c.host + ":" + addr_c.port + ","
                    + addr_r.host + ":" + addr_r.port + ">");
                return proxy_pair;
            }

            if (client_spec.match(/^[0-9A-Fa-f]{64}$/)) {
                s_c = new RTMFPSocket(RTMFP_URL);
                s_r = new Socket();
                proxy_pair = new ProxyPair(this, s_c, function ():void {
                    s_c.connect(client_spec);
                }, s_r, function ():void {
                    s_r.connect(addr_r.host, addr_r.port);
                });
                proxy_pair.set_name("<" + client_spec.substr(0, 4) + "...,"
                    + addr_r.host + ":" + addr_r.port + ">");
                return proxy_pair;
            }

            throw new ArgumentError("Can't parse client spec \"" + client_spec + "\".");
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.text.TextFormat;
import flash.text.TextField;
import flash.utils.getTimer;

class Badge extends flash.display.Sprite
{
    /* Number of proxy pairs currently connected. */
    private var num_proxy_pairs:int = 0;
    /* Number of proxy pairs ever connected. */
    private var total_proxy_pairs:int = 0;

    [Embed(source="badge.png")]
    private var BadgeImage:Class;
    private var tot_client_count_tf:TextField;
    private var tot_client_count_fmt:TextFormat;
    private var cur_client_count_tf:TextField;
    private var cur_client_count_fmt:TextFormat;

    public function Badge()
    {
        /* Setup client counter for badge. */
        tot_client_count_fmt = new TextFormat();
        tot_client_count_fmt.color = 0xFFFFFF;
        tot_client_count_fmt.align = "center";
        tot_client_count_fmt.font = "courier-new";
        tot_client_count_fmt.bold = true;
        tot_client_count_fmt.size = 10;
        tot_client_count_tf = new TextField();
        tot_client_count_tf.width = 20;
        tot_client_count_tf.height = 17;
        tot_client_count_tf.background = false;
        tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
        tot_client_count_tf.x=47;
        tot_client_count_tf.y=0;

        cur_client_count_fmt = new TextFormat();
        cur_client_count_fmt.color = 0xFFFFFF;
        cur_client_count_fmt.align = "center";
        cur_client_count_fmt.font = "courier-new";
        cur_client_count_fmt.bold = true;
        cur_client_count_fmt.size = 10;
        cur_client_count_tf = new TextField();
        cur_client_count_tf.width = 20;
        cur_client_count_tf.height = 17;
        cur_client_count_tf.background = false;
        cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
        cur_client_count_tf.x=47;
        cur_client_count_tf.y=6;

        addChild(new BadgeImage());
        addChild(tot_client_count_tf);
        addChild(cur_client_count_tf);

        /* Update the client counter on badge. */
        update_client_count();
    }

    public function proxy_begin():void
    {
        num_proxy_pairs++;
        total_proxy_pairs++;
        update_client_count();
    }

    public function proxy_end():void
    {
        num_proxy_pairs--;
        update_client_count();
    }

    private function update_client_count():void
    {
        /* Update total client count. */
        if (String(total_proxy_pairs).length == 1)
            tot_client_count_tf.text = "0" + String(total_proxy_pairs);
        else
            tot_client_count_tf.text = String(total_proxy_pairs);

        /* Update current client count. */
        cur_client_count_tf.text = "";
        for(var i:Number = 0; i < num_proxy_pairs; i++)
            cur_client_count_tf.appendText(".");
    }
}

class RateLimit
{
    public function RateLimit()
    {
    }

    public function update(n:Number):Boolean
    {
        return true;
    }

    public function when():Number
    {
        return 0.0;
    }

    public function is_limited():Boolean
    {
        return false;
    }
}

class RateUnlimit extends RateLimit
{
    public function RateUnlimit()
    {
    }

    public override function update(n:Number):Boolean
    {
        return true;
    }

    public override function when():Number
    {
        return 0.0;
    }

    public override function is_limited():Boolean
    {
        return false;
    }
}

class BucketRateLimit extends RateLimit
{
    private var amount:Number;
    private var capacity:Number;
    private var time:Number;
    private var last_update:uint;

    public function BucketRateLimit(capacity:Number, time:Number)
    {
        this.amount = 0.0;
        /* capacity / time is the rate we are aiming for. */
        this.capacity = capacity;
        this.time = time;
        this.last_update = getTimer();
    }

    private function age():void
    {
        var now:uint;
        var delta:Number;

        now = getTimer();
        delta = (now - last_update) / 1000.0;
        last_update = now;

        amount -= delta * capacity / time;
        if (amount < 0.0)
            amount = 0.0;
    }

    public override function update(n:Number):Boolean
    {
        age();
        amount += n;

        return amount <= capacity;
    }

    public override function when():Number
    {
        age();
        return (amount - capacity) / (capacity / time);
    }

    public override function is_limited():Boolean
    {
        age();
        return amount > capacity;
    }
}

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.external.ExternalInterface;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.net.Socket;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import flash.net.URLRequestMethod;
    import flash.net.URLVariables;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.setTimeout;

    public class swfcat extends Sprite
    {
        private const RTMFP_URL:String = "rtmfp://tor-facilitator.bamsoftware.com";

        private const DEFAULT_FACILITATOR_ADDR:Object = {
            host: "tor-facilitator.bamsoftware.com",
            port: 9002
        };

        /* Local Tor client to use in case of RTMFP connection. */
        private const DEFAULT_LOCAL_TOR_CLIENT_ADDR:Object = {
            host: "127.0.0.1",
            port: 9002
        };

        private const MAX_NUM_PROXY_PAIRS:uint = 100;

        // Milliseconds.
        private const FACILITATOR_POLL_INTERVAL:int = 10000;

        // Bytes per second. Set to undefined to disable limit.
        public static const RATE_LIMIT:Number = undefined;
        // Seconds.
        private static const RATE_LIMIT_HISTORY:Number = 5.0;

        /* TextField for debug output. */
        private var output_text:TextField;

        /* UI shown when debug is off. */
        private var badge:Badge;

        /* Proxy pairs currently connected (up to MAX_NUM_PROXY_PAIRS). */
        private var proxy_pairs:Array;

        private var fac_addr:Object;

        private var local_addr:Object;

        public var debug:Boolean;

        public var rate_limit:RateLimit;

        public function puts(s:String):void
        {
            if (output_text) {
                output_text.appendText(s + "\n");
                output_text.scrollV = output_text.maxScrollV;
            }
        }

        public function swfcat()
        {
            // Absolute positioning.
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            badge = new Badge();

            proxy_pairs = [];

            if (RATE_LIMIT)
                rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
            else
                rate_limit = new RateUnlimit();

            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            debug = this.loaderInfo.parameters["debug"];

            if (debug || this.loaderInfo.parameters["client"]) {
                output_text = new TextField();
                output_text.width = stage.stageWidth;
                output_text.height = stage.stageHeight;
                output_text.background = true;
                output_text.backgroundColor = 0x001f0f;
                output_text.textColor = 0x44cc44;
                addChild(output_text);
            } else {
                addChild(badge);
            }

            puts("Parameters loaded.");

            fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
            if (!fac_addr) {
                puts("Error: Facilitator spec must be in the form \"host:port\".");
                return;
            }

            local_addr = get_param_addr("local", DEFAULT_LOCAL_TOR_CLIENT_ADDR);
            if (!local_addr) {
                puts("Error: Local spec must be in the form \"host:port\".");
                return;
            }

            if (this.loaderInfo.parameters["client"])
                client_main();
            else
                proxy_main();
        }

        /* Get an address structure from the given movie parameter, or the given
           default. Returns null on error. */
        private function get_param_addr(param:String, default_addr:Object):Object
        {
            var spec:String;

            spec = this.loaderInfo.parameters[param];
            if (spec)
                return parse_addr_spec(spec);
            else
                return default_addr;
        }

        /* The main logic begins here, after start-up issues are taken care of. */
        private function proxy_main():void
        {
            var fac_url:String;
            var loader:URLLoader;

            if (proxy_pairs.length >= MAX_NUM_PROXY_PAIRS) {
                setTimeout(proxy_main, FACILITATOR_POLL_INTERVAL);
                return;
            }

            loader = new URLLoader();
            /* Get the x-www-form-urlencoded values. */
            loader.dataFormat = URLLoaderDataFormat.VARIABLES;
            loader.addEventListener(Event.COMPLETE, fac_complete);
            loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            fac_url = "http://" + encodeURIComponent(fac_addr.host)
                + ":" + encodeURIComponent(fac_addr.port) + "/";
            puts("Facilitator: connecting to " + fac_url + ".");
            loader.load(new URLRequest(fac_url));
        }

        private function fac_complete(e:Event):void
        {
            var loader:URLLoader;
            var client_spec:String;
            var relay_spec:String;
            var proxy_pair:Object;

            setTimeout(proxy_main, FACILITATOR_POLL_INTERVAL);

            loader = e.target as URLLoader;
            client_spec = loader.data.client;
            if (client_spec == "") {
                puts("No clients.");
                return;
            } else if (!client_spec) {
                puts("Error: missing \"client\" in response.");
                return;
            }
            relay_spec = loader.data.relay;
            if (!relay_spec) {
                puts("Error: missing \"relay\" in response.");
                return;
            }
            puts("Facilitator: got client:\"" + client_spec + "\" "
                + "relay:\"" + relay_spec + "\".");

            try {
                proxy_pair = make_proxy_pair(client_spec, relay_spec);
            } catch (e:ArgumentError) {
                puts("Error: " + e);
                return;
            }
            proxy_pairs.push(proxy_pair);
            proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
                proxy_pair.log("Complete.");
                /* Delete from the list of active proxy pairs. */
                proxy_pairs.splice(proxy_pairs.indexOf(proxy_pair), 1);
                badge.proxy_end();
            });
            proxy_pair.connect();

            badge.proxy_begin();
        }

        private function client_main():void
        {
            var rs:RTMFPSocket;

            puts("Making RTMFP socket.");
            rs = new RTMFPSocket(RTMFP_URL);
            rs.addEventListener(Event.COMPLETE, function (e:Event):void {
                puts("Got RTMFP id " + rs.id);
                register(rs);
            });
            rs.addEventListener(RTMFPSocket.ACCEPT_EVENT, client_accept);

            rs.listen();
        }

        private function client_accept(e:Event):void {
            var rs:RTMFPSocket;
            var s_t:Socket;
            var proxy_pair:ProxyPair;

            rs = e.target as RTMFPSocket;
            s_t = new Socket();

            puts("Got RTMFP connection from " + rs.peer_id);

            proxy_pair = new ProxyPair(this, rs, function ():void {
                /* Do nothing; already connected. */
            }, s_t, function ():void {
                s_t.connect(local_addr.host, local_addr.port);
            });
            proxy_pair.connect();
        }

        private function register(rs:RTMFPSocket):void {
            var fac_url:String;
            var loader:URLLoader;
            var request:URLRequest;

            loader = new URLLoader();
            loader.addEventListener(Event.COMPLETE, function (e:Event):void {
                puts("Facilitator: registered.");
            });
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
                rs.close();
            });
            loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
                rs.close();
            });

            fac_url = "http://" + encodeURIComponent(fac_addr.host)
                + ":" + encodeURIComponent(fac_addr.port) + "/";
            request = new URLRequest(fac_url);
            request.method = URLRequestMethod.POST;
            request.data = new URLVariables();
            request.data["client"] = rs.id;

            puts("Facilitator: connecting to " + fac_url + ".");
            loader.load(request);
        }

        private function make_proxy_pair(client_spec:String, relay_spec:String):ProxyPair
        {
            var proxy_pair:ProxyPair;
            var addr_c:Object;
            var addr_r:Object;
            var s_c:*;
            var s_r:Socket;

            addr_r = swfcat.parse_addr_spec(relay_spec);
            if (!addr_r)
                throw new ArgumentError("Relay spec must be in the form \"host:port\".");

            addr_c = swfcat.parse_addr_spec(client_spec);
            if (addr_c) {
                s_c = new Socket();
                s_r = new Socket();
                proxy_pair = new ProxyPair(this, s_c, function ():void {
                    s_c.connect(addr_c.host, addr_c.port);
                }, s_r, function ():void {
                    s_r.connect(addr_r.host, addr_r.port);
                });
                proxy_pair.set_name("<" + addr_c.host + ":" + addr_c.port + ","
                    + addr_r.host + ":" + addr_r.port + ">");
                return proxy_pair;
            }

            if (client_spec.match(/^[0-9A-Fa-f]{64}$/)) {
                s_c = new RTMFPSocket(RTMFP_URL);
                s_r = new Socket();
                proxy_pair = new ProxyPair(this, s_c, function ():void {
                    s_c.connect(client_spec);
                }, s_r, function ():void {
                    s_r.connect(addr_r.host, addr_r.port);
                });
                proxy_pair.set_name("<" + client_spec.substr(0, 4) + "...,"
                    + addr_r.host + ":" + addr_r.port + ">");
                return proxy_pair;
            }

            throw new ArgumentError("Can't parse client spec \"" + client_spec + "\".");
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.events.MouseEvent;
import flash.net.navigateToURL;
import flash.net.URLRequest;
import flash.text.TextFormat;
import flash.text.TextField;
import flash.utils.getTimer;

class Badge extends flash.display.Sprite
{
    private const FLASHPROXY_INFO_URL:String = "https://crypto.stanford.edu/flashproxy/";

    /* Number of proxy pairs currently connected. */
    private var num_proxy_pairs:int = 0;
    /* Number of proxy pairs ever connected. */
    private var total_proxy_pairs:int = 0;

    [Embed(source="badge.png")]
    private var BadgeImage:Class;
    private var tot_client_count_tf:TextField;
    private var tot_client_count_fmt:TextFormat;
    private var cur_client_count_tf:TextField;
    private var cur_client_count_fmt:TextFormat;

    public function Badge()
    {
        /* Setup client counter for badge. */
        tot_client_count_fmt = new TextFormat();
        tot_client_count_fmt.color = 0xFFFFFF;
        tot_client_count_fmt.align = "center";
        tot_client_count_fmt.font = "courier-new";
        tot_client_count_fmt.bold = true;
        tot_client_count_fmt.size = 10;
        tot_client_count_tf = new TextField();
        tot_client_count_tf.width = 20;
        tot_client_count_tf.height = 17;
        tot_client_count_tf.background = false;
        tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
        tot_client_count_tf.x=47;
        tot_client_count_tf.y=0;

        cur_client_count_fmt = new TextFormat();
        cur_client_count_fmt.color = 0xFFFFFF;
        cur_client_count_fmt.align = "center";
        cur_client_count_fmt.font = "courier-new";
        cur_client_count_fmt.bold = true;
        cur_client_count_fmt.size = 10;
        cur_client_count_tf = new TextField();
        cur_client_count_tf.width = 20;
        cur_client_count_tf.height = 17;
        cur_client_count_tf.background = false;
        cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
        cur_client_count_tf.x=47;
        cur_client_count_tf.y=6;

        addChild(new BadgeImage());
        addChild(tot_client_count_tf);
        addChild(cur_client_count_tf);

        /* Update the client counter on badge. */
        update_client_count();

        addEventListener(MouseEvent.CLICK, mouse_clicked);
    }

    public function proxy_begin():void
    {
        num_proxy_pairs++;
        total_proxy_pairs++;
        update_client_count();
    }

    public function proxy_end():void
    {
        num_proxy_pairs--;
        update_client_count();
    }

    private function update_client_count():void
    {
        /* Update total client count. */
        if (String(total_proxy_pairs).length == 1)
            tot_client_count_tf.text = "0" + String(total_proxy_pairs);
        else
            tot_client_count_tf.text = String(total_proxy_pairs);

        /* Update current client count. */
        cur_client_count_tf.text = "";
        for(var i:Number = 0; i < num_proxy_pairs; i++)
            cur_client_count_tf.appendText(".");
    }

    /* Show a web page with detailed information when the badge is clicked. */
    private function mouse_clicked(e:MouseEvent):void
    {
        try {
            navigateToURL(new URLRequest(FLASHPROXY_INFO_URL));
        } catch (err:Error) {
        }
    }
}

class RateLimit
{
    public function RateLimit()
    {
    }

    public function update(n:Number):Boolean
    {
        return true;
    }

    public function when():Number
    {
        return 0.0;
    }

    public function is_limited():Boolean
    {
        return false;
    }
}

class RateUnlimit extends RateLimit
{
    public function RateUnlimit()
    {
    }

    public override function update(n:Number):Boolean
    {
        return true;
    }

    public override function when():Number
    {
        return 0.0;
    }

    public override function is_limited():Boolean
    {
        return false;
    }
}

class BucketRateLimit extends RateLimit
{
    private var amount:Number;
    private var capacity:Number;
    private var time:Number;
    private var last_update:uint;

    public function BucketRateLimit(capacity:Number, time:Number)
    {
        this.amount = 0.0;
        /* capacity / time is the rate we are aiming for. */
        this.capacity = capacity;
        this.time = time;
        this.last_update = getTimer();
    }

    private function age():void
    {
        var now:uint;
        var delta:Number;

        now = getTimer();
        delta = (now - last_update) / 1000.0;
        last_update = now;

        amount -= delta * capacity / time;
        if (amount < 0.0)
            amount = 0.0;
    }

    public override function update(n:Number):Boolean
    {
        age();
        amount += n;

        return amount <= capacity;
    }

    public override function when():Number
    {
        age();
        return (amount - capacity) / (capacity / time);
    }

    public override function is_limited():Boolean
    {
        age();
        return amount > capacity;
    }
}

Make the badge clickable.

Make the badge clickable.


package aerys.minko.scene.node.light
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.material.phong.PhongProperties;
	import aerys.minko.render.resource.texture.CubeTextureResource;
	import aerys.minko.render.resource.texture.ITextureResource;
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.scene.controller.light.PointLightController;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.scene.node.Scene;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.enum.ShadowMappingType;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Vector4;

	use namespace minko_scene;

	/**
	 *
	 * @author Romain Gilliotte
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class PointLight extends AbstractLight
	{
		public static const LIGHT_TYPE : uint = 2;

		private static const TMP_VECTOR		: Vector4 = new Vector4();

		private var _shadowMapSize	: uint;

		public function get diffuse() : Number
		{
			return lightData.getLightProperty('diffuse') as Number;
		}
		public function set diffuse(v : Number)	: void
		{
			lightData.setLightProperty('diffuse', v);

			if (lightData.getLightProperty('diffuseEnabled') != (v != 0))
				lightData.setLightProperty('diffuseEnabled', v != 0);
		}

		public function get specular() : Number
		{
			return lightData.getLightProperty('specular') as Number;
		}
		public function set specular(v : Number) : void
		{
			lightData.setLightProperty('specular', v);

			if (lightData.getLightProperty('specularEnabled') != (v != 0))
				lightData.setLightProperty('specularEnabled', v != 0);
		}

		public function get shininess() : Number
		{
			return lightData.getLightProperty('shininess') as Number;
		}
		public function set shininess(v : Number) : void
		{
			lightData.setLightProperty('shininess', v);
		}

		public function get attenuationDistance() : Number
		{
			return lightData.getLightProperty('attenuationDistance') as Number;
		}
		public function set attenuationDistance(v : Number) : void
		{
			lightData.setLightProperty('attenuationDistance', v);

			if (lightData.getLightProperty('attenuationEnabled') != (v != 0))
				lightData.setLightProperty('attenuationEnabled', v != 0);
		}

		public function get shadowMapSize() : uint
		{
			return lightData.getLightProperty('shadowMapSize');
		}
		public function set shadowMapSize(v : uint) : void
		{
			lightData.setLightProperty('shadowMapSize', v);
		}

		public function get shadowZNear() : Number
		{
			return lightData.getLightProperty('shadowZNear');
		}
		public function set shadowZNear(v : Number) : void
		{
			lightData.setLightProperty('shadowZNear', v);
		}

		public function get shadowZFar() : Number
		{
			return lightData.getLightProperty('shadowZFar');
		}
		public function set shadowZFar(v : Number) : void
		{
			lightData.setLightProperty('shadowZFar', v);
		}

		public function get shadowCastingType() : uint
		{
			return lightData.getProperty('shadowCastingType');
		}
		public function set shadowCastingType(value : uint) : void
		{
			lightData.setLightProperty('shadowCastingType', value);
		}

        public function get shadowBias() : Number
        {
            return lightData.getLightProperty(PhongProperties.SHADOW_BIAS);
        }
        public function set shadowBias(value : Number) : void
        {
            lightData.setLightProperty(PhongProperties.SHADOW_BIAS, value);
        }

		public function PointLight(color				: uint		= 0xFFFFFFFF,
								   diffuse				: Number	= .6,
								   specular				: Number	= .8,
								   shininess			: Number	= 64,
								   attenuationDistance	: Number	= 0,
								   emissionMask			: uint		= 0x1,
								   shadowCastingType	: uint		= 0,
								   shadowMapSize		: uint		= 512,
								   shadowZNear			: Number	= 0.1,
								   shadowZFar			: Number	= 1000.,
                                   shadowBias           : uint      = 1. / 256. / 256.)
		{
			_shadowMapSize	= shadowMapSize;

			super(
				new PointLightController(),
				LIGHT_TYPE,
				color,
				emissionMask
			);

			this.diffuse				= diffuse;
			this.specular				= specular;
			this.shininess				= shininess;
			this.attenuationDistance	= attenuationDistance;
			this.shadowCastingType		= shadowCastingType;
			this.shadowZNear			= shadowZNear;
			this.shadowZFar		    	= shadowZFar;
            this.shadowBias             = shadowBias;
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var light : PointLight = new PointLight(
				color,
				diffuse,
				specular,
				shininess,
				attenuationDistance,
				emissionMask,
				shadowCastingType,
				shadowMapSize,
				shadowZFar,
				shadowZNear,
				shadowBias
			);

			light.name = this.name;
			light.transform.copyFrom(this.transform);

			return light;
		}
	}
}

package aerys.minko.scene.node.light
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.material.phong.PhongProperties;
	import aerys.minko.render.resource.texture.CubeTextureResource;
	import aerys.minko.render.resource.texture.ITextureResource;
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.scene.controller.light.PointLightController;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.scene.node.Scene;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.enum.ShadowMappingType;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Vector4;

	use namespace minko_scene;

	/**
	 *
	 * @author Romain Gilliotte
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class PointLight extends AbstractLight
	{
		public static const LIGHT_TYPE : uint = 2;

		private static const TMP_VECTOR		: Vector4 = new Vector4();

		public function get diffuse() : Number
		{
			return lightData.getLightProperty('diffuse') as Number;
		}
		public function set diffuse(v : Number)	: void
		{
			lightData.setLightProperty('diffuse', v);

			if (lightData.getLightProperty('diffuseEnabled') != (v != 0))
				lightData.setLightProperty('diffuseEnabled', v != 0);
		}

		public function get specular() : Number
		{
			return lightData.getLightProperty('specular') as Number;
		}
		public function set specular(v : Number) : void
		{
			lightData.setLightProperty('specular', v);

			if (lightData.getLightProperty('specularEnabled') != (v != 0))
				lightData.setLightProperty('specularEnabled', v != 0);
		}

		public function get shininess() : Number
		{
			return lightData.getLightProperty('shininess') as Number;
		}
		public function set shininess(v : Number) : void
		{
			lightData.setLightProperty('shininess', v);
		}

		public function get attenuationDistance() : Number
		{
			return lightData.getLightProperty('attenuationDistance') as Number;
		}
		public function set attenuationDistance(v : Number) : void
		{
			lightData.setLightProperty('attenuationDistance', v);

			if (lightData.getLightProperty('attenuationEnabled') != (v != 0))
				lightData.setLightProperty('attenuationEnabled', v != 0);
		}

		public function get shadowMapSize() : uint
		{
			return lightData.getLightProperty('shadowMapSize');
		}
		public function set shadowMapSize(v : uint) : void
		{
			lightData.setLightProperty('shadowMapSize', v);
		}

		public function get shadowZNear() : Number
		{
			return lightData.getLightProperty('shadowZNear');
		}
		public function set shadowZNear(v : Number) : void
		{
			lightData.setLightProperty('shadowZNear', v);
		}

		public function get shadowZFar() : Number
		{
			return lightData.getLightProperty('shadowZFar');
		}
		public function set shadowZFar(v : Number) : void
		{
			lightData.setLightProperty('shadowZFar', v);
		}

		public function get shadowCastingType() : uint
		{
			return lightData.getProperty('shadowCastingType');
		}
		public function set shadowCastingType(value : uint) : void
		{
			lightData.setLightProperty('shadowCastingType', value);
		}

        public function get shadowBias() : Number
        {
            return lightData.getLightProperty(PhongProperties.SHADOW_BIAS);
        }
        public function set shadowBias(value : Number) : void
        {
            lightData.setLightProperty(PhongProperties.SHADOW_BIAS, value);
        }

		public function PointLight(color				: uint		= 0xFFFFFFFF,
								   diffuse				: Number	= .6,
								   specular				: Number	= .8,
								   shininess			: Number	= 64,
								   attenuationDistance	: Number	= 0,
								   emissionMask			: uint		= 0x1,
								   shadowCastingType	: uint		= 0,
								   shadowMapSize		: uint		= 512,
								   shadowZNear			: Number	= 0.1,
								   shadowZFar			: Number	= 1000.,
                                   shadowBias           : uint      = 1. / 256. / 256.)
		{
			super(
				new PointLightController(),
				LIGHT_TYPE,
				color,
				emissionMask
			);

			this.diffuse				= diffuse;
			this.specular				= specular;
			this.shininess				= shininess;
			this.attenuationDistance	= attenuationDistance;
			this.shadowCastingType		= shadowCastingType;
            this.shadowMapSize          = shadowMapSize;
			this.shadowZNear			= shadowZNear;
			this.shadowZFar		    	= shadowZFar;
            this.shadowBias             = shadowBias;
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var light : PointLight = new PointLight(
				color,
				diffuse,
				specular,
				shininess,
				attenuationDistance,
				emissionMask,
				shadowCastingType,
				shadowMapSize,
				shadowZFar,
				shadowZNear,
				shadowBias
			);

			light.name = this.name;
			light.transform.copyFrom(this.transform);

			return light;
		}
	}
}

fix shadowMapSize init in PointLight constructor


// makeswf -v 7 -s 200x150 -r 1 -o movie23.swf movie23.as

trace ("Hello World!");

loadMovie ("fscommand:quit", "");

// makeswf -v 7 -s 200x150 -r 1 -o hello-world.swf hello-world.as

trace ("Hello World!");

loadMovie ("fscommand:quit", "");

fix comment

fix comment