<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -16,10 +16,10 @@ Features {#features}
 * Cancel running uploads, add files during upload
 * Everything is optional, documented and easy editable
 * New in 2.0
-  * Get the server response after upload for showing additional informations or previewing the image, etc.
-  * Shows the current upload speed and the time left
-  * Send additional request data via GET or POST variables
-  * Set the filename for the upload request
+	* Get the server response after upload for showing additional informations or previewing the image, etc.
+	* Shows the current upload speed and the time left
+	* Send additional request data via GET or POST variables
+	* Set the filename for the upload request
 * New in 3.0 (Completely rewritten API)
 	* Fully Flash 9 and 10 compatible and an additional IFrame-based uploader
 	* Browse-button can be an invisible overlay or an interactive image sprite
@@ -73,15 +73,18 @@ Documentation {#docs}
 * verbose: (*boolean*: defaults to false) Debug mode, logs messages and all events from Flash during development (using *console.info*).
 * target: (*element*: defaults to null) If given, the browse-element is overlayed with a transparent movie. The Events *click/mouseenter/mouseleave/disabled* are fired as events on *target*.
 * zIndex: (*number*: defaults to 9999) Only used if a *target* is given, this sets the z-index for the overlay.
-* buttonImage: (*string*: defaults to null) Sprite for the upload button, has to have 4 states vertical aligned: Normal, hovered, clicked and disabled. Make sure to adapt the options *width* and *height*.
+* buttonImage: (*string*: defaults to null) Sprite for the upload button, has to have 4 states vertically aligned: Normal, hovered, clicked and disabled. Make sure to adapt the options *width* and *height*.
+* policyFile: (*string*: defaults to null) Location the cross-domain policy file. See [Flash Security.loadPolicyFile](http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/Security.html#loadPolicyFile%28%29).
 * url: (*string*: defaults to null) URL to the server-side script (relative URLs are changed automatically to absolute paths). 
 * method: (*string*: defaults to 'post') If the method is 'get', *data* is appended as query-string to the URL. The upload will always be a POST request.
 * data: (*object|string*: defaults to null) Key/data values that are sent with the upload requests.
 * mergeData: (*boolean*: defaults to true) If true, the *data* option from uploader and file is merged (prioritised file data).
 * fieldName: (*string*: defaults to &quot;Filedata&quot;) The key of the uploaded file on your server, similar to *name* in a file-input. Linux Flash ignores it, better avoid it.
 * fileSizeMin: (*number*: defaults to 1) Validates the minimal size of a selected file *byte*.
-* fileSizeMax: (*number*: defaults to 0) Validates the maximal size of a selected file (official limit is 100 MB for FileReference) 
+* fileSizeMax: (*number*: defaults to 0) Validates the maximal size of a selected file (official limit is 100 MB for FileReference, I tested up to 2 GB) 
 * allowDuplicates: (*boolean*: defaults to false) Validates that no duplicate files are added.
+* timeLimit: (*number*: default 30, 0 for linux) Timeout in seconds. If the upload is without progress, it is cancelled and event `complete` gets fired (with error string `timeout`). Occurs usually when the server sends an empty response (also on redirects).
+* fileList: (*boolean*: defaults to false) Validates that no duplicate files are added.
 * fileListMax: (*number*: defaults to 0) Validates the overall file count.
 * fileListSizeMax: (*number*: defaults to 0) Validates the overall file size in *byte*.
 * instantStart: (*boolean*: defaults to false) If true, the upload starts right after a successful file selection.</diff>
      <filename>meta.md</filename>
    </modified>
    <modified>
      <diff>@@ -25,7 +25,7 @@
  * Only needed if you have a logged in user, see option appendCookieData,
  * which adds session id and other available cookies to the sent data.
  *
- * session_name('SID'); // whatever your session name is, adapt that!
+ * session_id($_POST['SID']); // whatever your session name is, adapt that!
  * session_start();
  */
 </diff>
      <filename>showcase/script.php</filename>
    </modified>
    <modified>
      <diff>@@ -3,11 +3,11 @@
  * 
  * Updated to latest 3.0 API. Hopefully 100% compat!
  *
- * @version		3.0 rc1
+ * @version		3.0
  *
  * @license		MIT License
  *
- * @author		Harald Kirschner &lt;mail [at] digitarald [dot] de&gt;
+ * @author		Harald Kirschner &lt;http://digitarald.de&gt;
  * @copyright	Authors
  */
 </diff>
      <filename>source/FancyUpload2.js</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 /**
  * FancyUpload.Attach - Flash meets Ajax for powerful and elegant uploads.
  *
- * @version		3.0 rc1
+ * @version		3.0 rc3
  *
  * @license		MIT License
  *</diff>
      <filename>source/FancyUpload3.Attach.js</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,12 @@
 /**
  * Swiff.Uploader - Flash FileReference Control
  *
- * @version		3.0 rc1
+ * @version		3.0
  *
  * @license		MIT License
  *
- * @author		Harald Kirschner &lt;mail [at] digitarald [dot] de&gt;
+ * @author		Harald Kirschner &lt;http://digitarald.de&gt;
+ * @author		Valerio Proietti, &lt;http://mad4milk.net&gt;
  * @copyright	Authors
  */
 
@@ -42,8 +43,9 @@ Swiff.Uploader = new Class({
 		fieldName: null,
 
 		fileSizeMin: 1,
-		fileSizeMax: null, // Official limit is 100 MB for FileReference!
+		fileSizeMax: null, // Official limit is 100 MB for FileReference, but I tested up to 2Gb!
 		allowDuplicates: false,
+		timeLimit: (Browser.Platform.linux) ? 0 : 30,
 
 		buttonImage: null,
 		policyFile: null,
@@ -230,6 +232,7 @@ Swiff.Uploader = new Class({
 			fileSizeMin: this.options.fileSizeMin,
 			fileSizeMax: this.options.fileSizeMax,
 			allowDuplicates: this.options.allowDuplicates,
+			timeLimit: this.options.timeLimit,
 			buttonImage: this.options.buttonImage,
 			policyFile: this.options.policyFile
 		});</diff>
      <filename>source/Swiff.Uploader.js</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>source/Swiff.Uploader.swf</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-&#65279;/** * Swiff.Uploader Class File * * @licence		MIT Licence * * @author		Harald Kirschner &lt;http://digitarald.de&gt; * @copyright	Authors */package{	import flash.events.*;	import flash.net.FileReference;	import flash.net.FileFilter;	import flash.net.URLRequest;	import flash.net.URLRequestMethod;	import flash.net.URLVariables;		/**	 * @author Harald Kirschner &lt;mail [at] digitarald.de&gt;	 */	public class File	{		static var idStack:uint = 1;				static const STATUS_QUEUED:uint = 0;		static const STATUS_RUNNING:uint = 1;		static const STATUS_ERROR:uint = 2;		static const STATUS_COMPLETE:uint = 3;		static const STATUS_STOPPED:uint = 4;		public var id:uint = 0;				public var status:uint = 0;		private var options:Object = {			url: null,			method: null,			data: null,			mergeData: null,			fieldName: null		}				public var reference:FileReference = null;		private var parent:Main = null;				public var responseText:String = null;		public var responseCode:uint = 0;		public var responseError:String = null;				public var validationError:String = null;				public var addDate:Date = null;		public var startDate:Date = null;		public var progressDate:Date = null;		public var completeDate:Date = null;				public var fileExtension:String = null;				public var bytesLoaded:uint = 0;		public var timeElapsed:uint = 0;		public var timeRemaining:uint = 0;				public var progressGraph:Array = new Array();		public var rate:uint = 0;		public var rateAvg:uint = 0;				private var lockProgress:uint = 0;				public function File(parent_init:Main, reference_init:FileReference)		{			id = File.idStack++;						reference = reference_init;			parent = parent_init;						reference.addEventListener(Event.OPEN, handleOpen);			reference.addEventListener(ProgressEvent.PROGRESS, handleProgress);			reference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, handleComplete);			reference.addEventListener(HTTPStatusEvent.HTTP_STATUS, handleHttpStatus);			reference.addEventListener(IOErrorEvent.IO_ERROR, handleIoError);			reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError);						fileExtension = reference.name.replace(/.+\.([^.]+)$/, '$1').toLowerCase();						addDate = new Date();		}				public function fireEvent(functionName:String, queue:Boolean = false):void		{			var args:Array = [export()];			if (queue) args.push(parent.queueUpdate());						parent.fireEvent('file' + functionName.charAt(0).toUpperCase() + functionName.substr(1), args);		}				private function handleOpen(event:Event):void		{			progressDate = startDate = new Date();						fireEvent('open');		}				private function handleProgress(event:ProgressEvent):void		{			var now:uint = new Date().getTime();						var allow:Boolean = (!lockProgress || lockProgress &lt; now - 100 || event.bytesLoaded == reference.size)						if (allow) {				updateProgress((event.bytesLoaded &gt;= 0) ? event.bytesLoaded : 0);								lockProgress = now;				fireEvent('progress', true);			} else {				// parent.verboseLog('Process Skipped', [event.bytesLoaded, now - lockProgress]);			}					}				private function resetProgress():void		{			responseText = responseError = null;			responseCode = 0;						progressGraph.length = 0;			startDate = progressDate = completeDate = null;			timeElapsed = timeRemaining = rate = rateAvg = bytesLoaded = 0;		}				private function updateProgress(bytes_loaded:uint, complete:Boolean = false)		{			var now:Date = new Date();			var i:uint = 0, length:uint = 0;						rate = rateAvg = 0;						if (bytes_loaded &amp;&amp; !complete) {								var bytes_diff:Number = (bytes_loaded - bytesLoaded) / (now.getTime() - progressDate.getTime());				length = progressGraph.unshift(Math.round(bytes_diff));								bytesLoaded = bytes_loaded;								if (length &gt; 1) {										if (length &gt; parent.options.progressGraphSize) length = parent.options.progressGraphSize;										var mean:Number = 0;					var variance:Number = 0;										for (i = 0; i &lt; length; i++) {						mean += progressGraph[i];						variance += Math.pow(progressGraph[i] - mean, 2);					}					mean /= length;										rate = rateAvg = Math.round(mean * 1000);										if (length &gt; 6) {						var standard_dev:Number = Math.sqrt(variance / length);						var deviation_range:Number = 2.0;												var filtered_sum:Number = 0;						var filtered_count:uint = 0;												for (i = 0; i &lt; length; i++) {							var value:Number = (progressGraph[i] - mean) / standard_dev;														if (value &lt;= deviation_range &amp;&amp; value &gt;= -deviation_range) {								filtered_sum += progressGraph[i];								filtered_count++;							}						}												rateAvg = Math.round(filtered_sum / filtered_count * 1000);						timeRemaining = (reference.size - bytes_loaded) / rateAvg;					}				}			}						timeElapsed = (now.getTime() - startDate.getTime()) / 1000;						progressDate = now;					parent.rate = parent.bytesLoaded = 0;						for (var i = 0; i &lt; parent.fileList.length; i++) {				var file:File = parent.fileList[i];				switch (file.status) {					case File.STATUS_RUNNING:						parent.rate += file.rateAvg;					case File.STATUS_COMPLETE:						parent.bytesLoaded += file.bytesLoaded;				}			}		}				private function handleComplete(event:DataEvent):void		{			complete(event.data);		}				private function handleIoError(event:IOErrorEvent):void		{			complete(event.text , event.type, null);		}				private function handleSecurityError(event:SecurityErrorEvent):void		{			complete(event.text, event.type, null);		}				private function handleHttpStatus(event:HTTPStatusEvent):void		{			if (parent.options.passStatus is Array) {				var list:Array = parent.options.passStatus;				if (list.length &amp;&amp; list.indexOf(event.status) != -1) {					complete(null, null, event.status);					return;				}			}						complete(null, event.type, event.status);		}				private function complete(text:String = null, error:String = null, code:int = 0)		{			if (status != File.STATUS_RUNNING) {				parent.verboseLog('File[' + id + ']::complete wasted!', [].concat(arguments));				return;			}									completeDate = new Date();						responseText = text;			responseCode = code;						if (error) {				responseError = error;				status = File.STATUS_ERROR;			} else {				status = File.STATUS_COMPLETE;			}						parent.uploading--;						updateProgress(reference.size, true);						fireEvent('complete', true);						parent.checkQueue(true);		}				public function setOptions(options_init:Object = null):void		{			if (options_init != null) {				for (var prop:String in options) {					if (options_init.hasOwnProperty(prop)) options[prop] = options_init[prop];				}			}		}				public function start():Boolean		{			if (status == File.STATUS_RUNNING) return false;						var options_parent:Object = parent.options;			var merged:Object = new Object();						for (var prop:String in options) {				merged[prop] = (options[prop] != null) ? options[prop] : options_parent[prop];			}						try {				var url_request:URLRequest = new URLRequest(merged.url || '');								if (merged.data != null &amp;&amp; merged.data != false) {					if (merged.mergeData &amp;&amp; options.data &amp;&amp; options_parent.data) {						if (options.data is String &amp;&amp; options_parent.data is String) {							merged.data = options_parent.data + '&amp;' + options.data;						} else {							merged.data = new Object();							for (var prop:String in options_parent.data) {								merged.data[prop] = options_parent.data[prop];							}							for (var prop:String in options.data) {								merged.data[prop] = options.data[prop];							}						}					}										var data:URLVariables = new URLVariables();					if (merged.data is String) data.decode(merged.data);					else for (var key:Object in merged.data) data[key] = merged.data[key];					url_request.data = data;				}							url_request.method = URLRequestMethod[(merged.method) ? merged.method.toUpperCase() : 'POST'];			} catch (e:Error) {				parent.verboseLog('File[' + id + ']::start - Exception (URLRequest)', String(e));				return false;			}						parent.verboseLog('File[' + id + ']::start', merged);						resetProgress();						status = File.STATUS_RUNNING;			parent.uploading++;						fireEvent('start', true);						try {				reference.upload(url_request, merged.fieldName || 'Filedata');			} catch (e:Error) {				parent.verboseLog('File[' + id + ']::start - Exception (upload)', String(e));				stop();				return false;			}						return true;		}				public function stop(eventful:Boolean = true):Boolean		{			if (status != File.STATUS_RUNNING) return false;						reference.cancel();			status = File.STATUS_STOPPED;						parent.uploading--;			parent.bytesLoaded -= bytesLoaded;			parent.rate -= rateAvg;						resetProgress();						if (eventful) {				fireEvent('stop', true);				parent.checkQueue(true);			}						return true;		}				public function requeue():Boolean		{			var running:Boolean = stop(false);						status = File.STATUS_QUEUED;						fireEvent('requeue');						if (running) parent.checkQueue(true);						return true;		}				public function remove():Boolean		{			var running:Boolean = stop(false);						var idx = parent.fileList.indexOf(this);			parent.fileList.splice(idx, 1);			parent.size -= reference.size;							fireEvent('remove', true);						if (running) parent.checkQueue(true);						reference = null;						return true;		}				public function validate():Boolean		{			if (!parent.options.allowDuplicates &amp;&amp; parent.hasFile(this)) {				validationError = 'duplicate';				return false;			}			if (parent.options.fileSizeMin &gt; 0 &amp;&amp; reference.size &lt; parent.options.fileSizeMin) {				validationError = 'sizeLimitMin';				return false;			}						if (parent.options.fileSizeMax &gt; 0 &amp;&amp; reference.size &gt; parent.options.fileSizeMax) {				validationError = 'sizeLimitMax';				return false;			}						return true;		}				public function export():Object		{			var export:Object = {				id: id,				name: reference.name,				size: reference.size,				modificationDate: reference.modificationDate,				creationDate: reference.creationDate,				extension: fileExtension,				status: status,				validationError: validationError,				addDate: addDate			};						if (startDate) {				export.startDate = startDate;				export.progressDate = progressDate;								export.progress = {					graph: progressGraph,					bytesLoaded: bytesLoaded,					percentLoaded: Math.ceil(bytesLoaded / reference.size * 100),					rate: rate,					rateAvg: rateAvg,					timeElapsed: timeElapsed,					timeRemaining: timeRemaining				};			};						if (completeDate) {				export.completeDate = completeDate;								export.response = {					text: responseText,					code: responseCode,					error: responseError				}			}						return export;		}				// Static methods				static public function exportMany(files:Array):Array		{			if (!files.length) return null;						return files.map(function(current:File, i:uint, self:Array) {				return current.export();			});		}	}	}
\ No newline at end of file
+&#65279;/** * Swiff.Uploader Class File * * @licence		MIT Licence * * @author		Harald Kirschner &lt;http://digitarald.de&gt; * @copyright	Authors */package{	import flash.events.*;	import flash.net.FileReference;	import flash.net.FileFilter;	import flash.utils.Timer;	import flash.net.URLRequest;	import flash.net.URLRequestMethod;	import flash.net.URLVariables;		/**	 * @author Harald Kirschner &lt;mail [at] digitarald.de&gt;	 */	public class File	{		static var idStack:uint = 1;				static const STATUS_QUEUED:uint = 0;		static const STATUS_RUNNING:uint = 1;		static const STATUS_ERROR:uint = 2;		static const STATUS_COMPLETE:uint = 3;		static const STATUS_STOPPED:uint = 4;		public var id:uint = 0;				public var status:uint = 0;		private var options:Object = {			url: null,			method: null,			data: null,			mergeData: null,			fieldName: null		}				public var reference:FileReference = null;		private var parent:Main = null;				public var responseText:String = null;		public var responseCode:uint = 0;		public var responseError:String = null;				public var validationError:String = null;				public var addDate:Date = null;		public var startDate:Date = null;		public var progressDate:Date = null;		public var completeDate:Date = null;				public var fileExtension:String = null;				public var bytesLoaded:uint = 0;		public var timeElapsed:uint = 0;		public var timeRemaining:uint = 0;				public var progressGraph:Array = new Array();		public var rate:uint = 0;		public var rateAvg:uint = 0;				private var timeout:Timer = null;		private var lockProgress:uint = 0;				public function File(parent_init:Main, reference_init:FileReference)		{			id = File.idStack++;						reference = reference_init;			parent = parent_init;						reference.addEventListener(Event.OPEN, handleOpen);			reference.addEventListener(ProgressEvent.PROGRESS, handleProgress);			reference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, handleComplete);			reference.addEventListener(HTTPStatusEvent.HTTP_STATUS, handleHttpStatus);			reference.addEventListener(IOErrorEvent.IO_ERROR, handleIoError);			reference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError);						fileExtension = reference.name.replace(/.+\.([^.]+)$/, '$1').toLowerCase();						addDate = new Date();						if (parent.options.timeLimit) {				timeout = new Timer(parent.options.timeLimit * 1000, 1);				timeout.addEventListener('timer', handleTimeout);				timeout.start();			}		}				public function fireEvent(functionName:String, queue:Boolean = false):void		{			var args:Array = [export()];			if (queue) args.push(parent.queueUpdate());						parent.fireEvent('file' + functionName.charAt(0).toUpperCase() + functionName.substr(1), args);		}				private function handleOpen(event:Event):void		{			progressDate = startDate = new Date();						if (timeout) timeout.start();						fireEvent('open');		}				private function handleProgress(event:ProgressEvent):void		{			if (timeout) {				timeout.reset();				timeout.start();			}						var now:uint = new Date().getTime();						var allow:Boolean = (!lockProgress || lockProgress &lt; now - 100 || event.bytesLoaded == reference.size)						if (allow) {				updateProgress((event.bytesLoaded &gt;= 0) ? event.bytesLoaded : 0);								lockProgress = now;				fireEvent('progress', true);			} else {				// parent.verboseLog('Process Skipped', [event.bytesLoaded, now - lockProgress]);			}					}				private function resetProgress():void		{			responseText = responseError = null;			responseCode = 0;						progressGraph.length = 0;			startDate = progressDate = completeDate = null;			timeElapsed = timeRemaining = rate = rateAvg = bytesLoaded = 0;		}				private function updateProgress(bytes_loaded:uint, complete:Boolean = false)		{			var now:Date = new Date();			var i:uint = 0, length:uint = 0;						rate = rateAvg = 0;						if (bytes_loaded &amp;&amp; !complete) {								var bytes_diff:Number = (bytes_loaded - bytesLoaded) / (now.getTime() - progressDate.getTime());				length = progressGraph.unshift(Math.round(bytes_diff));								bytesLoaded = bytes_loaded;				if (length &gt; 1) {										if (length &gt; parent.options.progressGraphSize) length = parent.options.progressGraphSize;										var mean:Number = 0;					var variance:Number = 0;										for (i = 0; i &lt; length; i++) {						mean += progressGraph[i];						variance += Math.pow(progressGraph[i] - mean, 2);					}					mean /= length;										rate = rateAvg = Math.round(mean * 1000);										if (length &gt; 6) {						var standard_dev:Number = Math.sqrt(variance / length);						var deviation_range:Number = 2.0;												var filtered_sum:Number = 0;						var filtered_count:uint = 0;												for (i = 0; i &lt; length; i++) {							var value:Number = (progressGraph[i] - mean) / standard_dev;														if (value &lt;= deviation_range &amp;&amp; value &gt;= -deviation_range) {								filtered_sum += progressGraph[i];								filtered_count++;							}						}												rateAvg = Math.round(filtered_sum / filtered_count * 1000);						timeRemaining = (reference.size - bytes_loaded) / rateAvg;					}				}			}						timeElapsed = (now.getTime() - startDate.getTime()) / 1000;						progressDate = now;					parent.rate = parent.bytesLoaded = 0;						for (var i = 0; i &lt; parent.fileList.length; i++) {				var file:File = parent.fileList[i];				switch (file.status) {					case File.STATUS_RUNNING:						parent.rate += file.rateAvg;					case File.STATUS_COMPLETE:						parent.bytesLoaded += file.bytesLoaded;				}			}		}				private function handleTimeout(event:TimerEvent):void		{			if (status != File.STATUS_RUNNING) return;						reference.cancel();						complete('timeLimit (' + options.timeLimit + 's) exceeded', 'timeout', null);		}				private function handleComplete(event:DataEvent):void		{			complete(event.data);		}				private function handleIoError(event:IOErrorEvent):void		{			complete(event.text, event.type, null);		}				private function handleSecurityError(event:SecurityErrorEvent):void		{			complete(event.text, event.type, null);		}				private function handleHttpStatus(event:HTTPStatusEvent):void		{			if (parent.options.passStatus is Array) {				var list:Array = parent.options.passStatus;				if (list.length &amp;&amp; list.indexOf(event.status) != -1) {					complete(null, null, event.status);					return;				}			}						complete(null, event.type, event.status);		}				private function complete(text:String = null, error:String = null, code:int = 0)		{			if (status != File.STATUS_RUNNING) {				parent.verboseLog('File[' + id + ']::complete wasted!', [].concat(arguments));				return;			}						if (timeout) timeout.reset();												completeDate = new Date();						responseText = text;			responseCode = code;						if (error) {				responseError = error;				status = File.STATUS_ERROR;			} else {				status = File.STATUS_COMPLETE;			}						parent.uploading--;						updateProgress(reference.size, true);						fireEvent('complete', true);						parent.checkQueue(true);		}				public function setOptions(options_init:Object = null):void		{			if (options_init != null) {				for (var prop:String in options) {					if (options_init.hasOwnProperty(prop)) options[prop] = options_init[prop];				}			}		}				public function start():Boolean		{			if (status == File.STATUS_RUNNING) return false;						var options_parent:Object = parent.options;			var merged:Object = new Object();						for (var prop:String in options) {				merged[prop] = (options[prop] != null) ? options[prop] : options_parent[prop];			}						try {				var url_request:URLRequest = new URLRequest(merged.url || '');								if (merged.data != null &amp;&amp; merged.data != false) {					if (merged.mergeData &amp;&amp; options.data &amp;&amp; options_parent.data) {						if (options.data is String &amp;&amp; options_parent.data is String) {							merged.data = options_parent.data + '&amp;' + options.data;						} else {							merged.data = new Object();							for (var prop:String in options_parent.data) {								merged.data[prop] = options_parent.data[prop];							}							for (var prop:String in options.data) {								merged.data[prop] = options.data[prop];							}						}					}										var data:URLVariables = new URLVariables();					if (merged.data is String) data.decode(merged.data);					else for (var key:Object in merged.data) data[key] = merged.data[key];					url_request.data = data;				}							url_request.method = URLRequestMethod[(merged.method) ? merged.method.toUpperCase() : 'POST'];			} catch (e:Error) {				parent.verboseLog('File[' + id + ']::start - Exception (URLRequest)', String(e));				return false;			}						parent.verboseLog('File[' + id + ']::start', merged);						resetProgress();						status = File.STATUS_RUNNING;			parent.uploading++;						fireEvent('start', true);						try {				reference.upload(url_request, merged.fieldName || 'Filedata');			} catch (e:Error) {				parent.verboseLog('File[' + id + ']::start - Exception (upload)', String(e));				stop();				return false;			}						return true;		}				public function stop(eventful:Boolean = true):Boolean		{			if (status != File.STATUS_RUNNING) return false;						if (timeout) timeout.reset();						reference.cancel();			status = File.STATUS_STOPPED;						parent.uploading--;			parent.bytesLoaded -= bytesLoaded;			parent.rate -= rateAvg;						resetProgress();						if (eventful) {				fireEvent('stop', true);				parent.checkQueue(true);			}						return true;		}				public function requeue():Boolean		{			var running:Boolean = stop(false);						status = File.STATUS_QUEUED;						fireEvent('requeue');						if (running) parent.checkQueue(true);						return true;		}				public function remove():Boolean		{			var running:Boolean = stop(false);						var idx = parent.fileList.indexOf(this);			parent.fileList.splice(idx, 1);			parent.size -= reference.size;							fireEvent('remove', true);						if (running) parent.checkQueue(true);						reference = null;						return true;		}				public function validate():Boolean		{			if (!parent.options.allowDuplicates &amp;&amp; parent.hasFile(this)) {				validationError = 'duplicate';				return false;			}			if (parent.options.fileSizeMin &gt; 0 &amp;&amp; reference.size &lt; parent.options.fileSizeMin) {				validationError = 'sizeLimitMin';				return false;			}						if (parent.options.fileSizeMax &gt; 0 &amp;&amp; reference.size &gt; parent.options.fileSizeMax) {				validationError = 'sizeLimitMax';				return false;			}						return true;		}				public function export():Object		{			var export:Object = {				id: id,				name: reference.name,				size: reference.size,				modificationDate: reference.modificationDate,				creationDate: reference.creationDate,				extension: fileExtension,				status: status,				validationError: validationError,				addDate: addDate			};						if (startDate) {				export.startDate = startDate;				export.progressDate = progressDate;								export.progress = {					graph: progressGraph,					bytesLoaded: bytesLoaded,					percentLoaded: Math.ceil(bytesLoaded / reference.size * 100),					rate: rate,					rateAvg: rateAvg,					timeElapsed: timeElapsed,					timeRemaining: timeRemaining				};			};						if (completeDate) {				export.completeDate = completeDate;								export.response = {					text: responseText,					code: responseCode,					error: responseError				}			}						return export;		}				// Static methods				static public function exportMany(files:Array):Array		{			if (!files.length) return null;						return files.map(function(current:File, i:uint, self:Array) {				return current.export();			});		}	}	}
\ No newline at end of file</diff>
      <filename>source/as3proj/File.as</filename>
    </modified>
    <modified>
      <diff>@@ -1,499 +1 @@
-&#65279;/**
- * Swiff.Uploader
- *
- * Credits: A lot of good parts are inspired by the awesome www.swfupload.org
- *
- * @licence		MIT Licence
- *
- * @author		Harald Kirschner &lt;http://digitarald.de&gt;
- * @author		Anders Rasmussen &lt;aras@dr.dk&gt;
- * @author		Valerio Proietti, &lt;http://mad4milk.net&gt;
- * @copyright	Authors
- */
-
-package
-{
-	import flash.display.Sprite;
-	import flash.display.StageAlign;
-	import flash.display.StageScaleMode;
-	import flash.display.MovieClip;
-	
-	import flash.display.Loader;
-	
-	import flash.events.*;
-	import flash.utils.*;
-	
-	import flash.system.Security;
-
-	import flash.net.FileReference;
-	import flash.net.FileReferenceList;
-	import flash.net.FileFilter;
-	
-	import flash.net.URLRequest;
-
-	import flash.external.ExternalInterface;
-	
-	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 Escaper;
-	
-	import File;
-	
-	public class Main extends Sprite
-	{
-
-		public var options:Object = {
-			typeFilter: null,
-			typeFilterDescription: null,
-			multiple: null,
-			queued: null,
-			verbose: null,
-			width: 128,
-			height: 32,
-			passStatus: null,
-			
-			url: null,
-			method: null,
-			data: null,
-			mergeData: null,
-			fieldName: null,
-			progressGraphSize: 10,
-			
-			fileSizeMin: 1,
-			fileSizeMax: null,// Official 100 MB limit for FileReference
-			allowDuplicates: false,
-			
-			policyFile: null,
-			buttonImage: null
-		};
-		
-		public var fileList:Array = new Array();
-		public var uploading:uint = 0;
-		
-		public var size:uint = 0;
-		public var bytesLoaded:uint = 0;
-		public var rate:uint = 0;
-		
-		private var dialog:*= null;
-		
-		private var buttonLoader:Loader;
-		private var buttonCursorSprite:Sprite;
-		
-		private var buttonState:uint = 0;
-		
-		const BUTTON_STATE_OVER = 1;
-		const BUTTON_STATE_DOWN = 2;
-		const BUTTON_STATE_DISABLED = 4;
-	
-		public function Main():void
-		{
-			if (stage) init();
-			else addEventListener(Event.ADDED_TO_STAGE, init);
-		}
-		
-		private function init(e:Event = null):void
-		{
-			removeEventListener(Event.ADDED_TO_STAGE, init);
-			
-			if (!flash.net.FileReference || !flash.external.ExternalInterface || !flash.external.ExternalInterface.available) {
-				return;
-			}
-			
-			// allow uploading to any domain
-			Security.allowDomain(&quot;*&quot;);
-			
-			// ExternalInterface callback adding copied
-			ExternalInterface.addCallback('initialize', xInitialize);
-			ExternalInterface.addCallback('setOptions', xSetOptions);
-			
-			ExternalInterface.addCallback('start', xStart);
-			ExternalInterface.addCallback('stop', xStop);
-			ExternalInterface.addCallback('remove', xRemove);
-			
-			ExternalInterface.addCallback('setEnabled', xSetEnabled);
-			
-			ExternalInterface.addCallback('fileSetOptions', xFileSetOptions);
-			ExternalInterface.addCallback('fileStart', xFileStart);
-			ExternalInterface.addCallback('fileStop', xFileStop);
-			ExternalInterface.addCallback('fileRemove', xFileRemove);
-			ExternalInterface.addCallback('fileRequeue', xFileRequeue);
-			
-			fireEvent('load');
-		}
-		
-		public function fireEvent(functionName:String, args:* = null):void
-		{
-			verboseLog('Main::fireEvent &quot;' + functionName + '&quot;', args);
-			
-			if (args !== null) {
-				if (args is Array) args = Escaper.escapeArray(args);
-				else args = [Escaper.escape(args)];
-			}
-			
-			ExternalInterface.call(root.loaderInfo.parameters.fireCallback, functionName, args || []);
-		}
-		
-		private function empty(fake:* = null):void
-		{}
-		
-		// External Interface - JS to Flash - calls
-		
-		private function xInitialize(options_override:Object = null):void
-		{
-			xSetOptions(options_override);
-			
-			// Make the stage clickable and transparent.
-			stage.align = StageAlign.TOP_LEFT;
-			stage.scaleMode = StageScaleMode.NO_SCALE;
-			
-			stage.addEventListener(MouseEvent.CLICK, stageClick);
-			stage.addEventListener(MouseEvent.MOUSE_DOWN, stageMouse);
-			stage.addEventListener(MouseEvent.MOUSE_UP, stageMouse);
-			stage.addEventListener(MouseEvent.MOUSE_OVER, stageMouse);
-			stage.addEventListener(MouseEvent.MOUSE_OUT, stageMouse);
-			stage.addEventListener(Event.MOUSE_LEAVE, stageLeave);
-			stage.addEventListener(Event.RESIZE, stageResize);
-			
-			
-			buttonLoader = new Loader();
-			buttonLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, empty);
-			buttonLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, empty);
-			
-			stage.addChild(buttonLoader);
-			
-			
-			buttonCursorSprite = new Sprite();
-			buttonCursorSprite.graphics.beginFill(0xFFFFFF, 0);
-			buttonCursorSprite.graphics.drawRect(0, 0, 1, 1);
-			buttonCursorSprite.graphics.endFill();
-			buttonCursorSprite.buttonMode = true;
-			buttonCursorSprite.useHandCursor = true;
-			buttonCursorSprite.x = 0;
-			buttonCursorSprite.y = 0;
-			buttonCursorSprite.addEventListener(MouseEvent.CLICK, empty);
-			
-			stage.addChild(buttonCursorSprite);
-			
-			initButton();
-			
-			verboseLog('initialized');
-		}
-		
-		private function xSetOptions(options_override:Object = null):void
-		{
-			if (options_override != null) {
-				for (var prop:String in options) {
-					if (options_override.hasOwnProperty(prop)) {
-						switch (prop) {
-							case 'policyFile':
-								if (options_override[prop] is String) Security.loadPolicyFile(options_override[prop]);
-								break;
-						}
-						options[prop] = options_override[prop];
-					}
-				}
-			}
-		}
-		
-		private function xFileSetOptions(id:uint, options_init:Object = null):Boolean
-		{
-			var ref:File = getFileById(id);
-			if (!ref) return false;
-			
-			ref.setOptions(options_init);
-			return true;
-		}
-		
-		private function xFileStart(id:uint):Boolean
-		{
-			var ref:File = getFileById(id);
-			if (!ref) return false;
-			
-			return ref.start();
-		}
-		
-		private function xFileStop(id:uint):Boolean
-		{
-			var ref:File = getFileById(id);
-			if (!ref) return false;
-			
-			return ref.stop();
-		}
-		
-		private function xFileRemove(id:uint):Boolean
-		{
-			var ref:File = getFileById(id);
-			if (!ref) return false;
-			
-			return ref.remove();
-		}
-		
-		public function queueUpdate():Object
-		{
-			return {
-				uploading: uploading,
-				size: size,
-				bytesLoaded: bytesLoaded,
-				percentLoaded: (size &gt; 0) ? Math.ceil(bytesLoaded / size * 100) : 0,
-				rate: rate
-			};
-		}
-		
-		private function xFileRequeue(id:uint):Boolean
-		{
-			var ref:File = getFileById(id);
-			if (!ref) return false;
-									
-			return ref.requeue();
-		}
-		
-		private function xStart():void
-		{
-			if (uploading) return;
-			checkQueue();
-			if (uploading) fireEvent('start');
-		}
-		
-		private function xSetEnabled(status:* = null):void
-		{
-			if (status == null) status = !(buttonState &amp; BUTTON_STATE_DISABLED);
-			
-			if (status) buttonState = buttonState &amp;~ BUTTON_STATE_DISABLED;
-			else buttonState = buttonState | BUTTON_STATE_DISABLED;
-			
-			buttonCursorSprite.useHandCursor = status;
-			
-			updateButton();
-		}
-		
-		private function xStop():void
-		{
-			for (var i:uint = fileList.length - 1; i &gt; 0; i--) {
-				if (fileList[i].status != File.STATUS_RUNNING) continue;
-				fileList[i].stop();
-			}
-		}
-		
-		private function xRemove():void
-		{
-			while (fileList.length) {
-				fileList[0].remove();
-			}
-		}
-		
-		public function checkQueue(eventful:Boolean = false):void
-		{
-			var queued:uint = (options.queued) ? ((options.queued &gt; 1) ? options.queued : 1) : 0;
-			
-			if (uploading &amp;&amp; queued &amp;&amp; uploading &gt;= queued) return;
-			
-			var length:uint = fileList.length;
-			
-			for (var i:uint = 0; i &lt; length; i++) {
-				if (fileList[i].status != File.STATUS_QUEUED) continue;
-				fileList[i].start();
-				if (queued &amp;&amp; uploading &gt;= queued) break;
-			}
-			
-			if (!uploading &amp;&amp; eventful) fireEvent('complete', [queueUpdate()]);
-		}
-		
-		private function stageClick(e:MouseEvent):void
-		{
-			if (buttonState &amp; BUTTON_STATE_DISABLED) {
-				fireEvent('disabledBrowse');
-				return;
-			}
-			
-			browse();
-		}
-		
-		private function stageLeave(e:Event):void
-		{
-			buttonState = buttonState &amp;~ BUTTON_STATE_DOWN;
-			buttonState = buttonState &amp;~ BUTTON_STATE_OVER;
-			
-			updateButton();
-		}
-		
-		private function stageResize(e:Event):void
-		{
-			updateSize();
-		}
-		
-		private function stageMouse(e:MouseEvent):void
-		{
-			switch (e.type) {
-				case MouseEvent.MOUSE_DOWN:
-					if (e.buttonDown) buttonState = buttonState | BUTTON_STATE_DOWN;
-					break;
-				case MouseEvent.MOUSE_UP:
-					buttonState = buttonState &amp;~ BUTTON_STATE_DOWN;
-					break;
-				case MouseEvent.MOUSE_OVER:
-					buttonState = buttonState | BUTTON_STATE_OVER;
-					break;
-				case MouseEvent.MOUSE_OUT:
-					buttonState = buttonState &amp;~ BUTTON_STATE_OVER;
-			}
-			
-			updateButton();
-		}
-		
-		private function updateSize():void
-		{
-			buttonCursorSprite.width = stage.stageWidth;
-			buttonCursorSprite.height = stage.stageHeight;
-		}
-		
-		private function initButton():void
-		{
-			if (options.buttonImage) {
-				buttonLoader.load(new URLRequest(options.buttonImage));
-			} else {
-				buttonLoader.unload();
-			}
-			
-			updateSize();
-			
-			updateButton();
-		}
-		
-		private function updateButton():void
-		{
-			var to_y:int = 0;
-			var event:String = 'Leave';
-			
-			if (buttonState &amp; BUTTON_STATE_DISABLED) {
-				to_y = stage.stageHeight * -3;
-				event = 'Disable';
-			} else if (buttonState &amp; BUTTON_STATE_DOWN) {
-				to_y = stage.stageHeight * -2;
-				event = 'Down';
-			} else if (buttonState &amp; BUTTON_STATE_OVER) {
-				to_y = stage.stageHeight * -1;
-				event = 'Enter';
-			}
-			
-			if (to_y != buttonLoader.y) {
-				buttonLoader.y = to_y;
-				fireEvent('button' + event);
-			}
-		}
-		
-		private function browse():void
-		{
-			var filter:Array = new Array();
-			
-			if (options.typeFilter is String) {
-				var description:String = options.typeFilterDescription || options.typeFilter;
-				var type:FileFilter = new FileFilter(description, options.typeFilter + '; ' + options.typeFilter.toUpperCase() + '; ' + options.typeFilter.toLowerCase());
-				filter.push(type);
-			} else if (options.typeFilter is Object) {
-				for (var key:String in options.typeFilter) {
-					filter.push(new FileFilter(key, options.typeFilter[key] + '; ' + options.typeFilter[key].toUpperCase() + '; ' + options.typeFilter[key].toLowerCase()));
-				}
-			}
-			
-			fireEvent('browse');
-			
-			dialog = (options.multiple) ? new FileReferenceList() : new FileReference();
-			dialog.addEventListener(Event.SELECT, handleSelect);
-			dialog.addEventListener(Event.CANCEL, handleCancel);
-			
-			try {
-				dialog.browse((filter.length) ? filter : null);
-			} catch (e:Error) {
-				verboseLog('Main::browse Exception', e.toString());
-			}
-		}
-		
-		private function handleSelect(event:Event):void
-		{
-			verboseLog('Main::handleSelect Adding Files');
-			
-			var added:Array = new Array();
-			
-			if (options.multiple) {
-				var refList:FileReferenceList = dialog;
-				for (var i:uint = 0; i &lt; refList.fileList.length; i++) {
-					var origin:FileReference = refList.fileList[i];
-					var ref:File = new File(this, origin);
-					added.push(ref);
-				}
-			} else {
-				var origin:FileReference = dialog;
-				var ref:File = new File(this, origin);
-				added.push(ref);
-			}
-			
-			var failed:Array = new Array();
-			added = added.filter(function(ref:File, i:uint, self:Array) {
-				if (!ref.validate()) {
-					ref.id = 0; // invalidate file reference
-					failed.push(ref);
-					return false;
-				}
-				size += ref.reference.size;
-				return true;
-			});
-			
-			fileList = fileList.concat(added);
-			
-			fireEvent('select', [File.exportMany(added), File.exportMany(failed), queueUpdate()]);
-			
-			dialog = null;
-		}
-		
-		private function handleCancel(event:Event):void
-		{
-			buttonState = buttonState &amp; ~ BUTTON_STATE_OVER;
-			updateButton();
-			
-			fireEvent('cancel');
-			
-			dialog = null;
-		}
-		
-		private function getFileById(id:uint):File
-		{
-			if (id &gt; 0) {
-				for (var i:uint = 0; i &lt; fileList.length; i++) {
-					if (fileList[i].id == id) return fileList[i];
-				}
-			}
-			
-			verboseLog('Main::getFileById', 'File not found: ' + id);
-			
-			return null;
-		}
-		
-		public function hasFile(check:File):Boolean
-		{
-			verboseLog('Main::hasFile', 'Checking ' + check.reference.name);
-			
-			return fileList.some(function(current:File, i:uint, self:Array) {
-				if (current.reference == check.reference) return true;
-				return (check.reference.name == current.reference.name &amp;&amp; check.reference.size == current.reference.size &amp;&amp; check.reference.creationDate.valueOf() == current.reference.creationDate.valueOf());
-			}, this);
-		}
-		
-		// Misc. helpers
-		
-		public function verboseLog(labelName:String, message:* = null):void
-		{
-			if (!options.verbose) return;
-			if (message) ExternalInterface.call('Swiff.Uploader.log', labelName + ':', Escaper.escape(message));
-			else ExternalInterface.call('Swiff.Uploader.log', labelName);
-		}
-		
-	}
-}
\ No newline at end of file
+&#65279;/** * Swiff.Uploader * * Credits: A lot of good parts are inspired by the awesome www.swfupload.org * * @licence		MIT Licence * * @author		Harald Kirschner &lt;http://digitarald.de&gt; * @author		Anders Rasmussen &lt;aras@dr.dk&gt; * @author		Valerio Proietti, &lt;http://mad4milk.net&gt; * @copyright	Authors */package{	import flash.display.Sprite;	import flash.display.StageAlign;	import flash.display.StageScaleMode;	import flash.display.MovieClip;		import flash.display.Loader;		import flash.events.*;	import flash.utils.*;		import flash.system.Security;	import flash.net.FileReference;	import flash.net.FileReferenceList;	import flash.net.FileFilter;		import flash.net.URLRequest;	import flash.external.ExternalInterface;		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 Escaper;		import File;		public class Main extends Sprite	{		public var options:Object = {			typeFilter: null,			typeFilterDescription: null,			multiple: null,			queued: null,			verbose: null,			width: 128,			height: 32,			passStatus: null,						url: null,			method: null,			data: null,			mergeData: null,			fieldName: null,			progressGraphSize: 10,						fileSizeMin: 1,			fileSizeMax: null,// Official 100 MB limit for FileReference			allowDuplicates: false,			timeLimit: null,						policyFile: null,			buttonImage: null		};				public var fileList:Array = new Array();		public var uploading:uint = 0;				public var size:uint = 0;		public var bytesLoaded:uint = 0;		public var rate:uint = 0;				private var dialog:*= null;				private var buttonLoader:Loader;		private var buttonCursorSprite:Sprite;				private var buttonState:uint = 0;				const BUTTON_STATE_OVER = 1;		const BUTTON_STATE_DOWN = 2;		const BUTTON_STATE_DISABLED = 4;			public function Main():void		{			if (stage) init();			else addEventListener(Event.ADDED_TO_STAGE, init);		}				private function init(e:Event = null):void		{			removeEventListener(Event.ADDED_TO_STAGE, init);						if (!flash.net.FileReference || !flash.external.ExternalInterface || !flash.external.ExternalInterface.available) {				return;			}						// allow uploading to any domain			Security.allowDomain(&quot;*&quot;);						// ExternalInterface callback adding copied			ExternalInterface.addCallback('initialize', xInitialize);			ExternalInterface.addCallback('setOptions', xSetOptions);						ExternalInterface.addCallback('start', xStart);			ExternalInterface.addCallback('stop', xStop);			ExternalInterface.addCallback('remove', xRemove);						ExternalInterface.addCallback('setEnabled', xSetEnabled);						ExternalInterface.addCallback('fileSetOptions', xFileSetOptions);			ExternalInterface.addCallback('fileStart', xFileStart);			ExternalInterface.addCallback('fileStop', xFileStop);			ExternalInterface.addCallback('fileRemove', xFileRemove);			ExternalInterface.addCallback('fileRequeue', xFileRequeue);						fireEvent('load');		}				public function fireEvent(functionName:String, args:* = null):void		{			verboseLog('Main::fireEvent &quot;' + functionName + '&quot;', args);						if (args !== null) {				if (args is Array) args = Escaper.escapeArray(args);				else args = [Escaper.escape(args)];			}						ExternalInterface.call(root.loaderInfo.parameters.fireCallback, functionName, args || []);		}				private function empty(fake:* = null):void		{}				// External Interface - JS to Flash - calls				private function xInitialize(options_override:Object = null):void		{			xSetOptions(options_override);						// Make the stage clickable and transparent.			stage.align = StageAlign.TOP_LEFT;			stage.scaleMode = StageScaleMode.NO_SCALE;						stage.addEventListener(MouseEvent.CLICK, stageClick);			stage.addEventListener(MouseEvent.MOUSE_DOWN, stageMouse);			stage.addEventListener(MouseEvent.MOUSE_UP, stageMouse);			stage.addEventListener(MouseEvent.MOUSE_OVER, stageMouse);			stage.addEventListener(MouseEvent.MOUSE_OUT, stageMouse);			stage.addEventListener(Event.MOUSE_LEAVE, stageLeave);			stage.addEventListener(Event.RESIZE, stageResize);									buttonLoader = new Loader();			buttonLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, empty);			buttonLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, empty);						stage.addChild(buttonLoader);									buttonCursorSprite = new Sprite();			buttonCursorSprite.graphics.beginFill(0xFFFFFF, 0);			buttonCursorSprite.graphics.drawRect(0, 0, 1, 1);			buttonCursorSprite.graphics.endFill();			buttonCursorSprite.buttonMode = true;			buttonCursorSprite.useHandCursor = true;			buttonCursorSprite.x = 0;			buttonCursorSprite.y = 0;			buttonCursorSprite.addEventListener(MouseEvent.CLICK, empty);						stage.addChild(buttonCursorSprite);						initButton();						verboseLog('initialized');		}				private function xSetOptions(options_override:Object = null):void		{			if (options_override != null) {				for (var prop:String in options) {					if (options_override.hasOwnProperty(prop)) {						switch (prop) {							case 'policyFile':								if (options_override[prop] is String) Security.loadPolicyFile(options_override[prop]);								break;						}						options[prop] = options_override[prop];					}				}			}		}				private function xFileSetOptions(id:uint, options_init:Object = null):Boolean		{			var ref:File = getFileById(id);			if (!ref) return false;						ref.setOptions(options_init);			return true;		}				private function xFileStart(id:uint):Boolean		{			var ref:File = getFileById(id);			if (!ref) return false;						return ref.start();		}				private function xFileStop(id:uint):Boolean		{			var ref:File = getFileById(id);			if (!ref) return false;						return ref.stop();		}				private function xFileRemove(id:uint):Boolean		{			var ref:File = getFileById(id);			if (!ref) return false;						return ref.remove();		}				public function queueUpdate():Object		{			return {				uploading: uploading,				size: size,				bytesLoaded: bytesLoaded,				percentLoaded: (size &gt; 0) ? Math.ceil(bytesLoaded / size * 100) : 0,				rate: rate			};		}				private function xFileRequeue(id:uint):Boolean		{			var ref:File = getFileById(id);			if (!ref) return false;												return ref.requeue();		}				private function xStart():void		{			if (uploading) return;			checkQueue();			if (uploading) fireEvent('start');		}				private function xSetEnabled(status:* = null):void		{			if (status == null) status = !(buttonState &amp; BUTTON_STATE_DISABLED);						if (status) buttonState = buttonState &amp;~ BUTTON_STATE_DISABLED;			else buttonState = buttonState | BUTTON_STATE_DISABLED;						buttonCursorSprite.useHandCursor = status;						updateButton();		}				private function xStop():void		{			for (var i:uint = fileList.length - 1; i &gt; 0; i--) {				if (fileList[i].status != File.STATUS_RUNNING) continue;				fileList[i].stop();			}		}				private function xRemove():void		{			while (fileList.length) {				fileList[0].remove();			}		}				public function checkQueue(eventful:Boolean = false):void		{			var queued:uint = (options.queued) ? ((options.queued &gt; 1) ? options.queued : 1) : 0;						if (uploading &amp;&amp; queued &amp;&amp; uploading &gt;= queued) return;						var length:uint = fileList.length;						for (var i:uint = 0; i &lt; length; i++) {				if (fileList[i].status != File.STATUS_QUEUED) continue;				fileList[i].start();				if (queued &amp;&amp; uploading &gt;= queued) break;			}						if (!uploading &amp;&amp; eventful) fireEvent('complete', [queueUpdate()]);		}				private function stageClick(e:MouseEvent):void		{			if (buttonState &amp; BUTTON_STATE_DISABLED) {				fireEvent('disabledBrowse');				return;			}						browse();		}				private function stageLeave(e:Event):void		{			buttonState = buttonState &amp;~ BUTTON_STATE_DOWN;			buttonState = buttonState &amp;~ BUTTON_STATE_OVER;						updateButton();		}				private function stageResize(e:Event):void		{			updateSize();		}				private function stageMouse(e:MouseEvent):void		{			switch (e.type) {				case MouseEvent.MOUSE_DOWN:					if (e.buttonDown) buttonState = buttonState | BUTTON_STATE_DOWN;					break;				case MouseEvent.MOUSE_UP:					buttonState = buttonState &amp;~ BUTTON_STATE_DOWN;					break;				case MouseEvent.MOUSE_OVER:					buttonState = buttonState | BUTTON_STATE_OVER;					break;				case MouseEvent.MOUSE_OUT:					buttonState = buttonState &amp;~ BUTTON_STATE_OVER;			}						updateButton();		}				private function updateSize():void		{			buttonCursorSprite.width = stage.stageWidth;			buttonCursorSprite.height = stage.stageHeight;		}				private function initButton():void		{			if (options.buttonImage) {				buttonLoader.load(new URLRequest(options.buttonImage));			} else {				buttonLoader.unload();			}						updateSize();						updateButton();		}				private function updateButton():void		{			var to_y:int = 0;			var event:String = 'Leave';						if (buttonState &amp; BUTTON_STATE_DISABLED) {				to_y = stage.stageHeight * -3;				event = 'Disable';			} else if (buttonState &amp; BUTTON_STATE_DOWN) {				to_y = stage.stageHeight * -2;				event = 'Down';			} else if (buttonState &amp; BUTTON_STATE_OVER) {				to_y = stage.stageHeight * -1;				event = 'Enter';			}						if (to_y != buttonLoader.y) {				buttonLoader.y = to_y;				fireEvent('button' + event);			}		}				private function browse():void		{			var filter:Array = new Array();						if (options.typeFilter is String) {				var description:String = options.typeFilterDescription || options.typeFilter;				var type:FileFilter = new FileFilter(description, options.typeFilter + '; ' + options.typeFilter.toUpperCase() + '; ' + options.typeFilter.toLowerCase());				filter.push(type);			} else if (options.typeFilter is Object) {				for (var key:String in options.typeFilter) {					filter.push(new FileFilter(key, options.typeFilter[key] + '; ' + options.typeFilter[key].toUpperCase() + '; ' + options.typeFilter[key].toLowerCase()));				}			}						fireEvent('browse');						dialog = (options.multiple) ? new FileReferenceList() : new FileReference();			dialog.addEventListener(Event.SELECT, handleSelect);			dialog.addEventListener(Event.CANCEL, handleCancel);						try {				dialog.browse((filter.length) ? filter : null);			} catch (e:Error) {				verboseLog('Main::browse Exception', e.toString());			}		}				private function handleSelect(event:Event):void		{			verboseLog('Main::handleSelect Adding Files');						var added:Array = new Array();						if (options.multiple) {				var refList:FileReferenceList = dialog;				for (var i:uint = 0; i &lt; refList.fileList.length; i++) {					var origin:FileReference = refList.fileList[i];					var ref:File = new File(this, origin);					added.push(ref);				}			} else {				var origin:FileReference = dialog;				var ref:File = new File(this, origin);				added.push(ref);			}						var failed:Array = new Array();			added = added.filter(function(ref:File, i:uint, self:Array) {				if (!ref.validate()) {					ref.id = 0; // invalidate file reference					failed.push(ref);					return false;				}				size += ref.reference.size;				return true;			});						fileList = fileList.concat(added);						fireEvent('select', [File.exportMany(added), File.exportMany(failed), queueUpdate()]);						dialog = null;		}				private function handleCancel(event:Event):void		{			buttonState = buttonState &amp; ~ BUTTON_STATE_OVER;			updateButton();						fireEvent('cancel');						dialog = null;		}				private function getFileById(id:uint):File		{			if (id &gt; 0) {				for (var i:uint = 0; i &lt; fileList.length; i++) {					if (fileList[i].id == id) return fileList[i];				}			}						verboseLog('Main::getFileById', 'File not found: ' + id);						return null;		}				public function hasFile(check:File):Boolean		{			verboseLog('Main::hasFile', 'Checking ' + check.reference.name);						return fileList.some(function(current:File, i:uint, self:Array) {				if (current.reference == check.reference) return true;				return (check.reference.name == current.reference.name &amp;&amp; check.reference.size == current.reference.size &amp;&amp; check.reference.creationDate.valueOf() == current.reference.creationDate.valueOf());			}, this);		}				// Misc. helpers				public function verboseLog(labelName:String, message:* = null):void		{			if (!options.verbose) return;			if (message) ExternalInterface.call('Swiff.Uploader.log', labelName + ':', Escaper.escape(message));			else ExternalInterface.call('Swiff.Uploader.log', labelName);		}			}}
\ No newline at end of file</diff>
      <filename>source/as3proj/Main.as</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>1fad5fea4dd003d4cab831c89ea30e2131936b7e</id>
    </parent>
  </parents>
  <author>
    <name>Harald Kirschner</name>
    <email>mail@digitarald.de</email>
  </author>
  <url>http://github.com/digitarald/digitarald-fancyupload/commit/af2379220a4bb59eded480a9c881e8e9ec375a05</url>
  <id>af2379220a4bb59eded480a9c881e8e9ec375a05</id>
  <committed-date>2009-05-25T01:14:29-07:00</committed-date>
  <authored-date>2009-05-25T01:14:29-07:00</authored-date>
  <message> - added option timeLimit and updated docs</message>
  <tree>ac8394bb9181eb16f30c5dd6970dfcc69b557c26</tree>
  <committer>
    <name>Harald Kirschner</name>
    <email>mail@digitarald.de</email>
  </committer>
</commit>
