| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 package { 2 import flash.display.BlendMode; 3 import flash.display.DisplayObjectContainer; 4 import flash.display.Loader; 5 import flash.display.Stage; 6 import flash.display.Sprite; 7 import flash.display.StageAlign; 8 import flash.display.StageScaleMode; 9 import flash.net.FileReferenceList; 10 import flash.net.FileReference; 11 import flash.net.FileFilter; 12 import flash.net.URLRequest; 13 import flash.net.URLRequestMethod; 14 import flash.net.URLVariables; 15 import flash.events.*; 16 import flash.external.ExternalInterface; 17 import flash.system.Security; 18 import flash.text.AntiAliasType; 19 import flash.text.GridFitType; 20 import flash.text.StaticText; 21 import flash.text.StyleSheet; 22 import flash.text.TextDisplayMode; 23 import flash.text.TextField; 24 import flash.text.TextFieldType; 25 import flash.text.TextFieldAutoSize; 26 import flash.text.TextFormat; 27 import flash.ui.Mouse; 28 import flash.utils.Timer; 29 30 import FileItem; 31 import ExternalCall; 32 33 public class SWFUpload extends Sprite { 34 // Cause SWFUpload to start as soon as the movie starts 35 public static function main():void 36 { 37 var SWFUpload:SWFUpload = new SWFUpload(); 38 } 39 40 private const build_number:String = "SWFUPLOAD 2.2.0"; 41 42 // State tracking variables 43 private var fileBrowserMany:FileReferenceList = new FileReferenceList(); 44 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 45 46 private var file_queue:Array = new Array(); // holds a list of all items that are to be uploaded. 47 private var current_file_item:FileItem = null; // the item that is currently being uploaded. 48 49 private var file_index:Array = new Array(); 50 51 private var successful_uploads:Number = 0; // Tracks the uploads that have been completed 52 private var queue_errors:Number = 0; // Tracks files rejected during queueing 53 private var upload_errors:Number = 0; // Tracks files that fail upload 54 private var upload_cancelled:Number = 0; // Tracks number of cancelled files 55 private var queued_uploads:Number = 0; // Tracks the FileItems that are waiting to be uploaded. 56 57 private var valid_file_extensions:Array = new Array();// Holds the parsed valid extensions. 58 59 private var serverDataTimer:Timer = null; 60 private var assumeSuccessTimer:Timer = null; 61 62 private var restoreExtIntTimer:Timer; 63 private var hasCalledFlashReady:Boolean = false; 64 65 // Callbacks 66 private var flashReady_Callback:String; 67 private var fileDialogStart_Callback:String; 68 private var fileQueued_Callback:String; 69 private var fileQueueError_Callback:String; 70 private var fileDialogComplete_Callback:String; 71 72 private var uploadStart_Callback:String; 73 private var uploadProgress_Callback:String; 74 private var uploadError_Callback:String; 75 private var uploadSuccess_Callback:String; 76 77 private var uploadComplete_Callback:String; 78 79 private var debug_Callback:String; 80 private var testExternalInterface_Callback:String; 81 private var cleanUp_Callback:String; 82 83 // Values passed in from the HTML 84 private var movieName:String; 85 private var uploadURL:String; 86 private var filePostName:String; 87 private var uploadPostObject:Object; 88 private var fileTypes:String; 89 private var fileTypesDescription:String; 90 private var fileSizeLimit:Number; 91 private var fileUploadLimit:Number = 0; 92 private var fileQueueLimit:Number = 0; 93 private var useQueryString:Boolean = false; 94 private var requeueOnError:Boolean = false; 95 private var httpSuccess:Array = []; 96 private var assumeSuccessTimeout:Number = 0; 97 private var debugEnabled:Boolean; 98 99 private var buttonLoader:Loader; 100 private var buttonTextField:TextField; 101 private var buttonCursorSprite:Sprite; 102 private var buttonImageURL:String; 103 private var buttonWidth:Number; 104 private var buttonHeight:Number; 105 private var buttonText:String; 106 private var buttonTextStyle:String; 107 private var buttonTextTopPadding:Number; 108 private var buttonTextLeftPadding:Number; 109 private var buttonAction:Number; 110 private var buttonCursor:Number; 111 private var buttonStateOver:Boolean; 112 private var buttonStateMouseDown:Boolean; 113 private var buttonStateDisabled:Boolean; 114 115 // Error code "constants" 116 // Size check constants 117 private var SIZE_TOO_BIG:Number = 1; 118 private var SIZE_ZERO_BYTE:Number = -1; 119 private var SIZE_OK:Number = 0; 120 121 // Queue errors 122 private var ERROR_CODE_QUEUE_LIMIT_EXCEEDED:Number = -100; 123 private var ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT:Number = -110; 124 private var ERROR_CODE_ZERO_BYTE_FILE:Number = -120; 125 private var ERROR_CODE_INVALID_FILETYPE:Number = -130; 126 127 // Upload Errors 128 private var ERROR_CODE_HTTP_ERROR:Number = -200; 129 private var ERROR_CODE_MISSING_UPLOAD_URL:Number = -210; 130 private var ERROR_CODE_IO_ERROR:Number = -220; 131 private var ERROR_CODE_SECURITY_ERROR:Number = -230; 132 private var ERROR_CODE_UPLOAD_LIMIT_EXCEEDED:Number = -240; 133 private var ERROR_CODE_UPLOAD_FAILED:Number = -250; 134 private var ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND:Number = -260; 135 private var ERROR_CODE_FILE_VALIDATION_FAILED:Number = -270; 136 private var ERROR_CODE_FILE_CANCELLED:Number = -280; 137 private var ERROR_CODE_UPLOAD_STOPPED:Number = -290; 138 139 140 // Button Actions 141 private var BUTTON_ACTION_SELECT_FILE:Number = -100; 142 private var BUTTON_ACTION_SELECT_FILES:Number = -110; 143 private var BUTTON_ACTION_START_UPLOAD:Number = -120; 144 145 private var BUTTON_CURSOR_ARROW:Number = -1; 146 private var BUTTON_CURSOR_HAND:Number = -2; 147 148 public function SWFUpload() { 149 // Do the feature detection. Make sure this version of Flash supports the features we need. If not 150 // abort initialization. 151 if (!flash.net.FileReferenceList || !flash.net.FileReference || !flash.net.URLRequest || !flash.external.ExternalInterface || !flash.external.ExternalInterface.available || !DataEvent.UPLOAD_COMPLETE_DATA) { 152 return; 153 } 154 155 Security.allowDomain("*"); // Allow uploading to any domain 156 157 // Keep Flash Player busy so it doesn't show the "flash script is running slowly" error 158 var counter:Number = 0; 159 root.addEventListener(Event.ENTER_FRAME, function ():void { if (++counter > 100) counter = 0; }); 160 161 // Setup file FileReferenceList events 162 this.fileBrowserMany.addEventListener(Event.SELECT, this.Select_Many_Handler); 163 this.fileBrowserMany.addEventListener(Event.CANCEL, this.DialogCancelled_Handler); 164 165 166 this.stage.align = StageAlign.TOP_LEFT; 167 this.stage.scaleMode = StageScaleMode.NO_SCALE; 168 169 // Setup the button and text label 170 this.buttonLoader = new Loader(); 171 var doNothing:Function = function ():void { }; 172 this.buttonLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, doNothing ); 173 this.buttonLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, doNothing ); 174 this.stage.addChild(this.buttonLoader); 175 176 var self:SWFUpload = this; 177 178 this.stage.addEventListener(MouseEvent.CLICK, function (event:MouseEvent):void { 179 self.UpdateButtonState(); 180 self.ButtonClickHandler(event); 181 }); 182 this.stage.addEventListener(MouseEvent.MOUSE_DOWN, function (event:MouseEvent):void { 183 self.buttonStateMouseDown = true; 184 self.UpdateButtonState(); 185 }); 186 this.stage.addEventListener(MouseEvent.MOUSE_UP, function (event:MouseEvent):void { 187 self.buttonStateMouseDown = false; 188 self.UpdateButtonState(); 189 }); 190 this.stage.addEventListener(MouseEvent.MOUSE_OVER, function (event:MouseEvent):void { 191 self.buttonStateMouseDown = event.buttonDown; 192 self.buttonStateOver = true; 193 self.UpdateButtonState(); 194 }); 195 this.stage.addEventListener(MouseEvent.MOUSE_OUT, function (event:MouseEvent):void { 196 self.buttonStateMouseDown = false; 197 self.buttonStateOver = false; 198 self.UpdateButtonState(); 199 }); 200 // Handle the mouse leaving the flash movie altogether 201 this.stage.addEventListener(Event.MOUSE_LEAVE, function (event:Event):void { 202 self.buttonStateMouseDown = false; 203 self.buttonStateOver = false; 204 self.UpdateButtonState(); 205 }); 206 207 this.buttonTextField = new TextField(); 208 this.buttonTextField.type = TextFieldType.DYNAMIC; 209 this.buttonTextField.antiAliasType = AntiAliasType.ADVANCED; 210 this.buttonTextField.autoSize = TextFieldAutoSize.NONE; 211 this.buttonTextField.cacheAsBitmap = true; 212 this.buttonTextField.multiline = true; 213 this.buttonTextField.wordWrap = false; 214 this.buttonTextField.tabEnabled = false; 215 this.buttonTextField.background = false; 216 this.buttonTextField.border = false; 217 this.buttonTextField.selectable = false; 218 this.buttonTextField.condenseWhite = true; 219 220 this.stage.addChild(this.buttonTextField); 221 222 223 this.buttonCursorSprite = new Sprite(); 224 this.buttonCursorSprite.graphics.beginFill(0xFFFFFF, 0); 225 this.buttonCursorSprite.graphics.drawRect(0, 0, 1, 1); 226 this.buttonCursorSprite.graphics.endFill(); 227 this.buttonCursorSprite.buttonMode = true; 228 this.buttonCursorSprite.x = 0; 229 this.buttonCursorSprite.y = 0; 230 this.buttonCursorSprite.addEventListener(MouseEvent.CLICK, doNothing); 231 this.stage.addChild(this.buttonCursorSprite); 232 233 // Get the movie name 234 this.movieName = root.loaderInfo.parameters.movieName; 235 236 // **Configure the callbacks** 237 // The JavaScript tracks all the instances of SWFUpload on a page. We can access the instance 238 // associated with this SWF file using the movieName. Each callback is accessible by making 239 // a call directly to it on our instance. There is no error handling for undefined callback functions. 240 // A developer would have to deliberately remove the default functions,set the variable to null, or remove 241 // it from the init function. 242 this.flashReady_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].flashReady"; 243 this.fileDialogStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogStart"; 244 this.fileQueued_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueued"; 245 this.fileQueueError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileQueueError"; 246 this.fileDialogComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].fileDialogComplete"; 247 248 this.uploadStart_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadStart"; 249 this.uploadProgress_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadProgress"; 250 this.uploadError_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadError"; 251 this.uploadSuccess_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadSuccess"; 252 253 this.uploadComplete_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].uploadComplete"; 254 255 this.debug_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].debug"; 256 257 this.testExternalInterface_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].testExternalInterface"; 258 this.cleanUp_Callback = "SWFUpload.instances[\"" + this.movieName + "\"].cleanUp"; 259 260 // Get the Flash Vars 261 this.uploadURL = root.loaderInfo.parameters.uploadURL; 262 this.filePostName = root.loaderInfo.parameters.filePostName; 263 this.fileTypes = root.loaderInfo.parameters.fileTypes; 264 this.fileTypesDescription = root.loaderInfo.parameters.fileTypesDescription + " (" + this.fileTypes + ")"; 265 this.loadPostParams(root.loaderInfo.parameters.params); 266 267 268 if (!this.filePostName) { 269 this.filePostName = "Filedata"; 270 } 271 if (!this.fileTypes) { 272 this.fileTypes = "*.*"; 273 } 274 if (!this.fileTypesDescription) { 275 this.fileTypesDescription = "All Files"; 276 } 277 278 this.LoadFileExensions(this.fileTypes); 279 280 try { 281 this.debugEnabled = root.loaderInfo.parameters.debugEnabled == "true" ? true : false; 282 } catch (ex:Object) { 283 this.debugEnabled = false; 284 } 285 286 try { 287 this.SetFileSizeLimit(String(root.loaderInfo.parameters.fileSizeLimit)); 288 } catch (ex:Object) { 289 this.fileSizeLimit = 0; 290 } 291 292 293 try { 294 this.fileUploadLimit = Number(root.loaderInfo.parameters.fileUploadLimit); 295 if (this.fileUploadLimit < 0) this.fileUploadLimit = 0; 296 } catch (ex:Object) { 297 this.fileUploadLimit = 0; 298 } 299 300 try { 301 this.fileQueueLimit = Number(root.loaderInfo.parameters.fileQueueLimit); 302 if (this.fileQueueLimit < 0) this.fileQueueLimit = 0; 303 } catch (ex:Object) { 304 this.fileQueueLimit = 0; 305 } 306 307 // Set the queue limit to match the upload limit when the queue limit is bigger than the upload limit 308 if (this.fileQueueLimit > this.fileUploadLimit && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit; 309 // The the queue limit is unlimited and the upload limit is not then set the queue limit to the upload limit 310 if (this.fileQueueLimit == 0 && this.fileUploadLimit != 0) this.fileQueueLimit = this.fileUploadLimit; 311 312 try { 313 this.useQueryString = root.loaderInfo.parameters.useQueryString == "true" ? true : false; 314 } catch (ex:Object) { 315 this.useQueryString = false; 316 } 317 318 try { 319 this.requeueOnError = root.loaderInfo.parameters.requeueOnError == "true" ? true : false; 320 } catch (ex:Object) { 321 this.requeueOnError = false; 322 } 323 324 try { 325 this.SetHTTPSuccess(String(root.loaderInfo.parameters.httpSuccess)); 326 } catch (ex:Object) { 327 this.SetHTTPSuccess([]); 328 } 329 330 try { 331 this.SetAssumeSuccessTimeout(Number(root.loaderInfo.parameters.assumeSuccessTimeout)); 332 } catch (ex:Object) { 333 this.SetAssumeSuccessTimeout(0); 334 } 335 336 337 try { 338 this.SetButtonDimensions(Number(root.loaderInfo.parameters.buttonWidth), Number(root.loaderInfo.parameters.buttonHeight)); 339 } catch (ex:Object) { 340 this.SetButtonDimensions(0, 0); 341 } 342 343 try { 344 this.SetButtonImageURL(String(root.loaderInfo.parameters.buttonImageURL)); 345 } catch (ex:Object) { 346 this.SetButtonImageURL(""); 347 } 348 349 try { 350 this.SetButtonText(String(root.loaderInfo.parameters.buttonText)); 351 } catch (ex:Object) { 352 this.SetButtonText(""); 353 } 354 355 try { 356 this.SetButtonTextPadding(Number(root.loaderInfo.parameters.buttonTextLeftPadding), Number(root.loaderInfo.parameters.buttonTextTopPadding)); 357 } catch (ex:Object) { 358 this.SetButtonTextPadding(0, 0); 359 } 360 361 try { 362 this.SetButtonTextStyle(String(root.loaderInfo.parameters.buttonTextStyle)); 363 } catch (ex:Object) { 364 this.SetButtonTextStyle(""); 365 } 366 367 try { 368 this.SetButtonAction(Number(root.loaderInfo.parameters.buttonAction)); 369 } catch (ex:Object) { 370 this.SetButtonAction(this.BUTTON_ACTION_SELECT_FILES); 371 } 372 373 try { 374 this.SetButtonDisabled(root.loaderInfo.parameters.buttonDisabled == "true" ? true : false); 375 } catch (ex:Object) { 376 this.SetButtonDisabled(Boolean(false)); 377 } 378 379 try { 380 this.SetButtonCursor(Number(root.loaderInfo.parameters.buttonCursor)); 381 } catch (ex:Object) { 382 this.SetButtonCursor(this.BUTTON_CURSOR_ARROW); 383 } 384 385 this.SetupExternalInterface(); 386 387 this.Debug("SWFUpload Init Complete"); 388 this.PrintDebugInfo(); 389 390 if (ExternalCall.Bool(this.testExternalInterface_Callback)) { 391 ExternalCall.Simple(this.flashReady_Callback); 392 this.hasCalledFlashReady = true; 393 } 394 395 // Start periodically checking the external interface 396 var oSelf:SWFUpload = this; 397 this.restoreExtIntTimer = new Timer(1000, 0); 398 this.restoreExtIntTimer.addEventListener(TimerEvent.TIMER, function ():void { oSelf.CheckExternalInterface();} ); 399 this.restoreExtIntTimer.start(); 400 } 401 402 // Used to periodically check that the External Interface functions are still working 403 private function CheckExternalInterface():void { 404 if (!ExternalCall.Bool(this.testExternalInterface_Callback)) { 405 this.SetupExternalInterface(); 406 this.Debug("ExternalInterface reinitialized"); 407 if (!this.hasCalledFlashReady) { 408 ExternalCall.Simple(this.flashReady_Callback); 409 this.hasCalledFlashReady = true; 410 } 411 } 412 } 413 414 // Called by JS to see if it can access the external interface 415 private function TestExternalInterface():Boolean { 416 return true; 417 } 418 419 private function SetupExternalInterface():void { 420 try { 421 ExternalInterface.addCallback("SelectFile", this.SelectFile); 422 ExternalInterface.addCallback("SelectFiles", this.SelectFiles); 423 ExternalInterface.addCallback("StartUpload", this.StartUpload); 424 ExternalInterface.addCallback("ReturnUploadStart", this.ReturnUploadStart); 425 ExternalInterface.addCallback("StopUpload", this.StopUpload); 426 ExternalInterface.addCallback("CancelUpload", this.CancelUpload); 427 ExternalInterface.addCallback("RequeueUpload", this.RequeueUpload); 428 429 ExternalInterface.addCallback("GetStats", this.GetStats); 430 ExternalInterface.addCallback("SetStats", this.SetStats); 431 ExternalInterface.addCallback("GetFile", this.GetFile); 432 ExternalInterface.addCallback("GetFileByIndex", this.GetFileByIndex); 433 434 ExternalInterface.addCallback("AddFileParam", this.AddFileParam); 435 ExternalInterface.addCallback("RemoveFileParam", this.RemoveFileParam); 436 437 ExternalInterface.addCallback("SetUploadURL", this.SetUploadURL); 438 ExternalInterface.addCallback("SetPostParams", this.SetPostParams); 439 ExternalInterface.addCallback("SetFileTypes", this.SetFileTypes); 440 ExternalInterface.addCallback("SetFileSizeLimit", this.SetFileSizeLimit); 441 ExternalInterface.addCallback("SetFileUploadLimit", this.SetFileUploadLimit); 442 ExternalInterface.addCallback("SetFileQueueLimit", this.SetFileQueueLimit); 443 ExternalInterface.addCallback("SetFilePostName", this.SetFilePostName); 444 ExternalInterface.addCallback("SetUseQueryString", this.SetUseQueryString); 445 ExternalInterface.addCallback("SetRequeueOnError", this.SetRequeueOnError); 446 ExternalInterface.addCallback("SetHTTPSuccess", this.SetHTTPSuccess); 447 ExternalInterface.addCallback("SetAssumeSuccessTimeout", this.SetAssumeSuccessTimeout); 448 ExternalInterface.addCallback("SetDebugEnabled", this.SetDebugEnabled); 449 450 ExternalInterface.addCallback("SetButtonImageURL", this.SetButtonImageURL); 451 ExternalInterface.addCallback("SetButtonDimensions", this.SetButtonDimensions); 452 ExternalInterface.addCallback("SetButtonText", this.SetButtonText); 453 ExternalInterface.addCallback("SetButtonTextPadding", this.SetButtonTextPadding); 454 ExternalInterface.addCallback("SetButtonTextStyle", this.SetButtonTextStyle); 455 ExternalInterface.addCallback("SetButtonAction", this.SetButtonAction); 456 ExternalInterface.addCallback("SetButtonDisabled", this.SetButtonDisabled); 457 ExternalInterface.addCallback("SetButtonCursor", this.SetButtonCursor); 458 459 ExternalInterface.addCallback("TestExternalInterface", this.TestExternalInterface); 460 461 } catch (ex:Error) { 462 this.Debug("Callbacks where not set: " + ex.message); 463 return; 464 } 465 466 ExternalCall.Simple(this.cleanUp_Callback); 467 } 468 469 /* ***************************************** 470 * FileReference Event Handlers 471 * *************************************** */ 472 private function DialogCancelled_Handler(event:Event):void { 473 this.Debug("Event: fileDialogComplete: File Dialog window cancelled."); 474 ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, 0, 0, this.queued_uploads); 475 } 476 477 private function Open_Handler(event:Event):void { 478 this.Debug("Event: uploadProgress (OPEN): File ID: " + this.current_file_item.id); 479 ExternalCall.UploadProgress(this.uploadProgress_Callback, this.current_file_item.ToJavaScriptObject(), 0, this.current_file_item.file_reference.size); 480 } 481 482 private function FileProgress_Handler(event:ProgressEvent):void { 483 // On early than Mac OS X 10.3 bytesLoaded is always -1, convert this to zero. Do bytesTotal for good measure. 484 // http://livedocs.adobe.com/flex/3/langref/flash/net/FileReference.html#event:progress 485 var bytesLoaded:Number = event.bytesLoaded < 0 ? 0 : event.bytesLoaded; 486 var bytesTotal:Number = event.bytesTotal < 0 ? 0 : event.bytesTotal; 487 488 // Because Flash never fires a complete event if the server doesn't respond after 30 seconds or on Macs if there 489 // is no content in the response we'll set a timer and assume that the upload is successful after the defined amount of 490 // time. If the timeout is zero then we won't use the timer. 491 if (bytesLoaded === bytesTotal && bytesTotal > 0 && this.assumeSuccessTimeout > 0) { 492 if (this.assumeSuccessTimer !== null) { 493 this.assumeSuccessTimer.stop(); 494 this.assumeSuccessTimer = null; 495 } 496 497 this.assumeSuccessTimer = new Timer(this.assumeSuccessTimeout * 1000, 1); 498 this.assumeSuccessTimer.addEventListener(TimerEvent.TIMER_COMPLETE, AssumeSuccessTimer_Handler); 499 this.assumeSuccessTimer.start(); 500 } 501 502 this.Debug("Event: uploadProgress: File ID: " + this.current_file_item.id + ". Bytes: " + bytesLoaded + ". Total: " + bytesTotal); 503 ExternalCall.UploadProgress(this.uploadProgress_Callback, this.current_file_item.ToJavaScriptObject(), bytesLoaded, bytesTotal); 504 } 505 506 private function AssumeSuccessTimer_Handler(event:TimerEvent):void { 507 this.Debug("Event: AssumeSuccess: " + this.assumeSuccessTimeout + " passed without server response"); 508 this.UploadSuccess(this.current_file_item, "", false); 509 } 510 511 private function Complete_Handler(event:Event):void { 512 /* Because we can't do COMPLETE or DATA events (we have to do both) we can't 513 * just call uploadSuccess from the complete handler, we have to wait for 514 * the Data event which may never come. However, testing shows it always comes 515 * within a couple milliseconds if it is going to come so the solution is: 516 * 517 * Set a timer in the COMPLETE event (which always fires) and if DATA is fired 518 * it will stop the timer and call uploadComplete 519 * 520 * If the timer expires then DATA won't be fired and we call uploadComplete 521 * */ 522 523 // Set the timer 524 if (serverDataTimer != null) { 525 this.serverDataTimer.stop(); 526 this.serverDataTimer = null; 527 } 528 529 this.serverDataTimer = new Timer(100, 1); 530 //var self:SWFUpload = this; 531 this.serverDataTimer.addEventListener(TimerEvent.TIMER, this.ServerDataTimer_Handler); 532 this.serverDataTimer.start(); 533 } 534 private function ServerDataTimer_Handler(event:TimerEvent):void { 535 this.UploadSuccess(this.current_file_item, ""); 536 } 537 538 private function ServerData_Handler(event:DataEvent):void { 539 this.UploadSuccess(this.current_file_item, event.data); 540 } 541 542 private function UploadSuccess(file:FileItem, serverData:String, responseReceived:Boolean = true):void { 543 if (this.serverDataTimer !== null) { 544 this.serverDataTimer.stop(); 545 this.serverDataTimer = null; 546 } 547 if (this.assumeSuccessTimer !== null) { 548 this.assumeSuccessTimer.stop(); 549 this.assumeSuccessTimer = null; 550 } 551 552 this.successful_uploads++; 553 file.file_status = FileItem.FILE_STATUS_SUCCESS; 554 555 this.Debug("Event: uploadSuccess: File ID: " + file.id + " Response Received: " + responseReceived.toString() + " Data: " + serverData); 556 ExternalCall.UploadSuccess(this.uploadSuccess_Callback, file.ToJavaScriptObject(), serverData, responseReceived); 557 558 this.UploadComplete(false); 559 560 } 561 562 private function HTTPError_Handler(event:HTTPStatusEvent):void { 563 var isSuccessStatus:Boolean = false; 564 for (var i:Number = 0; i < this.httpSuccess.length; i++) { 565 if (this.httpSuccess[i] === event.status) { 566 isSuccessStatus = true; 567 break; 568 } 569 } 570 571 572 if (isSuccessStatus) { 573 this.Debug("Event: httpError: Translating status code " + event.status + " to uploadSuccess"); 574 575 var serverDataEvent:DataEvent = new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, ""); 576 this.ServerData_Handler(serverDataEvent); 577 } else { 578 this.upload_errors++; 579 this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; 580 581 this.Debug("Event: uploadError: HTTP ERROR : File ID: " + this.current_file_item.id + ". HTTP Status: " + event.status + "."); 582 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_HTTP_ERROR, this.current_file_item.ToJavaScriptObject(), event.status.toString()); 583 this.UploadComplete(true); // An IO Error is also called so we don't want to complete the upload yet. 584 } 585 } 586 587 // Note: Flash Player does not support Uploads that require authentication. Attempting this will trigger an 588 // IO Error or it will prompt for a username and password and may crash the browser (FireFox/Opera) 589 private function IOError_Handler(event:IOErrorEvent):void { 590 // Only trigger an IO Error event if we haven't already done an HTTP error 591 if (this.current_file_item.file_status != FileItem.FILE_STATUS_ERROR) { 592 this.upload_errors++; 593 this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; 594 595 this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". IO Error: " + event.text); 596 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_IO_ERROR, this.current_file_item.ToJavaScriptObject(), event.text); 597 } 598 599 this.UploadComplete(true); 600 } 601 602 private function SecurityError_Handler(event:SecurityErrorEvent):void { 603 this.upload_errors++; 604 this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; 605 606 this.Debug("Event: uploadError : Security Error : File Number: " + this.current_file_item.id + ". Error text: " + event.text); 607 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SECURITY_ERROR, this.current_file_item.ToJavaScriptObject(), event.text); 608 609 this.UploadComplete(true); 610 } 611 612 private function Select_Many_Handler(event:Event):void { 613 this.Select_Handler(this.fileBrowserMany.fileList); 614 } 615 private function Select_One_Handler(event:Event):void { 616 var fileArray:Array = new Array(1); 617 fileArray[0] = this.fileBrowserOne; 618 this.Select_Handler(fileArray); 619 } 620 621 private function Select_Handler(file_reference_list:Array):void { 622 this.Debug("Select Handler: Received the files selected from the dialog. Processing the file list..."); 623 624 var num_files_queued:Number = 0; 625 626 // Determine how many queue slots are remaining (check the unlimited (0) settings, successful uploads and queued uploads) 627 var queue_slots_remaining:Number = 0; 628 if (this.fileUploadLimit == 0) { 629 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. 630 } else { 631 var remaining_uploads:Number = this.fileUploadLimit - this.successful_uploads - this.queued_uploads; 632 if (remaining_uploads < 0) remaining_uploads = 0; 633 if (this.fileQueueLimit == 0 || this.fileQueueLimit >= remaining_uploads) { 634 queue_slots_remaining = remaining_uploads; 635 } else if (this.fileQueueLimit < remaining_uploads) { 636 queue_slots_remaining = this.fileQueueLimit - this.queued_uploads; 637 } 638 } 639 640 if (queue_slots_remaining < 0) queue_slots_remaining = 0; 641 642 // Check if the number of files selected is greater than the number allowed to queue up. 643 if (queue_slots_remaining < file_reference_list.length) { 644 this.Debug("Event: fileQueueError : Selected Files (" + file_reference_list.length + ") exceeds remaining Queue size (" + queue_slots_remaining + ")."); 645 ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_QUEUE_LIMIT_EXCEEDED, null, queue_slots_remaining.toString()); 646 } else { 647 // Process each selected file 648 for (var i:Number = 0; i < file_reference_list.length; i++) { 649 var file_item:FileItem = new FileItem(file_reference_list[i], this.movieName, this.file_index.length); 650 this.file_index[file_item.index] = file_item; 651 652 // Verify that the file is accessible. Zero byte files and possibly other conditions can cause a file to be inaccessible. 653 var jsFileObj:Object = file_item.ToJavaScriptObject(); 654 var is_valid_file_reference:Boolean = (jsFileObj.filestatus !== FileItem.FILE_STATUS_ERROR); 655 656 if (is_valid_file_reference) { 657 // Check the size, if it's within the limit add it to the upload list. 658 var size_result:Number = this.CheckFileSize(file_item); 659 var is_valid_filetype:Boolean = this.CheckFileType(file_item); 660 if(size_result == this.SIZE_OK && is_valid_filetype) { 661 file_item.file_status = FileItem.FILE_STATUS_QUEUED; 662 this.file_queue.push(file_item); 663 this.queued_uploads++; 664 num_files_queued++; 665 this.Debug("Event: fileQueued : File ID: " + file_item.id); 666 ExternalCall.FileQueued(this.fileQueued_Callback, file_item.ToJavaScriptObject()); 667 } 668 else if (!is_valid_filetype) { 669 file_item.file_reference = null; // Cleanup the object 670 this.queue_errors++; 671 this.Debug("Event: fileQueueError : File not of a valid type."); 672 ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_INVALID_FILETYPE, file_item.ToJavaScriptObject(), "File is not an allowed file type."); 673 } 674 else if (size_result == this.SIZE_TOO_BIG) { 675 file_item.file_reference = null; // Cleanup the object 676 this.queue_errors++; 677 this.Debug("Event: fileQueueError : File exceeds size limit."); 678 ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT, file_item.ToJavaScriptObject(), "File size exceeds allowed limit."); 679 } 680 else if (size_result == this.SIZE_ZERO_BYTE) { 681 file_item.file_reference = null; // Cleanup the object 682 this.queue_errors++; 683 this.Debug("Event: fileQueueError : File is zero bytes."); 684 ExternalCall.FileQueueError(this.fileQueueError_Callback, this.ERROR_CODE_ZERO_BYTE_FILE, file_item.ToJavaScriptObject(), "File is zero bytes and cannot be uploaded."); 685 } 686 } else { 687 file_item.file_reference = null; // Cleanup the object 688 this.queue_errors++; 689 this.Debug("Event: fileQueueError : File is zero bytes or FileReference is invalid."); 690 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."); 691 } 692 } 693 } 694 695 this.Debug("Event: fileDialogComplete : Finished processing selected files. Files selected: " + file_reference_list.length + ". Files Queued: " + num_files_queued); 696 ExternalCall.FileDialogComplete(this.fileDialogComplete_Callback, file_reference_list.length, num_files_queued, this.queued_uploads); 697 } 698 699 700 /* **************************************************************** 701 Externally exposed functions 702 ****************************************************************** */ 703 // Opens a file browser dialog that allows one file to be selected. 704 private function SelectFile():void { 705 this.fileBrowserOne = new FileReference(); 706 this.fileBrowserOne.addEventListener(Event.SELECT, this.Select_One_Handler); 707 this.fileBrowserOne.addEventListener(Event.CANCEL, this.DialogCancelled_Handler); 708 709 // Default file type settings 710 var allowed_file_types:String = "*.*"; 711 var allowed_file_types_description:String = "All Files"; 712 713 // Get the instance settings 714 if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes; 715 if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription; 716 717 this.Debug("Event: fileDialogStart : Browsing files. Single Select. Allowed file types: " + allowed_file_types); 718 ExternalCall.Simple(this.fileDialogStart_Callback); 719 720 try { 721 this.fileBrowserOne.browse([new FileFilter(allowed_file_types_description, allowed_file_types)]); 722 } catch (ex:Error) { 723 this.Debug("Exception: " + ex.toString()); 724 } 725 } 726 727 // Opens a file browser dialog that allows multiple files to be selected. 728 private function SelectFiles():void { 729 var allowed_file_types:String = "*.*"; 730 var allowed_file_types_description:String = "All Files"; 731 732 if (this.fileTypes.length > 0) allowed_file_types = this.fileTypes; 733 if (this.fileTypesDescription.length > 0) allowed_file_types_description = this.fileTypesDescription; 734 735 this.Debug("Event: fileDialogStart : Browsing files. Multi Select. Allowed file types: " + allowed_file_types); 736 ExternalCall.Simple(this.fileDialogStart_Callback); 737 738 try { 739 this.fileBrowserMany.browse([new FileFilter(allowed_file_types_description, allowed_file_types)]); 740 } catch (ex:Error) { 741 this.Debug("Exception: " + ex.toString()); 742 } 743 } 744 745 746 // Cancel the current upload and stops. Doesn't advance the upload pointer. The current file is requeued at the beginning. 747 private function StopUpload():void { 748 if (this.current_file_item != null) { 749 // Cancel the upload and re-queue the FileItem 750 this.current_file_item.file_reference.cancel(); 751 752 // Remove the event handlers 753 this.removeFileReferenceEventListeners(this.current_file_item); 754 755 this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; 756 this.file_queue.unshift(this.current_file_item); 757 var js_object:Object = this.current_file_item.ToJavaScriptObject(); 758 this.current_file_item = null; 759 760 this.Debug("Event: uploadError: upload stopped. File ID: " + js_object.ID); 761 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_STOPPED, js_object, "Upload Stopped"); 762 this.Debug("Event: uploadComplete. File ID: " + js_object.ID); 763 ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object); 764 765 this.Debug("StopUpload(): upload stopped."); 766 } else { 767 this.Debug("StopUpload(): No file is currently uploading. Nothing to do."); 768 } 769 } 770 771 /* Cancels the upload specified by file_id 772 * If the file is currently uploading it is cancelled and the uploadComplete 773 * event gets called. 774 * If the file is not currently uploading then only the uploadCancelled event is fired. 775 * */ 776 private function CancelUpload(file_id:String, triggerErrorEvent:Boolean = true):void { 777 var file_item:FileItem = null; 778 779 // Check the current file item 780 if (this.current_file_item != null && (this.current_file_item.id == file_id || !file_id)) { 781 this.current_file_item.file_reference.cancel(); 782 this.current_file_item.file_status = FileItem.FILE_STATUS_CANCELLED; 783 this.upload_cancelled++; 784 785 if (triggerErrorEvent) { 786 this.Debug("Event: uploadError: File ID: " + this.current_file_item.id + ". Cancelled current upload"); 787 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, this.current_file_item.ToJavaScriptObject(), "File Upload Cancelled."); 788 } else { 789 this.Debug("Event: cancelUpload: File ID: " + this.current_file_item.id + ". Cancelled current upload. Suppressed uploadError event."); 790 } 791 this.UploadComplete(false); 792 } else if (file_id) { 793 // Find the file in the queue 794 var file_index:Number = this.FindIndexInFileQueue(file_id); 795 if (file_index >= 0) { 796 // Remove the file from the queue 797 file_item = FileItem(this.file_queue[file_index]); 798 file_item.file_status = FileItem.FILE_STATUS_CANCELLED; 799 this.file_queue[file_index] = null; 800 this.queued_uploads--; 801 this.upload_cancelled++; 802 803 // Cancel the file (just for good measure) and make the callback 804 file_item.file_reference.cancel(); 805 this.removeFileReferenceEventListeners(file_item); 806 file_item.file_reference = null; 807 808 if (triggerErrorEvent) { 809 this.Debug("Event: uploadError : " + file_item.id + ". Cancelled queued upload"); 810 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled"); 811 } else { 812 this.Debug("Event: cancelUpload: File ID: " + file_item.id + ". Cancelled current upload. Suppressed uploadError event."); 813 } 814 815 // Get rid of the file object 816 file_item = null; 817 } 818 } else { 819 // Get the first file and cancel it 820 while (this.file_queue.length > 0 && file_item == null) { 821 // Check that File Reference is valid (if not make sure it's deleted and get the next one on the next loop) 822 file_item = FileItem(this.file_queue.shift()); // Cast back to a FileItem 823 if (typeof(file_item) == "undefined") { 824 file_item = null; 825 continue; 826 } 827 } 828 829 if (file_item != null) { 830 file_item.file_status = FileItem.FILE_STATUS_CANCELLED; 831 this.queued_uploads--; 832 this.upload_cancelled++; 833 834 835 // Cancel the file (just for good measure) and make the callback 836 file_item.file_reference.cancel(); 837 this.removeFileReferenceEventListeners(file_item); 838 file_item.file_reference = null; 839 840 if (triggerErrorEvent) { 841 this.Debug("Event: uploadError : " + file_item.id + ". Cancelled queued upload"); 842 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_CANCELLED, file_item.ToJavaScriptObject(), "File Cancelled"); 843 } else { 844 this.Debug("Event: cancelUpload: File ID: " + file_item.id + ". Cancelled current upload. Suppressed uploadError event."); 845 } 846 847 // Get rid of the file object 848 file_item = null; 849 } 850 851 } 852 853 } 854 855 /* Requeues the indicated file. Returns true if successful or if the file is 856 * already in the queue. Otherwise returns false. 857 * */ 858 private function RequeueUpload(fileIdentifier:*):Boolean { 859 var file:FileItem = null; 860 if (typeof(fileIdentifier) === "number") { 861 var fileIndex:Number = Number(fileIdentifier); 862 if (fileIndex >= 0 && fileIndex < this.file_index.length) { 863 file = this.file_index[fileIndex]; 864 } 865 } else if (typeof(fileIdentifier) === "string") { 866 file = FindFileInFileIndex(String(fileIdentifier)); 867 } else { 868 return false; 869 } 870 871 if (file !== null) { 872 if (file.file_status === FileItem.FILE_STATUS_IN_PROGRESS || file.file_status === FileItem.FILE_STATUS_NEW) { 873 return false; 874 } else if (file.file_status !== FileItem.FILE_STATUS_QUEUED) { 875 file.file_status = FileItem.FILE_STATUS_QUEUED; 876 this.file_queue.unshift(file); 877 this.queued_uploads++; 878 } 879 return true; 880 } else { 881 return false; 882 } 883 } 884 885 886 private function GetStats():Object { 887 return { 888 in_progress : this.current_file_item == null ? 0 : 1, 889 files_queued : this.queued_uploads, 890 successful_uploads : this.successful_uploads, 891 upload_errors : this.upload_errors, 892 upload_cancelled : this.upload_cancelled, 893 queue_errors : this.queue_errors 894 }; 895 } 896 private function SetStats(stats:Object):void { 897 this.successful_uploads = typeof(stats["successful_uploads"]) === "number" ? stats["successful_uploads"] : this.successful_uploads; 898 this.upload_errors = typeof(stats["upload_errors"]) === "number" ? stats["upload_errors"] : this.upload_errors; 899 this.upload_cancelled = typeof(stats["upload_cancelled"]) === "number" ? stats["upload_cancelled"] : this.upload_cancelled; 900 this.queue_errors = typeof(stats["queue_errors"]) === "number" ? stats["queue_errors"] : this.queue_errors; 901 } 902 903 private function GetFile(file_id:String):Object { 904 var file_index:Number = this.FindIndexInFileQueue(file_id); 905 if (file_index >= 0) { 906 var file:FileItem = this.file_queue[file_index]; 907 } else { 908 if (this.current_file_item != null) { 909 file = this.current_file_item; 910 } else { 911 for (var i:Number = 0; i < this.file_queue.length; i++) { 912 file = this.file_queue[i]; 913 if (file != null) break; 914 } 915 } 916 } 917 918 if (file == null) { 919 return null; 920 } else { 921 return file.ToJavaScriptObject(); 922 } 923 924 } 925 926 private function GetFileByIndex(index:Number):Object { 927 if (index < 0 || index > this.file_index.length - 1) { 928 return null; 929 } else { 930 return this.file_index[index].ToJavaScriptObject(); 931 } 932 } 933 934 private function AddFileParam(file_id:String, name:String, value:String):Boolean { 935 var item:FileItem = this.FindFileInFileIndex(file_id); 936 if (item != null) { 937 item.AddParam(name, value); 938 return true; 939 } 940 else { 941 return false; 942 } 943 } 944 private function RemoveFileParam(file_id:String, name:String):Boolean { 945 var item:FileItem = this.FindFileInFileIndex(file_id); 946 if (item != null) { 947 item.RemoveParam(name); 948 return true; 949 } 950 else { 951 return false; 952 } 953 } 954 955 private function SetUploadURL(url:String):void { 956 if (typeof(url) !== "undefined" && url !== "") { 957 this.uploadURL = url; 958 } 959 } 960 961 private function SetPostParams(post_object:Object):void { 962 if (typeof(post_object) !== "undefined" && post_object !== null) { 963 this.uploadPostObject = post_object; 964 } 965 } 966 967 private function SetFileTypes(types:String, description:String):void { 968 this.fileTypes = types; 969 this.fileTypesDescription = description; 970 971 this.LoadFileExensions(this.fileTypes); 972 } 973 974 // Sets the file size limit. Accepts size values with units: 100 b, 1KB, 23Mb, 4 Gb 975 // Parsing is not robust. "100 200 MB KB B GB" parses as "100 MB" 976 private function SetFileSizeLimit(size:String):void { 977 var value:Number = 0; 978 var unit:String = "kb"; 979 980 // Trim the string 981 var trimPattern:RegExp = /^\s*|\s*$/; 982 983 size = size.toLowerCase(); 984 size = size.replace(trimPattern, ""); 985 986 987 // Get the value part 988 var values:Array = size.match(/^\d+/); 989 if (values !== null && values.length > 0) { 990 value = parseInt(values[0]); 991 } 992 if (isNaN(value) || value < 0) value = 0; 993 994 // Get the units part 995 var units:Array = size.match(/(b|kb|mb|gb)/); 996 if (units != null && units.length > 0) { 997 unit = units[0]; 998 } 999 1000 // Set the multiplier for converting the unit to bytes 1001 var multiplier:Number = 1024; 1002 if (unit === "b") 1003 multiplier = 1; 1004 else if (unit === "mb") 1005 multiplier = 1048576; 1006 else if (unit === "gb") 1007 multiplier = 1073741824; 1008 1009 this.fileSizeLimit = value * multiplier; 1010 } 1011 1012 private function SetFileUploadLimit(file_upload_limit:Number):void { 1013 if (file_upload_limit < 0) file_upload_limit = 0; 1014 this.fileUploadLimit = file_upload_limit; 1015 } 1016 1017 private function SetFileQueueLimit(file_queue_limit:Number):void { 1018 if (file_queue_limit < 0) file_queue_limit = 0; 1019 this.fileQueueLimit = file_queue_limit; 1020 } 1021 1022 private function SetFilePostName(file_post_name:String):void { 1023 if (file_post_name != "") { 1024 this.filePostName = file_post_name; 1025 } 1026 } 1027 1028 private function SetUseQueryString(use_query_string:Boolean):void { 1029 this.useQueryString = use_query_string; 1030 } 1031 1032 private function SetRequeueOnError(requeue_on_error:Boolean):void { 1033 this.requeueOnError = requeue_on_error; 1034 } 1035 1036 private function SetHTTPSuccess(http_status_codes:*):void { 1037 this.httpSuccess = []; 1038 1039 if (typeof http_status_codes === "string") { 1040 var status_code_strings:Array = http_status_codes.replace(" ", "").split(","); 1041 for each (var http_status_string:String in status_code_strings) 1042 { 1043 try { 1044 this.httpSuccess.push(Number(http_status_string)); 1045 } catch (ex:Object) { 1046 // Ignore errors 1047 this.Debug("Could not add HTTP Success code: " + http_status_string); 1048 } 1049 } 1050 } 1051 else if (typeof http_status_codes === "object" && typeof http_status_codes.length === "number") { 1052 for each (var http_status:* in http_status_codes) 1053 { 1054 try { 1055 this.Debug("adding: " + http_status); 1056 this.httpSuccess.push(Number(http_status)); 1057 } catch (ex:Object) { 1058 this.Debug("Could not add HTTP Success code: " + http_status); 1059 } 1060 } 1061 } 1062 } 1063 1064 private function SetAssumeSuccessTimeout(timeout_seconds:Number):void { 1065 this.assumeSuccessTimeout = timeout_seconds < 0 ? 0 : timeout_seconds; 1066 } 1067 1068 private function SetDebugEnabled(debug_enabled:Boolean):void { 1069 this.debugEnabled = debug_enabled; 1070 } 1071 1072 /* ************************************************************* 1073 Button Handling Functions 1074 *************************************************************** */ 1075 private function SetButtonImageURL(button_image_url:String):void { 1076 this.buttonImageURL = button_image_url; 1077 1078 try { 1079 if (this.buttonImageURL !== null && this.buttonImageURL !== "") { 1080 this.buttonLoader.load(new URLRequest(this.buttonImageURL)); 1081 } 1082 } catch (ex:Object) { 1083 } 1084 } 1085 1086 private function ButtonClickHandler(e:MouseEvent):void { 1087 if (!this.buttonStateDisabled) { 1088 if (this.buttonAction === this.BUTTON_ACTION_SELECT_FILE) { 1089 this.SelectFile(); 1090 } 1091 else if (this.buttonAction === this.BUTTON_ACTION_START_UPLOAD) { 1092 this.StartUpload(); 1093 } 1094 else { 1095 this.SelectFiles(); 1096 } 1097 } 1098 } 1099 1100 private function UpdateButtonState():void { 1101 var xOffset:Number = 0; 1102 var yOffset:Number = 0; 1103 1104 this.buttonLoader.x = xOffset; 1105 this.buttonLoader.y = yOffset; 1106 1107 if (this.buttonStateDisabled) { 1108 this.buttonLoader.y = this.buttonHeight * -3 + yOffset; 1109 } 1110 else if (this.buttonStateMouseDown) { 1111 this.buttonLoader.y = this.buttonHeight * -2 + yOffset; 1112 } 1113 else if (this.buttonStateOver) { 1114 this.buttonLoader.y = this.buttonHeight * -1 + yOffset; 1115 } 1116 else { 1117 this.buttonLoader.y = -yOffset; 1118 } 1119 }; 1120 1121 private function SetButtonDimensions(width:Number = -1, height:Number = -1):void { 1122 if (width >= 0) { 1123 this.buttonWidth = width; 1124 } 1125 if (height >= 0) { 1126 this.buttonHeight = height; 1127 } 1128 1129 this.buttonTextField.width = this.buttonWidth; 1130 this.buttonTextField.height = this.buttonHeight; 1131 this.buttonCursorSprite.width = this.buttonWidth; 1132 this.buttonCursorSprite.height = this.buttonHeight; 1133 1134 this.UpdateButtonState(); 1135 } 1136 1137 private function SetButtonText(button_text:String):void { 1138 this.buttonText = button_text; 1139 1140 this.SetButtonTextStyle(this.buttonTextStyle); 1141 } 1142 1143 private function SetButtonTextStyle(button_text_style:String):void { 1144 this.buttonTextStyle = button_text_style; 1145 1146 var style:StyleSheet = new StyleSheet(); 1147 style.parseCSS(this.buttonTextStyle); 1148 this.buttonTextField.styleSheet = style; 1149 this.buttonTextField.htmlText = this.buttonText; 1150 } 1151 1152 private function SetButtonTextPadding(left:Number, top:Number):void { 1153 this.buttonTextField.x = this.buttonTextLeftPadding = left; 1154 this.buttonTextField.y = this.buttonTextTopPadding = top; 1155 } 1156 1157 private function SetButtonDisabled(disabled:Boolean):void { 1158 this.buttonStateDisabled = disabled; 1159 this.UpdateButtonState(); 1160 } 1161 1162 private function SetButtonAction(button_action:Number):void { 1163 this.buttonAction = button_action; 1164 } 1165 1166 private function SetButtonCursor(button_cursor:Number):void { 1167 this.buttonCursor = button_cursor; 1168 1169 this.buttonCursorSprite.useHandCursor = (button_cursor === this.BUTTON_CURSOR_HAND); 1170 } 1171 1172 /* ************************************************************* 1173 File processing and handling functions 1174 *************************************************************** */ 1175 private function StartUpload(file_id:String = ""):void { 1176 // Only upload a file uploads are being processed. 1177 if (this.current_file_item != null) { 1178 this.Debug("StartUpload(): Upload already in progress. Not starting another upload."); 1179 return; 1180 } 1181 1182 this.Debug("StartUpload: " + (file_id ? "File ID: " + file_id : "First file in queue")); 1183 1184 // Check the upload limit 1185 if (this.successful_uploads >= this.fileUploadLimit && this.fileUploadLimit != 0) { 1186 this.Debug("Event: uploadError : Upload limit reached. No more files can be uploaded."); 1187 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_LIMIT_EXCEEDED, null, "The upload limit has been reached."); 1188 this.current_file_item = null; 1189 return; 1190 } 1191 1192 // Get the next file to upload 1193 if (!file_id) { 1194 while (this.file_queue.length > 0 && this.current_file_item == null) { 1195 this.current_file_item = FileItem(this.file_queue.shift()); 1196 if (typeof(this.current_file_item) == "undefined") { 1197 this.current_file_item = null; 1198 } 1199 } 1200 } else { 1201 var file_index:Number = this.FindIndexInFileQueue(file_id); 1202 if (file_index >= 0) { 1203 // Set the file as the current upload and remove it from the queue 1204 this.current_file_item = FileItem(this.file_queue[file_index]); 1205 this.file_queue[file_index] = null; 1206 } else { 1207 this.Debug("Event: uploadError : File ID not found in queue: " + file_id); 1208 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_SPECIFIED_FILE_ID_NOT_FOUND, null, "File ID not found in the queue."); 1209 } 1210 } 1211 1212 1213 if (this.current_file_item != null) { 1214 // Trigger the uploadStart event which will call ReturnUploadStart to begin the actual upload 1215 this.Debug("Event: uploadStart : File ID: " + this.current_file_item.id); 1216 1217 this.current_file_item.file_status = FileItem.FILE_STATUS_IN_PROGRESS; 1218 ExternalCall.UploadStart(this.uploadStart_Callback, this.current_file_item.ToJavaScriptObject()); 1219 } 1220 // Otherwise we've would have looped through all the FileItems. This means the queue is empty) 1221 else { 1222 this.Debug("StartUpload(): No files found in the queue."); 1223 } 1224 } 1225 1226 // This starts the upload when the user returns TRUE from the uploadStart event. Rather than just have the value returned from 1227 // the function we do a return function call so we can use the setTimeout work-around for Flash/JS circular calls. 1228 private function ReturnUploadStart(start_upload:Boolean):void { 1229 if (this.current_file_item == null) { 1230 this.Debug("ReturnUploadStart called but no file was prepped for uploading. The file may have been cancelled or stopped."); 1231 return; 1232 } 1233 1234 var js_object:Object; 1235 1236 if (start_upload) { 1237 try { 1238 // Set the event handlers 1239 this.current_file_item.file_reference.addEventListener(Event.OPEN, this.Open_Handler); 1240 this.current_file_item.file_reference.addEventListener(ProgressEvent.PROGRESS, this.FileProgress_Handler); 1241 this.current_file_item.file_reference.addEventListener(IOErrorEvent.IO_ERROR, this.IOError_Handler); 1242 this.current_file_item.file_reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.SecurityError_Handler); 1243 this.current_file_item.file_reference.addEventListener(HTTPStatusEvent.HTTP_STATUS, this.HTTPError_Handler); 1244 this.current_file_item.file_reference.addEventListener(Event.COMPLETE, this.Complete_Handler); 1245 this.current_file_item.file_reference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, this.ServerData_Handler); 1246 1247 // Get the request (post values, etc) 1248 var request:URLRequest = this.BuildRequest(); 1249 1250 if (this.uploadURL.length == 0) { 1251 this.Debug("Event: uploadError : IO Error : File ID: " + this.current_file_item.id + ". Upload URL string is empty."); 1252 1253 // Remove the event handlers 1254 this.removeFileReferenceEventListeners(this.current_file_item); 1255 1256 this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; 1257 this.file_queue.unshift(this.current_file_item); 1258 js_object = this.current_file_item.ToJavaScriptObject(); 1259 this.current_file_item = null; 1260 1261 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_MISSING_UPLOAD_URL, js_object, "Upload URL string is empty."); 1262 } else { 1263 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); 1264 this.current_file_item.file_status = FileItem.FILE_STATUS_IN_PROGRESS; 1265 this.current_file_item.file_reference.upload(request, this.filePostName, false); 1266 } 1267 } catch (ex:Error) { 1268 this.Debug("ReturnUploadStart: Exception occurred: " + message); 1269 1270 this.upload_errors++; 1271 this.current_file_item.file_status = FileItem.FILE_STATUS_ERROR; 1272 1273 var message:String = ex.errorID + "\n" + ex.name + "\n" + ex.message + "\n" + ex.getStackTrace(); 1274 this.Debug("Event: uploadError(): Upload Failed. Exception occurred: " + message); 1275 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_UPLOAD_FAILED, this.current_file_item.ToJavaScriptObject(), message); 1276 1277 this.UploadComplete(true); 1278 } 1279 } else { 1280 // Remove the event handlers 1281 this.removeFileReferenceEventListeners(this.current_file_item); 1282 1283 // Re-queue the FileItem 1284 this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; 1285 js_object = this.current_file_item.ToJavaScriptObject(); 1286 this.file_queue.unshift(this.current_file_item); 1287 this.current_file_item = null; 1288 1289 this.Debug("Event: uploadError : Call to uploadStart returned false. Not uploading the file."); 1290 ExternalCall.UploadError(this.uploadError_Callback, this.ERROR_CODE_FILE_VALIDATION_FAILED, js_object, "Call to uploadStart return false. Not uploading file."); 1291 this.Debug("Event: uploadComplete : Call to uploadStart returned false. Not uploading the file."); 1292 ExternalCall.UploadComplete(this.uploadComplete_Callback, js_object); 1293 } 1294 } 1295 1296 // Completes the file upload by deleting it's reference, advancing the pointer. 1297 // Once this event fires a new upload can be started. 1298 private function UploadComplete(eligible_for_requeue:Boolean):void { 1299 var jsFileObj:Object = this.current_file_item.ToJavaScriptObject(); 1300 1301 this.removeFileReferenceEventListeners(this.current_file_item); 1302 1303 if (!eligible_for_requeue || this.requeueOnError == false) { 1304 this.current_file_item.file_reference = null; 1305 this.queued_uploads--; 1306 } else if (this.requeueOnError == true) { 1307 this.current_file_item.file_status = FileItem.FILE_STATUS_QUEUED; 1308 this.file_queue.unshift(this.current_file_item); 1309 } 1310 1311 this.current_file_item = null; 1312 1313 this.Debug("Event: uploadComplete : Upload cycle complete."); 1314 ExternalCall.UploadComplete(this.uploadComplete_Callback, jsFileObj); 1315 } 1316 1317 1318 /* ************************************************************* 1319 Utility Functions 1320 *************************************************************** */ 1321 1322 1323 // 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 1324 private function CheckFileSize(file_item:FileItem):Number { 1325 if (file_item.file_reference.size == 0) { 1326 return this.SIZE_ZERO_BYTE; 1327 } else if (this.fileSizeLimit != 0 && file_item.file_reference.size > this.fileSizeLimit) { 1328 return this.SIZE_TOO_BIG; 1329 } else { 1330 return this.SIZE_OK; 1331 } 1332 } 1333 1334 private function CheckFileType(file_item:FileItem):Boolean { 1335 // If no extensions are defined then a *.* was passed and the check is unnecessary 1336 if (this.valid_file_extensions.length == 0) { 1337 return true; 1338 } 1339 1340 var fileRef:FileReference = file_item.file_reference; 1341 var last_dot_index:Number = fileRef.name.lastIndexOf("."); 1342 var extension:String = ""; 1343 if (last_dot_index >= 0) { 1344 extension = fileRef.name.substr(last_dot_index + 1).toLowerCase(); 1345 } 1346 1347 var is_valid_filetype:Boolean = false; 1348 for (var i:Number=0; i < this.valid_file_extensions.length; i++) { 1349 if (String(this.valid_file_extensions[i]) == extension) { 1350 is_valid_filetype = true; 1351 break; 1352 } 1353 } 1354 1355 return is_valid_filetype; 1356 } 1357 1358 private function BuildRequest():URLRequest { 1359 // Create the request object 1360 var request:URLRequest = new URLRequest(); 1361 request.method = URLRequestMethod.POST; 1362 1363 var file_post:Object = this.current_file_item.GetPostObject(); 1364 1365 if (this.useQueryString) { 1366 var pairs:Array = new Array(); 1367 for (key in this.uploadPostObject) { 1368 this.Debug("Global URL Item: " + key + "=" + this.uploadPostObject[key]); 1369 if (this.uploadPostObject.hasOwnProperty(key)) { 1370 pairs.push(escape(key) + "=" + escape(this.uploadPostObject[key])); 1371 } 1372 } 1373 1374 for (key in file_post) { 1375 this.Debug("File Post Item: " + key + "=" + file_post[key]); 1376 if (file_post.hasOwnProperty(key)) { 1377 pairs.push(escape(key) + "=" + escape(file_post[key])); 1378 } 1379 } 1380 1381 request.url = this.uploadURL + (this.uploadURL.indexOf("?") > -1 ? "&" : "?") + pairs.join("&"); 1382 1383 } else { 1384 var key:String; 1385 var post:URLVariables = new URLVariables(); 1386 for (key in this.uploadPostObject) { 1387 this.Debug("Global Post Item: " + key + "=" + this.uploadPostObject[key]); 1388 if (this.uploadPostObject.hasOwnProperty(key)) { 1389 post[key] = this.uploadPostObject[key]; 1390 } 1391 } 1392 1393 for (key in file_post) { 1394 this.Debug("File Post Item: " + key + "=" + file_post[key]); 1395 if (file_post.hasOwnProperty(key)) { 1396 post[key] = file_post[key]; 1397 } 1398 } 1399 1400 request.url = this.uploadURL; 1401 request.data = post; 1402 } 1403 1404 return request; 1405 } 1406 1407 private function Debug(msg:String):void { 1408 try { 1409 if (this.debugEnabled) { 1410 var lines:Array = msg.split("\n"); 1411 for (var i:Number=0; i < lines.length; i++) { 1412 lines[i] = "SWF DEBUG: " + lines[i]; 1413 } 1414 ExternalCall.Debug(this.debug_Callback, lines.join("\n")); 1415 } 1416 } catch (ex:Error) { 1417 // pretend nothing happened 1418 trace(ex); 1419 } 1420 } 1421 1422 private function PrintDebugInfo():void { 1423 var debug_info:String = "\n----- SWF DEBUG OUTPUT ----\n"; 1424 debug_info += "Build Number: " + this.build_number + "\n"; 1425 debug_info += "movieName: " + this.movieName + "\n"; 1426 debug_info += "Upload URL: " + this.uploadURL + "\n"; 1427 debug_info += "File Types String: " + this.fileTypes + "\n"; 1428 debug_info += "Parsed File Types: " + this.valid_file_extensions.toString() + "\n"; 1429 debug_info += "HTTP Success: " + this.httpSuccess.join(", ") + "\n"; 1430 debug_info += "File Types Description: " + this.fileTypesDescription + "\n"; 1431 debug_info += "File Size Limit: " + this.fileSizeLimit + " bytes\n"; 1432 debug_info += "File Upload Limit: " + this.fileUploadLimit + "\n"; 1433 debug_info += "File Queue Limit: " + this.fileQueueLimit + "\n"; 1434 debug_info += "Post Params:\n"; 1435 for (var key:String in this.uploadPostObject) { 1436 if (this.uploadPostObject.hasOwnProperty(key)) { 1437 debug_info += " " + key + "=" + this.uploadPostObject[key] + "\n"; 1438 } 1439 } 1440 debug_info += "----- END SWF DEBUG OUTPUT ----\n"; 1441 1442 this.Debug(debug_info); 1443 } 1444 1445 private function FindIndexInFileQueue(file_id:String):Number { 1446 for (var i:Number = 0; i < this.file_queue.length; i++) { 1447 var item:FileItem = this.file_queue[i]; 1448 if (item != null && item.id == file_id) return i; 1449 } 1450 1451 return -1; 1452 } 1453 1454 private function FindFileInFileIndex(file_id:String):FileItem { 1455 for (var i:Number = 0; i < this.file_index.length; i++) { 1456 var item:FileItem = this.file_index[i]; 1457 if (item != null && item.id == file_id) return item; 1458 } 1459 1460 return null; 1461 } 1462 1463 1464 // Parse the file extensions in to an array so we can validate them agains 1465 // the files selected later. 1466 private function LoadFileExensions(filetypes:String):void { 1467 var extensions:Array = filetypes.split(";"); 1468 this.valid_file_extensions = new Array(); 1469 1470 for (var i:Number=0; i < extensions.length; i++) { 1471 var extension:String = String(extensions[i]); 1472 var dot_index:Number = extension.lastIndexOf("."); 1473 1474 if (dot_index >= 0) { 1475 extension = extension.substr(dot_index + 1).toLowerCase(); 1476 } else { 1477 extension = extension.toLowerCase(); 1478 } 1479 1480 // If one of the extensions is * then we allow all files 1481 if (extension == "*") { 1482 this.valid_file_extensions = new Array(); 1483 break; 1484 } 1485 1486 this.valid_file_extensions.push(extension); 1487 } 1488 } 1489 1490 private function loadPostParams(param_string:String):void { 1491 var post_object:Object = {}; 1492 1493 if (param_string != null) { 1494 var name_value_pairs:Array = param_string.split("&"); 1495 1496 for (var i:Number = 0; i < name_value_pairs.length; i++) { 1497 var name_value:String = String(name_value_pairs[i]); 1498 var index_of_equals:Number = name_value.indexOf("="); 1499 if (index_of_equals > 0) { 1500 post_object[decodeURIComponent(name_value.substring(0, index_of_equals))] = decodeURIComponent(name_value.substr(index_of_equals + 1)); 1501 } 1502 } 1503 } 1504 this.uploadPostObject = post_object; 1505 } 1506 1507 private function removeFileReferenceEventListeners(file_item:FileItem):void { 1508 if (file_item != null && file_item.file_reference != null) { 1509 file_item.file_reference.removeEventListener(Event.OPEN, this.Open_Handler); 1510 file_item.file_reference.removeEventListener(ProgressEvent.PROGRESS, this.FileProgress_Handler); 1511 file_item.file_reference.removeEventListener(IOErrorEvent.IO_ERROR, this.IOError_Handler); 1512 file_item.file_reference.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.SecurityError_Handler); 1513 file_item.file_reference.removeEventListener(HTTPStatusEvent.HTTP_STATUS, this.HTTPError_Handler); 1514 file_item.file_reference.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, this.ServerData_Handler); 1515 } 1516 } 1517 1518 } 1519 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |