larsklevan_s3_swf_upload 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +6 -0
  2. data/CHANGELOG +26 -0
  3. data/Gemfile +4 -0
  4. data/MIT-LICENSE +20 -0
  5. data/Manifest +34 -0
  6. data/README.textile +222 -0
  7. data/Rakefile +14 -0
  8. data/flex_src/bin-release/flex-config.xml +356 -0
  9. data/flex_src/compile +2 -0
  10. data/flex_src/src/Globals.as +15 -0
  11. data/flex_src/src/S3Uploader.as +204 -0
  12. data/flex_src/src/com/adobe/net/MimeTypeMap.as +196 -0
  13. data/flex_src/src/com/elctech/S3UploadOptions.as +31 -0
  14. data/flex_src/src/com/elctech/S3UploadRequest.as +254 -0
  15. data/flex_src/src/com/nathancolgate/s3_swf_upload/BrowseButton.as +55 -0
  16. data/flex_src/src/com/nathancolgate/s3_swf_upload/S3Queue.as +117 -0
  17. data/flex_src/src/com/nathancolgate/s3_swf_upload/S3Signature.as +116 -0
  18. data/flex_src/src/com/nathancolgate/s3_swf_upload/S3Upload.as +111 -0
  19. data/lib/patch/integer.rb +12 -0
  20. data/lib/s3_swf_upload.rb +10 -0
  21. data/lib/s3_swf_upload/railtie.rb +16 -0
  22. data/lib/s3_swf_upload/railties/generators/s3_swf_upload.rb +19 -0
  23. data/lib/s3_swf_upload/railties/generators/uploader/USAGE +10 -0
  24. data/lib/s3_swf_upload/railties/generators/uploader/templates/amazon_s3.yml +20 -0
  25. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_down_button.gif +0 -0
  26. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_over_button.gif +0 -0
  27. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_up_button.gif +0 -0
  28. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_upload.js +118 -0
  29. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_upload.swf +0 -0
  30. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_uploads_controller.rb +53 -0
  31. data/lib/s3_swf_upload/railties/generators/uploader/uploader_generator.rb +20 -0
  32. data/lib/s3_swf_upload/railties/tasks/crossdomain.xml +5 -0
  33. data/lib/s3_swf_upload/s3_config.rb +43 -0
  34. data/lib/s3_swf_upload/signature.rb +203 -0
  35. data/lib/s3_swf_upload/view_helpers.rb +171 -0
  36. data/s3_swf_upload.gemspec +28 -0
  37. metadata +106 -0
@@ -0,0 +1,254 @@
1
+ package com.elctech {
2
+
3
+ // import flash.events.*;
4
+ import flash.events.EventDispatcher;
5
+ import flash.events.ProgressEvent;
6
+ import flash.events.Event;
7
+ import flash.events.IOErrorEvent;
8
+ import flash.events.SecurityErrorEvent;
9
+ import flash.events.HTTPStatusEvent;
10
+ import flash.events.DataEvent;
11
+
12
+ // import flash.net.*;
13
+ import flash.net.FileReference;
14
+ import flash.net.URLVariables;
15
+ import flash.net.URLRequest;
16
+ import flash.net.URLRequestMethod;
17
+
18
+ import flash.system.Security;
19
+ import flash.xml.XMLDocument;
20
+ import flash.xml.XMLNode;
21
+ // import mx.controls.Alert;
22
+
23
+ /**
24
+ * This class encapsulates a POST request to S3.
25
+ *
26
+ * After you create an S3PostRequest, invoke S3PostRequest::upload(fileReference:FileReference).
27
+ *
28
+ */
29
+ public class S3UploadRequest extends EventDispatcher {
30
+
31
+ [Event(name="open", type="flash.events.Event.OPEN")]
32
+ [Event(name="uploadCompleteData", type="flash.events.DataEvent.UPLOAD_COMPLETE_DATA")]
33
+ [Event(name="ioError", type="flash.events.IOErrorEvent.IO_ERROR")]
34
+ [Event(name="securityError", type="flash.events.SecurityErrorEvent.SECURITY_ERROR")]
35
+ [Event(name="progress", type="flash.events.ProgressEvent.PROGRESS")]
36
+
37
+ private var _accessKeyId:String;
38
+ private var _bucket:String;
39
+ private var _key:String;
40
+ private var _options:S3UploadOptions;
41
+ private var _httpStatusErrorReceived:Boolean;
42
+ private var _uploadStarted:Boolean;
43
+ private var fileReference:FileReference;
44
+
45
+ private const ENDPOINT:String = "s3.amazonaws.com";
46
+ private const MIN_BUCKET_LENGTH:int = 3;
47
+ private const MAX_BUCKET_LENGTH:int = 63;
48
+
49
+
50
+ /**
51
+ * Creates and initializes a new S3PostRequest object.
52
+ * @param accessKeyId The AWS access key id to authenticate the request
53
+ * @param bucket The bucket to POST into
54
+ * @param key The key to create
55
+ * @param options Options for this request
56
+ */
57
+ public function S3UploadRequest(options:S3UploadOptions) {
58
+
59
+ _accessKeyId = options.AWSAccessKeyId;
60
+ _bucket = options.bucket;
61
+ _key = options.key;
62
+ _options = options;
63
+ }
64
+
65
+ private function buildUrl():String {
66
+
67
+ var canUseVanityStyle:Boolean = canUseVanityStyle(_bucket);
68
+
69
+ if(_options.Secure!="false" && canUseVanityStyle && _bucket.match(/\./)) {
70
+ // We cannot use SSL for bucket names containing "."
71
+ // The certificate won't match "my.bucket.s3.amazonaws.com"
72
+ throw new SecurityError("Cannot use SSL with bucket name containing '.': " + _bucket);
73
+ }
74
+
75
+ var postUrl:String = "http" + ((_options.Secure == 'true') ? "s" : "") + "://";
76
+
77
+ if(canUseVanityStyle) {
78
+ postUrl += _bucket + "." + ENDPOINT;
79
+ } else {
80
+ postUrl += ENDPOINT + "/" + _bucket;
81
+ }
82
+
83
+ return postUrl;
84
+ }
85
+
86
+ private function canUseVanityStyle(bucket:String):Boolean {
87
+ if( bucket.length < MIN_BUCKET_LENGTH ||
88
+ bucket.length > MAX_BUCKET_LENGTH ||
89
+ bucket.match(/^\./) ||
90
+ bucket.match(/\.$/) ) {
91
+ return false;
92
+ }
93
+
94
+ // must be lower case
95
+ if(bucket.toLowerCase() != bucket) {
96
+ return false;
97
+ }
98
+
99
+ // Check not IPv4-like
100
+ if (bucket.match(/^[0-9]|+\.[0-9]|+\.[0-9]|+\.[0-9]|+$/)) {
101
+ return false;
102
+ }
103
+
104
+ // Check each label
105
+ if(bucket.match(/\./)) {
106
+ var labels:Array = bucket.split(/\./);
107
+ for (var i:int = 0;i < labels.length; i++) {
108
+ if(!labels[i].match(/^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$/)) {
109
+ return false;
110
+ }
111
+ }
112
+ }
113
+
114
+ return true;
115
+ }
116
+
117
+ private function loadPolicyFile(postUrl:String):void {
118
+ /*
119
+ * Due to the restrictions imposed by the Adobe Flash security sandbox,
120
+ * the bucket being uploaded to must contain a public-readable crossdomain.xml
121
+ * file that allows access from the domain that served the SWF hosting this code.
122
+ *
123
+ * Read Adobe's documentation on the Flash security sandbox for more information.
124
+ *
125
+ */
126
+
127
+ Security.loadPolicyFile(postUrl + "/crossdomain.xml");
128
+ }
129
+
130
+
131
+ public function removeListeners():void {
132
+ trace('removeListeners');
133
+ fileReference.removeEventListener(Event.OPEN, onOpen);
134
+ fileReference.removeEventListener(ProgressEvent.PROGRESS, onProgress);
135
+ fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onIOError);
136
+ fileReference.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
137
+ fileReference.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onUploadCompleteData);
138
+ fileReference.removeEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
139
+ }
140
+ /**
141
+ * Initiates a POST upload request to S3
142
+ * @param fileReference A FileReference object referencing the file to upload to S3.
143
+ */
144
+ public function upload(_fileReference:FileReference):void {
145
+
146
+ if(_uploadStarted) {
147
+ throw new Error("S3PostRequest object cannot be reused. Create another S3PostRequest object to send another request to Amazon S3.");
148
+ }
149
+ _uploadStarted = true;
150
+
151
+ // Save the FileReference object so that it doesn't get GCed.
152
+ // If this happens, we can lose events that should be dispatched.
153
+ fileReference = _fileReference;
154
+
155
+ var postUrl:String = buildUrl();
156
+ loadPolicyFile(postUrl);
157
+ var urlRequest:URLRequest = new URLRequest(postUrl);
158
+ urlRequest.method = URLRequestMethod.POST;
159
+ urlRequest.data = buildPostVariables();
160
+
161
+ // set up event handlers *****************************************************
162
+ fileReference.addEventListener(Event.OPEN, onOpen);
163
+ fileReference.addEventListener(ProgressEvent.PROGRESS, onProgress);
164
+ fileReference.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
165
+ fileReference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
166
+ fileReference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onUploadCompleteData);
167
+ fileReference.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
168
+ // *****************************************************************************
169
+
170
+ // send the request
171
+ fileReference.upload(urlRequest, "file", false);
172
+ }
173
+
174
+ private function buildPostVariables():URLVariables {
175
+
176
+ var postVariables:URLVariables = new URLVariables();
177
+
178
+ postVariables.key = _key;
179
+ postVariables.acl = _options.acl;
180
+ postVariables.AWSAccessKeyId = _accessKeyId;
181
+ postVariables.signature = _options.signature;
182
+ postVariables["Content-Type"] = _options.ContentType;
183
+ postVariables["Content-Disposition"] = "attachment";
184
+ postVariables.policy = _options.policy;
185
+
186
+ /**
187
+ * Certain combinations of Flash player version and platform don't handle
188
+ * HTTP responses with the header 'Content-Length: 0'. These clients do not
189
+ * dispatch completion or error events when such a response is received.
190
+ * Therefore it is impossible to tell when the upload has completed or failed.
191
+ *
192
+ * Flash clients should always set the success_action_status parameter to 201
193
+ * so that Amazon S3 returns a response with Content-Length being non-zero.
194
+ *
195
+ */
196
+ postVariables.success_action_status = "201";
197
+
198
+ return postVariables;
199
+ }
200
+
201
+ private function onOpen(event:Event):void {
202
+ trace('onOpen: '+this._key);
203
+ this.dispatchEvent(event);
204
+ }
205
+ private function onIOError(event:IOErrorEvent):void {
206
+ /*
207
+ * FileReference.upload likes to send cryptic IOErrors when it doesn't get a status code that it likes.
208
+ * If we already got an error HTTP status code, don't propagate this event since the HTTPStatusEvent
209
+ * event handler dispatches an IOErrorEvent.
210
+ */
211
+ if(!_httpStatusErrorReceived) {
212
+ this.dispatchEvent(event);
213
+ }
214
+ }
215
+ private function onSecurityError(event:SecurityErrorEvent):void {
216
+ this.dispatchEvent(event);
217
+ }
218
+ private function onProgress(event:ProgressEvent):void {
219
+ this.dispatchEvent(event);
220
+ }
221
+ private function onUploadCompleteData(event:DataEvent):void {
222
+ var data:String = event.data;
223
+ if(isError(data)) {
224
+ this.dispatchEvent(
225
+ new IOErrorEvent(IOErrorEvent.IO_ERROR, event.bubbles, event.cancelable, "Amazon S3 returned an error: " + data + ".")
226
+ );
227
+ } else {
228
+ this.dispatchEvent(new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, data));
229
+ }
230
+ }
231
+ private function onHttpStatus(event:HTTPStatusEvent):void {
232
+ _httpStatusErrorReceived = true;
233
+ if(Math.floor(event.status/100) == 2) {
234
+ this.dispatchEvent(new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, "Amazon S3 returned HTTP status " + event.status.toString() + "."));
235
+ } else {
236
+ this.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, event.bubbles, event.cancelable, "Amazon S3 returned an error: HTTP status " + event.status.toString() + "."));
237
+ }
238
+ }
239
+
240
+ private function isError(responseText:String):Boolean {
241
+ var xml:XMLDocument = new XMLDocument();
242
+ xml.ignoreWhite = true;
243
+ xml.parseXML(responseText);
244
+ var root:XMLNode = xml.firstChild;
245
+ if( root == null || root.nodeName != "Error" )
246
+ {
247
+ return false;
248
+ }
249
+ return true;
250
+ }
251
+
252
+ }
253
+
254
+ }
@@ -0,0 +1,55 @@
1
+ package com.nathancolgate.s3_swf_upload {
2
+
3
+ import flash.display.*;
4
+ import flash.events.MouseEvent;
5
+ import flash.events.Event;
6
+ import flash.net.*;
7
+
8
+ public dynamic class BrowseButton extends Sprite {
9
+
10
+ private var _playButton:flash.display.SimpleButton;
11
+
12
+ public function BrowseButton(width:Number,
13
+ height:Number,
14
+ buttonUpUrl:String,
15
+ buttonDownUrl:String,
16
+ buttonOverUrl:String)
17
+ {
18
+ super();
19
+
20
+ _playButton = new flash.display.SimpleButton();
21
+ _playButton.useHandCursor = true;
22
+ addChild(_playButton);
23
+
24
+ // Hit Test
25
+ var hit_test:Shape = new flash.display.Shape();
26
+ hit_test.graphics.beginFill(0xFFCC00);
27
+ hit_test.graphics.drawRect(0, 0, width, height);
28
+ hit_test.graphics.endFill();
29
+ _playButton.hitTestState = hit_test;
30
+
31
+ // Up
32
+ var upLoader:Loader = new Loader();
33
+ upLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
34
+ _playButton.upState = new Bitmap(e.target.content.bitmapData);
35
+ });
36
+ upLoader.load(new URLRequest(buttonUpUrl));
37
+
38
+ // Down
39
+ var downLoader:Loader = new Loader();
40
+ downLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
41
+ _playButton.downState = new Bitmap(e.target.content.bitmapData);
42
+ });
43
+ downLoader.load(new URLRequest(buttonDownUrl));
44
+
45
+ // Over
46
+ var overLoader:Loader = new Loader();
47
+ overLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
48
+ _playButton.overState = new Bitmap(e.target.content.bitmapData);
49
+ });
50
+ overLoader.load(new URLRequest(buttonOverUrl));
51
+ }
52
+
53
+
54
+ }
55
+ }
@@ -0,0 +1,117 @@
1
+ package com.nathancolgate.s3_swf_upload {
2
+
3
+ import mx.collections.ArrayCollection;
4
+ import mx.events.CollectionEvent;
5
+ import flash.external.ExternalInterface;
6
+ import flash.net.FileReference;
7
+ import com.nathancolgate.s3_swf_upload.*;
8
+
9
+ public class S3Queue extends ArrayCollection {
10
+
11
+ // S3 Interaction Vars
12
+ private var _signatureUrl:String;
13
+ private var _prefixPath:String;
14
+
15
+ public var currentSignature:S3Signature;
16
+
17
+ public function S3Queue(signatureUrl:String,
18
+ prefixPath:String,
19
+ source:Array = null) {
20
+
21
+ _signatureUrl = signatureUrl;
22
+ _prefixPath = prefixPath;
23
+ super(source);
24
+
25
+ // Outgoing calls
26
+ this.addEventListener(CollectionEvent.COLLECTION_CHANGE, changeHandler);
27
+ // Incoming calls
28
+ ExternalInterface.addCallback("startUploading", startUploadingHandler);
29
+ ExternalInterface.addCallback("clearQueue", clearHandler);
30
+ ExternalInterface.addCallback("stopUploading", stopUploadingHandler);
31
+ }
32
+
33
+ public function uploadNextFile():void{
34
+ // ExternalInterface.call('s3_swf.jsLog','uploadNextFile');
35
+ // ExternalInterface.call('s3_swf.jsLog','Start uploadNextFile...');
36
+ var next_file:FileReference = FileReference(this.getItemAt(0));
37
+ currentSignature = new S3Signature(next_file,_signatureUrl,_prefixPath);
38
+ // ExternalInterface.call('s3_swf.jsLog','End uploadNextFile');
39
+ }
40
+
41
+ // whenever the queue changes this function is called
42
+ private function changeHandler(event:CollectionEvent):void{
43
+ // ExternalInterface.call('s3_swf.jsLog','changeHandler');
44
+ // ExternalInterface.call('s3_swf.jsLog','Calling onQueueChange...');
45
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueChange',this.toJavascript());
46
+ // ExternalInterface.call('s3_swf.jsLog','onQueueChange called');
47
+ }
48
+
49
+ // Remove all files from the upload queue;
50
+ private function clearHandler():void{
51
+ // ExternalInterface.call('s3_swf.jsLog','clearHandler');
52
+ // ExternalInterface.call('s3_swf.jsLog','Removing All...');
53
+ this.removeAll();
54
+ // ExternalInterface.call('s3_swf.jsLog','All removed');
55
+ // ExternalInterface.call('s3_swf.jsLog','Calling onQueueClear...');
56
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueClear',this.toJavascript());
57
+ // ExternalInterface.call('s3_swf.jsLog','onQueueClear called');
58
+ }
59
+
60
+ // Start uploading the files from the queue
61
+ private function startUploadingHandler():void{
62
+ // ExternalInterface.call('s3_swf.jsLog','startUploadingHandler');
63
+ if (this.length > 0){
64
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadingStart...');
65
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadingStart');
66
+ // ExternalInterface.call('s3_swf.jsLog','onUploadingStart called');
67
+ // ExternalInterface.call('s3_swf.jsLog','Uploading next file...');
68
+ uploadNextFile();
69
+ // ExternalInterface.call('s3_swf.jsLog','Next file uploaded');
70
+ } else {
71
+ // ExternalInterface.call('s3_swf.jsLog','Calling onQueueEmpty...');
72
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueEmpty',this);
73
+ // ExternalInterface.call('s3_swf.jsLog','onQueueEmpty called');
74
+ }
75
+ }
76
+
77
+ // Cancel Current File Upload
78
+ // Which stops all future uploads as well
79
+ private function stopUploadingHandler():void{
80
+ // ExternalInterface.call('s3_swf.jsLog','stopUploadingHandler');
81
+ if (this.length > 0){
82
+ var current_file:FileReference = FileReference(this.getItemAt(0));
83
+ // ExternalInterface.call('s3_swf.jsLog','Cancelling current file...');
84
+ current_file.cancel();
85
+
86
+ currentSignature.s3upload.removeListeners();
87
+
88
+ // ExternalInterface.call('s3_swf.jsLog','Current file cancelled');
89
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadingStop...');
90
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadingStop');
91
+ // ExternalInterface.call('s3_swf.jsLog','onUploadingStop called');
92
+ } else {
93
+ // ExternalInterface.call('s3_swf.jsLog','Calling onQueueEmpty...');
94
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueEmpty',this.toJavascript());
95
+ // ExternalInterface.call('s3_swf.jsLog','onQueueEmpty called');
96
+ }
97
+ }
98
+
99
+ // This is a rather silly function to need, especially since it worked at one point
100
+ // In flash player 10.1, you could no longer send files over external reference
101
+ // This is the hack to get around the problem. Essentially: turn all those
102
+ // Files into objects
103
+ // August 27, 2010 - NCC@BNB
104
+ public function toJavascript():Object {
105
+ var faux_queue:Object = new Object();
106
+ faux_queue.files = new Array();
107
+ for (var i:int = 0;i < source.length; i++) {
108
+ faux_queue.files[i] = new Object();
109
+ faux_queue.files[i].name = source[i].name;
110
+ faux_queue.files[i].size = source[i].size;
111
+ faux_queue.files[i].type = source[i].type;
112
+ }
113
+ return faux_queue;
114
+ }
115
+
116
+ }
117
+ }
@@ -0,0 +1,116 @@
1
+ package com.nathancolgate.s3_swf_upload {
2
+
3
+ import com.elctech.S3UploadOptions;
4
+ import com.nathancolgate.s3_swf_upload.*;
5
+ import flash.external.ExternalInterface;
6
+ import com.adobe.net.MimeTypeMap;
7
+
8
+ import flash.net.*
9
+ import flash.events.*
10
+
11
+ public class S3Signature {
12
+
13
+ private var upload_options:S3UploadOptions;
14
+ private var _file:FileReference;
15
+
16
+ public var s3upload:S3Upload;
17
+
18
+ public function S3Signature(file:FileReference,
19
+ signatureUrl:String,
20
+ prefixPath:String) {
21
+ _file = file;
22
+
23
+ // Create options list for file s3 upload metadata
24
+ upload_options = new S3UploadOptions;
25
+ upload_options.FileSize = _file.size.toString();
26
+ upload_options.FileName = getFileName(_file);
27
+ upload_options.ContentType = getContentType(upload_options.FileName);
28
+ upload_options.key = prefixPath + upload_options.FileName;
29
+
30
+ var variables:URLVariables = new URLVariables();
31
+ variables.key = upload_options.key
32
+ variables.content_type = upload_options.ContentType;
33
+
34
+ var request:URLRequest = new URLRequest(signatureUrl);
35
+ request.method = URLRequestMethod.GET;
36
+ request.data = variables;
37
+
38
+ var signature:URLLoader = new URLLoader();
39
+ signature.dataFormat = URLLoaderDataFormat.TEXT;
40
+ signature.addEventListener(Event.OPEN, openHandler);
41
+ signature.addEventListener(ProgressEvent.PROGRESS, progressHandler);
42
+ signature.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
43
+ signature.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
44
+ signature.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
45
+ signature.addEventListener(Event.COMPLETE, completeHandler);
46
+ signature.load(request);
47
+ }
48
+
49
+ private function openHandler(event:Event):void {
50
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureOpen',toJavascript(_file),event);
51
+ }
52
+
53
+ private function progressHandler(progress_event:ProgressEvent):void {
54
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureProgress',toJavascript(_file),progress_event);
55
+ }
56
+
57
+ private function securityErrorHandler(security_error_event:SecurityErrorEvent):void {
58
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureSecurityError',toJavascript(_file),security_error_event);
59
+ }
60
+
61
+ private function httpStatusHandler(http_status_event:HTTPStatusEvent):void {
62
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureHttpStatus',toJavascript(_file),http_status_event);
63
+ }
64
+
65
+ private function ioErrorHandler(io_error_event:IOErrorEvent):void {
66
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureIOError',toJavascript(_file),io_error_event);
67
+ }
68
+
69
+ private function completeHandler(event:Event):void {
70
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureComplete',toJavascript(_file),event);
71
+ var loader:URLLoader = URLLoader(event.target);
72
+ var xml:XML = new XML(loader.data);
73
+
74
+ // create the s3 options object
75
+ upload_options.policy = xml.policy;
76
+ upload_options.signature = xml.signature;
77
+ upload_options.bucket = xml.bucket;
78
+ upload_options.AWSAccessKeyId = xml.accesskeyid;
79
+ upload_options.acl = xml.acl;
80
+ upload_options.Expires = xml.expirationdate;
81
+ upload_options.Secure = xml.https;
82
+
83
+ if (xml.errorMessage != "") {
84
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureXMLError',toJavascript(_file),xml.errorMessage);
85
+ return;
86
+ }
87
+
88
+ s3upload = new S3Upload(upload_options);
89
+ }
90
+
91
+ /* MISC */
92
+
93
+ private function getContentType(fileName:String):String {
94
+ var fileNameArray:Array = fileName.split(/\./);
95
+ var fileExtension:String = fileNameArray[fileNameArray.length - 1];
96
+ var mimeMap:MimeTypeMap = new MimeTypeMap;
97
+ var contentType:String = mimeMap.getMimeType(fileExtension);
98
+ return contentType;
99
+ }
100
+
101
+ private function getFileName(file:FileReference):String {
102
+ var fileName:String = file.name.replace(/^.*(\\|\/)/gi, '').replace(/[^A-Za-z0-9\.\-]/gi, '_');
103
+ return fileName;
104
+ }
105
+
106
+ // Turns a FileReference into an Object so that ExternalInterface doesn't choke
107
+ private function toJavascript(file:FileReference):Object{
108
+ var javascriptable_file:Object = new Object();
109
+ javascriptable_file.name = file.name;
110
+ javascriptable_file.size = file.size;
111
+ javascriptable_file.type = file.type;
112
+ return javascriptable_file;
113
+ }
114
+
115
+ }
116
+ }