s3_swf_upload 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +223 -0
  7. data/Rakefile +14 -0
  8. data/flex_src/bin-release/flex-config.xml +361 -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 +32 -0
  14. data/flex_src/src/com/elctech/S3UploadRequest.as +259 -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 +118 -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/railtie.rb +16 -0
  21. data/lib/s3_swf_upload/railties/generators/s3_swf_upload.rb +19 -0
  22. data/lib/s3_swf_upload/railties/generators/uploader/USAGE +10 -0
  23. data/lib/s3_swf_upload/railties/generators/uploader/templates/amazon_s3.yml +20 -0
  24. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_down_button.gif +0 -0
  25. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_over_button.gif +0 -0
  26. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_up_button.gif +0 -0
  27. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_upload.js +118 -0
  28. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_upload.swf +0 -0
  29. data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_uploads_controller.rb +53 -0
  30. data/lib/s3_swf_upload/railties/generators/uploader/uploader_generator.rb +20 -0
  31. data/lib/s3_swf_upload/railties/tasks/crossdomain.xml +5 -0
  32. data/lib/s3_swf_upload/s3_config.rb +43 -0
  33. data/lib/s3_swf_upload/signature.rb +203 -0
  34. data/lib/s3_swf_upload/view_helpers.rb +171 -0
  35. data/lib/s3_swf_upload.rb +10 -0
  36. data/s3_swf_upload.gemspec +29 -0
  37. metadata +103 -0
@@ -0,0 +1,118 @@
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
+ //private var _prefixPath:String
16
+
17
+ public var s3upload:S3Upload;
18
+
19
+ public function S3Signature(file:FileReference,
20
+ signatureUrl:String,
21
+ prefixPath:String) {
22
+ _file = file;
23
+ // _prefixPath = prefixPath
24
+ // Create options list for file s3 upload metadata
25
+ upload_options = new S3UploadOptions;
26
+ upload_options.FileSize = _file.size.toString();
27
+ upload_options.FileName = getFileName(_file);
28
+ upload_options.ContentType = getContentType(upload_options.FileName);
29
+ upload_options.key = prefixPath + upload_options.FileName;
30
+
31
+ var variables:URLVariables = new URLVariables();
32
+ variables.key = upload_options.key
33
+ variables.content_type = upload_options.ContentType;
34
+
35
+ var request:URLRequest = new URLRequest(signatureUrl);
36
+ request.method = URLRequestMethod.GET;
37
+ request.data = variables;
38
+
39
+ var signature:URLLoader = new URLLoader();
40
+ signature.dataFormat = URLLoaderDataFormat.TEXT;
41
+ signature.addEventListener(Event.OPEN, openHandler);
42
+ signature.addEventListener(ProgressEvent.PROGRESS, progressHandler);
43
+ signature.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
44
+ signature.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
45
+ signature.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
46
+ signature.addEventListener(Event.COMPLETE, completeHandler);
47
+ signature.load(request);
48
+ }
49
+
50
+ private function openHandler(event:Event):void {
51
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureOpen',toJavascript(_file),event);
52
+ }
53
+
54
+ private function progressHandler(progress_event:ProgressEvent):void {
55
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureProgress',toJavascript(_file),progress_event);
56
+ }
57
+
58
+ private function securityErrorHandler(security_error_event:SecurityErrorEvent):void {
59
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureSecurityError',toJavascript(_file),security_error_event);
60
+ }
61
+
62
+ private function httpStatusHandler(http_status_event:HTTPStatusEvent):void {
63
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureHttpStatus',toJavascript(_file),http_status_event);
64
+ }
65
+
66
+ private function ioErrorHandler(io_error_event:IOErrorEvent):void {
67
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureIOError',toJavascript(_file),io_error_event);
68
+ }
69
+
70
+ private function completeHandler(event:Event):void {
71
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureComplete',toJavascript(_file),event);
72
+ var loader:URLLoader = URLLoader(event.target);
73
+ var xml:XML = new XML(loader.data);
74
+
75
+ // create the s3 options object
76
+ upload_options.policy = xml.policy;
77
+ upload_options.signature = xml.signature;
78
+ upload_options.bucket = xml.bucket;
79
+ upload_options.AWSAccessKeyId = xml.accesskeyid;
80
+ upload_options.acl = xml.acl;
81
+ upload_options.Expires = xml.expirationdate;
82
+ upload_options.Secure = xml.https;
83
+ upload_options.newKey = xml.newKey; //NOTE that we stop caring about the specified prefix if we have a newkey.
84
+
85
+ if (xml.errorMessage != "") {
86
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureXMLError',toJavascript(_file),xml.errorMessage);
87
+ return;
88
+ }
89
+
90
+ s3upload = new S3Upload(upload_options);
91
+ }
92
+
93
+ /* MISC */
94
+
95
+ private function getContentType(fileName:String):String {
96
+ var fileNameArray:Array = fileName.split(/\./);
97
+ var fileExtension:String = fileNameArray[fileNameArray.length - 1];
98
+ var mimeMap:MimeTypeMap = new MimeTypeMap;
99
+ var contentType:String = mimeMap.getMimeType(fileExtension);
100
+ return contentType;
101
+ }
102
+
103
+ private function getFileName(file:FileReference):String {
104
+ var fileName:String = file.name.replace(/^.*(\\|\/)/gi, '').replace(/[^A-Za-z0-9\.\-]/gi, '_');
105
+ return fileName;
106
+ }
107
+
108
+ // Turns a FileReference into an Object so that ExternalInterface doesn't choke
109
+ private function toJavascript(file:FileReference):Object{
110
+ var javascriptable_file:Object = new Object();
111
+ javascriptable_file.name = file.name;
112
+ javascriptable_file.size = file.size;
113
+ javascriptable_file.type = file.type;
114
+ return javascriptable_file;
115
+ }
116
+
117
+ }
118
+ }
@@ -0,0 +1,111 @@
1
+ package com.nathancolgate.s3_swf_upload {
2
+
3
+ import com.elctech.S3UploadOptions;
4
+ import com.elctech.S3UploadRequest;
5
+ import flash.external.ExternalInterface;
6
+ import com.nathancolgate.s3_swf_upload.*;
7
+ import flash.net.*;
8
+ import flash.events.*;
9
+
10
+ public class S3Upload extends S3UploadRequest {
11
+
12
+ private var _upload_options:S3UploadOptions;
13
+
14
+ public function S3Upload(s3_upload_options:S3UploadOptions) {
15
+ super(s3_upload_options);
16
+
17
+ _upload_options = s3_upload_options;
18
+
19
+ addEventListener(Event.OPEN, openHandler);
20
+ addEventListener(ProgressEvent.PROGRESS, progressHandler);
21
+ addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
22
+ addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
23
+ addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
24
+ addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, completeHandler);
25
+
26
+ try {
27
+ var next_file:FileReference = FileReference(Globals.queue.getItemAt(0));
28
+ this.upload(next_file);
29
+ } catch(error:Error) {
30
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadError',_upload_options,error);
31
+ }
32
+ }
33
+
34
+ // called after the file is opened before _upload_options
35
+ private function openHandler(event:Event):void{
36
+ // This should only happen once per file
37
+ // But sometimes, after stopping and restarting the queeue
38
+ // It gets called multiple times
39
+ // BUG BUG BUG!
40
+ // ExternalInterface.call('s3_swf.jsLog','openHandler');
41
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadOpen...');
42
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadOpen',_upload_options,event);
43
+ // ExternalInterface.call('s3_swf.jsLog','onUploadOpen called');
44
+ }
45
+
46
+ // called during the file _upload_options of each file being _upload_optionsed
47
+ // we use this to feed the progress bar its data
48
+ private function progressHandler(progress_event:ProgressEvent):void {
49
+ // ExternalInterface.call('s3_swf.jsLog','progressHandler');
50
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadProgress...');
51
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadProgress',_upload_options,progress_event);
52
+ // ExternalInterface.call('s3_swf.jsLog','onUploadProgress called');
53
+ }
54
+
55
+ // only called if there is an error detected by flash player browsing or _upload_optionsing a file
56
+ private function ioErrorHandler(io_error_event:IOErrorEvent):void{
57
+ // ExternalInterface.call('s3_swf.jsLog','ioErrorHandler');
58
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadIOError...');
59
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadIOError',_upload_options,io_error_event);
60
+ // ExternalInterface.call('s3_swf.jsLog','onUploadIOError called');
61
+ }
62
+
63
+ private function httpStatusHandler(http_status_event:HTTPStatusEvent):void {
64
+ // ExternalInterface.call('s3_swf.jsLog','httpStatusHandler');
65
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadHttpStatus...');
66
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadHttpStatus',_upload_options,http_status_event);
67
+ // ExternalInterface.call('s3_swf.jsLog','onUploadHttpStatus called');
68
+ }
69
+
70
+ // only called if a security error detected by flash player such as a sandbox violation
71
+ private function securityErrorHandler(security_error_event:SecurityErrorEvent):void{
72
+ // ExternalInterface.call('s3_swf.jsLog','securityErrorHandler');
73
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadSecurityError...');
74
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadSecurityError',_upload_options,security_error_event);
75
+ // ExternalInterface.call('s3_swf.jsLog','onUploadSecurityError called');
76
+ }
77
+
78
+ private function completeHandler(event:Event):void{
79
+ // prepare to destroy
80
+ removeListeners();
81
+ removeEventListener(Event.OPEN, openHandler);
82
+ removeEventListener(ProgressEvent.PROGRESS, progressHandler);
83
+ removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
84
+ removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
85
+ removeEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
86
+ removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, completeHandler);
87
+
88
+ // callback
89
+ // ExternalInterface.call('s3_swf.jsLog','completeHandler');
90
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadComplete...');
91
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadComplete',_upload_options,event);
92
+ // ExternalInterface.call('s3_swf.jsLog','onUploadComplete called');
93
+ // ExternalInterface.call('s3_swf.jsLog','Removing item from global queue...');
94
+
95
+ // destroy
96
+ Globals.queue.removeItemAt(0);
97
+
98
+ // ExternalInterface.call('s3_swf.jsLog','Item removed from global queue');
99
+ if (Globals.queue.length > 0){
100
+ // ExternalInterface.call('s3_swf.jsLog','Uploading next item in global queue...');
101
+ Globals.queue.uploadNextFile();
102
+ // ExternalInterface.call('s3_swf.jsLog','Next ttem in global queue uploaded');
103
+ } else {
104
+ // ExternalInterface.call('s3_swf.jsLog','Calling onUploadingFinish...');
105
+ ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadingFinish');
106
+ // ExternalInterface.call('s3_swf.jsLog','onUploadingFinish called');
107
+ }
108
+ }
109
+
110
+ }
111
+ }
@@ -0,0 +1,12 @@
1
+ class Integer
2
+ # 32-bit left shift
3
+ def js_shl(count)
4
+ v = (self << count) & 0xffffffff
5
+ v > 2**31 ? v - 2**32 : v
6
+ end
7
+
8
+ # 32-bit zero-fill right shift (>>>)
9
+ def js_shr_zf(count)
10
+ self >> count & (2**(32-count)-1)
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require 's3_swf_upload'
2
+ require 'rails'
3
+
4
+ module S3SwfUpload
5
+ class Railtie < Rails::Railtie
6
+
7
+ initializer "s3_swf_upload.load_s3_swf_upload_config" do
8
+ S3SwfUpload::S3Config.load_config
9
+ end
10
+
11
+ generators do
12
+ require "s3_swf_upload/railties/generators/uploader/uploader_generator"
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ require 'rails/generators/base'
2
+
3
+ module S3SwfUpload
4
+ module Generators
5
+ class Base < Rails::Generators::Base #:nodoc:
6
+
7
+ def self.source_root
8
+ # puts '****'
9
+ # puts File.expand_path(File.join(File.dirname(__FILE__), generator_name, 'templates'))
10
+ File.expand_path(File.join(File.dirname(__FILE__),generator_name, 'templates'))
11
+ end
12
+
13
+ def self.banner
14
+ "#{$0} generate s3_swf_upload:#{generator_name} #{self.arguments.map{ |a| a.usage }.join(' ')}"
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ Description:
2
+ Adds the following files to your application:
3
+
4
+ * amazon_s3.yml config file
5
+ * s3_uploads_controller.rb
6
+ * s3_upload.js
7
+ * s3_upload.swf
8
+
9
+ And then, as if that were not enough, it adds a route for you, too!
10
+
@@ -0,0 +1,20 @@
1
+ development:
2
+ bucket:
3
+ access_key_id:
4
+ secret_access_key:
5
+ max_file_size: 10485760
6
+ acl: public-read
7
+
8
+ test:
9
+ bucket:
10
+ access_key_id:
11
+ secret_access_key:
12
+ max_file_size: 10485760
13
+ acl: public-read
14
+
15
+ production:
16
+ bucket:
17
+ access_key_id:
18
+ secret_access_key:
19
+ max_file_size: 10485760
20
+ acl: public-read
@@ -0,0 +1,118 @@
1
+ /* SWFObject v2.2 <http://code.google.com/p/swfobject/>
2
+ is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
3
+ */
4
+ var s3_upload_swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
5
+
6
+ /* S3_Upload V0.1
7
+ Copyright (c) 2008 Elctech,
8
+ This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
9
+ */
10
+ /* S3_Upload V0.2
11
+ Copyright (c) 2010 Nathan Colgate,
12
+ This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
13
+ */
14
+ var s3_swf;
15
+ function s3_swf_init(id, options)
16
+ {
17
+ var buttonWidth = (options.buttonWidth != undefined) ? options.buttonWidth : 50;
18
+ var buttonHeight = (options.buttonHeight != undefined) ? options.buttonHeight : 50;
19
+ var flashVersion = (options.flashVersion != undefined) ? options.flashVersion : '9.0.0';
20
+ var queueSizeLimit = (options.queueSizeLimit != undefined) ? options.queueSizeLimit : 10;
21
+ var fileSizeLimit = (options.fileSizeLimit != undefined) ? options.fileSizeLimit : 524288000;
22
+ var fileTypes = (options.fileTypes != undefined) ? options.fileTypes : "*.*";
23
+ var fileTypeDescs = (options.fileTypeDescs != undefined) ? options.fileTypeDescs : "All Files";
24
+ var selectMultipleFiles = (options.selectMultipleFiles != undefined) ? options.selectMultipleFiles : true;
25
+ var keyPrefix = (options.keyPrefix != undefined) ? options.keyPrefix : "";
26
+ var signaturePath = (options.signaturePath != undefined) ? options.signaturePath : "s3_uploads.xml";
27
+ var swfFilePath = (options.swfFilePath != undefined) ? options.swfFilePath : "/flash/s3_upload.swf";
28
+ var buttonUpPath = (options.buttonUpPath != undefined) ? options.buttonUpPath : "";
29
+ var buttonOverPath = (options.buttonOverPath != undefined) ? options.buttonOverPath : "";
30
+ var buttonDownPath = (options.buttonDownPath != undefined) ? options.buttonDownPath : "";
31
+
32
+ var onFileAdd = (options.onFileAdd != undefined) ? options.onFileAdd : function(file){};
33
+ var onFileRemove = (options.onFileRemove != undefined) ? options.onFileRemove : function(file){};
34
+ var onFileSizeLimitReached = (options.onFileSizeLimitReached != undefined) ? options.onFileSizeLimitReached : function(file){};
35
+ var onFileNotInQueue = (options.onFileNotInQueue != undefined) ? options.onFileNotInQueue : function(file){};
36
+
37
+ var onQueueChange = (options.onQueueChange != undefined) ? options.onQueueChange : function(queue){};
38
+ var onQueueClear = (options.onQueueClear != undefined) ? options.onQueueClear : function(queue){};
39
+ var onQueueSizeLimitReached = (options.onQueueSizeLimitReached != undefined) ? options.onQueueSizeLimitReached : function(queue){};
40
+ var onQueueEmpty = (options.onQueueEmpty != undefined) ? options.onQueueEmpty : function(queue){};
41
+
42
+ var onUploadingStop = (options.onUploadingStop != undefined) ? options.onUploadingStop : function(){};
43
+ var onUploadingStart = (options.onUploadingStart != undefined) ? options.onUploadingStart : function(){};
44
+ var onUploadingFinish = (options.onUploadingFinish != undefined) ? options.onUploadingFinish : function(){};
45
+
46
+ var onSignatureOpen = (options.onSignatureOpen != undefined) ? options.onSignatureOpen : function(file,event){};
47
+ var onSignatureProgress = (options.onSignatureProgress != undefined) ? options.onSignatureProgress : function(file,progress_event){};
48
+ var onSignatureHttpStatus = (options.onSignatureHttpStatus != undefined) ? options.onSignatureHttpStatus : function(file,http_status_event){};
49
+ var onSignatureComplete = (options.onSignatureComplete != undefined) ? options.onSignatureComplete : function(file,event){};
50
+ var onSignatureSecurityError = (options.onSignatureSecurityError != undefined) ? options.onSignatureSecurityError : function(file,security_error_event){};
51
+ var onSignatureIOError = (options.onSignatureIOError != undefined) ? options.onSignatureIOError : function(file,io_error_event){};
52
+ var onSignatureXMLError = (options.onSignatureXMLError != undefined) ? options.onSignatureXMLError : function(file,error_message){};
53
+
54
+ var onUploadOpen = (options.onUploadOpen != undefined) ? options.onUploadOpen : function(upload_options,event){};
55
+ var onUploadProgress = (options.onUploadProgress != undefined) ? options.onUploadProgress : function(upload_options,progress_event){};
56
+ var onUploadHttpStatus = (options.onUploadHttpStatus != undefined) ? options.onUploadHttpStatus : function(upload_options,http_status_event){};
57
+ var onUploadComplete = (options.onUploadComplete != undefined) ? options.onUploadComplete : function(upload_options,event){};
58
+ var onUploadIOError = (options.onUploadIOError != undefined) ? options.onUploadIOError : function(upload_options,io_error_event){};
59
+ var onUploadSecurityError = (options.onUploadSecurityError != undefined) ? options.onUploadSecurityError : function(upload_options,security_error_event){};
60
+ var onUploadError = (options.onUploadError != undefined) ? options.onUploadError : function(upload_options,error){};
61
+
62
+ var flashvars = {"s3_swf_obj": (options.swfVarObj != undefined ? options.swfVarObj : 's3_swf')}; //fallback to the global var incase script is used outside of view helper
63
+ var params = {};
64
+ var attributes = {};
65
+ params.wmode = "transparent";
66
+ params.menu = "false";
67
+ params.quality = "low";
68
+
69
+ s3_upload_swfobject.embedSWF(swfFilePath+"?t=" + new Date().getTime(), id, buttonWidth, buttonHeight, flashVersion, false, flashvars, params, attributes);
70
+
71
+ var signatureUrl = window.location.protocol + '//' + window.location.host + signaturePath;
72
+ var buttonUpUrl = window.location.protocol + '//' + window.location.host + buttonUpPath;
73
+ var buttonDownUrl = window.location.protocol + '//' + window.location.host + buttonDownPath;
74
+ var buttonOverUrl = window.location.protocol + '//' + window.location.host + buttonOverPath;
75
+
76
+ s3_swf = {
77
+ obj: function() { return document[id]; },
78
+
79
+ init: function() { this.obj().init(signatureUrl, keyPrefix, fileSizeLimit, queueSizeLimit, fileTypes, fileTypeDescs, selectMultipleFiles,buttonWidth,buttonHeight,buttonUpUrl,buttonDownUrl,buttonOverUrl); },
80
+ clearQueue: function() { this.obj().clearQueue();},
81
+ startUploading: function() { this.obj().startUploading();},
82
+ stopUploading: function() { this.obj().stopUploading();},
83
+ removeFileFromQueue: function(index) { this.obj().removeFileFromQueue(index); },
84
+
85
+ onFileAdd: onFileAdd,
86
+ onFileRemove: onFileRemove,
87
+ onFileSizeLimitReached: onFileSizeLimitReached,
88
+ onFileNotInQueue: onFileNotInQueue,
89
+
90
+ onQueueChange: onQueueChange,
91
+ onQueueClear: onQueueClear,
92
+ onQueueSizeLimitReached: onQueueSizeLimitReached,
93
+ onQueueEmpty: onQueueEmpty,
94
+
95
+ onUploadingStop: onUploadingStop,
96
+ onUploadingStart: onUploadingStart,
97
+ onUploadingFinish: onUploadingFinish,
98
+
99
+ onSignatureOpen: onSignatureOpen,
100
+ onSignatureProgress: onSignatureProgress,
101
+ onSignatureHttpStatus: onSignatureHttpStatus,
102
+ onSignatureComplete: onSignatureComplete,
103
+ onSignatureSecurityError: onSignatureSecurityError,
104
+ onSignatureIOError: onSignatureIOError,
105
+ onSignatureXMLError: onSignatureXMLError,
106
+
107
+ onUploadOpen: onUploadOpen,
108
+ onUploadProgress: onUploadProgress,
109
+ onUploadHttpStatus: onUploadHttpStatus,
110
+ onUploadComplete: onUploadComplete,
111
+ onUploadIOError: onUploadIOError,
112
+ onUploadSecurityError: onUploadSecurityError,
113
+ onUploadError: onUploadError
114
+
115
+ }
116
+
117
+ return(s3_swf);
118
+ }
@@ -0,0 +1,53 @@
1
+ require 'base64'
2
+
3
+ class S3UploadsController < ApplicationController
4
+
5
+ # You might want to look at https and expiration_date below.
6
+ # Possibly these should also be configurable from S3Config...
7
+
8
+ skip_before_filter :verify_authenticity_token
9
+ include S3SwfUpload::Signature
10
+
11
+ def index
12
+ bucket = S3SwfUpload::S3Config.bucket
13
+ access_key_id = S3SwfUpload::S3Config.access_key_id
14
+ acl = S3SwfUpload::S3Config.acl
15
+ secret_key = S3SwfUpload::S3Config.secret_access_key
16
+ key = params[:key]
17
+ content_type = params[:content_type]
18
+ https = 'false'
19
+ error_message = ''
20
+ expiration_date = 1.hours.from_now.utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')
21
+
22
+ policy = Base64.encode64(
23
+ "{
24
+ 'expiration': '#{expiration_date}',
25
+ 'conditions': [
26
+ {'bucket': '#{bucket}'},
27
+ {'key': '#{key}'},
28
+ {'acl': '#{acl}'},
29
+ {'Content-Type': '#{content_type}'},
30
+ {'Content-Disposition': 'attachment'},
31
+ ['starts-with', '$Filename', ''],
32
+ ['eq', '$success_action_status', '201']
33
+ ]
34
+ }").gsub(/\n|\r/, '')
35
+
36
+ signature = b64_hmac_sha1(secret_key, policy)
37
+
38
+ respond_to do |format|
39
+ format.xml {
40
+ render :xml => {
41
+ :policy => policy,
42
+ :signature => signature,
43
+ :bucket => bucket,
44
+ :accesskeyid => access_key_id,
45
+ :acl => acl,
46
+ :expirationdate => expiration_date,
47
+ :https => https,
48
+ :errorMessage => error_message.to_s
49
+ }.to_xml
50
+ }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,20 @@
1
+ require 's3_swf_upload/railties/generators/s3_swf_upload'
2
+
3
+ module S3SwfUpload
4
+ module Generators
5
+ class UploaderGenerator < Base
6
+
7
+ def create_uploader
8
+ copy_file 'amazon_s3.yml', File.join('config','amazon_s3.yml')
9
+ copy_file 's3_uploads_controller.rb', File.join('app','controllers', 's3_uploads_controller.rb')
10
+ copy_file 's3_upload.js', File.join('public','javascripts', 's3_upload.js')
11
+ copy_file 's3_upload.swf', File.join('public','flash', 's3_upload.swf')
12
+ copy_file 's3_up_button.gif', File.join('public','flash', 's3_up_button.gif')
13
+ copy_file 's3_down_button.gif', File.join('public','flash', 's3_down_button.gif')
14
+ copy_file 's3_over_button.gif', File.join('public','flash', 's3_over_button.gif')
15
+ route "resources :s3_uploads"
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0"?>
2
+ <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
3
+ <cross-domain-policy>
4
+ <allow-access-from domain="*" />
5
+ </cross-domain-policy>
@@ -0,0 +1,43 @@
1
+ module S3SwfUpload
2
+ class S3Config
3
+ require 'erb' unless defined?(ERB)
4
+ require 'yaml' unless defined?(YAML)
5
+
6
+ cattr_reader :access_key_id, :secret_access_key
7
+ cattr_accessor :bucket, :max_file_size, :acl
8
+
9
+ def self.load_config
10
+ begin
11
+ filename = "#{Rails.root}/config/amazon_s3.yml"
12
+
13
+ buf = IO.read(filename)
14
+ expanded = ERB.new(buf).result(binding)
15
+ config = YAML.load(expanded)[Rails.env]
16
+
17
+ if config == nil
18
+ raise "Could not load config options for #{Rails.env} from #{filename}."
19
+ end
20
+
21
+ @@access_key_id = config['access_key_id'] || ENV['AWS_ACCESS_KEY_ID']
22
+ @@secret_access_key = config['secret_access_key'] || ENV['AWS_SECRET_ACCESS_KEY']
23
+ @@bucket = config['bucket']
24
+ @@max_file_size = config['max_file_size']
25
+ @@acl = config['acl'] || 'private'
26
+
27
+
28
+
29
+ unless @@access_key_id && @@secret_access_key && @@bucket
30
+ raise "Please configure your S3 settings in #{filename} before continuing so that S3 SWF Upload can function properly."
31
+ end
32
+ rescue Errno::ENOENT
33
+ # Using put inside a rake task may mess with some rake tasks
34
+ # According to: https://github.com/mhodgson/s3-swf-upload-plugin/commit/f5cc849e1d8b43c1f0d30eb92b772c10c9e73891
35
+ # Going to comment this out for the time being
36
+ # NCC@BNB - 11/16/10
37
+ # No config file yet. Not a big deal. Just issue a warning
38
+ # puts "WARNING: You are using the S3 SWF Uploader gem, which wants a config file at #{filename}, " +
39
+ # "but none could be found. You should try running 'rails generate s3_swf_upload:uploader'"
40
+ end
41
+ end
42
+ end
43
+ end