Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Update with a snapshot of the release to market of WebWorks for Table…

…t OS v2.1.0.6
commit 7244a070509cc3c0e0a1914989934ede52499e72 1 parent c0ece6c
@kwhatmough kwhatmough authored
Showing with 5,149 additions and 841 deletions.
  1. +52 −41 framework/src/WebWorksAppTemplate.as
  2. +35 −14 framework/src/webworks/FunctionBroker.as
  3. +8 −2 framework/src/webworks/JavaScriptLoader.as
  4. +5 −5 framework/src/webworks/access/Feature.as
  5. +3 −3 framework/src/webworks/config/ConfigData.as
  6. +30 −7 framework/src/webworks/extension/DefaultExtension.as
  7. +67 −0 framework/src/webworks/extension/WebWorksReturnValue.as
  8. +466 −0 framework/src/webworks/fullScreenView/FullScreenView.as
  9. +8 −0 framework/src/webworks/loadingScreen/LoadingScreen.as
  10. +22 −31 framework/src/webworks/loadingScreen/Transitions.as
  11. +24 −0 framework/src/webworks/service/IWebWorksData.as
  12. +25 −0 framework/src/webworks/service/IWebWorksService.as
  13. +44 −0 framework/src/webworks/service/ServiceManager.as
  14. +533 −0 framework/src/webworks/service/blob/BlobManager.as
  15. +8 −0 framework/src/webworks/util/DeviceURL.as
  16. +99 −0 framework/src/webworks/util/IntUtil.as
  17. +281 −0 framework/src/webworks/util/MD5.as
  18. +56 −2 framework/src/webworks/webkit/WebkitControl.as
  19. +5 −0 framework/src/webworks/webkit/WebkitEvent.as
  20. +0 −71 js_api/BlackBerry_Application/library.xml
  21. +0 −71 js_api/BlackBerry_Application_Events/library.xml
  22. +0 −106 js_api/BlackBerry_Invoke/library.xml
  23. +0 −115 js_api/BlackBerry_System/library.xml
  24. +0 −61 js_api/BlackBerry_System_Events/library.xml
  25. +0 −105 js_api/BlackBerry_Ui/library.xml
  26. +0 −73 js_api/BlackBerry_Utilities/library.xml
  27. BIN  js_api/Common_AS/JSONLibrary/bin/JSONLibrary.swc
  28. +7 −0 js_api/Common_AS/JSONLibrary/src/json/JSONEncoder.as
  29. 0  js_api/{BlackBerry_Application_Events → blackberry.app.event}/js/common/app_event_dispatcher.js
  30. 0  js_api/{BlackBerry_Application_Events → blackberry.app.event}/js/common/app_event_ns.js
  31. +24 −0 js_api/blackberry.app.event/library.xml
  32. 0  ...→ blackberry.app.event}/src/Air/ApplicationEvents/src/blackberry/applicationEvents/ApplicationEvent.as
  33. 0  js_api/{BlackBerry_Application → blackberry.app}/js/common/app_dispatcher.js
  34. 0  js_api/{BlackBerry_Application → blackberry.app}/js/common/app_ns.js
  35. +24 −0 js_api/blackberry.app/library.xml
  36. +5 −4 ...BlackBerry_Application → blackberry.app}/src/Air/Application/src/blackberry/application/Application.as
  37. +37 −0 js_api/blackberry.identity/js/common/identity_dispatcher.js
  38. +26 −0 js_api/blackberry.identity/js/common/identity_ns.js
  39. +24 −0 js_api/blackberry.identity/library.xml
  40. +49 −0 js_api/blackberry.identity/src/Air/Identity/src/blackberry/identity/Identity.as
  41. 0  js_api/{BlackBerry_Invoke → blackberry.invoke}/js/common/invoke_dispatcher.js
  42. 0  js_api/{BlackBerry_Invoke → blackberry.invoke}/js/common/invoke_ns.js
  43. +24 −0 js_api/blackberry.invoke/library.xml
  44. 0  js_api/{BlackBerry_Invoke → blackberry.invoke}/src/Air/Invoke/src/blackberry/invoke/Invoke.as
  45. +147 −0 js_api/blackberry.io.dir/js/common/dir_dispatcher.js
  46. +42 −0 js_api/blackberry.io.dir/js/common/dir_ns.js
  47. +24 −0 js_api/blackberry.io.dir/library.xml
  48. +295 −0 js_api/blackberry.io.dir/src/Air/Directory/src/blackberry/io/dir/DirectoryExtension.as
  49. +162 −0 js_api/blackberry.io.file/js/common/file_dispatcher.js
  50. +49 −0 js_api/blackberry.io.file/js/common/file_ns.js
  51. +24 −0 js_api/blackberry.io.file/library.xml
  52. +317 −0 js_api/blackberry.io.file/src/Air/File/src/blackberry/io/file/FileExtension.as
  53. +45 −0 js_api/blackberry.media.camera/js/common/camera_dispatcher.js
  54. +66 −0 js_api/blackberry.media.camera/js/common/camera_ns.js
  55. +23 −0 js_api/blackberry.media.camera/library.xml
  56. +122 −0 js_api/blackberry.media.camera/src/Air/Camera/src/blackberry/media/camera/Camera.as
  57. +60 −0 js_api/blackberry.media.microphone/js/common/mic_dispatcher.js
  58. +33 −0 js_api/blackberry.media.microphone/js/common/mic_ns.js
  59. +24 −0 js_api/blackberry.media.microphone/library.xml
  60. +136 −0 js_api/blackberry.media.microphone/src/Air/Microphone/src/blackberry/media/microphone/MicrophoneExtension.as
  61. +40 −0 js_api/blackberry.media.microphone/src/Air/Microphone/src/org/bytearray/micrecorder/IEncoder.as
  62. +331 −0 js_api/blackberry.media.microphone/src/Air/Microphone/src/org/bytearray/micrecorder/MicRecorder.as
  63. +107 −0 js_api/blackberry.media.microphone/src/Air/Microphone/src/org/bytearray/micrecorder/encoder/WaveEncoder.as
  64. +84 −0 js_api/blackberry.media.microphone/src/Air/Microphone/src/org/bytearray/micrecorder/events/RecordingEvent.as
  65. +80 −0 js_api/blackberry.payment/js/common/payment_dispatcher.js
  66. +30 −0 js_api/blackberry.payment/js/common/payment_ns.js
  67. +24 −0 js_api/blackberry.payment/library.xml
  68. +159 −0 js_api/blackberry.payment/src/Air/Payment/src/blackberry/payment/Payment.as
  69. +41 −0 js_api/blackberry.payment/src/Air/Payment/src/blackberry/payment/PurchaseData.as
  70. 0  js_api/{BlackBerry_System_Events → blackberry.system.event}/js/common/system_event_dispatcher.js
  71. 0  js_api/{BlackBerry_System_Events → blackberry.system.event}/js/common/system_event_ns.js
  72. +24 −0 js_api/blackberry.system.event/library.xml
  73. 0  ...tem_Events → blackberry.system.event}/src/Air/SystemEvents/src/blackberry/system/event/SystemEvents.as
  74. 0  js_api/{BlackBerry_System → blackberry.system}/js/common/system_dispatcher.js
  75. 0  js_api/{BlackBerry_System → blackberry.system}/js/common/system_ns.js
  76. +24 −0 js_api/blackberry.system/library.xml
  77. +6 −5 js_api/{BlackBerry_System → blackberry.system}/src/Air/System/src/blackberry/system/System.as
  78. 0  js_api/{BlackBerry_Ui → blackberry.ui.dialog}/js/common/dialog/dialog_dispatcher.js
  79. 0  js_api/{BlackBerry_Ui → blackberry.ui.dialog}/js/common/dialog/dialog_ns.js
  80. +24 −0 js_api/blackberry.ui.dialog/library.xml
  81. 0  js_api/{BlackBerry_Ui → blackberry.ui.dialog}/src/Air/UserInterface/src/blackberry/ui/dialog/Dialog.as
  82. 0  js_api/{BlackBerry_Utilities → blackberry.utils}/js/common/utilities_ns.js
  83. +23 −0 js_api/blackberry.utils/library.xml
  84. 0  js_api/{BlackBerry_Utilities → blackberry.utils}/src/Air/Utilities/src/blackberry/utils/Utilities.as
  85. +4 −4 js_api/globalJS/3_xhr.js
  86. +38 −0 js_api/globalJS/5_blob.js
  87. +3 −4 packager/src/net/rim/tumbler/WidgetPackager.java
  88. +185 −50 packager/src/net/rim/tumbler/airpackager/AirPackager.java
  89. +57 −15 packager/src/net/rim/tumbler/config/WidgetConfig.java
  90. +102 −0 packager/src/net/rim/tumbler/extension/ExtensionDependencyManager.java
  91. +21 −1 packager/src/net/rim/tumbler/extension/ExtensionDescriptor.java
  92. +102 −47 packager/src/net/rim/tumbler/extension/ExtensionMap.java
  93. +4 −1 packager/src/net/rim/tumbler/log/resources/MessageBundle_en_CA.properties
  94. +22 −0 packager/src/net/rim/tumbler/session/BBWPProperties.java
  95. +54 −3 packager/src/net/rim/tumbler/xml/ConfigXMLParser.java
View
93 framework/src/WebWorksAppTemplate.as
@@ -35,6 +35,7 @@ package
import webworks.extension.IApiExtension;
import webworks.loadingScreen.LoadingScreen;
import webworks.loadingScreen.Transitions;
+ import webworks.service.ServiceManager;
import webworks.webkit.WebkitControl;
import webworks.webkit.WebkitEvent;
@@ -44,12 +45,13 @@ package
{
private static var LOCAL_PROTOCOL:String = "local:///";
- private var entryURL:String;
- private var webWindow:WebkitControl;
- private var errorDialog:AlertDialog;
- private var loadingScreen:LoadingScreen;
- private var transitions:Transitions;
- private var broker:FunctionBroker;
+ private var _entryURL:String;
+ private var _webWindow:WebkitControl;
+ private var _errorDialog:AlertDialog;
+ private var _loadingScreen:LoadingScreen;
+ private var _transitions:Transitions;
+ private var _broker:FunctionBroker;
+ private var _serviceManager:ServiceManager;
public function WebWorksAppTemplate()
{
@@ -64,7 +66,7 @@ package
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE, onOrientationChange);
- entryURL = ConfigData.getInstance().getProperty(ConfigConstants.CONTENT);
+ _entryURL = ConfigData.getInstance().getProperty(ConfigConstants.CONTENT);
NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, appActive);
NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, appBackground);
appInitialized();
@@ -73,7 +75,7 @@ package
private function appActive(event:Event):void
{
stage.frameRate = 30;
- webWindow.visible = true;
+ _webWindow.visible = true;
trace("Increased Framerate to " + stage.frameRate + " | " + event);
}
@@ -87,12 +89,19 @@ package
{
setupStage();
setupWebkit();
- ConfigData.getInstance().setProperty(ConfigConstants.ENV_WEBVIEW, webWindow.qnxWebView);
+
+ ConfigData.getInstance().setProperty(ConfigConstants.ENV_WEBVIEW, _webWindow.qnxWebView);
ConfigData.getInstance().setProperty(ConfigConstants.ENV_APPLICATION, this);
- loadingScreen = new LoadingScreen(0,0, stage.stageWidth,stage.stageHeight);
- transitions = new Transitions(loadingScreen);
- broker = new FunctionBroker(webWindow.qnxWebView);
- registerExtensions(ConfigData.getInstance().properties);
+
+ _loadingScreen = new LoadingScreen(0,0, stage.stageWidth,stage.stageHeight);
+ _transitions = new Transitions(_loadingScreen, _webWindow.viewPort);
+ _serviceManager = new ServiceManager(_webWindow);
+ _broker = new FunctionBroker(_webWindow.qnxWebView, _serviceManager);
+
+ var configProperties:Dictionary = ConfigData.getInstance().properties;
+ configProperties["serviceManager"] = _serviceManager;
+
+ registerExtensions(configProperties);
}
private function registerExtensions(env:Dictionary):void
@@ -118,16 +127,16 @@ package
private function setupWebkit():void
{
var creationID:Number = int(Math.random() * 1000000) + new Date().time;
- webWindow = new WebkitControl(creationID, stage);
- webWindow.setViewPort(new Rectangle(0, 0, stage.stageWidth, stage.stageHeight));
+ _webWindow = new WebkitControl(creationID, stage);
+ _webWindow.setViewPort(new Rectangle(0, 0, stage.stageWidth, stage.stageHeight));
- webWindow.addEventListener(WebkitEvent.TAB_LOAD_COMPLETE, tabLoadComplete);
- webWindow.addEventListener(WebkitEvent.TAB_LOAD_ERROR, webkitLoadError);
- webWindow.addEventListener(WebkitEvent.WEBVIEW_CREATED, webkitWindowReady);
- webWindow.addEventListener(WebkitEvent.TAB_LOCATION_CHANGING, webkitLocationChanging);
- webWindow.addEventListener(WebkitEvent.TAB_LOCATION_CHANGED, webkitLocationChanged);
- webWindow.addEventListener(WebkitEvent.TAB_UNKNOWNPROTOCOL, handleUnknownProtocol)
- addChild(webWindow);
+ _webWindow.addEventListener(WebkitEvent.TAB_LOAD_COMPLETE, tabLoadComplete);
+ _webWindow.addEventListener(WebkitEvent.TAB_LOAD_ERROR, webkitLoadError);
+ _webWindow.addEventListener(WebkitEvent.WEBVIEW_CREATED, webkitWindowReady);
+ _webWindow.addEventListener(WebkitEvent.TAB_LOCATION_CHANGING, webkitLocationChanging);
+ _webWindow.addEventListener(WebkitEvent.TAB_LOCATION_CHANGED, webkitLocationChanged);
+ _webWindow.addEventListener(WebkitEvent.TAB_UNKNOWNPROTOCOL, handleUnknownProtocol)
+ addChild(_webWindow);
}
private function handleUnknownProtocol(event:WebkitEvent):void
@@ -148,24 +157,24 @@ package
var returnedBody:String = "";
try {
- returnedBody = broker.handleXHRRequest(upe.url).toString();
- webWindow.qnxWebView.notifyResourceOpened(sid, HTTPErrorMapping.getSuccessCode(), HTTPErrorMapping.getSuccessMessage());
+ returnedBody = _broker.handleXHRRequest(upe.url).toString();
+ _webWindow.qnxWebView.notifyResourceOpened(sid, HTTPErrorMapping.getSuccessCode(), HTTPErrorMapping.getSuccessMessage());
}
catch (e:Error) {
var httpError:HTTPErrorMapping = new HTTPErrorMapping(e);
- webWindow.qnxWebView.notifyResourceOpened(sid,httpError.code, httpError.message);
+ _webWindow.qnxWebView.notifyResourceOpened(sid,httpError.code, httpError.message);
}
var byteData:ByteArray;
byteData = new ByteArray();
byteData.writeUTFBytes(returnedBody);
- webWindow.qnxWebView.notifyResourceHeaderReceived(sid, "Content-Type", "text/plain");
- webWindow.qnxWebView.notifyResourceHeaderReceived(sid, "Content-Length", byteData.length.toString());
- webWindow.qnxWebView.notifyResourceDataReceived(sid, byteData);
+ _webWindow.qnxWebView.notifyResourceHeaderReceived(sid, "Content-Type", "text/plain");
+ _webWindow.qnxWebView.notifyResourceHeaderReceived(sid, "Content-Length", byteData.length.toString());
+ _webWindow.qnxWebView.notifyResourceDataReceived(sid, byteData);
- webWindow.qnxWebView.notifyResourceDone(sid);
+ _webWindow.qnxWebView.notifyResourceDone(sid);
}
private function tabLoadComplete(event:WebkitEvent):void
@@ -175,7 +184,7 @@ package
private function webkitWindowReady(event:WebkitEvent):void
{
- loadURL(entryURL);
+ loadURL(_entryURL);
}
private function webkitLoadError(event:WebkitEvent):void
@@ -196,28 +205,30 @@ package
var url:String = qnxEvent.location;
// add loading screen only if the location changes
- if (url.search(webWindow.qnxWebView.originalLocation) < 0 && loadingScreen.isLoadingScreenRequired(url))
+ if (url.search(_webWindow.qnxWebView.originalLocation) < 0 && _loadingScreen.isLoadingScreenRequired(url))
{
- loadingScreen.show(url);
+ _loadingScreen.show(url);
}
- if (loadingScreen.firstLaunchFlag)
+ if (_loadingScreen.firstLaunchFlag)
{
- loadingScreen.clearFirstLaunchFlag();
+ _loadingScreen.clearFirstLaunchFlag();
}
}
private function webkitLocationChanged(event:WebkitEvent):void
{
trace("webkitLocationChanged event");
- loadingScreen.hideIfNecessary();
+ _loadingScreen.hideIfNecessary();
}
private function onOrientationChange(event:StageOrientationEvent):void
{
- if (webWindow != null)
+ if (_webWindow != null)
{
- webWindow.setViewPort(new Rectangle(0, 0, stage.stageWidth, stage.stageHeight));
+ _webWindow.setViewPort(new Rectangle(0, 0, stage.stageWidth, stage.stageHeight));
+ _transitions.setViewPort(new Rectangle(0, 0, stage.stageWidth, stage.stageHeight));
+ _loadingScreen.setLoadingScreenArea(new Rectangle(0, 0, stage.stageWidth, stage.stageHeight));
}
}
@@ -227,15 +238,15 @@ package
url = LOCAL_PROTOCOL + url;
}
- if (loadingScreen.showOnFirstLaunch) {
- loadingScreen.show(url);
+ if (_loadingScreen.showOnFirstLaunch) {
+ _loadingScreen.show(url);
}
- webWindow.go(url);
+ _webWindow.go(url);
}
public function get transitionEffect():Transitions
{
- return transitions;
+ return _transitions;
}
}
}
View
49 framework/src/webworks/FunctionBroker.as
@@ -24,6 +24,8 @@ package webworks
import webworks.config.ConfigData;
import webworks.errors.WebWorksError;
import webworks.extension.IApiExtension;
+ import webworks.service.IWebWorksService;
+ import webworks.service.ServiceManager;
import webworks.util.DeviceURL;
import webworks.webkit.WebkitEvent;
@@ -34,11 +36,13 @@ package webworks
*/
public class FunctionBroker extends EventDispatcher
{
- private var webView:QNXStageWebView;
+ private var _serviceManager:ServiceManager;
+ private var _webView:QNXStageWebView;
- public function FunctionBroker(webview:QNXStageWebView, target:IEventDispatcher=null)
+ public function FunctionBroker(webview:QNXStageWebView, serviceManager:ServiceManager, target:IEventDispatcher=null)
{
- webView = webview;
+ _serviceManager = serviceManager;
+ _webView = webview;
super(target);
}
@@ -53,7 +57,7 @@ package webworks
public function handleXHRRequest(obj:Object):String
{
- if ( webView == null )
+ if ( _webView == null )
throw new WebWorksError(WebWorksError.SERVER_ERROR);
var deviceUrl:String = null;
@@ -79,18 +83,35 @@ package webworks
if ( deviceUrl == null || !device.isDeviceProtocol())
throw new WebWorksError(WebWorksError.BAD_REQUEST);
- //validate the feature
- if ( ConfigData.getInstance().isFeatureAllowed(device.featureName, webView.location))
+ //If it's a service call, skip validation
+ if( device.isService())
{
- var extension:IApiExtension = ConfigData.getInstance().getExtension(device.featureName);
- if ( extension != null )
- return extension.invokeFunction(device.methodName, device.unescapedQuery);
- else
- throw new WebWorksError(WebWorksError.NOT_IMPLEMENTED);
+ var service:IWebWorksService = _serviceManager.getEndPointForMethod(deviceUrl);
+
+ if(service != null)
+ {
+ return service.execute(device.methodName, device.parametersAsObject).json;
+ }
+ else
+ {
+ throw new WebWorksError(WebWorksError.NOT_IMPLEMENTED);
+ }
}
- else
- {
- throw new WebWorksError(WebWorksError.FORBIDDEN);
+ else
+ {
+ //validate the feature
+ if ( ConfigData.getInstance().isFeatureAllowed(device.featureName, _webView.location))
+ {
+ var extension:IApiExtension = ConfigData.getInstance().getExtension(device.featureName);
+ if ( extension != null )
+ return extension.invokeFunction(device.methodName, device.unescapedQuery);
+ else
+ throw new WebWorksError(WebWorksError.NOT_IMPLEMENTED);
+ }
+ else
+ {
+ throw new WebWorksError(WebWorksError.FORBIDDEN);
+ }
}
}
}
View
10 framework/src/webworks/JavaScriptLoader.as
@@ -56,18 +56,24 @@ package webworks
var features:Array = access.getFeatures();
var extension:IApiExtension;
var paths:Array;
+
+ //sort features in white list in ascending order
+ //when APIs get loaded in JavaScript, we must load parent namespace before child namespace
+ //e.g. a.b must be loaded before a.b.c, otherwise a.b.c gets overwritten by a.b
+ features.sortOn("id");
+
for(var index:String in features)
{
var feature:Feature = features[index] as Feature;
if ( feature == null )
continue;
- var widgetExt:Object = ConfigData.getInstance().getWidgetExtension(feature.getID());
+ var widgetExt:Object = ConfigData.getInstance().getWidgetExtension(feature.id);
if ( widgetExt != null )
{
//call loadFeature() of the extension
extension = widgetExt[ConfigConstants.ENTRYCLASS] as IApiExtension;
if ( extension != null )
- extension.loadFeature(feature.getID(), feature.getVersion());
+ extension.loadFeature(feature.id, feature.version);
//register js files for the feature
paths = widgetExt[ConfigConstants.REQUIREDJSFILES] as Array;
jsfiles = jsfiles.concat(paths);
View
10 framework/src/webworks/access/Feature.as
@@ -40,25 +40,25 @@ package webworks.access {
//
//-----------------------------------------------------------------------------
- public function getID():String {
+ public function get id():String {
return _id;
}
- public function isRequired():Boolean {
+ public function get isRequired():Boolean {
return _isRequired;
}
- public function getVersion():String {
+ public function get version():String {
return _version;
}
- public function getDependentFeatures():Array {
+ public function get dependentFeatures():Array {
return _dependentFeatures;
}
public function isEqual(feature:Feature):Boolean
{
- return _id == feature.getID();
+ return _id == feature.id;
}
}
}
View
6 framework/src/webworks/config/ConfigData.as
@@ -98,8 +98,8 @@ package webworks.config
var features:Array = extension.getFeatureList();
for(var index:String in features)
{
- if ( feature.getID() == features[index] )
- featureList[feature.getID()] = widgetExtensions[key];
+ if ( feature.id == features[index] )
+ featureList[feature.id] = widgetExtensions[key];
}
}
}
@@ -192,7 +192,7 @@ package webworks.config
for(var index:String in features)
{
var feature:Feature = features[index];
- if ( feature != null && feature.getID() == featureId )
+ if ( feature != null && feature.id == featureId )
return true;
}
}
View
37 framework/src/webworks/extension/DefaultExtension.as
@@ -54,11 +54,15 @@ package webworks.extension
//If a "method" that does not exist is called a reference error will be thrown,
// we will catch this in the WebWorksAppTemplate
- myReturn = this[method].apply(this, _paramValues);
-
+ myReturn = resolveMethod(method).apply(this, _paramValues);
+
return JSON.encode(myReturn);
}
+ protected function resolveMethod(method:String):Function {
+ return this[method];
+ }
+
protected function get query() : String {
return _query;
}
@@ -89,13 +93,20 @@ package webworks.extension
return (index < 0) ? null : _paramValues[index];
}
- protected function evalJavaScriptEvent(id:String,params:Array) : void {
+ protected function evalJavaScriptEvent(id:String,params:Array) : void
+ {
var javaScript:String = "blackberry.events.getEventHandler("+id+")(";
- for (var i:Number=0; i<params.length;i++){
- if(i== 0){
+ params = encodeEventParams(params);
+
+ for (var i:Number=0; i<params.length;i++)
+ {
+ if(i== 0)
+ {
javaScript += params[i];
- }else{
+ }
+ else
+ {
javaScript += ","+ params[i];
}
}
@@ -105,12 +116,24 @@ package webworks.extension
this.webView.executeJavaScript(javaScript);
}
+ private function encodeEventParams(params:Array):Array
+ {
+ var jsonParams:Array = [];
+
+ for each (var p:Object in params)
+ {
+ jsonParams.push(JSON.encode(p));
+ }
+
+ return jsonParams;
+ }
+
private function getParamKVArray(keyValuePairs : Array) : Array {
var keys : Array = new Array();
var values : Array = new Array();
for (var i : int = 0; i < keyValuePairs.length; i++) {
-
+
var decompParam : Array = keyValuePairs[i].split("=");
keys.push(decompParam[0]);
values.push(unescape(decompParam[1]));
View
67 framework/src/webworks/extension/WebWorksReturnValue.as
@@ -0,0 +1,67 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed 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 webworks.extension
+{
+ import json.JSONEncoder;
+
+ import webworks.service.IWebWorksData;
+
+ public class WebWorksReturnValue
+ {
+ private var _msg:String;
+ private var _rc:Number;
+ private var _data:*;
+
+ public static const RET_SUCCESS:Number = 0;
+
+ public function WebWorksReturnValue(data:*, returnCode:Number = WebWorksReturnValue.RET_SUCCESS, message:String=null)
+ {
+ //If the data parameter is of type IWebWorksData, which contains a return value in the form of a complex AS object
+ //and a simpler JS-friendly data object, keep it as-is. Otherwise create an instance of IWebWorksData for which both
+ //the AS and JS objects are the same.
+ _data = data;
+ _rc = returnCode;
+ _msg = message;
+ }
+
+ public function get data():*
+ {
+ return (_data is IWebWorksData) ? _data.actionScriptObject : _data;
+ }
+
+ //Temporary method that retrieves the underlying JS-friendly return object.
+ //It exists because for function calls, DefaultExtension does the conversion to JSON
+ //For service calls the IWebWorksData Implementation returns the jsObject which the service
+ //manager converts into JSON
+ public function get jsObject():Object
+ {
+ var d:* = (_data is IWebWorksData) ? _data.jsObject : _data;
+ return {
+ "code" : _rc,
+ "msg" : _msg,
+ "data" : d
+ };
+ }
+
+ public function get json():String
+ {
+ var encoder:JSONEncoder = new JSONEncoder(this.jsObject);
+
+ return encoder.getString();
+ }
+ }
+}
View
466 framework/src/webworks/fullScreenView/FullScreenView.as
@@ -0,0 +1,466 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed 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 webworks.fullScreenView
+{
+ import caurina.transitions.Tweener;
+
+ import flash.display.Screen;
+ import flash.display.Sprite;
+ import flash.display.StageAspectRatio;
+ import flash.display.StageOrientation;
+ import flash.events.Event;
+ import flash.events.MouseEvent;
+ import flash.events.StageOrientationEvent;
+ import flash.events.TimerEvent;
+ import flash.geom.Point;
+ import flash.utils.Timer;
+
+ import qnx.display.IowWindow;
+ import qnx.display.IowWindowSensitivity;
+ import qnx.display.IowWindowTransparency;
+ import qnx.fullscreen.FullscreenClient;
+ import qnx.fullscreen.FullscreenClientEvent;
+ import qnx.media.impl.mmr.MMR;
+ import qnx.media.impl.mmr.MMRContext;
+ import qnx.media.impl.mmr.MMREvent;
+ import qnx.media.impl.mmr.MMROutput;
+ import qnx.system.QNXSystem;
+ import qnx.ui.core.UIComponent;
+ import qnx.ui.events.MediaControlEvent;
+ import qnx.ui.media.MediaControl;
+ import qnx.ui.media.MediaControlOption;
+ import qnx.ui.media.MediaControlProperty;
+ import qnx.ui.media.MediaControlState;
+
+ import webworks.config.ConfigConstants;
+ import webworks.config.ConfigData;
+ import webworks.webkit.WebkitEvent;
+
+ public class FullScreenView extends UIComponent
+ {
+ private var _controlLayer:Sprite;
+ private var _hideTimer:Timer;
+ private var _fc:FullscreenClient;
+ private var _mmr:MMR;
+ private var _context:MMRContext;
+ private var window_id:String;
+ private var _output:MMROutput;
+ private var _curPosition:int;
+ private var _bkgColor:uint;
+
+ private var controls:MediaControl;
+
+ private var app:WebWorksAppTemplate;
+
+ public function FullScreenView(fcClient:FullscreenClient)
+ {
+ //Debug.log("Fullscreen controller enabled", Debug.USER_GLOBAL, this);
+ _controlLayer = new Sprite();
+ _hideTimer = new Timer(3000, 1);
+ _bkgColor = 0x000000;
+
+ try {
+ _mmr = new MMR();
+ _fc = fcClient;
+ _fc.addEventListener(FullscreenClientEvent.ENTER, enterFullScreen);
+ _fc.addEventListener(FullscreenClientEvent.EXIT, exitFullScreen);
+ } catch (e:Error) {
+ //Debug.error("Unable to connector mm-renderer");
+ }
+ _hideTimer.addEventListener(TimerEvent.TIMER_COMPLETE, hideControls);
+ var window:IowWindow = IowWindow.getAirWindow();
+ window.sensitivity = IowWindowSensitivity.ALWAYS;
+ super();
+
+ }
+
+ protected override function init():void {
+ __startWidth = Math.max(Screen.mainScreen.bounds.width, Screen.mainScreen.bounds.height);
+ __startHeight = Math.min(Screen.mainScreen.bounds.height, Screen.mainScreen.bounds.width);
+ super.init();
+
+
+ controls = new MediaControl();
+ controls.setOption( MediaControlOption.PLAY_PAUSE, true );
+ controls.setOption( MediaControlOption.SEEKBAR, true );
+ controls.setOption( MediaControlOption.FULLSCREEN, true );
+
+ controls.addEventListener( MediaControlEvent.STATE_CHANGE, playbackChange );
+ controls.addEventListener( MediaControlEvent.PROPERTY_CHANGE, controlPropertyChange );
+
+ _controlLayer.addChild(controls);
+
+ addChild(_controlLayer);
+ }
+
+ private function playbackChange(event:MediaControlEvent):void {
+ if (!_context){
+ return;
+ }
+
+ var state:String = controls.getState();
+ if (state == MediaControlState.PLAY)
+ {
+ if (_context.state.state != "playing") {
+ _context.play();
+ } else {
+ _context.setSpeed(1000);
+ }
+ } else {
+ _context.setSpeed(0);
+ }
+ }
+
+ private function controlPropertyChange( event:MediaControlEvent ):void
+ {
+ switch( event.property )
+ {
+ case MediaControlProperty.POSITION:
+
+ var value:Number = Number( controls.getProperty( MediaControlProperty.POSITION ) );
+ var position:uint = uint( value );
+ _context.seek( position.toString() );
+ break;
+ case MediaControlProperty.FULLSCREEN:
+ //Debug.log("controlPropertyChange - calling fullscreenExited", Debug.USER_GLOBAL, this);
+ _fc.fullscreenExited(true);
+ break;
+ }
+ }
+
+ public override function destroy():void {
+ var window:IowWindow = IowWindow.getAirWindow();
+ window.sensitivity = IowWindowSensitivity.ALPHA_TEST; //This will return
+ super.destroy();
+ if (_mmr)
+ {
+ _mmr.release();
+ _mmr = null;
+ }
+ else
+ {
+ //Debug.error("_mmr.release() called when it does not exist", this);
+ }
+ }
+
+ private function enterFullScreen(event:FullscreenClientEvent):void {
+ //Debug.log("enterFullScreen " + event, Debug.USER_GLOBAL, this);
+ _context = _mmr.openContext(event.context);
+ _context.addEventListener(MMREvent.CONTEXT_READY, contextReady);
+ _context.addEventListener(MMREvent.CONTEXT_CLOSED, contextClosed);
+ _context.addEventListener(MMREvent.STATE_CHANGE, stateChange);
+ _context.addEventListener(MMREvent.METADATA_CHANGE, metadataChange);
+ _context.addEventListener(MMREvent.OUTPUT_ATTACHED, outputAttached);
+ _context.addEventListener(MMREvent.STATUS_CHANGE, statusChange);
+
+ }
+
+ private function exitFullScreen(event:FullscreenClientEvent):void {
+ //Debug.log("exitFullScreen " + event, Debug.USER_GLOBAL, this);
+ if (_context ) {
+ _context.close();
+ if (_output) {
+ _output = null;
+ dispatchEvent(new WebkitEvent(WebkitEvent.FULL_SCREEN_EXIT));
+ }
+ }
+ _hideTimer.stop();
+ Tweener.removeTweens(_controlLayer);
+ _controlLayer.visible = false;
+ IowWindow.getAirWindow().transparency = IowWindowTransparency.ALPHA;
+ IowWindow.getAirWindow().setWindowProperty(61, 0x7673); // SCREEN_CBABC_MODE_UI
+ }
+
+ private function outputAttached(event:MMREvent):void {
+ //Debug.log("outputAttached " + event, Debug.USER_GLOBAL, this);
+ if (MMROutput(event.data).type == "video") {
+ _output = MMROutput(event.data);
+ IowWindow.getAirWindow().setWindowProperty(61, 0x7672); // SCREEN_CBABC_MODE_VIDEO
+ draw();
+ dispatchEvent(new WebkitEvent(WebkitEvent.FULL_SCREEN_ENTER));
+ controls.setProperty( MediaControlProperty.FULLSCREEN, true );
+ showControls(true);
+ }
+ }
+
+ private function onOrientationChanging(e:StageOrientationEvent):void
+ {
+ if (visible) {
+ if (e.afterOrientation == StageOrientation.ROTATED_LEFT || e.afterOrientation == StageOrientation.ROTATED_RIGHT) {
+ e.preventDefault();
+ return;
+ }
+ }
+ }
+
+ protected override function onAdded():void {
+ stage.addEventListener(MouseEvent.MOUSE_DOWN, handleTouch, true);
+ stage.addEventListener(MouseEvent.MOUSE_UP, handleTouch, true);
+ draw();
+ }
+
+ protected override function onRemoved():void {
+ stage.removeEventListener(MouseEvent.MOUSE_DOWN, handleTouch, true);
+ stage.removeEventListener(MouseEvent.MOUSE_UP, handleTouch, true);
+ draw();
+ }
+
+ private function handleTouch(event:MouseEvent):void
+ {
+ if (event.type== MouseEvent.MOUSE_DOWN) {
+ showControls(false);
+ } else if (event.type == MouseEvent.MOUSE_UP) {
+ showControls(true);
+ }
+ }
+
+ private function showControls(startTimer:Boolean):void
+ {
+ IowWindow.getAirWindow().transparency = IowWindowTransparency.ALPHA;
+ _controlLayer.visible = true;
+ Tweener.addTween(_controlLayer, {time:1.0,_autoAlpha:1});
+ _hideTimer.stop();
+ _hideTimer.reset();
+
+ if (startTimer) {
+ _hideTimer.start();
+ }
+
+ }
+
+ private function hideControls(e:TimerEvent):void
+ {
+ var hideComplete:Function = function():void {
+ IowWindow.getAirWindow().transparency = IowWindowTransparency.DISCARD;
+ }
+
+ Tweener.addTween(_controlLayer, {time:1.0,_autoAlpha:0, onComplete:hideComplete});
+ }
+
+ private function contextReady(event:MMREvent):void {
+ if (_context.state.state != "playing") {
+ _context.play();
+ } else {
+ if (_context.state.speed == 0) {
+ controls.setState( MediaControlState.PAUSE );
+ } else {
+ controls.setState( MediaControlState.PLAY );
+ }
+ }
+ controls.setProperty( MediaControlProperty.DURATION, _context.metadata["md_title_duration"] );
+ showControls(true);
+ }
+
+ private function contextClosed(event:MMREvent):void {
+ _context = null;
+ }
+
+ private function metadataChange(event:MMREvent):void {
+ if (event.data["md_title_duration"]) {
+ controls.setProperty( MediaControlProperty.DURATION, _context.metadata["md_title_duration"] );
+ }
+ if (event.data["md_video_height"] || event.data["md_video_width"]) {
+ draw();
+ }
+ }
+
+ private function stateChange(event:MMREvent):void {
+ if (event.data["state"]) {
+ if (_context.state["state"] != "playing") {
+ controls.setState( MediaControlState.STOP );
+ _fc.fullscreenExited(true);
+ } else {
+ controls.setState( MediaControlState.PLAY) ;
+ }
+ } else if (event.data["speed"]) {
+ if (_context.state.speed == 0) {
+ controls.setState( MediaControlState.PAUSE );
+ } else {
+ controls.setState( MediaControlState.PLAY );
+ }
+ }
+ }
+
+ private function statusChange(event:MMREvent):void {
+ if (event.data["position"]) {
+ var position : int;
+ var pos : String = _context.status["position"];
+ position = new int(pos);
+ if (position != _curPosition) {
+ _curPosition = position;
+ controls.setProperty( MediaControlProperty.POSITION, _curPosition );
+ }
+ }
+ }
+
+ private function videoEnabled():Boolean {
+ return _context && _output && stage && visible;
+ }
+
+ /**
+ * @override
+ * @inheritDoc
+ */
+ override public function get visible():Boolean {
+ return super.visible;
+ }
+
+ /**
+ * @override
+ */
+ override public function set visible(value:Boolean):void {
+ super.visible = value;
+ draw();
+ }
+
+ /**
+ * The background color of the VideoDisplay object.
+ */
+ public function set backgroundColor(rgb:uint):void {
+ _bkgColor = rgb;
+ draw();
+ }
+
+ /**
+ * The background color of the VideoDisplay object.
+ *
+ * @param rgb The RGB value of the background color.
+ * @return An RGB value representing the background color.
+ */
+
+ public function get backgroundColor():uint {
+ return _bkgColor;
+ }
+
+ public function get controlLayer():Sprite
+ {
+ return _controlLayer;
+ }
+
+ protected override function draw():void {
+ validate();
+ if (false) {
+ if (width != 0 && height != 0) {
+ drawBars(null);
+ }
+ return;
+ }
+ var dest:Rect = new Rect(0, 0, __width, __height);
+ // adjust dest for aspect ratio
+ var newDest:Rect = fitToSize( new int(_context.metadata["md_video_width"]), new int(_context.metadata["md_video_height"]), dest );
+
+ var tl:Point = new Point(x, y);
+ //tl = parent.localToGlobal(tl);
+ var params:Object = {};
+ params["video_dest_x"] = new String(tl.x + newDest.left);
+ params["video_dest_y"] = new String(tl.y + newDest.top);
+ params["video_dest_w"] = new String(newDest.right - newDest.left);
+ params["video_dest_h"] = new String(newDest.bottom - newDest.top);
+ _context.setOutputParameters(_output, params);
+
+ drawBars(newDest);
+
+ controls.width = __width - 100;
+ controls.y = height - controls.height - 20;
+ controls.x = __width / 2 - controls.width / 2;
+
+ //_control.qnxWebView.zOrder = -1;
+ }
+
+ private function drawBars(videoRect:Rect):void {
+ graphics.clear();
+ graphics.beginFill(_bkgColor);
+ if (videoEnabled() && videoRect != null) {
+ graphics.drawRect(0, 0, __width, videoRect.top); // top
+ graphics.drawRect(0, videoRect.top, videoRect.left, videoRect.height ); //left
+ graphics.drawRect(videoRect.right, videoRect.top, __width - videoRect.right, videoRect.height ); // right
+ graphics.drawRect(0, videoRect.bottom, __width, __height - videoRect.bottom); // bottom
+ } else {
+ graphics.drawRect(0, 0, __width, __height);
+ }
+ graphics.endFill();
+ }
+
+ private function fitToSize( source_width:int, source_height:int, dest:Rect ):Rect {
+ var rect:Rect = new Rect();
+ var tw:int = dest.right - dest.left;
+ var th:int = dest.bottom - dest.top;
+
+ if (source_width == 0) {
+ source_width = dest.right - dest.left;
+ }
+ if (source_height == 0) {
+ source_height = dest.bottom - dest.top;
+ }
+ var ar:Number = source_width / source_height;
+ // calc target size based on AR
+ if ( source_width > source_height ) {
+ // width fit
+ rect.right = tw;
+ rect.bottom = tw / ar;
+ if (rect.bottom > th ) {
+ rect.bottom = th;
+ rect.right = th * ar;
+ }
+ } else {
+ // height fit
+ rect.bottom = th;
+ rect.right = th / ar;
+ if ( rect.right > th ) {
+ rect.right = tw;
+ rect.bottom = tw * ar;
+ }
+ }
+ var xa:int = ( tw - rect.right ) / 2;
+ var ya:int = ( th - rect.bottom ) / 2;
+
+ // calc new dest
+ rect.left = dest.left + xa;
+ rect.top = dest.top + ya;
+ rect.right = rect.left + rect.right;
+ rect.bottom = rect.top + rect.bottom;
+ return( rect );
+ }
+
+ }
+}
+
+class Rect {
+ public var left:uint;
+ public var top:uint;
+ public var right:uint;
+ public var bottom:uint;
+
+ public function Rect(left_:uint = 0, top_:uint = 0, right_:uint = 0, bottom_:uint = 0) {
+ left = left_;
+ top = top_;
+ right = right_;
+ bottom = bottom_;
+ }
+
+ public function get width():uint {
+ return right - left;
+ }
+
+ public function get height():uint {
+ return bottom - top;
+ }
+
+ public function toString():String {
+ return "Rect:( left:" + left + ", top:" + top + ", right:" + right + ", bottom:" + bottom + ")";
+ }
+
+}
View
8 framework/src/webworks/loadingScreen/LoadingScreen.as
@@ -226,5 +226,13 @@ package webworks.loadingScreen
{
isFirstLaunch = false;
}
+
+ public function setLoadingScreenArea(rrect:Rectangle):void
+ {
+ this.x = rrect.x;
+ this.y = rrect.y;
+ this.width = rrect.width;
+ this.height = rrect.height;
+ }
}
}
View
53 framework/src/webworks/loadingScreen/Transitions.as
@@ -18,6 +18,7 @@ package webworks.loadingScreen
import caurina.transitions.Tweener;
import flash.display.DisplayObject;
+ import flash.geom.Rectangle;
import webworks.config.ConfigConstants;
import webworks.config.ConfigData;
@@ -32,10 +33,13 @@ package webworks.loadingScreen
private var type:int = TransitionConstants.TRANSITION_NONE;
private var duration:Number = 0.25; //seconds
private var direction:int = TransitionConstants.DIRECTION_LEFT;
+
+ private var viewPort:Rectangle;
- public function Transitions(target:LoadingScreen)
+ public function Transitions(target:LoadingScreen, viewP:Rectangle)
{
this.loadingScreen = target;
+ this.viewPort = viewP;
setProperties();
}
@@ -68,10 +72,7 @@ package webworks.loadingScreen
public function resetEffect():void
{
Tweener.removeTweens(loadingScreen);
- loadingScreen.x = 0;
- loadingScreen.y = 0;
- loadingScreen.width = 1024;
- loadingScreen.height = 600;
+ loadingScreen.setLoadingScreenArea(viewPort);
loadingScreen.alpha = 1;
}
@@ -98,6 +99,11 @@ package webworks.loadingScreen
nonTransition();
}
+ public function setViewPort(viewP:Rectangle):void
+ {
+ this.viewPort = viewP;
+ }
+
private function nonTransition():void
{
loadingScreen.hideIfNecessary();
@@ -105,13 +111,10 @@ package webworks.loadingScreen
private function zoomIn():void
{
- var w:Number = 1024;
- var h:Number = 600;
+ var w:Number = viewPort.width;
+ var h:Number = viewPort.height;
- loadingScreen.x = w/2;
- loadingScreen.y = h/2;
- loadingScreen.width = 0;
- loadingScreen.height = 0;
+ loadingScreen.setLoadingScreenArea(new Rectangle(w/2, h/2, 0,0));
Tweener.addTween(loadingScreen,{x:0, y:0, width:w, height:h, time:duration, delay:0, alpha:1, onComplete:loadingScreen.hideIfNecessary});
}
@@ -148,36 +151,24 @@ package webworks.loadingScreen
}
private function wipeEffect():void {
- var w:Number = 1024;
- var h:Number = 600;
+ var w:Number = viewPort.width;
+ var h:Number = viewPort.height;
if(direction == TransitionConstants.DIRECTION_LEFT) {
- loadingScreen.x = 0;
- loadingScreen.y = 0;
- loadingScreen.width = 0;
- loadingScreen.height = h;
+ loadingScreen.setLoadingScreenArea(new Rectangle(0,0,0,h));
} else if (direction == TransitionConstants.DIRECTION_RIGHT) {
- loadingScreen.x = w;
- loadingScreen.y = 0;
- loadingScreen.width = 0;
- loadingScreen.height = h;
+ loadingScreen.setLoadingScreenArea(new Rectangle(w,0,0,h));
} else if (direction == TransitionConstants.DIRECTION_UP) {
- loadingScreen.x = 0;
- loadingScreen.y = h;
- loadingScreen.width = w;
- loadingScreen.height = 0;
+ loadingScreen.setLoadingScreenArea(new Rectangle(0,h,w,0));
} else { // TransitionConstants.DIRECTION_DOWN
- loadingScreen.x = 0;
- loadingScreen.y = 0;
- loadingScreen.width = w;
- loadingScreen.height = 0;
+ loadingScreen.setLoadingScreenArea(new Rectangle(0,0,w,0));
}
Tweener.addTween(loadingScreen,{x:0, y:0, width:w, height:h, time:duration, delay:0, alpha:1, onComplete:loadingScreen.hideIfNecessary});
}
private function fadeEffect():void {
loadingScreen.alpha = 0;
- var w:Number = 1024;
- var h:Number = 600;
+ var w:Number = viewPort.width;
+ var h:Number = viewPort.height;
Tweener.addTween(loadingScreen, {alpha:1, time:duration, onComplete:loadingScreen.hideIfNecessary});
}
}
View
24 framework/src/webworks/service/IWebWorksData.as
@@ -0,0 +1,24 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed 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 webworks.service
+{
+ public interface IWebWorksData
+ {
+ function get actionScriptObject():*;
+ function get jsObject():Object;
+ }
+}
View
25 framework/src/webworks/service/IWebWorksService.as
@@ -0,0 +1,25 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed 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 webworks.service
+{
+ import webworks.extension.WebWorksReturnValue;
+
+ public interface IWebWorksService
+ {
+ function execute(operation:String, parameterMap:Object):WebWorksReturnValue;
+ }
+}
View
44 framework/src/webworks/service/ServiceManager.as
@@ -0,0 +1,44 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed 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 webworks.service
+{
+ import flash.utils.Dictionary;
+
+ import webworks.service.blob.BlobManager;
+ import webworks.util.DeviceURL;
+ import webworks.webkit.WebkitControl;
+
+ public class ServiceManager
+ {
+ private var _services:Dictionary;
+
+ public function ServiceManager(webkitControl:WebkitControl)
+ {
+ _services = new Dictionary();
+ _services["services.blob"] = new BlobManager(webkitControl);
+ }
+
+ public function getEndPointForMethod(serviceUrl:String):IWebWorksService
+ {
+ //The URL request comes in the form authority/request_path (ie: services/blob/slice)
+ //Our service keys be the feature name of the requested URL (ie: services/blob)
+ //Convert it to a DeviceURL to take advantage of the built-in parsing
+ var url:DeviceURL = new DeviceURL(serviceUrl);
+ return _services[url.featureName];
+ }
+ }
+}
View
533 framework/src/webworks/service/blob/BlobManager.as
@@ -0,0 +1,533 @@
+/*
+* Copyright 2010 Research In Motion Limited.
+*
+* Licensed 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 webworks.service.blob
+{
+ import flash.events.LocationChangeEvent;
+ import flash.utils.ByteArray;
+ import flash.utils.Dictionary;
+
+ import webworks.extension.WebWorksReturnValue;
+ import webworks.service.IWebWorksService;
+ import webworks.webkit.WebkitControl;
+
+ public class BlobManager implements IWebWorksService {
+ private var _blobRepository:Dictionary;
+
+ private const ERROR_GENERAL_INVALID_OP:Number = 1;
+ private const ERROR_GENERAL_NO_ID:Number = 2;
+ private const ERROR_GENERAL_BLOB_NOT_FOUND:Number = 3;
+
+ private const ERROR_BLOB_INTERNAL:Number = 4;
+
+ private const ERROR_CREATE_NO_BYTES:Number = 5;
+
+ public function BlobManager(webkitControl:WebkitControl) {
+ init(webkitControl);
+ }
+
+ public function createBlob(fromBytes:ByteArray):Blob {
+ //Hash the blob's bytes to generate a unique identifier based on the byte content
+ var blobId:String = MD5.hashBytes(fromBytes);
+ var newBlob:Blob;
+
+ //If the blob already exists in our repository, we return it...
+ if(_blobRepository[blobId]) newBlob = _blobRepository[blobId];
+
+ //...otherwise we create and add it to the repository before returning it
+ else
+ {
+ newBlob = new Blob(blobId, fromBytes);
+ _blobRepository[newBlob.id] = newBlob;
+ }
+
+ return newBlob;
+ }
+
+ public function execute(operation:String, parameters:Object):WebWorksReturnValue
+ {
+ var retVal:WebWorksReturnValue = null;
+
+ try
+ {
+ //Figure out what operation was requested at invoke the specific handler
+ switch(operation)
+ {
+ case "createBlob" : retVal = handleCreate(parameters); break;
+
+ case "getBlob" : retVal = handleGet(parameters); break;
+
+ case "sliceBlob" : retVal = handleSlice(parameters); break;
+
+ default : throw new Error("Blob operation not supported: " + operation, ERROR_GENERAL_INVALID_OP);
+ }
+ }
+ catch(e:Error)
+ {
+ //Catch any exceptions thrown by the Blob and map them to the generic
+ //service-level error code
+ retVal = new WebWorksReturnValue(e.message, ERROR_BLOB_INTERNAL);
+ }
+ finally
+ {
+ return retVal;
+ }
+ }
+
+ private function handleCreate(parameters:Object):WebWorksReturnValue
+ {
+ if(parameters["bytes"] == null) throw new Error("Source bytes not passed to createBlob.", ERROR_CREATE_NO_BYTES);
+
+ return new WebWorksReturnValue(createBlob(parameters["bytes"]));
+ }
+
+ private function handleGet(parameters:Object):WebWorksReturnValue
+ {
+ if(parameters["id"] == null) throw new Error("Blob ID not passed to getBlob.", ERROR_GENERAL_NO_ID);
+
+ var blobId:String = parameters["id"] as String;
+ var blob:Blob = getBlobFromRepository(blobId);
+
+ return new WebWorksReturnValue(blob);
+ }
+
+ private function handleSlice(parameters:Object):WebWorksReturnValue
+ {
+ if(parameters["id"] == null) throw new Error("Blob ID not passed to slice.", ERROR_GENERAL_NO_ID);
+
+ var blobId:String = parameters["id"] as String;
+ var blob:Blob = getBlobFromRepository(blobId);
+
+ //Get the Blob to slice itself and return the sub-array of bytes
+ var slicedBlobBytes:ByteArray = blob.slice(parameters["offset"], parameters["length"]);
+
+ //Create a new Blob based on it...
+ var slicedBlob:Blob = createBlob(slicedBlobBytes);
+
+ //...and return it
+ return new WebWorksReturnValue(slicedBlob);
+ }
+
+ private function getBlobFromRepository(blobId:String):Blob
+ {
+ var blob:Blob = _blobRepository[blobId];
+
+ if(blob == null) throw new Error("Blob not found for ID: " + blobId, ERROR_GENERAL_BLOB_NOT_FOUND);
+
+ return blob;
+ }
+
+ private function init(webkitControl:WebkitControl):void {
+ webkitControl.addEventListener(LocationChangeEvent.LOCATION_CHANGE, onPageChanged);
+ initRepository();
+ }
+
+ private function onPageChanged():void {
+ //Dump the old blob repository when we go to a new page to avoid memory leaks
+ initRepository();
+ }
+
+ private function initRepository():void {
+ _blobRepository = new Dictionary();
+ }
+ }
+}
+
+import flash.utils.ByteArray;
+import flash.utils.Endian;
+
+import webworks.service.IWebWorksData;
+
+internal class Blob implements IWebWorksData
+{
+ import flash.utils.ByteArray;
+
+ import mx.utils.UIDUtil;
+
+ private var _id:String;
+ private var _data:ByteArray;
+ private var _encoding:String;
+
+ private static const ERROR_CREATE_NO_BYTES:Error = new Error("ByteArray required to construct Blob.", 10);
+
+ private static const ERROR_SLICE_NAN_OFFSET:Error = new Error("Invalid offset. Must be a number. Possible undefined value passed.", 20);
+ private static const ERROR_SLICE_INVALID_OFFSET:Error = new Error("Invalid offset. Must be greater than or equal to 0 and " +
+ "less than the length of the blob.", 21);
+ private static const ERROR_SLICE_INVALID_LENGTH:Error = new Error("Invalid length. Must be greater than or equal to 0 and offset + length " +
+ "must be less than the length of the blob.", 22);
+
+
+ public function Blob(id:String, fromBytes:ByteArray, e:String = "")
+ {
+ super();
+
+ if(fromBytes == null) throw ERROR_CREATE_NO_BYTES;
+
+ //The data is a copy of the bytes so we don't hold a reference to the original array.
+ _data = new ByteArray();
+ _data.writeBytes(fromBytes);
+
+ _id = id;
+
+ _encoding = e.toLowerCase();
+ }
+
+ public function slice(offset:Number, length:Number=0):ByteArray
+ {
+ //Check the error conditions
+ if(isNaN(offset)) throw ERROR_SLICE_NAN_OFFSET;
+ if(offset < 0 || offset >= _data.length) throw ERROR_SLICE_INVALID_OFFSET;
+ if(length < 0 || offset + length >= _data.length) throw ERROR_SLICE_INVALID_LENGTH;
+
+ //Copy a new byte array with the requested offset/length...
+ var newBlobBytes:ByteArray = new ByteArray();
+ newBlobBytes.writeBytes(_data, offset, length);
+
+ //...and return it.
+ return newBlobBytes;
+ }
+
+ public function get bytes():ByteArray
+ {
+ return _data;
+ }
+
+ public function get id():String
+ {
+ return _id;
+ }
+
+ //Implementation of IWebWorksData
+ public function get actionScriptObject():*
+ {
+ return this;
+ }
+
+ //Implementation of IWebWorksData
+ public function get jsObject():Object
+ {
+ return {
+ id : _id,
+ length : _data.length
+ };
+ }
+}
+
+/*
+* Helper classes for the Blob's ID generator
+*
+*
+*/
+internal class MD5 {
+
+ public static var digest:ByteArray;
+ /**
+ * Performs the MD5 hash algorithm on a string.
+ *
+ * @param s The string to hash
+ * @return A string containing the hash value of s
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 8.5
+ * @tiptext
+ */
+
+ public static function hash(s:String) :String{
+ //Convert to byteArray and send through hashBinary function
+ // so as to only have complex code in one location
+ var ba:ByteArray = new ByteArray();
+ ba.writeUTFBytes(s);
+ return hashBinary(ba);
+ }
+
+ public static function hashBytes(s:ByteArray) :String{
+ return hashBinary(s);
+ }
+
+ /**
+ * Performs the MD5 hash algorithm on a ByteArray.
+ *
+ * @param s The string to hash
+ * @return A string containing the hash value of s
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 8.5
+ * @tiptext
+ */
+ public static function hashBinary( s:ByteArray ):String {
+ // initialize the md buffers
+ var a:int = 1732584193;
+ var b:int = -271733879;
+ var c:int = -1732584194;
+ var d:int = 271733878;
+
+ // variables to store previous values
+ var aa:int;
+ var bb:int;
+ var cc:int;
+ var dd:int;
+
+ // create the blocks from the string and
+ // save the length as a local var to reduce
+ // lookup in the loop below
+ var x:Array = createBlocks( s );
+ var len:int = x.length;
+
+ // loop over all of the blocks
+ for ( var i:int = 0; i < len; i += 16) {
+ // save previous values
+ aa = a;
+ bb = b;
+ cc = c;
+ dd = d;
+
+ // Round 1
+ a = ff( a, b, c, d, x[int(i+ 0)], 7, -680876936 ); // 1
+ d = ff( d, a, b, c, x[int(i+ 1)], 12, -389564586 ); // 2
+ c = ff( c, d, a, b, x[int(i+ 2)], 17, 606105819 ); // 3
+ b = ff( b, c, d, a, x[int(i+ 3)], 22, -1044525330 ); // 4
+ a = ff( a, b, c, d, x[int(i+ 4)], 7, -176418897 ); // 5
+ d = ff( d, a, b, c, x[int(i+ 5)], 12, 1200080426 ); // 6
+ c = ff( c, d, a, b, x[int(i+ 6)], 17, -1473231341 ); // 7
+ b = ff( b, c, d, a, x[int(i+ 7)], 22, -45705983 ); // 8
+ a = ff( a, b, c, d, x[int(i+ 8)], 7, 1770035416 ); // 9
+ d = ff( d, a, b, c, x[int(i+ 9)], 12, -1958414417 ); // 10
+ c = ff( c, d, a, b, x[int(i+10)], 17, -42063 ); // 11
+ b = ff( b, c, d, a, x[int(i+11)], 22, -1990404162 ); // 12
+ a = ff( a, b, c, d, x[int(i+12)], 7, 1804603682 ); // 13
+ d = ff( d, a, b, c, x[int(i+13)], 12, -40341101 ); // 14
+ c = ff( c, d, a, b, x[int(i+14)], 17, -1502002290 ); // 15
+ b = ff( b, c, d, a, x[int(i+15)], 22, 1236535329 ); // 16
+
+ // Round 2
+ a = gg( a, b, c, d, x[int(i+ 1)], 5, -165796510 ); // 17
+ d = gg( d, a, b, c, x[int(i+ 6)], 9, -1069501632 ); // 18
+ c = gg( c, d, a, b, x[int(i+11)], 14, 643717713 ); // 19
+ b = gg( b, c, d, a, x[int(i+ 0)], 20, -373897302 ); // 20
+ a = gg( a, b, c, d, x[int(i+ 5)], 5, -701558691 ); // 21
+ d = gg( d, a, b, c, x[int(i+10)], 9, 38016083 ); // 22
+ c = gg( c, d, a, b, x[int(i+15)], 14, -660478335 ); // 23
+ b = gg( b, c, d, a, x[int(i+ 4)], 20, -405537848 ); // 24
+ a = gg( a, b, c, d, x[int(i+ 9)], 5, 568446438 ); // 25
+ d = gg( d, a, b, c, x[int(i+14)], 9, -1019803690 ); // 26
+ c = gg( c, d, a, b, x[int(i+ 3)], 14, -187363961 ); // 27
+ b = gg( b, c, d, a, x[int(i+ 8)], 20, 1163531501 ); // 28
+ a = gg( a, b, c, d, x[int(i+13)], 5, -1444681467 ); // 29
+ d = gg( d, a, b, c, x[int(i+ 2)], 9, -51403784 ); // 30
+ c = gg( c, d, a, b, x[int(i+ 7)], 14, 1735328473 ); // 31
+ b = gg( b, c, d, a, x[int(i+12)], 20, -1926607734 ); // 32
+
+ // Round 3
+ a = hh( a, b, c, d, x[int(i+ 5)], 4, -378558 ); // 33
+ d = hh( d, a, b, c, x[int(i+ 8)], 11, -2022574463 ); // 34
+ c = hh( c, d, a, b, x[int(i+11)], 16, 1839030562 ); // 35
+ b = hh( b, c, d, a, x[int(i+14)], 23, -35309556 ); // 36
+ a = hh( a, b, c, d, x[int(i+ 1)], 4, -1530992060 ); // 37
+ d = hh( d, a, b, c, x[int(i+ 4)], 11, 1272893353 ); // 38
+ c = hh( c, d, a, b, x[int(i+ 7)], 16, -155497632 ); // 39
+ b = hh( b, c, d, a, x[int(i+10)], 23, -1094730640 ); // 40
+ a = hh( a, b, c, d, x[int(i+13)], 4, 681279174 ); // 41
+ d = hh( d, a, b, c, x[int(i+ 0)], 11, -358537222 ); // 42
+ c = hh( c, d, a, b, x[int(i+ 3)], 16, -722521979 ); // 43
+ b = hh( b, c, d, a, x[int(i+ 6)], 23, 76029189 ); // 44
+ a = hh( a, b, c, d, x[int(i+ 9)], 4, -640364487 ); // 45
+ d = hh( d, a, b, c, x[int(i+12)], 11, -421815835 ); // 46
+ c = hh( c, d, a, b, x[int(i+15)], 16, 530742520 ); // 47
+ b = hh( b, c, d, a, x[int(i+ 2)], 23, -995338651 ); // 48
+
+ // Round 4
+ a = ii( a, b, c, d, x[int(i+ 0)], 6, -198630844 ); // 49
+ d = ii( d, a, b, c, x[int(i+ 7)], 10, 1126891415 ); // 50
+ c = ii( c, d, a, b, x[int(i+14)], 15, -1416354905 ); // 51
+ b = ii( b, c, d, a, x[int(i+ 5)], 21, -57434055 ); // 52
+ a = ii( a, b, c, d, x[int(i+12)], 6, 1700485571 ); // 53
+ d = ii( d, a, b, c, x[int(i+ 3)], 10, -1894986606 ); // 54
+ c = ii( c, d, a, b, x[int(i+10)], 15, -1051523 ); // 55
+ b = ii( b, c, d, a, x[int(i+ 1)], 21, -2054922799 ); // 56
+ a = ii( a, b, c, d, x[int(i+ 8)], 6, 1873313359 ); // 57
+ d = ii( d, a, b, c, x[int(i+15)], 10, -30611744 ); // 58
+ c = ii( c, d, a, b, x[int(i+ 6)], 15, -1560198380 ); // 59
+ b = ii( b, c, d, a, x[int(i+13)], 21, 1309151649 ); // 60
+ a = ii( a, b, c, d, x[int(i+ 4)], 6, -145523070 ); // 61
+ d = ii( d, a, b, c, x[int(i+11)], 10, -1120210379 ); // 62
+ c = ii( c, d, a, b, x[int(i+ 2)], 15, 718787259 ); // 63
+ b = ii( b, c, d, a, x[int(i+ 9)], 21, -343485551 ); // 64
+
+ a += aa;
+ b += bb;
+ c += cc;
+ d += dd;
+ }
+ digest = new ByteArray()
+ digest.writeInt(a);
+ digest.writeInt(b);
+ digest.writeInt(c);
+ digest.writeInt(d);
+ digest.position = 0;
+ // Finish up by concatening the buffers with their hex output
+ return IntUtil.toHex( a ) + IntUtil.toHex( b ) + IntUtil.toHex( c ) + IntUtil.toHex( d );
+ }
+
+ /**
+ * Auxiliary function f as defined in RFC
+ */
+ private static function f( x:int, y:int, z:int ):int {
+ return ( x & y ) | ( (~x) & z );
+ }
+
+ /**
+ * Auxiliary function g as defined in RFC
+ */
+ private static function g( x:int, y:int, z:int ):int {
+ return ( x & z ) | ( y & (~z) );
+ }
+
+ /**
+ * Auxiliary function h as defined in RFC
+ */
+ private static function h( x:int, y:int, z:int ):int {
+ return x ^ y ^ z;
+ }
+
+ /**
+ * Auxiliary function i as defined in RFC
+ */
+ private static function i( x:int, y:int, z:int ):int {
+ return y ^ ( x | (~z) );
+ }
+
+ /**
+ * A generic transformation function. The logic of ff, gg, hh, and
+ * ii are all the same, minus the function used, so pull that logic
+ * out and simplify the method bodies for the transoformation functions.
+ */
+ private static function transform( func:Function, a:int, b:int, c:int, d:int, x:int, s:int, t:int):int {
+ var tmp:int = a + int( func( b, c, d ) ) + x + t;
+ return IntUtil.rol( tmp, s ) + b;
+ }
+
+ /**
+ * ff transformation function
+ */
+ private static function ff ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int {
+ return transform( f, a, b, c, d, x, s, t );
+ }
+
+ /**
+ * gg transformation function
+ */
+ private static function gg ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int {
+ return transform( g, a, b, c, d, x, s, t );
+ }
+
+ /**
+ * hh transformation function
+ */
+ private static function hh ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int {
+ return transform( h, a, b, c, d, x, s, t );
+ }
+
+ /**
+ * ii transformation function
+ */
+ private static function ii ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int {
+ return transform( i, a, b, c, d, x, s, t );
+ }
+
+ /**
+ * Converts a string to a sequence of 16-word blocks
+ * that we'll do the processing on. Appends padding
+ * and length in the process.
+ *
+ * @param s The string to split into blocks
+ * @return An array containing the blocks that s was
+ * split into.
+ */
+ private static function createBlocks( s:ByteArray ):Array {
+ var blocks:Array = new Array();
+ var len:int = s.length * 8;
+ var mask:int = 0xFF; // ignore hi byte of characters > 0xFF
+ for( var i:int = 0; i < len; i += 8 ) {
+ blocks[ int(i >> 5) ] |= ( s[ i / 8 ] & mask ) << ( i % 32 );
+ }
+
+ // append padding and length
+ blocks[ int(len >> 5) ] |= 0x80 << ( len % 32 );
+ blocks[ int(( ( ( len + 64 ) >>> 9 ) << 4 ) + 14) ] = len;
+ return blocks;
+ }
+}
+
+/**
+ * Contains reusable methods for operations pertaining
+ * to int values.
+ */
+internal class IntUtil {
+
+ /**
+ * Rotates x left n bits
+ *
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 9.0
+ * @tiptext
+ */
+ public static function rol ( x:int, n:int ):int {
+ return ( x << n ) | ( x >>> ( 32 - n ) );
+ }
+
+ /**
+ * Rotates x right n bits
+ *
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 9.0
+ * @tiptext
+ */
+ public static function ror ( x:int, n:int ):uint {
+ var nn:int = 32 - n;
+ return ( x << nn ) | ( x >>> ( 32 - nn ) );
+ }
+
+ /** String for quick lookup of a hex character based on index */
+ private static var hexChars:String = "0123456789abcdef";
+
+ /**
+ * Outputs the hex value of a int, allowing the developer to specify
+ * the endinaness in the process. Hex output is lowercase.
+ *
+ * @param n The int value to output as hex
+ * @param bigEndian Flag to output the int as big or little endian
+ * @return A string of length 8 corresponding to the
+ * hex representation of n ( minus the leading "0x" )
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 9.0
+ * @tiptext
+ */
+ public static function toHex( n:int, bigEndian:Boolean = false ):String {
+ var s:String = "";
+
+ if ( bigEndian ) {
+ for ( var i:int = 0; i < 4; i++ ) {
+ s += hexChars.charAt( ( n >> ( ( 3 - i ) * 8 + 4 ) ) & 0xF )
+ + hexChars.charAt( ( n >> ( ( 3 - i ) * 8 ) ) & 0xF );
+ }
+ } else {
+ for ( var x:int = 0; x < 4; x++ ) {
+ s += hexChars.charAt( ( n >> ( x * 8 + 4 ) ) & 0xF )
+ + hexChars.charAt( ( n >> ( x * 8 ) ) & 0xF );
+ }
+ }
+
+ return s;
+ }
+}
View
8 framework/src/webworks/util/DeviceURL.as
@@ -40,6 +40,14 @@ package webworks.util
}
/**
+ * Returns true if the URI to which a request was made is a child of the services constant
+ */
+ public function isService():Boolean
+ {
+ return _uri.authority == "service";
+ }
+
+ /**
* The raw query string, everything after the first '?' character, and up to the '#' if it exists.
*/
public function get query():String
View
99 framework/src/webworks/util/IntUtil.as
@@ -0,0 +1,99 @@
+/*
+ Copyright (c) 2008, Adobe Systems Incorporated
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Adobe Systems Incorporated nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+package webworks.util {
+
+ import flash.utils.Endian;
+
+ /**
+ * Contains reusable methods for operations pertaining
+ * to int values.
+ */
+ public class IntUtil {
+
+ /**
+ * Rotates x left n bits
+ *
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 9.0
+ * @tiptext
+ */
+ public static function rol ( x:int, n:int ):int {
+ return ( x << n ) | ( x >>> ( 32 - n ) );
+ }
+
+ /**
+ * Rotates x right n bits
+ *
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 9.0
+ * @tiptext
+ */
+ public static function ror ( x:int, n:int ):uint {
+ var nn:int = 32 - n;
+ return ( x << nn ) | ( x >>> ( 32 - nn ) );
+ }
+
+ /** String for quick lookup of a hex character based on index */
+ private static var hexChars:String = "0123456789abcdef";
+
+ /**
+ * Outputs the hex value of a int, allowing the developer to specify
+ * the endinaness in the process. Hex output is lowercase.
+ *
+ * @param n The int value to output as hex
+ * @param bigEndian Flag to output the int as big or little endian
+ * @return A string of length 8 corresponding to the
+ * hex representation of n ( minus the leading "0x" )
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 9.0
+ * @tiptext
+ */
+ public static function toHex( n:int, bigEndian:Boolean = false ):String {
+ var s:String = "";
+
+ if ( bigEndian ) {
+ for ( var i:int = 0; i < 4; i++ ) {
+ s += hexChars.charAt( ( n >> ( ( 3 - i ) * 8 + 4 ) ) & 0xF )
+ + hexChars.charAt( ( n >> ( ( 3 - i ) * 8 ) ) & 0xF );
+ }
+ } else {
+ for ( var x:int = 0; x < 4; x++ ) {
+ s += hexChars.charAt( ( n >> ( x * 8 + 4 ) ) & 0xF )
+ + hexChars.charAt( ( n >> ( x * 8 ) ) & 0xF );
+ }
+ }
+
+ return s;
+ }
+ }
+
+}
View
281 framework/src/webworks/util/MD5.as
@@ -0,0 +1,281 @@
+/*
+ Copyright (c) 2008, Adobe Systems Incorporated
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Adobe Systems Incorporated nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package webworks.util {
+
+ import webworks.util.IntUtil;
+ import flash.utils.ByteArray;
+ /**
+ * The MD5 Message-Digest Algorithm
+ *
+ * Implementation based on algorithm description at
+ * http://www.faqs.org/rfcs/rfc1321.html
+ */
+ public class MD5 {
+
+ public static var digest:ByteArray;
+ /**
+ * Performs the MD5 hash algorithm on a string.
+ *
+ * @param s The string to hash
+ * @return A string containing the hash value of s
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 8.5
+ * @tiptext
+ */
+
+ public static function hash(s:String) :String{
+ //Convert to byteArray and send through hashBinary function
+ // so as to only have complex code in one location
+ var ba:ByteArray = new ByteArray();
+ ba.writeUTFBytes(s);
+ return hashBinary(ba);
+ }
+
+ public static function hashBytes(s:ByteArray) :String{
+ return hashBinary(s);
+ }
+
+ /**
+ * Performs the MD5 hash algorithm on a ByteArray.
+ *
+ * @param s The string to hash
+ * @return A string containing the hash value of s
+ * @langversion ActionScript 3.0
+ * @playerversion Flash 8.5
+ * @tiptext
+ */
+ public static function hashBinary( s:ByteArray ):String {
+ // initialize the md buffers
+ var a:int = 1732584193;
+ var b:int = -271733879;
+ var c:int = -1732584194;
+ var d:int = 271733878;
+
+ // variables to store previous values
+ var aa:int;
+ var bb:int;
+ var cc:int;
+ var dd:int;
+
+ // create the blocks from the string and
+ // save the length as a local var to reduce
+ // lookup in the loop below
+ var x:Array = createBlocks( s );
+ var len:int = x.length;
+
+ // loop over all of the blocks
+ for ( var i:int = 0; i < len; i += 16) {
+ // save previous values
+ aa = a;
+ bb = b;
+ cc = c;
+ dd = d;
+
+ // Round 1
+ a = ff( a, b, c, d, x[int(i+ 0)], 7, -680876936 ); // 1
+ d = ff( d, a, b, c, x[int(i+ 1)], 12, -389564586 ); // 2
+ c = ff( c, d, a, b, x[int(i+ 2)], 17, 606105819 ); // 3
+ b = ff( b, c, d, a, x[int(i+ 3)], 22, -1044525330 ); // 4
+ a = ff( a, b, c, d, x[int(i+ 4)], 7, -176418897 ); // 5
+ d = ff( d, a, b, c, x[int(i+ 5)], 12, 1200080426 ); // 6
+ c = ff( c, d, a, b, x[int(i+ 6)], 17, -1473231341 ); // 7
+ b = ff( b, c, d, a, x[int(i+ 7)], 22, -45705983 ); // 8
+ a = ff( a, b, c, d, x[int(i+ 8)], 7, 1770035416 ); // 9
+ d = ff( d, a, b, c, x[int(i+ 9)], 12, -1958414417 ); // 10
+ c = ff( c, d, a, b, x[int(i+10)], 17, -42063 ); // 11
+ b = ff( b, c, d, a, x[int(i+11)], 22, -1990404162 ); // 12
+ a = ff( a, b, c, d, x[int(i+12)], 7, 1804603682 ); // 13
+ d = ff( d, <