/*
#
# Copyright (c) 2005-2009 rPath, Inc.
#
# All rights reserved
#
*/

/*
#
# Copyright (c) 2009 rPath, Inc.
#
# This program is distributed under the terms of the MIT License as found
# in a file called LICENSE. If it is not present, the license
# is always available at http://www.opensource.org/licenses/mit-license.php.
#
# This program is distributed in the hope that it will be useful, but
# without any waranty; without even the implied warranty of merchantability
# or fitness for a particular purpose. See the MIT License for full details.
*/

package com.rpath.raf.util
{
    import flash.utils.Dictionary;

    import mx.collections.ArrayCollection;
    import spark.components.Application;
    import mx.core.FlexGlobals;
    import mx.core.IFlexDisplayObject;
    import mx.formatters.NumberBaseRoundType;
    import mx.formatters.NumberFormatter;
    import mx.managers.PopUpManager;
    import mx.managers.PopUpManagerChildList;

    public class UIHelper
    {

        public static function checkBooleans(...args):Boolean
        {
            for each (var b:* in args)
            {
                if (b is Array || b is ArrayCollection)
                {
                    for each (var c:* in b)
                    {
                        // allow for nested arrays
                        checkBooleans(c);
                    }
                }
                else
                {
                    if (!b)
                        return false;
                }
            }
            return true;
        }

        public static function checkOneOf(...args):Boolean
        {
            for each (var b:* in args)
            {
                if (b)
                    return true;
            }
            return false;
        }

        public static function formattedDate(unixTimestamp:Number):String
        {
            if (isNaN(unixTimestamp))
                return "";

            var date:Date = new Date(unixTimestamp * 1000);
            /*
             * Note that we add 1 to month b/c January is 0 in Flex
             */
            return padLeft(date.getMonth() +1) + "/" + padLeft(date.getDate()) +
                "/" + padLeft(date.getFullYear()) + " " + padLeft(date.getHours()) +
                ":" + padLeft(date.getMinutes()) + ":" + padLeft(date.getSeconds());
        }

        private static function padLeft(number:Number):String
        {
            var strNum:String = number.toString();
            if (number.toString().length == 1)
                strNum = "0" + strNum;

            return strNum;
        }

        /**
         * Replace \r\n with \n, replace \r with \n
         */
        public static function processCarriageReturns(value:String):String
        {
            if (!value)
                return value;

            var cr:String = String.fromCharCode(13);
            var crRegex:RegExp = new RegExp(cr, "gm");

            var crnl:String = String.fromCharCode(13, 10);
            var crnlRegex:RegExp = new RegExp(crnl, "gm");

            // process CRNL first
            value = value.replace(crnlRegex, '\n');

            // process CR
            value = value.replace(crRegex, '\n');

            return value;
        }

        private static var popupModelMap:Dictionary = new Dictionary(true);
        private static var popupOwnerMap:Dictionary = new Dictionary(true);

        public static function createPopup(clazz:Class):*
        {
            var popup:Object = PopUpManager.createPopUp(FlexGlobals.topLevelApplication as Application,
                clazz, false, PopUpManagerChildList.APPLICATION) as clazz;
            return popup as IFlexDisplayObject;
        }

        public static function createSingletonPopupForModel(clazz:Class, model:Object, owner:Object=null):*
        {
            var popup:Object;

            popup = popupForModel(model);
            if (popup == null)
            {
                popup = PopUpManager.createPopUp(FlexGlobals.topLevelApplication as Application,
                    clazz, false, PopUpManagerChildList.APPLICATION) as clazz;

                popupModelMap[model] = popup;

                if (owner)
                {
                    popupOwnerMap[popup] = owner;
                }
            }

            return popup as IFlexDisplayObject;
        }

        public static function popupForModel(model:Object):*
        {
            return popupModelMap[model];
        }

        public static function removePopupForModel(model:Object):void
        {
            var popup:IFlexDisplayObject = popupModelMap[model];
            if (popup)
            {
                delete popupModelMap[model];
                delete popupOwnerMap[popup];
            }

        }

        public static function removePopupsForOwner(owner:Object):void
        {
            for (var popup:* in popupOwnerMap)
            {
                if (popupOwnerMap[popup] === owner)
                {
                    delete popupOwnerMap[popup];
                    // scan the model map too
                    for (var model:* in popupModelMap)
                    {
                        if (popupModelMap[model] === popup)
                        {
                            delete popupModelMap[model];
                        }
                    }
                }
            }
        }

        public static function popupsForOwner(owner:Object):Array
        {
            var result:Array = [];
            for (var popup:* in popupOwnerMap)
            {
                if (popupOwnerMap[popup] === owner)
                {
                    result.push(popup);
                }
            }

            return result;
        }

        public static function closePopupsForOwner(owner:Object):void
        {
            for each (var popup:* in UIHelper.popupsForOwner(owner))
            {
                PopUpManager.removePopUp(popup);
            }

            removePopupsForOwner(owner);
        }

        // make bytes human readable
        public static function humanReadableSize(bytes:int, precision:int=1):String
        {
            var s:String = bytes + ' bytes';

            var nf:NumberFormatter = new NumberFormatter();
            nf.precision = precision;
            nf.useThousandsSeparator = true;
            nf.useNegativeSign = true;
            nf.rounding = NumberBaseRoundType.NEAREST;

            if (bytes > 1073741824)
            {
                s = nf.format((bytes / 1073741824.0)) + ' GB' + ' (' + (s) + ')';
            }
            else if (bytes > 1048576)
            {
                s = nf.format((bytes / 1048576.0)) + ' MB' + ' (' + (s) + ')';
            }
            else if (bytes > 1024)
            {
                s = nf.format((bytes / 1024.0)) + ' KB' + ' (' + (s) + ')';
            }

            return s;
        }
    }
}

/*
#
# Copyright (c) 2005-2009 rPath, Inc.
#
# All rights reserved
#
*/

/*
#
# Copyright (c) 2009 rPath, Inc.
#
# This program is distributed under the terms of the MIT License as found
# in a file called LICENSE. If it is not present, the license
# is always available at http://www.opensource.org/licenses/mit-license.php.
#
# This program is distributed in the hope that it will be useful, but
# without any waranty; without even the implied warranty of merchantability
# or fitness for a particular purpose. See the MIT License for full details.
*/

package com.rpath.raf.util
{
    import flash.utils.Dictionary;

    import mx.collections.ArrayCollection;
    import spark.components.Application;
    import mx.core.FlexGlobals;
    import mx.core.IFlexDisplayObject;
    import mx.formatters.NumberBaseRoundType;
    import mx.formatters.NumberFormatter;
    import mx.managers.PopUpManager;
    import mx.managers.PopUpManagerChildList;

    public class UIHelper
    {

        public static function checkBooleans(...args):Boolean
        {
            for each (var b:* in args)
            {
                if (b is Array || b is ArrayCollection)
                {
                    for each (var c:* in b)
                    {
                        // allow for nested arrays
                        checkBooleans(c);
                    }
                }
                else
                {
                    if (!b)
                        return false;
                }
            }
            return true;
        }

        public static function checkOneOf(...args):Boolean
        {
            for each (var b:* in args)
            {
                if (b)
                    return true;
            }
            return false;
        }

        public static function formattedDate(unixTimestamp:Number):String
        {
            if (isNaN(unixTimestamp))
                return "";

            var date:Date = new Date(unixTimestamp * 1000);
            /*
             * Note that we add 1 to month b/c January is 0 in Flex
             */
            return padLeft(date.getMonth() +1) + "/" + padLeft(date.getDate()) +
                "/" + padLeft(date.getFullYear()) + " " + padLeft(date.getHours()) +
                ":" + padLeft(date.getMinutes()) + ":" + padLeft(date.getSeconds());
        }

        public static function padLeft(number:Number):String
        {
            var strNum:String = number.toString();
            if (number.toString().length == 1)
                strNum = "0" + strNum;

            return strNum;
        }

        /**
         * Replace \r\n with \n, replace \r with \n
         */
        public static function processCarriageReturns(value:String):String
        {
            if (!value)
                return value;

            var cr:String = String.fromCharCode(13);
            var crRegex:RegExp = new RegExp(cr, "gm");

            var crnl:String = String.fromCharCode(13, 10);
            var crnlRegex:RegExp = new RegExp(crnl, "gm");

            // process CRNL first
            value = value.replace(crnlRegex, '\n');

            // process CR
            value = value.replace(crRegex, '\n');

            return value;
        }

        private static var popupModelMap:Dictionary = new Dictionary(true);
        private static var popupOwnerMap:Dictionary = new Dictionary(true);

        public static function createPopup(clazz:Class):*
        {
            var popup:Object = PopUpManager.createPopUp(FlexGlobals.topLevelApplication as Application,
                clazz, false, PopUpManagerChildList.APPLICATION) as clazz;
            return popup as IFlexDisplayObject;
        }

        public static function createSingletonPopupForModel(clazz:Class, model:Object, owner:Object=null):*
        {
            var popup:Object;

            popup = popupForModel(model);
            if (popup == null)
            {
                popup = PopUpManager.createPopUp(FlexGlobals.topLevelApplication as Application,
                    clazz, false, PopUpManagerChildList.APPLICATION) as clazz;

                popupModelMap[model] = popup;

                if (owner)
                {
                    popupOwnerMap[popup] = owner;
                }
            }

            return popup as IFlexDisplayObject;
        }

        public static function popupForModel(model:Object):*
        {
            return popupModelMap[model];
        }

        public static function removePopupForModel(model:Object):void
        {
            var popup:IFlexDisplayObject = popupModelMap[model];
            if (popup)
            {
                delete popupModelMap[model];
                delete popupOwnerMap[popup];
            }

        }

        public static function removePopupsForOwner(owner:Object):void
        {
            for (var popup:* in popupOwnerMap)
            {
                if (popupOwnerMap[popup] === owner)
                {
                    delete popupOwnerMap[popup];
                    // scan the model map too
                    for (var model:* in popupModelMap)
                    {
                        if (popupModelMap[model] === popup)
                        {
                            delete popupModelMap[model];
                        }
                    }
                }
            }
        }

        public static function popupsForOwner(owner:Object):Array
        {
            var result:Array = [];
            for (var popup:* in popupOwnerMap)
            {
                if (popupOwnerMap[popup] === owner)
                {
                    result.push(popup);
                }
            }

            return result;
        }

        public static function closePopupsForOwner(owner:Object):void
        {
            for each (var popup:* in UIHelper.popupsForOwner(owner))
            {
                PopUpManager.removePopUp(popup);
            }

            removePopupsForOwner(owner);
        }

        // make bytes human readable
        public static function humanReadableSize(bytes:int, precision:int=1):String
        {
            var s:String = bytes + ' bytes';

            var nf:NumberFormatter = new NumberFormatter();
            nf.precision = precision;
            nf.useThousandsSeparator = true;
            nf.useNegativeSign = true;
            nf.rounding = NumberBaseRoundType.NEAREST;

            if (bytes > 1073741824)
            {
                s = nf.format((bytes / 1073741824.0)) + ' GB' + ' (' + (s) + ')';
            }
            else if (bytes > 1048576)
            {
                s = nf.format((bytes / 1048576.0)) + ' MB' + ' (' + (s) + ')';
            }
            else if (bytes > 1024)
            {
                s = nf.format((bytes / 1024.0)) + ' KB' + ' (' + (s) + ')';
            }

            return s;
        }
    }
}

make UIHelper.padLeft public

make UIHelper.padLeft public


package com.threerings.mx.controls {

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;

import flash.geom.Rectangle;

import mx.controls.Menu;
import mx.core.mx_internal;
import mx.events.MenuEvent;

import com.threerings.mx.events.CommandEvent;

/**
 * A pretty standard menu that can submit CommandEvents if menu items
 * have "command" and possibly "arg" properties.
 *
 * Example dataProvider array:
 * [ { label: "Go home", icon: homeIconClass,
 *     command: Controller.GO_HOME, arg: homeId },
 *   { type: "separator"},
 *   { label: "Other places", children: subMenuArray }
 * ];
 *
 * See "Defining menu structure and data" in the Flex manual for the
 * full list.
 */
public class CommandMenu extends Menu
{
    public function CommandMenu ()
    {
        super();

        addEventListener(MenuEvent.ITEM_CLICK, itemClicked);
    }

    /**
     * Factory method to create a command menu.
     *
     * @param parent The parent of this menu.
     * @param items an array of menu items.
     */
    public static function createMenu (
        parent :DisplayObjectContainer, items :Array) :CommandMenu
    {
        var menu :CommandMenu = new CommandMenu();
        menu.tabEnabled = false;
        menu.showRoot = true;
        Menu.popUpMenu(menu, parent, items);
        return menu;
    }

    /**
     * Actually pop up the menu. This can be used instead of show().
     */
    public function popUp (
        trigger :DisplayObject, popUpwards :Boolean = true) :void
    {
        var r :Rectangle = trigger.getBounds(trigger.stage);

        if (popUpwards) {
            show(r.x, 0);
            // then, reposition the y once we know our size
            y = r.y - getExplicitOrMeasuredHeight();

        } else {
            // simply position it below the trigger
            show(r.x, r.y + r.height);
        }
    }

    /**
     * Callback for MenuEvent.ITEM_CLICK.
     */
    protected function itemClicked (event :MenuEvent) :void
    {
        var cmd :String = getItemCommand(event.item);
        if (cmd != null) {
            event.stopImmediatePropagation();
            var arg :Object = getItemArgument(event.item);
            CommandEvent.dispatch(mx_internal::parentDisplayObject, cmd, arg);
        }
    }

    /**
     * Get the command for the specified item, if any.
     * Somewhat similar to bits in the DefaultDataDescriptor.
     */
    protected function getItemCommand (item :Object) :String
    {
        try {
            if (item is XML) {
                return String(item.@command);

            } else if (item is Object) {
                return String(item.command);
            }
        } catch (e :Error) {
            // fall through
        }

        return null;
    }

    /**
     * Get the command for the specified item, if any.
     * Somewhat similar to bits in the DefaultDataDescriptor.
     */
    protected function getItemArgument (item :Object) :Object
    {
        try {
            if (item is XML) {
                return item.@arg;

            } else if (item is Object) {
                return item.arg;
            }
        } catch (e :Error) {
            // fall through
        }

        return null;
    }
}
}

package com.threerings.mx.controls {

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;

import flash.geom.Rectangle;

import mx.controls.Menu;
import mx.core.mx_internal;
import mx.core.ScrollPolicy;
import mx.events.MenuEvent;

import com.threerings.mx.events.CommandEvent;

/**
 * A pretty standard menu that can submit CommandEvents if menu items
 * have "command" and possibly "arg" properties. Commands are submitted to
 * controllers for processing. Alternatively, you may specify
 * "callback" properties that specify a function closure to call, with the
 * "arg" property containing either a single arg or an array of args.
 *
 * Example dataProvider array:
 * [ { label: "Go home", icon: homeIconClass,
 *     command: Controller.GO_HOME, arg: homeId },
 *   { type: "separator"},
     { label: "Crazytown", callback: setCrazy, arg: [ true, false ] },
 *   { label: "Other places", children: subMenuArray }
 * ];
 *
 * See "Defining menu structure and data" in the Flex manual for the
 * full list.
 */
public class CommandMenu extends Menu
{
    public function CommandMenu ()
    {
        super();

        addEventListener(MenuEvent.ITEM_CLICK, itemClicked);
//        addEventListener(MenuEvent.MENU_SHOW, handleMenuShown);
    }

    /**
     * Factory method to create a command menu.
     *
     * @param parent The parent of this menu.
     * @param items an array of menu items.
     */
    public static function createMenu (
        parent :DisplayObjectContainer, items :Array) :CommandMenu
    {
        var menu :CommandMenu = new CommandMenu();
        menu.tabEnabled = false;
        menu.showRoot = true;
        Menu.popUpMenu(menu, parent, items);
        return menu;
    }

    /**
     * Actually pop up the menu. This can be used instead of show().
     */
    public function popUp (
        trigger :DisplayObject, popUpwards :Boolean = true) :void
    {
        var r :Rectangle = trigger.getBounds(trigger.stage);

        if (popUpwards) {
            show(r.x, 0);
            // then, reposition the y once we know our size
            y = r.y - getExplicitOrMeasuredHeight();

        } else {
            // simply position it below the trigger
            show(r.x, r.y + r.height);
        }
    }

    /**
     * Callback for MenuEvent.ITEM_CLICK.
     */
    protected function itemClicked (event :MenuEvent) :void
    {
        var arg :Object = getItemArgument(event.item);
        var cmd :String = getItemCommand(event.item);
        var fn :Function;
        if (cmd == null) {
            fn = getItemCallback(event.item);
        }
        if (cmd != null || fn != null) {
            event.stopImmediatePropagation();
            if (cmd != null) {
                CommandEvent.dispatch(mx_internal::parentDisplayObject, cmd, arg);

            } else {
                try {
                    var args :Array = (arg as Array);
                    if (args == null && arg != null) {
                        args = [ arg ];
                    }
                    fn.apply(null, args);

                } catch (err :Error) {
                    Log.getLog(this).warning("Unable to call menu callback: " +
                        event.item);
                }
            }
        }
    }

//    /**
//     * Callback for MenuEvent.MENU_SHOW.
//     */
//    protected function handleMenuShown (event :MenuEvent) :void
//    {
//        // just ensure that every menu can scroll
//        event.menu.verticalScrollPolicy = ScrollPolicy.ON;
//    }

    /**
     * Get the command for the specified item, if any.
     * Somewhat similar to bits in the DefaultDataDescriptor.
     */
    protected function getItemCommand (item :Object) :String
    {
        try {
            if (item is XML) {
                return (item.@command as String);

            } else if (item is Object) {
                return (item.command as String);
            }
        } catch (e :Error) {
            // fall through
        }

        return null;
    }

    /**
     * Get the callback function for the specified item, if any.
     */
    protected function getItemCallback (item :Object) :Function
    {
        try {
            if (item is XML) {
                return (item.@callback as Function);

            } else if (item is Object) {
                return (item.callback as Function);
            }
        } catch (e :Error) {
            // fall through
        }

        return null;
    }

    /**
     * Get the command for the specified item, if any.
     * Somewhat similar to bits in the DefaultDataDescriptor.
     */
    protected function getItemArgument (item :Object) :Object
    {
        try {
            if (item is XML) {
                return item.@arg;

            } else if (item is Object) {
                return item.arg;
            }
        } catch (e :Error) {
            // fall through
        }

        return null;
    }
}
}

Allow menu items to be configured with a callback function directly
(to which any args will be passed), instead of only dispatching
controller commands.

git-svn-id: a1a4b28b82a3276cc491891159dd9963a0a72fae@4465 542714f4-19e9-0310-aa3c-eee0fc999fb1


package org.jivesoftware.xiff.core
{
	import flash.events.ErrorEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.xml.XMLDocument;
	import flash.xml.XMLNode;

	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;

	import org.jivesoftware.xiff.auth.Anonymous;
	import org.jivesoftware.xiff.auth.External;
	import org.jivesoftware.xiff.auth.Plain;
	import org.jivesoftware.xiff.auth.SASLAuth;
	import org.jivesoftware.xiff.data.IQ;
	import org.jivesoftware.xiff.data.bind.BindExtension;
	import org.jivesoftware.xiff.data.session.SessionExtension;
	import org.jivesoftware.xiff.events.ConnectionSuccessEvent;
	import org.jivesoftware.xiff.events.IncomingDataEvent;
	import org.jivesoftware.xiff.events.LoginEvent;
	import org.jivesoftware.xiff.events.XIFFErrorEvent;
	import org.jivesoftware.xiff.util.Callback;

	public class XMPPBOSHConnection extends XMPPConnection
	{
		private static var saslMechanisms:Object = {
			"PLAIN":Plain,
			"ANONYMOUS":Anonymous,
            "EXTERNAL":External
		};

		private var maxConcurrentRequests:uint = 2;
		private var boshVersion:Number = 1.6;
		private var headers:Object = {
			"post": [],
			"get": ['Cache-Control', 'no-store', 'Cache-Control', 'no-cache', 'Pragma', 'no-cache']
		};
		private var requestCount:int = 0;
		private var failedRequests:Array = [];
		private var requestQueue:Array = [];
		private var responseQueue:Array = [];
		private const responseTimer:Timer = new Timer(0.0, 1);
		private var isDisconnecting:Boolean = false;
		private var boshPollingInterval:Number = 10000;
		private var sid:String;
		private var rid:Number;
		private var wait:int;
		private var inactivity:int;
		private var pollTimer:Timer;
		private var isCurrentlyPolling:Boolean = false;

		private var auth:SASLAuth;
		private var authHandler:Function;
		private var https:Boolean = false;
		private var _port:Number = -1;

		private var callbacks:Object = {};

		public static var logger:Object = null;

		public override function connect(streamType:String=null):Boolean
		{
			if(logger)
				logger.log("CONNECT()", "INFO");
			BindExtension.enable();
			active = false;
			loggedIn = false;
			var attrs:Object = {
	            xmlns: "http://jabber.org/protocol/httpbind",
	            hold: maxConcurrentRequests,
	            rid: nextRID,
	            secure: https,
	            wait: 10,
	            ver: boshVersion
	        }

	        var result:XMLNode = new XMLNode(1, "body");
	        result.attributes = attrs;
	        sendRequests(result);

	        return true;
		}

		public static function registerSASLMechanism(name:String, authClass:Class):void
		{
			saslMechanisms[name] = authClass;
		}

		public static function disableSASLMechanism(name:String):void
		{
			saslMechanisms[name] = null;
		}

		public function set secure(flag:Boolean):void
		{
			https = flag;
		}

		public override function set port(portnum:Number):void
		{
			_port = portnum;
		}

		public override function get port():Number
		{
			if(_port == -1)
				return https ? 8483 : 8080;
			return _port;
		}

		public function get httpServer():String
		{
			return (https ? "https" : "http") + "://" + server + ":" + port + "/http-bind/";
		}

		public override function disconnect():void
		{
			super.disconnect();
			pollTimer.stop();
			pollTimer = null;
		}

		public function processConnectionResponse(responseBody:XMLNode):void
		{
			var attributes:Object = responseBody.attributes;
			sid = attributes.sid;
	        boshPollingInterval = attributes.polling * 1000;
	        // if we have a polling interval of 1, we want to add an extra second for a little bit of
	        // padding.
	        if(boshPollingInterval <= 1000 && boshPollingInterval > 0)
	            boshPollingInterval += 1000;

	        wait = attributes.wait;
	        inactivity = attributes.inactivity;
	        var serverRequests:int = attributes.requests;
	        if (serverRequests)
	            maxConcurrentRequests = Math.min(serverRequests, maxConcurrentRequests);
	        active = true;
	        configureConnection(responseBody);
	        responseTimer.addEventListener(TimerEvent.TIMER_COMPLETE, processResponse);
	        pollTimer = new Timer(boshPollingInterval, 1);
	        pollTimer.addEventListener(TimerEvent.TIMER, pollServer);
		}

		private function processResponse(event:TimerEvent=null):void
		{
			// Read the data and send it to the appropriate parser
			var currentNode:XMLNode = responseQueue.shift();
			var nodeName:String = currentNode.nodeName.toLowerCase();

			switch( nodeName )
			{
				case "stream:features":
					//we already handled this in httpResponse()
					break;

				case "stream:error":
					handleStreamError( currentNode );
					break;

				case "iq":
					handleIQ( currentNode );
					break;

				case "message":
					handleMessage( currentNode );
					break;

				case "presence":
					handlePresence( currentNode );
					break;

				case "success":
					handleAuthentication( currentNode );
					break;
				default:
					dispatchError( "undefined-condition", "Unknown Error", "modify", 500 );
					break;
			}

			resetResponseProcessor();
		}

		private function resetResponseProcessor():void
		{
			if(responseQueue.length > 0)
			{
				responseTimer.reset();
				responseTimer.start();
			}
		}

		private function httpResponse(req:XMLNode, isPollResponse:Boolean, evt:ResultEvent):void
		{
			requestCount--;
			var rawXML:String = evt.result as String;

			if(logger)
	       		logger.log(rawXML, "INCOMING");

			var xmlData:XMLDocument = new XMLDocument();
			xmlData.ignoreWhite = this.ignoreWhite;
			xmlData.parseXML( rawXML );
			var bodyNode:XMLNode = xmlData.firstChild;

			var event:IncomingDataEvent = new IncomingDataEvent();
			event.data = xmlData;
			dispatchEvent( event );

			if(bodyNode.attributes["type"] == "terminal")
			{
				dispatchError( "BOSH Error", bodyNode.attributes["condition"], "", -1 );
				active = false;
			}

			for each(var childNode:XMLNode in bodyNode.childNodes)
			{
				if(childNode.nodeName == "stream:features")
				{
					_expireTagSearch = false;
					processConnectionResponse( bodyNode );
				}
				else
					responseQueue.push(childNode);
			}

			resetResponseProcessor();

			//if we just processed a poll response, we're no longer in mid-poll
			if(isPollResponse)
				isCurrentlyPolling = false;

			//if we have queued requests we want to send them before attempting to poll again
			//otherwise, if we don't already have a countdown going for the next poll, start one
	        if (!sendQueuedRequests() && (!pollTimer || !pollTimer.running))
	        	resetPollTimer();
		}

		private function httpError(req:XMLNode, isPollResponse:Boolean, evt:FaultEvent):void
		{
			active = false;
			dispatchError("Unknown HTTP Error", evt.fault.rootCause.text, "", -1);
		}

		protected override function sendXML(body:*):void
		{
			sendQueuedRequests(body);
		}

		private function sendQueuedRequests(body:*=null):Boolean
		{
			if(body)
				requestQueue.push(body);
			else if(requestQueue.length == 0)
				return false;

			return sendRequests();
		}

		//returns true if any requests were sent
		private function sendRequests(data:XMLNode = null, isPoll:Boolean=false):Boolean
		{
			if(requestCount >= maxConcurrentRequests)
				return false;

			if(isPoll)
				trace("Polling at: " + new Date().getSeconds());

			requestCount++;

			if(!data)
			{
				if(isPoll)
				{
					data = createRequest();
				}
				else
				{
					var temp:Array = [];
					for(var i:uint = 0; i < 10 && requestQueue.length > 0; i++)
					{
						temp.push(requestQueue.shift());
					}
					data = createRequest(temp);
				}
			}

			//build the http request
	        var request:HTTPService = new HTTPService();
	        request.method = "post";
	        request.headers = headers[request.method];
	        request.url = httpServer;
	        request.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
	        request.contentType = "text/xml";

	        var responseCallback:Callback = new Callback(this, httpResponse, data, isPoll);
	        var errorCallback:Callback = new Callback(this, httpError, data, isPoll);

	        request.addEventListener(ResultEvent.RESULT, responseCallback.call, false);
	        request.addEventListener(FaultEvent.FAULT, errorCallback.call, false);

	       	if(logger)
	       		logger.log(data, "OUTGOING");

			request.send(data);

			resetPollTimer();

			return true;
		}

    	private function resetPollTimer():void
    	{
    		if(!pollTimer)
    			return;
    		pollTimer.reset();
    		pollTimer.start();
    	}

    	private function pollServer(evt:TimerEvent):void
    	{
    		//We shouldn't poll if the connection is dead, if we had requests to send instead, or if there's already one in progress
    		if(!isActive() || sendQueuedRequests() || isCurrentlyPolling)
    			return;

    		//this should be safe since sendRequests checks to be sure it's not over the concurrent requests limit, and we just ensured that the queue is empty by calling sendQueuedRequests()
    		isCurrentlyPolling = sendRequests(null, true);
    	}

    	private function get nextRID():Number {
    		if(!rid)
    			rid = Math.floor(Math.random() * 1000000);
    		return ++rid;
    	}

    	private function createRequest(bodyContent:Array=null):XMLNode {
    		var attrs:Object = {
    			xmlns: "http://jabber.org/protocol/httpbind",
				rid: nextRID,
				sid: sid
    		}
    		var req:XMLNode = new XMLNode(1, "body");
    		if(bodyContent)
    			for each(var content:XMLNode in bodyContent)
    					req.appendChild(content);

    		req.attributes = attrs;

    		return req;
    	}

	    private function handleAuthentication(responseBody:XMLNode):void
	    {
	    //    if(!response || response.length == 0) {
	     //       return;
	     //   }
	        var status:Object = auth.handleResponse(0, responseBody);
	        if (status.authComplete) {
	            if (status.authSuccess) {
	                bindConnection();
	            }
	            else {
	                dispatchEvent(new ErrorEvent(ErrorEvent.ERROR));
	                disconnect();
	            }
	        }
	    }

	    private function configureConnection(responseBody:XMLNode):void
	    {
	    	var features:XMLNode = responseBody.firstChild;

	        var authentication:Object = {};
	        for each(var feature:XMLNode in features.childNodes)
			{
	            if (feature.nodeName == "mechanisms")
	                authentication.auth = configureAuthMechanisms(feature);
	            else if (feature.nodeName == "bind")
	                authentication.bind = true;
	            else if (feature.nodeName == "session")
	                authentication.session = true;
	        }

	        auth = authentication.auth;
	        dispatchEvent(new ConnectionSuccessEvent());
	        authHandler = handleAuthentication;
	        sendXML(auth.request);
	    }

	    private function configureAuthMechanisms(mechanisms:XMLNode):SASLAuth
	    {
	        var authMechanism:SASLAuth;
	        var authClass:Class;
	        for each(var mechanism:XMLNode in mechanisms.childNodes)
	        {
	        	authClass = saslMechanisms[mechanism.firstChild.nodeValue];
	   			if(authClass)
	   				break;
	        }

	        if (!authClass) {
	        	dispatchError("SASL missing", "The server is not configured to support any available SASL mechanisms", "SASL", -1);
	        	return null;
	        }

	   		return new authClass(this);
	    }

	    public function handleBindResponse(packet:IQ):void
	    {
	    	var bind:BindExtension = packet.getExtension("bind") as BindExtension;

            var jid:String = bind.getJID();

            var parts:Array = jid.split("/");
            myResource = parts[1];
            parts = parts[0].split("@");
            myUsername = parts[0];
            domain = parts[1];

            establishSession();
	    }

	    private function bindConnection():void
	    {
	    	var bindIQ:IQ = new IQ(null, "set");

			var bindExt:BindExtension = new BindExtension();
			if(resource)
	        	bindExt.resource = resource;

	        bindIQ.addExtension(bindExt);

			//this is laaaaaame, it should be a function
			bindIQ.callbackName = "handleBindResponse";
			bindIQ.callbackScope = this;

	        send(bindIQ);
	    }

	    public function handleSessionResponse(packet:IQ):void
	    {
	    	dispatchEvent(new LoginEvent());
	    }

	    private function establishSession():void
	    {
	        var sessionIQ:IQ = new IQ(null, "set");

	        sessionIQ.addExtension(new SessionExtension());

	        sessionIQ.callbackName = "handleSessionResponse";
	        sessionIQ.callbackScope = this;

	        send(sessionIQ);
	    }

		//do nothing, we use polling instead
		public override function sendKeepAlive():void {}
	}
}

package org.jivesoftware.xiff.core
{
	import flash.events.ErrorEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.xml.XMLDocument;
	import flash.xml.XMLNode;

	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;

	import org.jivesoftware.xiff.auth.Anonymous;
	import org.jivesoftware.xiff.auth.External;
	import org.jivesoftware.xiff.auth.Plain;
	import org.jivesoftware.xiff.auth.SASLAuth;
	import org.jivesoftware.xiff.data.IQ;
	import org.jivesoftware.xiff.data.bind.BindExtension;
	import org.jivesoftware.xiff.data.session.SessionExtension;
	import org.jivesoftware.xiff.events.ConnectionSuccessEvent;
	import org.jivesoftware.xiff.events.IncomingDataEvent;
	import org.jivesoftware.xiff.events.LoginEvent;
	import org.jivesoftware.xiff.events.XIFFErrorEvent;
	import org.jivesoftware.xiff.util.Callback;

	public class XMPPBOSHConnection extends XMPPConnection
	{
		private static var saslMechanisms:Object = {
			"PLAIN":Plain,
			"ANONYMOUS":Anonymous,
            "EXTERNAL":External
		};

		private var maxConcurrentRequests:uint = 2;
		private var boshVersion:Number = 1.6;
		private var headers:Object = {
			"post": [],
			"get": ['Cache-Control', 'no-store', 'Cache-Control', 'no-cache', 'Pragma', 'no-cache']
		};
		private var requestCount:int = 0;
		private var failedRequests:Array = [];
		private var requestQueue:Array = [];
		private var responseQueue:Array = [];
		private const responseTimer:Timer = new Timer(0.0, 1);
		private var isDisconnecting:Boolean = false;
		private var boshPollingInterval:Number = 10000;
		private var sid:String;
		private var rid:Number;
		private var wait:int;
		private var inactivity:int;
		private var pollTimer:Timer;
		private var isCurrentlyPolling:Boolean = false;

		private var auth:SASLAuth;
		private var authHandler:Function;
		private var https:Boolean = false;
		private var _port:Number = -1;

		private var callbacks:Object = {};

		public static var logger:Object = null;

		public override function connect(streamType:String=null):Boolean
		{
			if(logger)
				logger.log("CONNECT()", "INFO");
			BindExtension.enable();
			active = false;
			loggedIn = false;
			var attrs:Object = {
	            xmlns: "http://jabber.org/protocol/httpbind",
	            hold: maxConcurrentRequests,
	            rid: nextRID,
	            secure: https,
	            wait: 10,
	            ver: boshVersion
	        }

	        var result:XMLNode = new XMLNode(1, "body");
	        result.attributes = attrs;
	        sendRequests(result);

	        return true;
		}

		public static function registerSASLMechanism(name:String, authClass:Class):void
		{
			saslMechanisms[name] = authClass;
		}

		public static function disableSASLMechanism(name:String):void
		{
			saslMechanisms[name] = null;
		}

		public function set secure(flag:Boolean):void
		{
			https = flag;
		}

		public override function set port(portnum:Number):void
		{
			_port = portnum;
		}

		public override function get port():Number
		{
			if(_port == -1)
				return https ? 8483 : 8080;
			return _port;
		}

		public function get httpServer():String
		{
			return (https ? "https" : "http") + "://" + server + ":" + port + "/http-bind/";
		}

		public override function disconnect():void
		{
			super.disconnect();
			pollTimer.stop();
			pollTimer = null;
		}

		public function processConnectionResponse(responseBody:XMLNode):void
		{
			var attributes:Object = responseBody.attributes;
			sid = attributes.sid;
	        boshPollingInterval = attributes.polling * 1000;

	        wait = attributes.wait;
	        inactivity = attributes.inactivity * 1000;
	        if(inactivity - 2000 >= boshPollingInterval || (boshPollingInterval <= 1000 && boshPollingInterval > 0))
	        {
	        	boshPollingInterval += 1000;
	        }

	        var serverRequests:int = attributes.requests;
	        if (serverRequests)
	            maxConcurrentRequests = Math.min(serverRequests, maxConcurrentRequests);
	        active = true;
	        configureConnection(responseBody);
	        responseTimer.addEventListener(TimerEvent.TIMER_COMPLETE, processResponse);
	        pollTimer = new Timer(boshPollingInterval, 1);
	        pollTimer.addEventListener(TimerEvent.TIMER, pollServer);
		}

		private function processResponse(event:TimerEvent=null):void
		{
			// Read the data and send it to the appropriate parser
			var currentNode:XMLNode = responseQueue.shift();
			var nodeName:String = currentNode.nodeName.toLowerCase();

			switch( nodeName )
			{
				case "stream:features":
					//we already handled this in httpResponse()
					break;

				case "stream:error":
					handleStreamError( currentNode );
					break;

				case "iq":
					handleIQ( currentNode );
					break;

				case "message":
					handleMessage( currentNode );
					break;

				case "presence":
					handlePresence( currentNode );
					break;

				case "success":
					handleAuthentication( currentNode );
					break;
				default:
					dispatchError( "undefined-condition", "Unknown Error", "modify", 500 );
					break;
			}

			resetResponseProcessor();
		}

		private function resetResponseProcessor():void
		{
			if(responseQueue.length > 0)
			{
				responseTimer.reset();
				responseTimer.start();
			}
		}

		private function httpResponse(req:XMLNode, isPollResponse:Boolean, evt:ResultEvent):void
		{
			requestCount--;
			var rawXML:String = evt.result as String;

			if(logger)
	       		logger.log(rawXML, "INCOMING");

			var xmlData:XMLDocument = new XMLDocument();
			xmlData.ignoreWhite = this.ignoreWhite;
			xmlData.parseXML( rawXML );
			var bodyNode:XMLNode = xmlData.firstChild;

			var event:IncomingDataEvent = new IncomingDataEvent();
			event.data = xmlData;
			dispatchEvent( event );

			if(bodyNode.attributes["type"] == "terminal")
			{
				dispatchError( "BOSH Error", bodyNode.attributes["condition"], "", -1 );
				active = false;
			}

			for each(var childNode:XMLNode in bodyNode.childNodes)
			{
				if(childNode.nodeName == "stream:features")
				{
					_expireTagSearch = false;
					processConnectionResponse( bodyNode );
				}
				else
					responseQueue.push(childNode);
			}

			resetResponseProcessor();

			//if we just processed a poll response, we're no longer in mid-poll
			if(isPollResponse)
				isCurrentlyPolling = false;

			//if we have queued requests we want to send them before attempting to poll again
			//otherwise, if we don't already have a countdown going for the next poll, start one
	        if (!sendQueuedRequests() && (!pollTimer || !pollTimer.running))
	        	resetPollTimer();
		}

		private function httpError(req:XMLNode, isPollResponse:Boolean, evt:FaultEvent):void
		{
			active = false;
			dispatchError("Unknown HTTP Error", evt.fault.rootCause.text, "", -1);
		}

		protected override function sendXML(body:*):void
		{
			sendQueuedRequests(body);
		}

		private function sendQueuedRequests(body:*=null):Boolean
		{
			if(body)
				requestQueue.push(body);
			else if(requestQueue.length == 0)
				return false;

			return sendRequests();
		}

		//returns true if any requests were sent
		private function sendRequests(data:XMLNode = null, isPoll:Boolean=false):Boolean
		{
			if(requestCount >= maxConcurrentRequests)
				return false;

			if(isPoll)
				trace("Polling at: " + new Date().getSeconds());

			requestCount++;

			if(!data)
			{
				if(isPoll)
				{
					data = createRequest();
				}
				else
				{
					var temp:Array = [];
					for(var i:uint = 0; i < 10 && requestQueue.length > 0; i++)
					{
						temp.push(requestQueue.shift());
					}
					data = createRequest(temp);
				}
			}

			//build the http request
	        var request:HTTPService = new HTTPService();
	        request.method = "post";
	        request.headers = headers[request.method];
	        request.url = httpServer;
	        request.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
	        request.contentType = "text/xml";

	        var responseCallback:Callback = new Callback(this, httpResponse, data, isPoll);
	        var errorCallback:Callback = new Callback(this, httpError, data, isPoll);

	        request.addEventListener(ResultEvent.RESULT, responseCallback.call, false);
	        request.addEventListener(FaultEvent.FAULT, errorCallback.call, false);

	       	if(logger)
	       		logger.log(data, "OUTGOING");

			request.send(data);

			resetPollTimer();

			return true;
		}

    	private function resetPollTimer():void
    	{
    		if(!pollTimer)
    			return;
    		pollTimer.reset();
    		pollTimer.start();
    	}

    	private function pollServer(evt:TimerEvent):void
    	{
    		//We shouldn't poll if the connection is dead, if we had requests to send instead, or if there's already one in progress
    		if(!isActive() || sendQueuedRequests() || isCurrentlyPolling)
    			return;

    		//this should be safe since sendRequests checks to be sure it's not over the concurrent requests limit, and we just ensured that the queue is empty by calling sendQueuedRequests()
    		isCurrentlyPolling = sendRequests(null, true);
    	}

    	private function get nextRID():Number {
    		if(!rid)
    			rid = Math.floor(Math.random() * 1000000);
    		return ++rid;
    	}

    	private function createRequest(bodyContent:Array=null):XMLNode {
    		var attrs:Object = {
    			xmlns: "http://jabber.org/protocol/httpbind",
				rid: nextRID,
				sid: sid
    		}
    		var req:XMLNode = new XMLNode(1, "body");
    		if(bodyContent)
    			for each(var content:XMLNode in bodyContent)
    					req.appendChild(content);

    		req.attributes = attrs;

    		return req;
    	}

	    private function handleAuthentication(responseBody:XMLNode):void
	    {
	    //    if(!response || response.length == 0) {
	     //       return;
	     //   }
	        var status:Object = auth.handleResponse(0, responseBody);
	        if (status.authComplete) {
	            if (status.authSuccess) {
	                bindConnection();
	            }
	            else {
	                dispatchEvent(new ErrorEvent(ErrorEvent.ERROR));
	                disconnect();
	            }
	        }
	    }

	    private function configureConnection(responseBody:XMLNode):void
	    {
	    	var features:XMLNode = responseBody.firstChild;

	        var authentication:Object = {};
	        for each(var feature:XMLNode in features.childNodes)
			{
	            if (feature.nodeName == "mechanisms")
	                authentication.auth = configureAuthMechanisms(feature);
	            else if (feature.nodeName == "bind")
	                authentication.bind = true;
	            else if (feature.nodeName == "session")
	                authentication.session = true;
	        }

	        auth = authentication.auth;
	        dispatchEvent(new ConnectionSuccessEvent());
	        authHandler = handleAuthentication;
	        sendXML(auth.request);
	    }

	    private function configureAuthMechanisms(mechanisms:XMLNode):SASLAuth
	    {
	        var authMechanism:SASLAuth;
	        var authClass:Class;
	        for each(var mechanism:XMLNode in mechanisms.childNodes)
	        {
	        	authClass = saslMechanisms[mechanism.firstChild.nodeValue];
	   			if(authClass)
	   				break;
	        }

	        if (!authClass) {
	        	dispatchError("SASL missing", "The server is not configured to support any available SASL mechanisms", "SASL", -1);
	        	return null;
	        }

	   		return new authClass(this);
	    }

	    public function handleBindResponse(packet:IQ):void
	    {
	    	var bind:BindExtension = packet.getExtension("bind") as BindExtension;

            var jid:String = bind.getJID();

            var parts:Array = jid.split("/");
            myResource = parts[1];
            parts = parts[0].split("@");
            myUsername = parts[0];
            domain = parts[1];

            establishSession();
	    }

	    private function bindConnection():void
	    {
	    	var bindIQ:IQ = new IQ(null, "set");

			var bindExt:BindExtension = new BindExtension();
			if(resource)
	        	bindExt.resource = resource;

	        bindIQ.addExtension(bindExt);

			//this is laaaaaame, it should be a function
			bindIQ.callbackName = "handleBindResponse";
			bindIQ.callbackScope = this;

	        send(bindIQ);
	    }

	    public function handleSessionResponse(packet:IQ):void
	    {
	    	dispatchEvent(new LoginEvent());
	    }

	    private function establishSession():void
	    {
	        var sessionIQ:IQ = new IQ(null, "set");

	        sessionIQ.addExtension(new SessionExtension());

	        sessionIQ.callbackName = "handleSessionResponse";
	        sessionIQ.callbackScope = this;

	        send(sessionIQ);
	    }

		//do nothing, we use polling instead
		public override function sendKeepAlive():void {}
	}
}

Add a little padding on BOSH polling; sacrifices a tiny bit of responsiveness for some safety, HOPEFULLY fixing XIFF-31. r=Daniel

git-svn-id: c197267f952b24206666de142881703007ca05d5@10583 b35dd754-fafc-0310-a699-88a17e54d16e


package mns.crypto{
	import com.hurlant.crypto.prng.Random;
	import com.hurlant.crypto.rsa.RSAKey;
	import com.hurlant.util.Hex;

	import flash.external.ExternalInterface;
	import flash.utils.ByteArray;
	public class KeyGenerator
	{
		public static function generateKeys():void{
			var exp:String = "10001";
			var rsa:RSAKey = RSAKey.generate(1024, exp);
			ExternalInterface.call("setvalue", "publickey", rsa.n.toString());
			ExternalInterface.call("setvalue", "d", rsa.d.toString());
			ExternalInterface.call("setvalue", "p", rsa.p.toString());
			ExternalInterface.call("setvalue", "q", rsa.q.toString());
			ExternalInterface.call("setvalue", "dmp", rsa.dmp1.toString());
			ExternalInterface.call("setvalue", "dmq", rsa.dmq1.toString());
			ExternalInterface.call("setvalue", "qinv", rsa.coeff.toString());
			var data:ByteArray, prehashedkey:ByteArray, hashedkey:ByteArray;

			var r:Random = new Random;
			var rankey:ByteArray = new ByteArray
			r.nextBytes(rankey, 32);
			ExternalInterface.call("setvalue", "rk", Hex.fromArray(rankey));
		}
	}
}

package dse{
	import com.hurlant.crypto.prng.Random;
	import com.hurlant.crypto.rsa.RSAKey;
	import com.hurlant.util.Hex;

	import flash.external.ExternalInterface;
	import flash.utils.ByteArray;
	public class KeyGenerator
	{
		public static function generateKeys():void{
			var exp:String = "10001";
			var rsa:RSAKey = RSAKey.generate(1024, exp);
			ExternalInterface.call("setvalue", "publickey", rsa.n.toString());
			ExternalInterface.call("setvalue", "d", rsa.d.toString());
			ExternalInterface.call("setvalue", "p", rsa.p.toString());
			ExternalInterface.call("setvalue", "q", rsa.q.toString());
			ExternalInterface.call("setvalue", "dmp", rsa.dmp1.toString());
			ExternalInterface.call("setvalue", "dmq", rsa.dmq1.toString());
			ExternalInterface.call("setvalue", "qinv", rsa.coeff.toString());
			var data:ByteArray, prehashedkey:ByteArray, hashedkey:ByteArray;

			var r:Random = new Random;
			var rankey:ByteArray = new ByteArray
			r.nextBytes(rankey, 32);
			ExternalInterface.call("setvalue", "rk", Hex.fromArray(rankey));
		}
	}
}

change package of ActionScript class

change package of ActionScript class


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls {
    import org.mangui.hls.constant.HLSSeekMode;
    import org.mangui.hls.constant.HLSMaxLevelCappingMode;

    public final class HLSSettings extends Object {
        /**
         * autoStartLoad
         *
         * if set to true,
         *      start level playlist and first fragments will be loaded automatically,
         *      after triggering of HlsEvent.MANIFEST_PARSED event
         * if set to false,
         *      an explicit API call (hls.startLoad()) will be needed
         *      to start quality level/fragment loading.
         *
         * Default is true
         */
        public static var autoStartLoad : Boolean = true;
        /**
         * capLevelToStage
         *
         * Limit levels usable in auto-quality by the stage dimensions (width and height).
         *      true - level width and height (defined in m3u8 playlist) will be compared with the player width and height (stage.stageWidth and stage.stageHeight).
         *             Max level will be set depending on the maxLevelCappingMode option.
         *      false - levels will not be limited. All available levels could be used in auto-quality mode taking only bandwidth into consideration.
         *
         * Note: this setting is ignored in manual mode so all the levels could be selected manually.
         *
         * Default is false
         */
        public static var capLevelToStage : Boolean = false;

        /**
         * maxLevelCappingMode
         *
         * Defines the max level capping mode to the one available in HLSMaxLevelCappingMode
         *      HLSMaxLevelCappingMode.DOWNSCALE - max capped level should be the one with the dimensions equal or greater than the stage dimensions (so the video will be downscaled)
         *      HLSMaxLevelCappingMode.UPSCALE - max capped level should be the one with the dimensions equal or lower than the stage dimensions (so the video will be upscaled)
         *
         * Default is HLSMaxLevelCappingMode.DOWNSCALE
         */
        public static var maxLevelCappingMode : String = HLSMaxLevelCappingMode.DOWNSCALE;

        // // // // // // /////////////////////////////////
        //
        // org.mangui.hls.stream.HLSNetStream
        //
        // // // // // // /////////////////////////////////
        /**
         * minBufferLength
         *
         * Defines minimum buffer length in seconds before playback can start, after seeking or buffer stalling.
         *
         * Default is -1 = auto
         */
        public static var minBufferLength : Number = -1;

        /**
         * minBufferLengthCapping
         *
         * Defines minimum buffer length capping value (max value) if minBufferLength is set to -1
         *
         * Default is -1 = no capping
         */
        public static var minBufferLengthCapping : Number = -1;

        /**
         * maxBufferLength
         *
         * Defines maximum buffer length in seconds.
         * (0 means infinite buffering)
         *
         * Default is 120
         */
        public static var maxBufferLength : Number = 120;

        /**
         * maxBackBufferLength
         *
         * Defines maximum back buffer length in seconds.
         * (0 means infinite back buffering)
         *
         * Default is 30
         */
        public static var maxBackBufferLength : Number = 30;

        /**
         * lowBufferLength
         *
         * Defines low buffer length in seconds.
         * When crossing down this threshold, HLS will switch to buffering state.
         *
         * Default is 3
         */
        public static var lowBufferLength : Number = 3;

        /**
         * mediaTimeUpdatePeriod
         *
         * time update period in ms
         * period at which HLSEvent.MEDIA_TIME will be triggered
         * Default is 100 ms
         */
        public static var mediaTimePeriod : int = 100;

        /**
         * fpsDroppedMonitoringPeriod
         *
         * dropped FPS Monitor Period in ms
         * period at which nb dropped FPS will be checked
         * Default is 5000 ms
         */
        public static var fpsDroppedMonitoringPeriod : int = 5000;

        /**
         * fpsDroppedMonitoringThreshold
         *
         * dropped FPS Threshold
         * every fpsDroppedMonitoringPeriod, dropped FPS will be compared to displayed FPS.
         * if during that period, ratio of (dropped FPS/displayed FPS) is greater or equal
         * than fpsDroppedMonitoringThreshold, HLSEvent.FPS_DROP event will be fired
         * Default is 0.2 (20%)
         */
        public static var fpsDroppedMonitoringThreshold : Number = 0.2;

        /**
         * capLevelonFPSDrop
         *
         * Limit levels usable in auto-quality when FPS drop is detected
         * i.e. if frame drop is detected on level 5, auto level will be capped to level 4 a
         *      true -  enabled
         *      false - disabled
         *
         * Note: this setting is ignored in manual mode so all the levels could be selected manually.
         *
         * Default is false
         */
        public static var capLevelonFPSDrop : Boolean = false;

        /**
         * smoothAutoSwitchonFPSDrop
         *
         * force a smooth level switch Limit when FPS drop is detected in auto-quality
         * i.e. if frame drop is detected on level 5, it will trigger an auto quality level switch
         * to level 4 for next fragment
         *      true -  enabled
         *      false - disabled
         *
         * Note: this setting is active only if capLevelonFPSDrop==true
         *
         * Default is true
         */
        public static var smoothAutoSwitchonFPSDrop : Boolean = true;

        /**
         * switchDownOnLevelError
         *
         * if level loading fails, and if in auto mode, and we are not on lowest level
         * don't report Level loading error straight-away, try to switch down first
         *      true -  enabled
         *      false - disabled
         *
         * Default is true
         */
        public static var switchDownOnLevelError : Boolean = true;

        /**
         * seekMode
         *
         * Defines seek mode to one form available in HLSSeekMode class:
         *      HLSSeekMode.ACCURATE_SEEK - accurate seeking to exact requested position
         *      HLSSeekMode.KEYFRAME_SEEK - key-frame based seeking (seek to nearest key frame before requested seek position)
         *
         * Default is HLSSeekMode.KEYFRAME_SEEK
         */
        public static var seekMode : String = HLSSeekMode.KEYFRAME_SEEK;

        /**
         * keyLoadMaxRetry
         *
         * Max nb of retries for Key Loading in case I/O errors are met,
         *      0, means no retry, error will be triggered automatically
         *     -1 means infinite retry
         *
         * Default is 3
         */
        public static var keyLoadMaxRetry : int = 3;

        /**
         * keyLoadMaxRetryTimeout
         *
         * Maximum key retry timeout (in milliseconds) in case I/O errors are met.
         * Every fail on key request, player will exponentially increase the timeout to try again.
         * It starts waiting 1 second (1000ms), than 2, 4, 8, 16, until keyLoadMaxRetryTimeout is reached.
         *
         * Default is 64000.
         */
        public static var keyLoadMaxRetryTimeout : Number = 64000;

        /**
         * fragmentLoadMaxRetry
         *
         * Max number of retries for Fragment Loading in case I/O errors are met,
         *      0, means no retry, error will be triggered automatically
         *     -1 means infinite retry
         *
         * Default is 3
         */
        public static var fragmentLoadMaxRetry : int = 3;

        /**
         * fragmentLoadMaxRetryTimeout
         *
         * Maximum Fragment retry timeout (in milliseconds) in case I/O errors are met.
         * Every fail on fragment request, player will exponentially increase the timeout to try again.
         * It starts waiting 1 second (1000ms), than 2, 4, 8, 16, until fragmentLoadMaxRetryTimeout is reached.
         *
         * Default is 4000
         */
        public static var fragmentLoadMaxRetryTimeout : Number = 4000

        /**
         * fragmentLoadSkipAfterMaxRetry
         *
         * control behaviour in case fragment load still fails after max retry timeout
         * if set to true, fragment will be skipped and next one will be loaded.
         * If set to false, an I/O Error will be raised.
         *
         * Default is true.
         */
        public static var fragmentLoadSkipAfterMaxRetry : Boolean = true;

        /**
         * flushLiveURLCache
         *
         * If set to true, live playlist will be flushed from URL cache before reloading
         * (this is to workaround some cache issues with some combination of Flash Player / IE version)
         *
         * Default is false
         */
        public static var flushLiveURLCache : Boolean = false;

        /**
         * initialLiveManifestSize
         *
         * Number of segments needed to start playback of Live stream.
         *
         * Default is 1
         */
        public static var initialLiveManifestSize: uint = 1;

        /**
         * manifestLoadMaxRetry
         *
         * max nb of retries for Manifest Loading in case I/O errors are met,
         *      0, means no retry, error will be triggered automatically
         *     -1 means infinite retry
         */
        public static var manifestLoadMaxRetry : int = 3;

        /**
         * manifestLoadMaxRetryTimeout
         *
         * Maximum Manifest retry timeout (in milliseconds) in case I/O errors are met.
         * Every fail on fragment request, player will exponentially increase the timeout to try again.
         * It starts waiting 1 second (1000ms), than 2, 4, 8, 16, until manifestLoadMaxRetryTimeout is reached.
         *
         * Default is 64000
         */
        public static var manifestLoadMaxRetryTimeout : Number = 64000;

		/**
		 * manifestRedundantLoadmaxRetry
		 *
		 * max nb of looping over the redundant streams.
		 *   >0  means looping over the stream array 2 or more times
		 *    0  means looping exactly once (no retries) - default behaviour
		 *   -1  means infinite retry
		 */
		public static var manifestRedundantLoadmaxRetry : int = 3;

        /**
         * startFromBitrate
         *
         * If greater than 0, specifies the preferred bitrate.
         * If -1, and startFromLevel is not specified, automatic start level selection will be used.
         * This parameter, if set, will take priority over startFromLevel.
         *
         * Default is -1
         */
        public static var startFromBitrate : Number = -1;

        /**
         * startFromLevel
         *
         * start level :
         *  from 0 to 1 : indicates the "normalized" preferred level. As such, if it is 0.5, the closest to the middle bitrate will be selected and used first.
         * -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment)
         * -2 : playback will start from the first level appearing in Manifest (not sorted by bitrate)
         *
         * Default is -1
         */
        public static var startFromLevel : Number = -1;

        /**
         * autoStartMaxDuration
         *
         * max fragment loading duration in automatic start level selection mode (in ms)
         * -1 : max duration not capped
         * other : max duration is capped to avoid long playback starting time
         *
         * Default is -1
         */
        public static var autoStartMaxDuration : Number = -1;

        /**
         * seekFromLevel
         *
         * Seek level:
         *  from 0 to 1: indicates the "normalized" preferred bitrate. As such, if it is 0.5, the closest to the middle bitrate will be selected and used first.
         * -1 : automatic start level selection, keep previous level matching previous download bandwidth
         *
         * Default is -1
         */
        public static var seekFromLevel : Number = -1;

        /**
         * useHardwareVideoDecoder
         *
         * Use hardware video decoder:
         *  it will set NetStream.useHardwareDecoder
         *  refer to http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#useHardwareDecoder
         *
         * Default is true
         */
        public static var useHardwareVideoDecoder : Boolean = true;

        /**
         * logInfo
         *
         * Defines whether INFO level log messages will will appear in the console
         *
         * Default is true
         */
        public static var logInfo : Boolean = true;

        /**
         * logDebug
         *
         * Defines whether DEBUG level log messages will will appear in the console
         *
         * Default is false
         */
        public static var logDebug : Boolean = false;

        /**
         * logDebug2
         *
         * Defines whether DEBUG2 level log messages will will appear in the console
         *
         * Default is false
         */
        public static var logDebug2 : Boolean = false;

        /**
         * logWarn
         *
         * Defines whether WARN level log messages will will appear in the console
         *
         * Default is true
         */
        public static var logWarn : Boolean = true;

        /**
         * logError
         *
         * Defines whether ERROR level log messages will will appear in the console
         *
         * Default is true
         */
        public static var logError : Boolean = true;
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls {
    import org.mangui.hls.constant.HLSSeekMode;
    import org.mangui.hls.constant.HLSMaxLevelCappingMode;

    public final class HLSSettings extends Object {
        /**
         * autoStartLoad
         *
         * if set to true,
         *      start level playlist and first fragments will be loaded automatically,
         *      after triggering of HlsEvent.MANIFEST_PARSED event
         * if set to false,
         *      an explicit API call (hls.startLoad()) will be needed
         *      to start quality level/fragment loading.
         *
         * Default is true
         */
        public static var autoStartLoad : Boolean = true;
        /**
         * capLevelToStage
         *
         * Limit levels usable in auto-quality by the stage dimensions (width and height).
         *      true - level width and height (defined in m3u8 playlist) will be compared with the player width and height (stage.stageWidth and stage.stageHeight).
         *             Max level will be set depending on the maxLevelCappingMode option.
         *      false - levels will not be limited. All available levels could be used in auto-quality mode taking only bandwidth into consideration.
         *
         * Note: this setting is ignored in manual mode so all the levels could be selected manually.
         *
         * Default is false
         */
        public static var capLevelToStage : Boolean = false;

        /**
         * maxLevelCappingMode
         *
         * Defines the max level capping mode to the one available in HLSMaxLevelCappingMode
         *      HLSMaxLevelCappingMode.DOWNSCALE - max capped level should be the one with the dimensions equal or greater than the stage dimensions (so the video will be downscaled)
         *      HLSMaxLevelCappingMode.UPSCALE - max capped level should be the one with the dimensions equal or lower than the stage dimensions (so the video will be upscaled)
         *
         * Default is HLSMaxLevelCappingMode.DOWNSCALE
         */
        public static var maxLevelCappingMode : String = HLSMaxLevelCappingMode.DOWNSCALE;

        // // // // // // /////////////////////////////////
        //
        // org.mangui.hls.stream.HLSNetStream
        //
        // // // // // // /////////////////////////////////
        /**
         * minBufferLength
         *
         * Defines minimum buffer length in seconds before playback can start, after seeking or buffer stalling.
         *
         * Default is -1 = auto
         */
        public static var minBufferLength : Number = -1;

        /**
         * minBufferLengthCapping
         *
         * Defines minimum buffer length capping value (max value) if minBufferLength is set to -1
         *
         * Default is -1 = no capping
         */
        public static var minBufferLengthCapping : Number = -1;

        /**
         * maxBufferLength
         *
         * Defines maximum buffer length in seconds.
         * (0 means infinite buffering)
         *
         * Default is 120
         */
        public static var maxBufferLength : Number = 120;

        /**
         * maxBackBufferLength
         *
         * Defines maximum back buffer length in seconds.
         * (0 means infinite back buffering)
         *
         * Default is 30
         */
        public static var maxBackBufferLength : Number = 30;

        /**
         * lowBufferLength
         *
         * Defines low buffer length in seconds.
         * When crossing down this threshold, HLS will switch to buffering state.
         *
         * Default is 3
         */
        public static var lowBufferLength : Number = 3;

        /**
         * mediaTimeUpdatePeriod
         *
         * time update period in ms
         * period at which HLSEvent.MEDIA_TIME will be triggered
         * Default is 100 ms
         */
        public static var mediaTimePeriod : int = 100;

        /**
         * fpsDroppedMonitoringPeriod
         *
         * dropped FPS Monitor Period in ms
         * period at which nb dropped FPS will be checked
         * Default is 5000 ms
         */
        public static var fpsDroppedMonitoringPeriod : int = 5000;

        /**
         * fpsDroppedMonitoringThreshold
         *
         * dropped FPS Threshold
         * every fpsDroppedMonitoringPeriod, dropped FPS will be compared to displayed FPS.
         * if during that period, ratio of (dropped FPS/displayed FPS) is greater or equal
         * than fpsDroppedMonitoringThreshold, HLSEvent.FPS_DROP event will be fired
         * Default is 0.2 (20%)
         */
        public static var fpsDroppedMonitoringThreshold : Number = 0.2;

        /**
         * capLevelonFPSDrop
         *
         * Limit levels usable in auto-quality when FPS drop is detected
         * i.e. if frame drop is detected on level 5, auto level will be capped to level 4 a
         *      true -  enabled
         *      false - disabled
         *
         * Note: this setting is ignored in manual mode so all the levels could be selected manually.
         *
         * Default is false
         */
        public static var capLevelonFPSDrop : Boolean = false;

        /**
         * smoothAutoSwitchonFPSDrop
         *
         * force a smooth level switch Limit when FPS drop is detected in auto-quality
         * i.e. if frame drop is detected on level 5, it will trigger an auto quality level switch
         * to level 4 for next fragment
         *      true -  enabled
         *      false - disabled
         *
         * Note: this setting is active only if capLevelonFPSDrop==true
         *
         * Default is true
         */
        public static var smoothAutoSwitchonFPSDrop : Boolean = true;

        /**
         * switchDownOnLevelError
         *
         * if level loading fails, and if in auto mode, and we are not on lowest level
         * don't report Level loading error straight-away, try to switch down first
         *      true -  enabled
         *      false - disabled
         *
         * Default is true
         */
        public static var switchDownOnLevelError : Boolean = true;

        /**
         * seekMode
         *
         * Defines seek mode to one form available in HLSSeekMode class:
         *      HLSSeekMode.ACCURATE_SEEK - accurate seeking to exact requested position
         *      HLSSeekMode.KEYFRAME_SEEK - key-frame based seeking (seek to nearest key frame before requested seek position)
         *
         * Default is HLSSeekMode.KEYFRAME_SEEK
         */
        public static var seekMode : String = HLSSeekMode.KEYFRAME_SEEK;

        /**
         * keyLoadMaxRetry
         *
         * Max nb of retries for Key Loading in case I/O errors are met,
         *      0, means no retry, error will be triggered automatically
         *     -1 means infinite retry
         *
         * Default is 3
         */
        public static var keyLoadMaxRetry : int = 3;

        /**
         * keyLoadMaxRetryTimeout
         *
         * Maximum key retry timeout (in milliseconds) in case I/O errors are met.
         * Every fail on key request, player will exponentially increase the timeout to try again.
         * It starts waiting 1 second (1000ms), than 2, 4, 8, 16, until keyLoadMaxRetryTimeout is reached.
         *
         * Default is 64000.
         */
        public static var keyLoadMaxRetryTimeout : Number = 64000;

        /**
         * fragmentLoadMaxRetry
         *
         * Max number of retries for Fragment Loading in case I/O errors are met,
         *      0, means no retry, error will be triggered automatically
         *     -1 means infinite retry
         *
         * Default is 3
         */
        public static var fragmentLoadMaxRetry : int = 3;

        /**
         * fragmentLoadMaxRetryTimeout
         *
         * Maximum Fragment retry timeout (in milliseconds) in case I/O errors are met.
         * Every fail on fragment request, player will exponentially increase the timeout to try again.
         * It starts waiting 1 second (1000ms), than 2, 4, 8, 16, until fragmentLoadMaxRetryTimeout is reached.
         *
         * Default is 4000
         */
        public static var fragmentLoadMaxRetryTimeout : Number = 4000;

        /**
         * fragmentLoadSkipAfterMaxRetry
         *
         * control behaviour in case fragment load still fails after max retry timeout
         * if set to true, fragment will be skipped and next one will be loaded.
         * If set to false, an I/O Error will be raised.
         *
         * Default is true.
         */
        public static var fragmentLoadSkipAfterMaxRetry : Boolean = true;

        /**
         * flushLiveURLCache
         *
         * If set to true, live playlist will be flushed from URL cache before reloading
         * (this is to workaround some cache issues with some combination of Flash Player / IE version)
         *
         * Default is false
         */
        public static var flushLiveURLCache : Boolean = false;

        /**
         * initialLiveManifestSize
         *
         * Number of segments needed to start playback of Live stream.
         *
         * Default is 1
         */
        public static var initialLiveManifestSize : uint = 1;

        /**
         * manifestLoadMaxRetry
         *
         * max nb of retries for Manifest Loading in case I/O errors are met,
         *      0, means no retry, error will be triggered automatically
         *     -1 means infinite retry
         */
        public static var manifestLoadMaxRetry : int = 3;

        /**
         * manifestLoadMaxRetryTimeout
         *
         * Maximum Manifest retry timeout (in milliseconds) in case I/O errors are met.
         * Every fail on fragment request, player will exponentially increase the timeout to try again.
         * It starts waiting 1 second (1000ms), than 2, 4, 8, 16, until manifestLoadMaxRetryTimeout is reached.
         *
         * Default is 64000
         */
        public static var manifestLoadMaxRetryTimeout : Number = 64000;

		/**
		 * manifestRedundantLoadmaxRetry
		 *
		 * max nb of looping over the redundant streams.
		 *   >0  means looping over the stream array 2 or more times
		 *    0  means looping exactly once (no retries) - default behaviour
		 *   -1  means infinite retry
		 */
        public static var manifestRedundantLoadmaxRetry : int = 3;

        /**
         * startFromBitrate
         *
         * If greater than 0, specifies the preferred bitrate.
         * If -1, and startFromLevel is not specified, automatic start level selection will be used.
         * This parameter, if set, will take priority over startFromLevel.
         *
         * Default is -1
         */
        public static var startFromBitrate : Number = -1;

        /**
         * startFromLevel
         *
         * start level :
         *  from 0 to 1 : indicates the "normalized" preferred level. As such, if it is 0.5, the closest to the middle bitrate will be selected and used first.
         * -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment)
         * -2 : playback will start from the first level appearing in Manifest (not sorted by bitrate)
         *
         * Default is -1
         */
        public static var startFromLevel : Number = -1;

        /**
         * autoStartMaxDuration
         *
         * max fragment loading duration in automatic start level selection mode (in ms)
         * -1 : max duration not capped
         * other : max duration is capped to avoid long playback starting time
         *
         * Default is -1
         */
        public static var autoStartMaxDuration : Number = -1;

        /**
         * seekFromLevel
         *
         * Seek level:
         *  from 0 to 1: indicates the "normalized" preferred bitrate. As such, if it is 0.5, the closest to the middle bitrate will be selected and used first.
         * -1 : automatic start level selection, keep previous level matching previous download bandwidth
         *
         * Default is -1
         */
        public static var seekFromLevel : Number = -1;

        /**
         * useHardwareVideoDecoder
         *
         * Use hardware video decoder:
         *  it will set NetStream.useHardwareDecoder
         *  refer to http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#useHardwareDecoder
         *
         * Default is true
         */
        public static var useHardwareVideoDecoder : Boolean = true;

        /**
         * logInfo
         *
         * Defines whether INFO level log messages will will appear in the console
         *
         * Default is true
         */
        public static var logInfo : Boolean = true;

        /**
         * logDebug
         *
         * Defines whether DEBUG level log messages will will appear in the console
         *
         * Default is false
         */
        public static var logDebug : Boolean = false;

        /**
         * logDebug2
         *
         * Defines whether DEBUG2 level log messages will will appear in the console
         *
         * Default is false
         */
        public static var logDebug2 : Boolean = false;

        /**
         * logWarn
         *
         * Defines whether WARN level log messages will will appear in the console
         *
         * Default is true
         */
        public static var logWarn : Boolean = true;

        /**
         * logError
         *
         * Defines whether ERROR level log messages will will appear in the console
         *
         * Default is true
         */
        public static var logError : Boolean = true;
    }
}

add missing colon and indent in HLSSettings.as


////////////////////////////////////////////////////////////////////////////////
//
//  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.core
{
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.utils.MXMLDataInterpreter;

	[DefaultProperty("mxmlContent")]
	public class ViewBase extends UIBase
	{
		public function ViewBase()
		{
			super();
		}

		public function initUI(model:Object):void
		{
			_applicationModel = model;
			dispatchEvent(new Event("modelChanged"));

			// each MXML file can also have styles in fx:Style block
			ValuesManager.valuesImpl.init(this);

			MXMLDataInterpreter.generateMXMLProperties(this, MXMLProperties);
			MXMLDataInterpreter.generateMXMLInstances(this, this, MXMLDescriptor);
		}

		public function get MXMLDescriptor():Array
		{
			return null;
		}

		public function get MXMLProperties():Array
		{
			return null;
		}

		public var mxmlContent:Array;

		private var _applicationModel:Object;

		[Bindable("modelChanged")]
		public function get applicationModel():Object
		{
			return _applicationModel;
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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.core
{
	import org.apache.flex.core.ValuesManager;
	import org.apache.flex.events.Event;
	import org.apache.flex.utils.MXMLDataInterpreter;

	[Event(name="initComplete", type="org.apache.flex.events.Event")]
	[DefaultProperty("mxmlContent")]
	public class ViewBase extends UIBase
	{
		public function ViewBase()
		{
			super();
		}

		public function initUI(model:Object):void
		{
			_applicationModel = model;
			dispatchEvent(new Event("modelChanged"));

			// each MXML file can also have styles in fx:Style block
			ValuesManager.valuesImpl.init(this);

			MXMLDataInterpreter.generateMXMLProperties(this, MXMLProperties);
			MXMLDataInterpreter.generateMXMLInstances(this, this, MXMLDescriptor);

			dispatchEvent(new Event("initComplete"))
		}

		public function get MXMLDescriptor():Array
		{
			return null;
		}

		public function get MXMLProperties():Array
		{
			return null;
		}

		public var mxmlContent:Array;

		private var _applicationModel:Object;

		[Bindable("modelChanged")]
		public function get applicationModel():Object
		{
			return _applicationModel;
		}
	}
}

add initComplete event sort of like creationComplete in current Flex SDK