From a9c818418b81b93680170e1a84d4e221e578ad2f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:56:53 +0200 Subject: Adding debian version 6.4.3+dfsg1-1. Signed-off-by: Daniel Baumann --- .../swfupload/Flash/ExternalCall.as | 121 ++ debian/missing-sources/swfupload/Flash/FileItem.as | 112 ++ .../swfupload/Flash/SWFUpload v2.as3proj | 79 + .../missing-sources/swfupload/Flash/SWFUpload.as | 1519 ++++++++++++++++++++ debian/missing-sources/swfupload/Flash/deploy.bat | 3 + .../swfupload/Flash/obj/SWFUpload-v2Config.old | 22 + .../swfupload/Flash/obj/SWFUpload-v2Config.xml | 22 + .../missing-sources/swfupload/Flash/swfupload.swf | Bin 0 -> 12787 bytes 8 files changed, 1878 insertions(+) create mode 100644 debian/missing-sources/swfupload/Flash/ExternalCall.as create mode 100644 debian/missing-sources/swfupload/Flash/FileItem.as create mode 100644 debian/missing-sources/swfupload/Flash/SWFUpload v2.as3proj create mode 100644 debian/missing-sources/swfupload/Flash/SWFUpload.as create mode 100644 debian/missing-sources/swfupload/Flash/deploy.bat create mode 100644 debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.old create mode 100644 debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.xml create mode 100644 debian/missing-sources/swfupload/Flash/swfupload.swf (limited to 'debian/missing-sources/swfupload/Flash') diff --git a/debian/missing-sources/swfupload/Flash/ExternalCall.as b/debian/missing-sources/swfupload/Flash/ExternalCall.as new file mode 100644 index 0000000..091f5ec --- /dev/null +++ b/debian/missing-sources/swfupload/Flash/ExternalCall.as @@ -0,0 +1,121 @@ +package { + import flash.external.ExternalInterface; + + internal class ExternalCall + { + + /*public function ExternalCall() + { + + } + */ + + public static function Simple(callback:String):void { + ExternalInterface.call(callback); + } + public static function FileQueued(callback:String, file_object:Object):void { + ExternalInterface.call(callback, EscapeMessage(file_object)); + } + public static function FileQueueError(callback:String, error_code:Number, file_object:Object, message:String):void { + + ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(error_code), EscapeMessage(message)); + + } + public static function FileDialogComplete(callback:String, num_files_selected:Number, num_files_queued:Number, total_num_files_queued:Number):void { + + ExternalInterface.call(callback, EscapeMessage(num_files_selected), EscapeMessage(num_files_queued), EscapeMessage(total_num_files_queued)); + + } + + public static function UploadStart(callback:String, file_object:Object):void { + ExternalInterface.call(callback, EscapeMessage(file_object)); + } + + public static function UploadProgress(callback:String, file_object:Object, bytes_loaded:uint, bytes_total:uint):void { + + ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(bytes_loaded), EscapeMessage(bytes_total)); + + } + public static function UploadSuccess(callback:String, file_object:Object, server_data:String, responseReceived:Boolean):void { + + ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(server_data), EscapeMessage(responseReceived)); + + } + public static function UploadError(callback:String, error_code:Number, file_object:Object, message:String):void { + + ExternalInterface.call(callback, EscapeMessage(file_object), EscapeMessage(error_code), EscapeMessage(message)); + + } + public static function UploadComplete(callback:String, file_object:Object):void { + + ExternalInterface.call(callback, EscapeMessage(file_object)); + + } + public static function Debug(callback:String, message:String):void { + + ExternalInterface.call(callback, EscapeMessage(message)); + } + + public static function Bool(callback:String):Boolean { + return ExternalInterface.call(callback); + } + + + /* Escapes all the backslashes which are not translated correctly in the Flash -> JavaScript Interface + * + * These functions had to be developed because the ExternalInterface has a bug that simply places the + * value a string in quotes (except for a " which is escaped) in a JavaScript string literal which + * is executed by the browser. These often results in improperly escaped string literals if your + * input string has any backslash characters. For example the string: + * "c:\Program Files\uploadtools\" + * is placed in a string literal (with quotes escaped) and becomes: + * var __flash__temp = "\"c:\Program Files\uploadtools\\""; + * This statement will cause errors when executed by the JavaScript interpreter: + * 1) The first \" is succesfully transformed to a " + * 2) \P is translated to P and the \ is lost + * 3) \u is interpreted as a unicode character and causes an error in IE + * 4) \\ is translated to \ + * 5) leaving an unescaped " which causes an error + * + * I fixed this by escaping \ characters in all outgoing strings. The above escaped string becomes: + * var __flash__temp = "\"c:\\Program Files\\uploadtools\\\""; + * which contains the correct string literal. + * + * Note: The "var __flash__temp = " portion of the example is part of the ExternalInterface not part of + * my escaping routine. + */ + private static function EscapeMessage(message:*):* { + if (message is String) { + message = EscapeString(message); + } + else if (message is Array) { + message = EscapeArray(message); + } + else if (message is Object) { + message = EscapeObject(message); + } + + return message; + } + + private static function EscapeString(message:String):String { + var replacePattern:RegExp = /\\/g; //new RegExp("/\\/", "g"); + return message.replace(replacePattern, "\\\\"); + } + private static function EscapeArray(message_array:Array):Array { + var length:uint = message_array.length; + var i:uint = 0; + for (i; i < length; i++) { + message_array[i] = EscapeMessage(message_array[i]); + } + return message_array; + } + private static function EscapeObject(message_obj:Object):Object { + for (var name:String in message_obj) { + message_obj[name] = EscapeMessage(message_obj[name]); + } + return message_obj; + } + + } +} \ No newline at end of file diff --git a/debian/missing-sources/swfupload/Flash/FileItem.as b/debian/missing-sources/swfupload/Flash/FileItem.as new file mode 100644 index 0000000..9eb3952 --- /dev/null +++ b/debian/missing-sources/swfupload/Flash/FileItem.as @@ -0,0 +1,112 @@ +package { + import flash.net.FileReference; + + internal class FileItem + { + private static var file_id_sequence:Number = 0; // tracks the file id sequence + + private var postObject:Object; + public var file_reference:FileReference; + public var id:String; + public var index:Number = -1; + public var file_status:int = 0; + private var js_object:Object; + + public static var FILE_STATUS_QUEUED:int = -1; + public static var FILE_STATUS_IN_PROGRESS:int = -2; + public static var FILE_STATUS_ERROR:int = -3; + public static var FILE_STATUS_SUCCESS:int = -4; + public static var FILE_STATUS_CANCELLED:int = -5; + public static var FILE_STATUS_NEW:int = -6; // This file status should never be sent to JavaScript + + public function FileItem(file_reference:FileReference, control_id:String, index:Number) + { + this.postObject = {}; + this.file_reference = file_reference; + this.id = control_id + "_" + (FileItem.file_id_sequence++); + this.file_status = FileItem.FILE_STATUS_NEW; + this.index = index; + + this.js_object = { + id: this.id, + index: this.index, + post: this.GetPostObject() + }; + + // Cleanly attempt to retrieve the FileReference info + // this can fail and so is wrapped in try..catch + try { + this.js_object.name = this.file_reference.name; + this.js_object.size = this.file_reference.size; + this.js_object.type = this.file_reference.type || ""; + this.js_object.creationdate = this.file_reference.creationDate || new Date(0); + this.js_object.modificationdate = this.file_reference.modificationDate || new Date(0); + } catch (ex:Error) { + this.file_status = FileItem.FILE_STATUS_ERROR; + } + + this.js_object.filestatus = this.file_status; + } + + public function AddParam(name:String, value:String):void { + this.postObject[name] = value; + } + + public function RemoveParam(name:String):void { + delete this.postObject[name]; + } + + public function GetPostObject(escape:Boolean = false):Object { + if (escape) { + var escapedPostObject:Object = { }; + for (var k:String in this.postObject) { + if (this.postObject.hasOwnProperty(k)) { + var escapedName:String = FileItem.EscapeParamName(k); + escapedPostObject[escapedName] = this.postObject[k]; + } + } + return escapedPostObject; + } else { + return this.postObject; + } + } + + // Create the simply file object that is passed to the browser + public function ToJavaScriptObject():Object { + this.js_object.filestatus = this.file_status; + this.js_object.post = this.GetPostObject(true); + + return this.js_object; + } + + public function toString():String { + return "FileItem - ID: " + this.id; + } + + /* + // The purpose of this function is to escape the property names so when Flash + // passes them back to javascript they can be interpretted correctly. + // ***They have to be unescaped again by JavaScript.** + // + // This works around a bug where Flash sends objects this way: + // object.parametername = "value"; + // instead of + // object["parametername"] = "value"; + // This can be a problem if the parameter name has characters that are not + // allowed in JavaScript identifiers: + // object.parameter.name! = "value"; + // does not work but, + // object["parameter.name!"] = "value"; + // would have worked. + */ + public static function EscapeParamName(name:String):String { + name = name.replace(/[^a-z0-9_]/gi, FileItem.EscapeCharacter); + name = name.replace(/^[0-9]/, FileItem.EscapeCharacter); + return name; + } + public static function EscapeCharacter():String { + return "$" + ("0000" + arguments[0].charCodeAt(0).toString(16)).substr(-4, 4); + } + + } +} \ No newline at end of file diff --git a/debian/missing-sources/swfupload/Flash/SWFUpload v2.as3proj b/debian/missing-sources/swfupload/Flash/SWFUpload v2.as3proj new file mode 100644 index 0000000..302944a --- /dev/null +++ b/debian/missing-sources/swfupload/Flash/SWFUpload v2.as3proj @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + deploy.bat + + + + \ No newline at end of file diff --git a/debian/missing-sources/swfupload/Flash/SWFUpload.as b/debian/missing-sources/swfupload/Flash/SWFUpload.as new file mode 100644 index 0000000..3b0e11d --- /dev/null +++ b/debian/missing-sources/swfupload/Flash/SWFUpload.as @@ -0,0 +1,1519 @@ +package { + import flash.display.BlendMode; + import flash.display.DisplayObjectContainer; + import flash.display.Loader; + import flash.display.Stage; + import flash.display.Sprite; + import flash.display.StageAlign; + import flash.display.StageScaleMode; + import flash.net.FileReferenceList; + import flash.net.FileReference; + import flash.net.FileFilter; + import flash.net.URLRequest; + import flash.net.URLRequestMethod; + import flash.net.URLVariables; + import flash.events.*; + import flash.external.ExternalInterface; + import flash.system.Security; + import flash.text.AntiAliasType; + import flash.text.GridFitType; + import flash.text.StaticText; + import flash.text.StyleSheet; + import flash.text.TextDisplayMode; + import flash.text.TextField; + import flash.text.TextFieldType; + import flash.text.TextFieldAutoSize; + import flash.text.TextFormat; + import flash.ui.Mouse; + import flash.utils.Timer; + + import FileItem; + import ExternalCall; + + public class SWFUpload extends Sprite { + // Cause SWFUpload to start as soon as the movie starts + public static function main():void + { + var SWFUpload:SWFUpload = new SWFUpload(); + } + + private const build_number:String = "SWFUPLOAD 2.2.0"; + + // State tracking variables + private var fileBrowserMany:FileReferenceList = new FileReferenceList(); + private var fileBrowserOne:FileReference = null; // This isn't set because it can't be reused like the FileReferenceList. It gets setup in the SelectFile method + + private var file_queue:Array = new Array(); // holds a list of all items that are to be uploaded. + private var current_file_item:FileItem = null; // the item that is currently being uploaded. + + private var file_index:Array = new Array(); + + private var successful_uploads:Number = 0; // Tracks the uploads that have been completed + private var queue_errors:Number = 0; // Tracks files rejected during queueing + private var upload_errors:Number = 0; // Tracks files that fail upload + private var upload_cancelled:Number = 0; // Tracks number of cancelled files + private var queued_uploads:Number = 0; // Tracks the FileItems that are waiting to be uploaded. + + private var valid_file_extensions:Array = new Array();// Holds the parsed valid extensions. + + private var serverDataTimer:Timer = null; + private var assumeSuccessTimer:Timer = null; + + private var restoreExtIntTimer:Timer; + private var hasCalledFlashReady:Boolean = false; + + // Callbacks + private var flashReady_Callback:String; + private var fileDialogStart_Callback:String; + private var fileQueued_Callback:String; + private var fileQueueError_Callback:String; + private var fileDialogComplete_Callback:String; + + private var uploadStart_Callback:String; + private var uploadProgress_Callback:String; + private var uploadError_Callback:String; + private var uploadSuccess_Callback:String; + + private var uploadComplete_Callback:String; + + private var debug_Callback:String; + private var testExternalInterface_Callback:String; + private var cleanUp_Callback:String; + + // Values passed in from the HTML + private var movieName:String; + private var uploadURL:String; + private var filePostName:String; + private var uploadPostObject:Object; + private var fileTypes:String; + private var fileTypesDescription:String; + private var fileSizeLimit:Number; + private var fileUploadLimit:Number = 0; + private var fileQueueLimit:Number = 0; + private var useQueryString:Boolean = false; + private var requeueOnError:Boolean = false; + private var httpSuccess:Array = []; + private var assumeSuccessTimeout:Number = 0; + private var debugEnabled:Boolean; + + private var buttonLoader:Loader; + private var buttonTextField:TextField; + private var buttonCursorSprite:Sprite; + private var buttonImageURL:String; + private var buttonWidth:Number; + private var buttonHeight:Number; + private var buttonText:String; + private var buttonTextStyle:String; + private var buttonTextTopPadding:Number; + private var buttonTextLeftPadding:Number; + private var buttonAction:Number; + private var buttonCursor:Number; + private var buttonStateOver:Boolean; + private var buttonStateMouseDown:Boolean; + private var buttonStateDisabled:Boolean; + + // Error code "constants" + // Size check constants + private var SIZE_TOO_BIG:Number = 1; + private var SIZE_ZERO_BYTE:Number = -1; + private var SIZE_OK:Number = 0; + + // Queue errors + private var ERROR_CODE_QUEUE_LIMIT_EXCEEDED:Number = -100; + private var ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT:Number = -110; + private var ERROR_CODE_ZERO_BYTE_FILE:Number = -120; + private var ERROR_CODE_INVALID_FILETYPE:Number = -130; + + // Upload Errors + private var ERROR_CODE_HTTP_ERROR:Number = -200; + private var ERROR_CODE_MISSING_UPLOAD_URL:Number = -210; + private var ERROR_CODE_IO_ERROR:Number = -220; + private var ERROR_CODE_SECURITY_ERROR:Number = -230; + private var ERROR_CODE_UPLOAD_LIMIT_EXCEEDED:Number = -240; + private var ERROR_CODE_UPLOAD_FAILED:Number = -250; + private var ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND:Number = -260; + private var ERROR_CODE_FILE_VALIDATION_FAILED:Number = -270; + private var ERROR_CODE_FILE_CANCELLED:Number = -280; + private var ERROR_CODE_UPLOAD_STOPPED:Number = -290; + + + // Button Actions + private var BUTTON_ACTION_SELECT_FILE:Number = -100; + private var BUTTON_ACTION_SELECT_FILES:Number = -110; + private var BUTTON_ACTION_START_UPLOAD:Number = -120; + + private var BUTTON_CURSOR_ARROW:Number = -1; + private var BUTTON_CURSOR_HAND:Number = -2; + + public function SWFUpload() { + // Do the feature detection. Make sure this version of Flash supports the features we need. If not + // abort initialization. + if (!flash.net.FileReferenceList || !flash.net.FileReference || !flash.net.URLRequest || !flash.external.ExternalInterface || !flash.external.ExternalInterface.available || !DataEvent.UPLOAD_COMPLETE_DATA) { + return; + } + + Security.allowDomain("*"); // Allow uploading to any domain + + // Keep Flash Player busy so it doesn't show the "flash script is running slowly" error + var counter:Number = 0; + root.addEventListener(Event.ENTER_FRAME, function ():void { if (++counter > 100) counter = 0; }); + + // Setup file FileReferenceList events + this.fileBrowserMany.addEventListener(Event.SELECT, this.Select_Many_Handler); + this.fileBrowserMany.addEventListener(Event.CANCEL, this.DialogCancelled_Handler); + + + this.stage.align = StageAlign.TOP_LEFT; + this.stage.scaleMode = StageScaleMode.NO_SCALE; + + // Setup the button and text label + this.buttonLoader = new Loader(); + var doNothing:Function = function ():void { }; + this.buttonLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, doNothing ); + this.buttonLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, doNothing ); + this.stage.addChild(this.buttonLoader); + + var self:SWFUpload = this; + + this.stage.addEventListener(MouseEvent.CLICK, function (event:MouseEvent):void { + self.UpdateButtonState(); + self.ButtonClickHandler(event); + }); + this.stage.addEventListener(MouseEvent.MOUSE_DOWN, function (event:MouseEvent):void { + self.buttonStateMouseDown = true; + self.UpdateButtonState(); + }); + this.stage.addEventListener(MouseEvent.MOUSE_UP, function (event:MouseEvent):void { + self.buttonStateMouseDown = false; + self.UpdateButtonState(); + }); + this.stage.addEventListener(MouseEvent.MOUSE_OVER, function (event:MouseEvent):void { + self.buttonStateMouseDown = event.buttonDown; + self.buttonStateOver = true; + self.UpdateButtonState(); + }); + this.stage.addEventListener(MouseEvent.MOUSE_OUT, function (event:MouseEvent):void { + self.buttonStateMouseDown = false; + self.buttonStateOver = false; + self.UpdateButtonState(); + }); + // Handle the mouse leaving the flash movie altogether + this.stage.addEventListener(Event.MOUSE_LEAVE, function (event:Event):void { + self.buttonStateMouseDown = false; + self.buttonStateOver = false; + self.UpdateButtonState(); + }); + + this.buttonTextField = new TextField(); + this.buttonTextField.type = TextFieldType.DYNAMIC; + this.buttonTextField.antiAliasType = AntiAliasType.ADVANCED; + this.buttonTextField.autoSize = TextFieldAutoSize.NONE; + this.buttonTextField.cacheAsBitmap = true; + this.buttonTextField.multiline = true; + this.buttonTextField.wordWrap = false; + this.buttonTextField.tabEnabled = false; + this.buttonTextField.background = false; + this.buttonTextField.border = false; + this.buttonTextField.selectable = false; + this.buttonTextField.condenseWhite = true; + + this.stage.addChild(this.buttonTextField); + + + this.buttonCursorSprite = new Sprite(); + this.buttonCursorSprite.graphics.beginFill(0xFFFFFF, 0); + this.buttonCursorSprite.graphics.drawRect(0, 0, 1, 1); + this.buttonCursorSprite.graphics.endFill(); + this.buttonCursorSprite.buttonMode = true; + this.buttonCursorSprite.x = 0; + this.buttonCursorSprite.y = 0; + this.buttonCursorSprite.addEventListener(MouseEvent.CLICK, doNothing); + this.stage.addChild(this.buttonCursorSprite); + + // Get the movie name + this.movieName = root.loaderInfo.parameters.movieName; + + // **Configure the callbacks** + // The JavaScript tracks all the instances of SWFUpload on a page. We can access the instance + // associated with this SWF file using the movieName. Each callback is accessible by making + // a call directly to it on our instance. There is no error handling for undefined callback functions. + // A developer would have to deliberately remove the default functions,set the variable to null, or remove + // it from the init function. + this.flashReady_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].flashReady"; + this.fileDialogStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogStart"; + this.fileQueued_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueued"; + this.fileQueueError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueueError"; + this.fileDialogComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogComplete"; + + this.uploadStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadStart"; + this.uploadProgress_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadProgress"; + this.uploadError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadError"; + this.uploadSuccess_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadSuccess"; + + this.uploadComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadComplete"; + + this.debug_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].debug"; + + this.testExternalInterface_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].testExternalInterface"; + this.cleanUp_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].cleanUp"; + + // Get the Flash Vars + this.uploadURL = root.loaderInfo.parameters.uploadURL; + this.filePostName = root.loaderInfo.parameters.filePostName; + this.fileTypes = root.loaderInfo.parameters.fileTypes; + this.fileTypesDescription = root.loaderInfo.parameters.fileTypesDescription + " (" + this.fileTypes + ")"; + this.loadPostParams(root.loaderInfo.parameters.params); + + + if (!this.filePostName) { + this.filePostName = "Filedata"; + } + if (!this.fileTypes) { + this.fileTypes = "*.*"; + } + if (!this.fileTypesDescription) { + this.fileTypesDescription = "All Files"; + } + + this.LoadFileExensions(this.fileTypes); + + try { + this.debugEnabled = root.loaderInfo.parameters.debugEnabled == "true" ? true : false; + } catch (ex:Object) { + this.debugEnabled = false; + } + + try { + this.SetFileSizeLimit(String(root.loaderInfo.parameters.fileSizeLimit)); + } catch (ex:Object) { + this.fileSizeLimit = 0; + } + + + try { + this.fileUploadLimit = Number(root.loaderInfo.parameters.fileUploadLimit); + if (this.fileUploadLimit < 0) this.fileUploadLimit = 0; + } catch (ex:Object) { + this.fileUploadLimit = 0; + } + + try { + this.fileQueueLimit = Number(root.loaderInfo.parameters.fileQueueLimit); + if (this.fileQueueLimit < 0) this.fileQueueLimit = 0; + } catch (ex:Object) { + this.fileQueueLimit = 0; + } + + // Set the queue limit to match the upload limit when the queue limit is bigger than the upload limit + if (this.fileQueueLimit > this.fileUploadLimit && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit; + // The the queue limit is unlimited and the upload limit is not then set the queue limit to the upload limit + if (this.fileQueueLimit == 0 && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit; + + try { + this.useQueryString = root.loaderInfo.parameters.useQueryString == "true" ? true : false; + } catch (ex:Object) { + this.useQueryString = false; + } + + try { + this.requeueOnError = root.loaderInfo.parameters.requeueOnError == "true" ? true : false; + } catch (ex:Object) { + this.requeueOnError = false; + } + + try { + this.SetHTTPSuccess(String(root.loaderInfo.parameters.httpSuccess)); + } catch (ex:Object) { + this.SetHTTPSuccess([]); + } + + try { + this.SetAssumeSuccessTimeout(Number(root.loaderInfo.parameters.assumeSuccessTimeout)); + } catch (ex:Object) { + this.SetAssumeSuccessTimeout(0); + } + + + try { + this.SetButtonDimensions(Number(root.loaderInfo.parameters.buttonWidth), Number(root.loaderInfo.parameters.buttonHeight)); + } catch (ex:Object) { + this.SetButtonDimensions(0, 0); + } + + try { + this.SetButtonImageURL(String(root.loaderInfo.parameters.buttonImageURL)); + } catch (ex:Object) { + this.SetButtonImageURL(""); + } + + try { + this.SetButtonText(String(root.loaderInfo.parameters.buttonText)); + } catch (ex:Object) { + this.SetButtonText(""); + } + + try { + this.SetButtonTextPadding(Number(root.loaderInfo.parameters.buttonTextLeftPadding), Number(root.loaderInfo.parameters.buttonTextTopPadding)); + } catch (ex:Object) { + this.SetButtonTextPadding(0, 0); + } + + try { + this.SetButtonTextStyle(String(root.loaderInfo.parameters.buttonTextStyle)); + } catch (ex:Object) { + this.SetButtonTextStyle(""); + } + + try { + this.SetButtonAction(Number(root.loaderInfo.parameters.buttonAction)); + } catch (ex:Object) { + this.SetButtonAction(this.BUTTON_ACTION_SELECT_FILES); + } + + try { + this.SetButtonDisabled(root.loaderInfo.parameters.buttonDisabled == "true" ? true : false); + } catch (ex:Object) { + this.SetButtonDisabled(Boolean(false)); + } + + try { + this.SetButtonCursor(Number(root.loaderInfo.parameters.buttonCursor)); + } catch (ex:Object) { + this.SetButtonCursor(this.BUTTON_CURSOR_ARROW); + } + + this.SetupExternalInterface(); + + this.Debug("SWFUpload Init Complete"); + this.PrintDebugInfo(); + + if (ExternalCall.Bool(this.testExternalInterface_Callback)) { + ExternalCall.Simple(this.flashReady_Callback); + this.hasCalledFlashReady = true; + } + + // Start periodically checking the external interface + var oSelf:SWFUpload = this; + this.restoreExtIntTimer = new Timer(1000, 0); + this.restoreExtIntTimer.addEventListener(TimerEvent.TIMER, function ():void { oSelf.CheckExternalInterface();} ); + this.restoreExtIntTimer.start(); + } + + // Used to periodically check that the External Interface functions are still working + private function CheckExternalInterface():void { + if (!ExternalCall.Bool(this.testExternalInterface_Callback)) { + this.SetupExternalInterface(); + this.Debug("ExternalInterface reinitialized"); + if (!this.hasCalledFlashReady) { + ExternalCall.Simple(this.flashReady_Callback); + this.hasCalledFlashReady = true; + } + } + } + + // Called by JS to see if it can access the external interface + private function TestExternalInterface():Boolean { + return true; + } + + private function SetupExternalInterface():void { + try { + ExternalInterface.addCallback("SelectFile", this.SelectFile); + ExternalInterface.addCallback("SelectFiles", this.SelectFiles); + ExternalInterface.addCallback("StartUpload", this.StartUpload); + ExternalInterface.addCallback("ReturnUploadStart", this.ReturnUploadStart); + ExternalInterface.addCallback("StopUpload", this.StopUpload); + ExternalInterface.addCallback("CancelUpload", this.CancelUpload); + ExternalInterface.addCallback("RequeueUpload", this.RequeueUpload); + + ExternalInterface.addCallback("GetStats", this.GetStats); + ExternalInterface.addCallback("SetStats", this.SetStats); + ExternalInterface.addCallback("GetFile", this.GetFile); + ExternalInterface.addCallback("GetFileByIndex", this.GetFileByIndex); + + ExternalInterface.addCallback("AddFileParam", this.AddFileParam); + ExternalInterface.addCallback("RemoveFileParam", this.RemoveFileParam); + + ExternalInterface.addCallback("SetUploadURL", this.SetUploadURL); + ExternalInterface.addCallback("SetPostParams", this.SetPostParams); + ExternalInterface.addCallback("SetFileTypes", this.SetFileTypes); + ExternalInterface.addCallback("SetFileSizeLimit", this.SetFileSizeLimit); + ExternalInterface.addCallback("SetFileUploadLimit", this.SetFileUploadLimit); + ExternalInterface.addCallback("SetFileQueueLimit", this.SetFileQueueLimit); + ExternalInterface.addCallback("SetFilePostName", this.SetFilePostName); + ExternalInterface.addCallback("SetUseQueryString", this.SetUseQueryString); + ExternalInterface.addCallback("SetRequeueOnError", this.SetRequeueOnError); + ExternalInterface.addCallback("SetHTTPSuccess", this.SetHTTPSuccess); + ExternalInterface.addCallback("SetAssumeSuccessTimeout", this.SetAssumeSuccessTimeout); + ExternalInterface.addCallback("SetDebugEnabled", this.SetDebugEnabled); + + ExternalInterface.addCallback("SetButtonImageURL", this.SetButtonImageURL); + ExternalInterface.addCallback("SetButtonDimensions", this.SetButtonDimensions); + ExternalInterface.addCallback("SetButtonText", this.SetButtonText); + ExternalInterface.addCallback("SetButtonTextPadding", this.SetButtonTextPadding); + ExternalInterface.addCallback("SetButtonTextStyle", this.SetButtonTextStyle); + ExternalInterface.addCallback("SetButtonAction", this.SetButtonAction); + ExternalInterface.addCallback("SetButtonDisabled", this.SetButtonDisabled); + ExternalInterface.addCallback("SetButtonCursor", this.SetButtonCursor); + + ExternalInterface.addCallback("TestExternalInterface", this.TestExternalInterface); + + } catch (ex:Error) { + this.Debug("Callbacks where not set: " + ex.message); + return; + } + + ExternalCall.Simple(this.cleanUp_Callback); + } + + /* ***************************************** + * FileReference Event Handlers + * *************************************** */ + private function DialogCancelled_Handler(event:Event):void { + this.Debug("Event: fileDialogComplete: File Dialog window cancelled."); + ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, 0, 0, this.queued_uploads); + } + + private function Open_Handler(event:Event):void { + this.Debug("Event: uploadProgress (OPEN): File ID: " + this.current_file_item.id); + ExternalCall.UploadProgress(this.uploadProgress_Callback, this.current_file_item.ToJavaScriptObject(), 0, this.current_file_item.file_reference.size); + } + + private function FileProgress_Handler(event:ProgressEvent):void { + // On early than Mac OS X 10.3 bytesLoaded is always -1, convert this to zero. Do bytesTotal for good measure. + // http://livedocs.adobe.com/flex/3/langref/flash/net/FileReference.html#event:progress + var bytesLoaded:Number = event.bytesLoaded < 0 ? 0 : event.bytesLoaded; + var bytesTotal:Number = event.bytesTotal < 0 ? 0 : event.bytesTotal; + + // Because Flash never fires a complete event if the server doesn't respond after 30 seconds or on Macs if there + // is no content in the response we'll set a timer and assume that the upload is successful after the defined amount of + // time. If the timeout is zero then we won't use the timer. + if (bytesLoaded === bytesTotal && bytesTotal > 0 && this.assumeSuccessTimeout > 0) { + if (this.assumeSuccessTimer !== null) { + this.assumeSuccessTimer.stop(); + this.assumeSuccessTimer = null; + } + + this.assumeSuccessTimer = new Timer(this.assumeSuccessTimeout * 1000, 1); + this.assumeSuccessTimer.addEventListener(TimerEvent.TIMER_COMPLETE, AssumeSuccessTimer_Handler); + this.assumeSuccessTimer.start(); + } + + this.Debug("Event: uploadProgress: File ID: " + this.current_file_item.id + ". Bytes: " + bytesLoaded + ". Total: " + bytesTotal); + ExternalCall.UploadProgress(this.uploadProgress_Callback, this.current_file_item.ToJavaScriptObject(), bytesLoaded, bytesTotal); + } + + private function AssumeSuccessTimer_Handler(event:TimerEvent):void { + this.Debug("Event: AssumeSuccess: " + this.assumeSuccessTimeout + " passed without server response"); + this.UploadSuccess(this.current_file_item, "", false); + } + + private function Complete_Handler(event:Event):void { + /* Because we can't do COMPLETE or DATA events (we have to do both) we can't + * just call uploadSuccess from the complete handler, we have to wait for + * the Data event which may never come. However, testing shows it always comes + * within a couple milliseconds if it is going to come so the solution is: + * + * Set a timer in the COMPLETE event (which always fires) and if DATA is fired + * it will stop the timer and call uploadComplete + * + * If the timer expires then DATA won't be fired and we call uploadComplete + * */ + + // Set the timer + if (serverDataTimer != null) { + this.serverDataTimer.stop(); + this.serverDataTimer = null; + } + + this.serverDataTimer = new Timer(100, 1); + //var self:SWFUpload = this; + this.serverDataTimer.addEventListener(TimerEvent.TIMER, this.ServerDataTimer_Handler); + this.serverDataTimer.start(); + } + private function ServerDataTimer_Handler(event:TimerEvent):void { + this.UploadSuccess(this.current_file_item, ""); + } + + private function ServerData_Handler(event:DataEvent):void { + this.UploadSuccess(this.current_file_item, event.data); + } + + private function UploadSuccess(file:FileItem, serverData:String, responseReceived:Boolean = true):void { + if (this.serverDataTimer !== null) { + this.serverDataTimer.stop(); + this.serverDataTimer = null; + } + if (this.assumeSuccessTimer !== null) { + this.assumeSuccessTimer.stop(); + this.assumeSuccessTimer = null; + } + + this.successful_uploads++; + file.file_status = FileItem.FILE_STATUS_SUCCESS; + + this.Debug("Event: uploadSuccess: File ID: " + file.id + " Response Received: " + responseReceived.toString() + " Data: " + serverData); + ExternalCall.UploadSuccess(this.uploadSuccess_Callback, file.ToJavaScriptObject(), serverData, responseReceived); + + this.UploadComplete(false); + + } + + private function HTTPError_Handler(event:HTTPStatusEvent):void { + var isSuccessStatus:Boolean = false; + for (var i:Number = 0; i < this.httpSuccess.length; i++) { + if (this.httpSuccess[i] === event.status) { + isSuccessStatus = true; + break; + } + } + + + if (isSuccessStatus) { + this.Debug("Event: httpError: Translating status code " + event.status + " to uploadSuccess"); + + var serverDataEvent:DataEvent = new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, ""); + this.ServerData_Handler(serverDataEvent); + } else { + this.upload_errors++; + this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; + + this.Debug("Event: uploadError: HTTP ERROR : File ID: " + this.current_file_item.id + ". HTTP Status: " + event.status + "."); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_HTTP_ERROR, this.current_file_item.ToJavaScriptObject(), event.status.toString()); + this.UploadComplete(true); // An IO Error is also called so we don't want to complete the upload yet. + } + } + + // Note: Flash Player does not support Uploads that require authentication. Attempting this will trigger an + // IO Error or it will prompt for a username and password and may crash the browser (FireFox/Opera) + private function IOError_Handler(event:IOErrorEvent):void { + // Only trigger an IO Error event if we haven't already done an HTTP error + if (this.current_file_item.file_status != FileItem.FILE_STATUS_ERROR) { + this.upload_errors++; + this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; + + this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". IO Error: " + event.text); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_IO_ERROR, this.current_file_item.ToJavaScriptObject(), event.text); + } + + this.UploadComplete(true); + } + + private function SecurityError_Handler(event:SecurityErrorEvent):void { + this.upload_errors++; + this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; + + this.Debug("Event: uploadError : Security Error : File Number: " + this.current_file_item.id + ". Error text: " + event.text); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SECURITY_ERROR, this.current_file_item.ToJavaScriptObject(), event.text); + + this.UploadComplete(true); + } + + private function Select_Many_Handler(event:Event):void { + this.Select_Handler(this.fileBrowserMany.fileList); + } + private function Select_One_Handler(event:Event):void { + var fileArray:Array = new Array(1); + fileArray[0] = this.fileBrowserOne; + this.Select_Handler(fileArray); + } + + private function Select_Handler(file_reference_list:Array):void { + this.Debug("Select Handler: Received the files selected from the dialog. Processing the file list..."); + + var num_files_queued:Number = 0; + + // Determine how many queue slots are remaining (check the unlimited (0) settings, successful uploads and queued uploads) + var queue_slots_remaining:Number = 0; + if (this.fileUploadLimit == 0) { + queue_slots_remaining = this.fileQueueLimit == 0 ? file_reference_list.length : (this.fileQueueLimit - this.queued_uploads); // If unlimited queue make the allowed size match however many files were selected. + } else { + var remaining_uploads:Number = this.fileUploadLimit - this.successful_uploads - this.queued_uploads; + if (remaining_uploads < 0) remaining_uploads = 0; + if (this.fileQueueLimit == 0 || this.fileQueueLimit >= remaining_uploads) { + queue_slots_remaining = remaining_uploads; + } else if (this.fileQueueLimit < remaining_uploads) { + queue_slots_remaining = this.fileQueueLimit - this.queued_uploads; + } + } + + if (queue_slots_remaining < 0) queue_slots_remaining = 0; + + // Check if the number of files selected is greater than the number allowed to queue up. + if (queue_slots_remaining < file_reference_list.length) { + this.Debug("Event: fileQueueError : Selected Files (" + file_reference_list.length + ") exceeds remaining Queue size (" + queue_slots_remaining + ")."); + ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_QUEUE_LIMIT_EXCEEDED, null, queue_slots_remaining.toString()); + } else { + // Process each selected file + for (var i:Number = 0; i < file_reference_list.length; i++) { + var file_item:FileItem = new FileItem(file_reference_list[i], this.movieName, this.file_index.length); + this.file_index[file_item.index] = file_item; + + // Verify that the file is accessible. Zero byte files and possibly other conditions can cause a file to be inaccessible. + var jsFileObj:Object = file_item.ToJavaScriptObject(); + var is_valid_file_reference:Boolean = (jsFileObj.filestatus !== FileItem.FILE_STATUS_ERROR); + + if (is_valid_file_reference) { + // Check the size, if it's within the limit add it to the upload list. + var size_result:Number = this.CheckFileSize(file_item); + var is_valid_filetype:Boolean = this.CheckFileType(file_item); + if(size_result == this.SIZE_OK && is_valid_filetype) { + file_item.file_status = FileItem.FILE_STATUS_QUEUED; + this.file_queue.push(file_item); + this.queued_uploads++; + num_files_queued++; + this.Debug("Event: fileQueued : File ID: " + file_item.id); + ExternalCall.FileQueued(this.fileQueued_Callback, file_item.ToJavaScriptObject()); + } + else if (!is_valid_filetype) { + file_item.file_reference = null; // Cleanup the object + this.queue_errors++; + this.Debug("Event: fileQueueError : File not of a valid type."); + ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_INVALID_FILETYPE, file_item.ToJavaScriptObject(), "File is not an allowed file type."); + } + else if (size_result == this.SIZE_TOO_BIG) { + file_item.file_reference = null; // Cleanup the object + this.queue_errors++; + this.Debug("Event: fileQueueError : File exceeds size limit."); + ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT, file_item.ToJavaScriptObject(), "File size exceeds allowed limit."); + } + else if (size_result == this.SIZE_ZERO_BYTE) { + file_item.file_reference = null; // Cleanup the object + this.queue_errors++; + this.Debug("Event: fileQueueError : File is zero bytes."); + ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_ZERO_BYTE_FILE, file_item.ToJavaScriptObject(), "File is zero bytes and cannot be uploaded."); + } + } else { + file_item.file_reference = null; // Cleanup the object + this.queue_errors++; + this.Debug("Event: fileQueueError : File is zero bytes or FileReference is invalid."); + ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_ZERO_BYTE_FILE, file_item.ToJavaScriptObject(), "File is zero bytes or cannot be accessed and cannot be uploaded."); + } + } + } + + this.Debug("Event: fileDialogComplete : Finished processing selected files. Files selected: " + file_reference_list.length + ". Files Queued: " + num_files_queued); + ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, file_reference_list.length, num_files_queued, this.queued_uploads); + } + + + /* **************************************************************** + Externally exposed functions + ****************************************************************** */ + // Opens a file browser dialog that allows one file to be selected. + private function SelectFile():void { + this.fileBrowserOne = new FileReference(); + this.fileBrowserOne.addEventListener(Event.SELECT, this.Select_One_Handler); + this.fileBrowserOne.addEventListener(Event.CANCEL, this.DialogCancelled_Handler); + + // Default file type settings + var allowed_file_types:String = "*.*"; + var allowed_file_types_description:String = "All Files"; + + // Get the instance settings + if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes; + if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription; + + this.Debug("Event: fileDialogStart : Browsing files. Single Select. Allowed file types: " + allowed_file_types); + ExternalCall.Simple(this.fileDialogStart_Callback); + + try { + this.fileBrowserOne.browse([new FileFilter(allowed_file_types_description, allowed_file_types)]); + } catch (ex:Error) { + this.Debug("Exception: " + ex.toString()); + } + } + + // Opens a file browser dialog that allows multiple files to be selected. + private function SelectFiles():void { + var allowed_file_types:String = "*.*"; + var allowed_file_types_description:String = "All Files"; + + if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes; + if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription; + + this.Debug("Event: fileDialogStart : Browsing files. Multi Select. Allowed file types: " + allowed_file_types); + ExternalCall.Simple(this.fileDialogStart_Callback); + + try { + this.fileBrowserMany.browse([new FileFilter(allowed_file_types_description, allowed_file_types)]); + } catch (ex:Error) { + this.Debug("Exception: " + ex.toString()); + } + } + + + // Cancel the current upload and stops. Doesn't advance the upload pointer. The current file is requeued at the beginning. + private function StopUpload():void { + if (this.current_file_item != null) { + // Cancel the upload and re-queue the FileItem + this.current_file_item.file_reference.cancel(); + + // Remove the event handlers + this.removeFileReferenceEventListeners(this.current_file_item); + + this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; + this.file_queue.unshift(this.current_file_item); + var js_object:Object = this.current_file_item.ToJavaScriptObject(); + this.current_file_item = null; + + this.Debug("Event: uploadError: upload stopped. File ID: " + js_object.ID); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_STOPPED, js_object, "Upload Stopped"); + this.Debug("Event: uploadComplete. File ID: " + js_object.ID); + ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object); + + this.Debug("StopUpload(): upload stopped."); + } else { + this.Debug("StopUpload(): No file is currently uploading. Nothing to do."); + } + } + + /* Cancels the upload specified by file_id + * If the file is currently uploading it is cancelled and the uploadComplete + * event gets called. + * If the file is not currently uploading then only the uploadCancelled event is fired. + * */ + private function CancelUpload(file_id:String, triggerErrorEvent:Boolean = true):void { + var file_item:FileItem = null; + + // Check the current file item + if (this.current_file_item != null && (this.current_file_item.id == file_id || !file_id)) { + this.current_file_item.file_reference.cancel(); + this.current_file_item.file_status = FileItem.FILE_STATUS_CANCELLED; + this.upload_cancelled++; + + if (triggerErrorEvent) { + this.Debug("Event: uploadError: File ID: " + this.current_file_item.id + ". Cancelled current upload"); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, this.current_file_item.ToJavaScriptObject(), "File Upload Cancelled."); + } else { + this.Debug("Event: cancelUpload: File ID: " + this.current_file_item.id + ". Cancelled current upload. Suppressed uploadError event."); + } + this.UploadComplete(false); + } else if (file_id) { + // Find the file in the queue + var file_index:Number = this.FindIndexInFileQueue(file_id); + if (file_index >= 0) { + // Remove the file from the queue + file_item = FileItem(this.file_queue[file_index]); + file_item.file_status = FileItem.FILE_STATUS_CANCELLED; + this.file_queue[file_index] = null; + this.queued_uploads--; + this.upload_cancelled++; + + // Cancel the file (just for good measure) and make the callback + file_item.file_reference.cancel(); + this.removeFileReferenceEventListeners(file_item); + file_item.file_reference = null; + + if (triggerErrorEvent) { + this.Debug("Event: uploadError : " + file_item.id + ". Cancelled queued upload"); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled"); + } else { + this.Debug("Event: cancelUpload: File ID: " + file_item.id + ". Cancelled current upload. Suppressed uploadError event."); + } + + // Get rid of the file object + file_item = null; + } + } else { + // Get the first file and cancel it + while (this.file_queue.length > 0 && file_item == null) { + // Check that File Reference is valid (if not make sure it's deleted and get the next one on the next loop) + file_item = FileItem(this.file_queue.shift()); // Cast back to a FileItem + if (typeof(file_item) == "undefined") { + file_item = null; + continue; + } + } + + if (file_item != null) { + file_item.file_status = FileItem.FILE_STATUS_CANCELLED; + this.queued_uploads--; + this.upload_cancelled++; + + + // Cancel the file (just for good measure) and make the callback + file_item.file_reference.cancel(); + this.removeFileReferenceEventListeners(file_item); + file_item.file_reference = null; + + if (triggerErrorEvent) { + this.Debug("Event: uploadError : " + file_item.id + ". Cancelled queued upload"); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled"); + } else { + this.Debug("Event: cancelUpload: File ID: " + file_item.id + ". Cancelled current upload. Suppressed uploadError event."); + } + + // Get rid of the file object + file_item = null; + } + + } + + } + + /* Requeues the indicated file. Returns true if successful or if the file is + * already in the queue. Otherwise returns false. + * */ + private function RequeueUpload(fileIdentifier:*):Boolean { + var file:FileItem = null; + if (typeof(fileIdentifier) === "number") { + var fileIndex:Number = Number(fileIdentifier); + if (fileIndex >= 0 && fileIndex < this.file_index.length) { + file = this.file_index[fileIndex]; + } + } else if (typeof(fileIdentifier) === "string") { + file = FindFileInFileIndex(String(fileIdentifier)); + } else { + return false; + } + + if (file !== null) { + if (file.file_status === FileItem.FILE_STATUS_IN_PROGRESS || file.file_status === FileItem.FILE_STATUS_NEW) { + return false; + } else if (file.file_status !== FileItem.FILE_STATUS_QUEUED) { + file.file_status = FileItem.FILE_STATUS_QUEUED; + this.file_queue.unshift(file); + this.queued_uploads++; + } + return true; + } else { + return false; + } + } + + + private function GetStats():Object { + return { + in_progress : this.current_file_item == null ? 0 : 1, + files_queued : this.queued_uploads, + successful_uploads : this.successful_uploads, + upload_errors : this.upload_errors, + upload_cancelled : this.upload_cancelled, + queue_errors : this.queue_errors + }; + } + private function SetStats(stats:Object):void { + this.successful_uploads = typeof(stats["successful_uploads"]) === "number" ? stats["successful_uploads"] : this.successful_uploads; + this.upload_errors = typeof(stats["upload_errors"]) === "number" ? stats["upload_errors"] : this.upload_errors; + this.upload_cancelled = typeof(stats["upload_cancelled"]) === "number" ? stats["upload_cancelled"] : this.upload_cancelled; + this.queue_errors = typeof(stats["queue_errors"]) === "number" ? stats["queue_errors"] : this.queue_errors; + } + + private function GetFile(file_id:String):Object { + var file_index:Number = this.FindIndexInFileQueue(file_id); + if (file_index >= 0) { + var file:FileItem = this.file_queue[file_index]; + } else { + if (this.current_file_item != null) { + file = this.current_file_item; + } else { + for (var i:Number = 0; i < this.file_queue.length; i++) { + file = this.file_queue[i]; + if (file != null) break; + } + } + } + + if (file == null) { + return null; + } else { + return file.ToJavaScriptObject(); + } + + } + + private function GetFileByIndex(index:Number):Object { + if (index < 0 || index > this.file_index.length - 1) { + return null; + } else { + return this.file_index[index].ToJavaScriptObject(); + } + } + + private function AddFileParam(file_id:String, name:String, value:String):Boolean { + var item:FileItem = this.FindFileInFileIndex(file_id); + if (item != null) { + item.AddParam(name, value); + return true; + } + else { + return false; + } + } + private function RemoveFileParam(file_id:String, name:String):Boolean { + var item:FileItem = this.FindFileInFileIndex(file_id); + if (item != null) { + item.RemoveParam(name); + return true; + } + else { + return false; + } + } + + private function SetUploadURL(url:String):void { + if (typeof(url) !== "undefined" && url !== "") { + this.uploadURL = url; + } + } + + private function SetPostParams(post_object:Object):void { + if (typeof(post_object) !== "undefined" && post_object !== null) { + this.uploadPostObject = post_object; + } + } + + private function SetFileTypes(types:String, description:String):void { + this.fileTypes = types; + this.fileTypesDescription = description; + + this.LoadFileExensions(this.fileTypes); + } + + // Sets the file size limit. Accepts size values with units: 100 b, 1KB, 23Mb, 4 Gb + // Parsing is not robust. "100 200 MB KB B GB" parses as "100 MB" + private function SetFileSizeLimit(size:String):void { + var value:Number = 0; + var unit:String = "kb"; + + // Trim the string + var trimPattern:RegExp = /^\s*|\s*$/; + + size = size.toLowerCase(); + size = size.replace(trimPattern, ""); + + + // Get the value part + var values:Array = size.match(/^\d+/); + if (values !== null && values.length > 0) { + value = parseInt(values[0]); + } + if (isNaN(value) || value < 0) value = 0; + + // Get the units part + var units:Array = size.match(/(b|kb|mb|gb)/); + if (units != null && units.length > 0) { + unit = units[0]; + } + + // Set the multiplier for converting the unit to bytes + var multiplier:Number = 1024; + if (unit === "b") + multiplier = 1; + else if (unit === "mb") + multiplier = 1048576; + else if (unit === "gb") + multiplier = 1073741824; + + this.fileSizeLimit = value * multiplier; + } + + private function SetFileUploadLimit(file_upload_limit:Number):void { + if (file_upload_limit < 0) file_upload_limit = 0; + this.fileUploadLimit = file_upload_limit; + } + + private function SetFileQueueLimit(file_queue_limit:Number):void { + if (file_queue_limit < 0) file_queue_limit = 0; + this.fileQueueLimit = file_queue_limit; + } + + private function SetFilePostName(file_post_name:String):void { + if (file_post_name != "") { + this.filePostName = file_post_name; + } + } + + private function SetUseQueryString(use_query_string:Boolean):void { + this.useQueryString = use_query_string; + } + + private function SetRequeueOnError(requeue_on_error:Boolean):void { + this.requeueOnError = requeue_on_error; + } + + private function SetHTTPSuccess(http_status_codes:*):void { + this.httpSuccess = []; + + if (typeof http_status_codes === "string") { + var status_code_strings:Array = http_status_codes.replace(" ", "").split(","); + for each (var http_status_string:String in status_code_strings) + { + try { + this.httpSuccess.push(Number(http_status_string)); + } catch (ex:Object) { + // Ignore errors + this.Debug("Could not add HTTP Success code: " + http_status_string); + } + } + } + else if (typeof http_status_codes === "object" && typeof http_status_codes.length === "number") { + for each (var http_status:* in http_status_codes) + { + try { + this.Debug("adding: " + http_status); + this.httpSuccess.push(Number(http_status)); + } catch (ex:Object) { + this.Debug("Could not add HTTP Success code: " + http_status); + } + } + } + } + + private function SetAssumeSuccessTimeout(timeout_seconds:Number):void { + this.assumeSuccessTimeout = timeout_seconds < 0 ? 0 : timeout_seconds; + } + + private function SetDebugEnabled(debug_enabled:Boolean):void { + this.debugEnabled = debug_enabled; + } + + /* ************************************************************* + Button Handling Functions + *************************************************************** */ + private function SetButtonImageURL(button_image_url:String):void { + this.buttonImageURL = button_image_url; + + try { + if (this.buttonImageURL !== null && this.buttonImageURL !== "") { + this.buttonLoader.load(new URLRequest(this.buttonImageURL)); + } + } catch (ex:Object) { + } + } + + private function ButtonClickHandler(e:MouseEvent):void { + if (!this.buttonStateDisabled) { + if (this.buttonAction === this.BUTTON_ACTION_SELECT_FILE) { + this.SelectFile(); + } + else if (this.buttonAction === this.BUTTON_ACTION_START_UPLOAD) { + this.StartUpload(); + } + else { + this.SelectFiles(); + } + } + } + + private function UpdateButtonState():void { + var xOffset:Number = 0; + var yOffset:Number = 0; + + this.buttonLoader.x = xOffset; + this.buttonLoader.y = yOffset; + + if (this.buttonStateDisabled) { + this.buttonLoader.y = this.buttonHeight * -3 + yOffset; + } + else if (this.buttonStateMouseDown) { + this.buttonLoader.y = this.buttonHeight * -2 + yOffset; + } + else if (this.buttonStateOver) { + this.buttonLoader.y = this.buttonHeight * -1 + yOffset; + } + else { + this.buttonLoader.y = -yOffset; + } + }; + + private function SetButtonDimensions(width:Number = -1, height:Number = -1):void { + if (width >= 0) { + this.buttonWidth = width; + } + if (height >= 0) { + this.buttonHeight = height; + } + + this.buttonTextField.width = this.buttonWidth; + this.buttonTextField.height = this.buttonHeight; + this.buttonCursorSprite.width = this.buttonWidth; + this.buttonCursorSprite.height = this.buttonHeight; + + this.UpdateButtonState(); + } + + private function SetButtonText(button_text:String):void { + this.buttonText = button_text; + + this.SetButtonTextStyle(this.buttonTextStyle); + } + + private function SetButtonTextStyle(button_text_style:String):void { + this.buttonTextStyle = button_text_style; + + var style:StyleSheet = new StyleSheet(); + style.parseCSS(this.buttonTextStyle); + this.buttonTextField.styleSheet = style; + this.buttonTextField.htmlText = this.buttonText; + } + + private function SetButtonTextPadding(left:Number, top:Number):void { + this.buttonTextField.x = this.buttonTextLeftPadding = left; + this.buttonTextField.y = this.buttonTextTopPadding = top; + } + + private function SetButtonDisabled(disabled:Boolean):void { + this.buttonStateDisabled = disabled; + this.UpdateButtonState(); + } + + private function SetButtonAction(button_action:Number):void { + this.buttonAction = button_action; + } + + private function SetButtonCursor(button_cursor:Number):void { + this.buttonCursor = button_cursor; + + this.buttonCursorSprite.useHandCursor = (button_cursor === this.BUTTON_CURSOR_HAND); + } + + /* ************************************************************* + File processing and handling functions + *************************************************************** */ + private function StartUpload(file_id:String = ""):void { + // Only upload a file uploads are being processed. + if (this.current_file_item != null) { + this.Debug("StartUpload(): Upload already in progress. Not starting another upload."); + return; + } + + this.Debug("StartUpload: " + (file_id ? "File ID: " + file_id : "First file in queue")); + + // Check the upload limit + if (this.successful_uploads >= this.fileUploadLimit && this.fileUploadLimit != 0) { + this.Debug("Event: uploadError : Upload limit reached. No more files can be uploaded."); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_LIMIT_EXCEEDED, null, "The upload limit has been reached."); + this.current_file_item = null; + return; + } + + // Get the next file to upload + if (!file_id) { + while (this.file_queue.length > 0 && this.current_file_item == null) { + this.current_file_item = FileItem(this.file_queue.shift()); + if (typeof(this.current_file_item) == "undefined") { + this.current_file_item = null; + } + } + } else { + var file_index:Number = this.FindIndexInFileQueue(file_id); + if (file_index >= 0) { + // Set the file as the current upload and remove it from the queue + this.current_file_item = FileItem(this.file_queue[file_index]); + this.file_queue[file_index] = null; + } else { + this.Debug("Event: uploadError : File ID not found in queue: " + file_id); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND, null, "File ID not found in the queue."); + } + } + + + if (this.current_file_item != null) { + // Trigger the uploadStart event which will call ReturnUploadStart to begin the actual upload + this.Debug("Event: uploadStart : File ID: " + this.current_file_item.id); + + this.current_file_item.file_status = FileItem.FILE_STATUS_IN_PROGRESS; + ExternalCall.UploadStart(this.uploadStart_Callback, this.current_file_item.ToJavaScriptObject()); + } + // Otherwise we've would have looped through all the FileItems. This means the queue is empty) + else { + this.Debug("StartUpload(): No files found in the queue."); + } + } + + // This starts the upload when the user returns TRUE from the uploadStart event. Rather than just have the value returned from + // the function we do a return function call so we can use the setTimeout work-around for Flash/JS circular calls. + private function ReturnUploadStart(start_upload:Boolean):void { + if (this.current_file_item == null) { + this.Debug("ReturnUploadStart called but no file was prepped for uploading. The file may have been cancelled or stopped."); + return; + } + + var js_object:Object; + + if (start_upload) { + try { + // Set the event handlers + this.current_file_item.file_reference.addEventListener(Event.OPEN, this.Open_Handler); + this.current_file_item.file_reference.addEventListener(ProgressEvent.PROGRESS, this.FileProgress_Handler); + this.current_file_item.file_reference.addEventListener(IOErrorEvent.IO_ERROR, this.IOError_Handler); + this.current_file_item.file_reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.SecurityError_Handler); + this.current_file_item.file_reference.addEventListener(HTTPStatusEvent.HTTP_STATUS, this.HTTPError_Handler); + this.current_file_item.file_reference.addEventListener(Event.COMPLETE, this.Complete_Handler); + this.current_file_item.file_reference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, this.ServerData_Handler); + + // Get the request (post values, etc) + var request:URLRequest = this.BuildRequest(); + + if (this.uploadURL.length == 0) { + this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". Upload URL string is empty."); + + // Remove the event handlers + this.removeFileReferenceEventListeners(this.current_file_item); + + this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; + this.file_queue.unshift(this.current_file_item); + js_object = this.current_file_item.ToJavaScriptObject(); + this.current_file_item = null; + + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_MISSING_UPLOAD_URL, js_object, "Upload URL string is empty."); + } else { + this.Debug("ReturnUploadStart(): File accepted by startUpload event and readied for upload. Starting upload to " + request.url + " for File ID: " + this.current_file_item.id); + this.current_file_item.file_status = FileItem.FILE_STATUS_IN_PROGRESS; + this.current_file_item.file_reference.upload(request, this.filePostName, false); + } + } catch (ex:Error) { + this.Debug("ReturnUploadStart: Exception occurred: " + message); + + this.upload_errors++; + this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; + + var message:String = ex.errorID + "\n" + ex.name + "\n" + ex.message + "\n" + ex.getStackTrace(); + this.Debug("Event: uploadError(): Upload Failed. Exception occurred: " + message); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_FAILED, this.current_file_item.ToJavaScriptObject(), message); + + this.UploadComplete(true); + } + } else { + // Remove the event handlers + this.removeFileReferenceEventListeners(this.current_file_item); + + // Re-queue the FileItem + this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; + js_object = this.current_file_item.ToJavaScriptObject(); + this.file_queue.unshift(this.current_file_item); + this.current_file_item = null; + + this.Debug("Event: uploadError : Call to uploadStart returned false. Not uploading the file."); + ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_VALIDATION_FAILED, js_object, "Call to uploadStart return false. Not uploading file."); + this.Debug("Event: uploadComplete : Call to uploadStart returned false. Not uploading the file."); + ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object); + } + } + + // Completes the file upload by deleting it's reference, advancing the pointer. + // Once this event fires a new upload can be started. + private function UploadComplete(eligible_for_requeue:Boolean):void { + var jsFileObj:Object = this.current_file_item.ToJavaScriptObject(); + + this.removeFileReferenceEventListeners(this.current_file_item); + + if (!eligible_for_requeue || this.requeueOnError == false) { + this.current_file_item.file_reference = null; + this.queued_uploads--; + } else if (this.requeueOnError == true) { + this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; + this.file_queue.unshift(this.current_file_item); + } + + this.current_file_item = null; + + this.Debug("Event: uploadComplete : Upload cycle complete."); + ExternalCall.UploadComplete(this.uploadComplete_Callback, jsFileObj); + } + + + /* ************************************************************* + Utility Functions + *************************************************************** */ + + + // Check the size of the file against the allowed file size. If it is less the return TRUE. If it is too large return FALSE + private function CheckFileSize(file_item:FileItem):Number { + if (file_item.file_reference.size == 0) { + return this.SIZE_ZERO_BYTE; + } else if (this.fileSizeLimit != 0 && file_item.file_reference.size > this.fileSizeLimit) { + return this.SIZE_TOO_BIG; + } else { + return this.SIZE_OK; + } + } + + private function CheckFileType(file_item:FileItem):Boolean { + // If no extensions are defined then a *.* was passed and the check is unnecessary + if (this.valid_file_extensions.length == 0) { + return true; + } + + var fileRef:FileReference = file_item.file_reference; + var last_dot_index:Number = fileRef.name.lastIndexOf("."); + var extension:String = ""; + if (last_dot_index >= 0) { + extension = fileRef.name.substr(last_dot_index + 1).toLowerCase(); + } + + var is_valid_filetype:Boolean = false; + for (var i:Number=0; i < this.valid_file_extensions.length; i++) { + if (String(this.valid_file_extensions[i]) == extension) { + is_valid_filetype = true; + break; + } + } + + return is_valid_filetype; + } + + private function BuildRequest():URLRequest { + // Create the request object + var request:URLRequest = new URLRequest(); + request.method = URLRequestMethod.POST; + + var file_post:Object = this.current_file_item.GetPostObject(); + + if (this.useQueryString) { + var pairs:Array = new Array(); + for (key in this.uploadPostObject) { + this.Debug("Global URL Item: " + key + "=" + this.uploadPostObject[key]); + if (this.uploadPostObject.hasOwnProperty(key)) { + pairs.push(escape(key) + "=" + escape(this.uploadPostObject[key])); + } + } + + for (key in file_post) { + this.Debug("File Post Item: " + key + "=" + file_post[key]); + if (file_post.hasOwnProperty(key)) { + pairs.push(escape(key) + "=" + escape(file_post[key])); + } + } + + request.url = this.uploadURL + (this.uploadURL.indexOf("?") > -1 ? "&" : "?") + pairs.join("&"); + + } else { + var key:String; + var post:URLVariables = new URLVariables(); + for (key in this.uploadPostObject) { + this.Debug("Global Post Item: " + key + "=" + this.uploadPostObject[key]); + if (this.uploadPostObject.hasOwnProperty(key)) { + post[key] = this.uploadPostObject[key]; + } + } + + for (key in file_post) { + this.Debug("File Post Item: " + key + "=" + file_post[key]); + if (file_post.hasOwnProperty(key)) { + post[key] = file_post[key]; + } + } + + request.url = this.uploadURL; + request.data = post; + } + + return request; + } + + private function Debug(msg:String):void { + try { + if (this.debugEnabled) { + var lines:Array = msg.split("\n"); + for (var i:Number=0; i < lines.length; i++) { + lines[i] = "SWF DEBUG: " + lines[i]; + } + ExternalCall.Debug(this.debug_Callback, lines.join("\n")); + } + } catch (ex:Error) { + // pretend nothing happened + trace(ex); + } + } + + private function PrintDebugInfo():void { + var debug_info:String = "\n----- SWF DEBUG OUTPUT ----\n"; + debug_info += "Build Number: " + this.build_number + "\n"; + debug_info += "movieName: " + this.movieName + "\n"; + debug_info += "Upload URL: " + this.uploadURL + "\n"; + debug_info += "File Types String: " + this.fileTypes + "\n"; + debug_info += "Parsed File Types: " + this.valid_file_extensions.toString() + "\n"; + debug_info += "HTTP Success: " + this.httpSuccess.join(", ") + "\n"; + debug_info += "File Types Description: " + this.fileTypesDescription + "\n"; + debug_info += "File Size Limit: " + this.fileSizeLimit + " bytes\n"; + debug_info += "File Upload Limit: " + this.fileUploadLimit + "\n"; + debug_info += "File Queue Limit: " + this.fileQueueLimit + "\n"; + debug_info += "Post Params:\n"; + for (var key:String in this.uploadPostObject) { + if (this.uploadPostObject.hasOwnProperty(key)) { + debug_info += " " + key + "=" + this.uploadPostObject[key] + "\n"; + } + } + debug_info += "----- END SWF DEBUG OUTPUT ----\n"; + + this.Debug(debug_info); + } + + private function FindIndexInFileQueue(file_id:String):Number { + for (var i:Number = 0; i < this.file_queue.length; i++) { + var item:FileItem = this.file_queue[i]; + if (item != null && item.id == file_id) return i; + } + + return -1; + } + + private function FindFileInFileIndex(file_id:String):FileItem { + for (var i:Number = 0; i < this.file_index.length; i++) { + var item:FileItem = this.file_index[i]; + if (item != null && item.id == file_id) return item; + } + + return null; + } + + + // Parse the file extensions in to an array so we can validate them agains + // the files selected later. + private function LoadFileExensions(filetypes:String):void { + var extensions:Array = filetypes.split(";"); + this.valid_file_extensions = new Array(); + + for (var i:Number=0; i < extensions.length; i++) { + var extension:String = String(extensions[i]); + var dot_index:Number = extension.lastIndexOf("."); + + if (dot_index >= 0) { + extension = extension.substr(dot_index + 1).toLowerCase(); + } else { + extension = extension.toLowerCase(); + } + + // If one of the extensions is * then we allow all files + if (extension == "*") { + this.valid_file_extensions = new Array(); + break; + } + + this.valid_file_extensions.push(extension); + } + } + + private function loadPostParams(param_string:String):void { + var post_object:Object = {}; + + if (param_string != null) { + var name_value_pairs:Array = param_string.split("&"); + + for (var i:Number = 0; i < name_value_pairs.length; i++) { + var name_value:String = String(name_value_pairs[i]); + var index_of_equals:Number = name_value.indexOf("="); + if (index_of_equals > 0) { + post_object[decodeURIComponent(name_value.substring(0, index_of_equals))] = decodeURIComponent(name_value.substr(index_of_equals + 1)); + } + } + } + this.uploadPostObject = post_object; + } + + private function removeFileReferenceEventListeners(file_item:FileItem):void { + if (file_item != null && file_item.file_reference != null) { + file_item.file_reference.removeEventListener(Event.OPEN, this.Open_Handler); + file_item.file_reference.removeEventListener(ProgressEvent.PROGRESS, this.FileProgress_Handler); + file_item.file_reference.removeEventListener(IOErrorEvent.IO_ERROR, this.IOError_Handler); + file_item.file_reference.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.SecurityError_Handler); + file_item.file_reference.removeEventListener(HTTPStatusEvent.HTTP_STATUS, this.HTTPError_Handler); + file_item.file_reference.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, this.ServerData_Handler); + } + } + + } +} diff --git a/debian/missing-sources/swfupload/Flash/deploy.bat b/debian/missing-sources/swfupload/Flash/deploy.bat new file mode 100644 index 0000000..a6a95f8 --- /dev/null +++ b/debian/missing-sources/swfupload/Flash/deploy.bat @@ -0,0 +1,3 @@ +@echo off +copy ..\swfupload.js ..\..\samples\demos\swfupload +copy swfupload.swf ..\..\samples\demos\swfupload diff --git a/debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.old b/debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.old new file mode 100644 index 0000000..0f4039a --- /dev/null +++ b/debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.old @@ -0,0 +1,22 @@ + + + + + + + + + C:\inetpub\wwwroot\other\swfupload\core\Flash + C:\Program Files (x86)\FlashDevelop\Library\AS3\classes + + + + C:\inetpub\wwwroot\other\swfupload\core\Flash\SWFUpload.as + + #FFFFFF + 15 + + 300 + 300 + + \ No newline at end of file diff --git a/debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.xml b/debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.xml new file mode 100644 index 0000000..0f4039a --- /dev/null +++ b/debian/missing-sources/swfupload/Flash/obj/SWFUpload-v2Config.xml @@ -0,0 +1,22 @@ + + + + + + + + + C:\inetpub\wwwroot\other\swfupload\core\Flash + C:\Program Files (x86)\FlashDevelop\Library\AS3\classes + + + + C:\inetpub\wwwroot\other\swfupload\core\Flash\SWFUpload.as + + #FFFFFF + 15 + + 300 + 300 + + \ No newline at end of file diff --git a/debian/missing-sources/swfupload/Flash/swfupload.swf b/debian/missing-sources/swfupload/Flash/swfupload.swf new file mode 100644 index 0000000..e3f7670 Binary files /dev/null and b/debian/missing-sources/swfupload/Flash/swfupload.swf differ -- cgit v1.2.3