condo 1.0.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.textile +19 -32
  3. data/lib/condo.rb +124 -127
  4. data/lib/condo/configuration.rb +41 -76
  5. data/lib/condo/engine.rb +32 -39
  6. data/lib/condo/errors.rb +6 -8
  7. data/lib/condo/strata/amazon_s3.rb +246 -294
  8. data/lib/condo/strata/google_cloud_storage.rb +238 -272
  9. data/lib/condo/strata/open_stack_swift.rb +251 -0
  10. data/lib/condo/version.rb +1 -1
  11. metadata +31 -96
  12. data/app/assets/javascripts/condo.js +0 -9
  13. data/app/assets/javascripts/condo/amazon.js +0 -403
  14. data/app/assets/javascripts/condo/condo.js +0 -184
  15. data/app/assets/javascripts/condo/config.js +0 -69
  16. data/app/assets/javascripts/condo/google.js +0 -338
  17. data/app/assets/javascripts/condo/md5/hash.worker.emulator.js +0 -23
  18. data/app/assets/javascripts/condo/md5/hash.worker.js +0 -11
  19. data/app/assets/javascripts/condo/md5/hasher.js +0 -119
  20. data/app/assets/javascripts/condo/md5/spark-md5.js +0 -599
  21. data/app/assets/javascripts/condo/rackspace.js +0 -326
  22. data/app/assets/javascripts/condo/services/abstract-md5.js.erb +0 -86
  23. data/app/assets/javascripts/condo/services/base64.js +0 -184
  24. data/app/assets/javascripts/condo/services/broadcaster.js +0 -26
  25. data/app/assets/javascripts/condo/services/uploader.js +0 -302
  26. data/app/assets/javascripts/core/core.js +0 -4
  27. data/app/assets/javascripts/core/services/1-safe-apply.js +0 -17
  28. data/app/assets/javascripts/core/services/2-messaging.js +0 -171
  29. data/lib/condo/strata/rackspace_cloud_files.rb +0 -245
  30. data/test/condo_test.rb +0 -27
  31. data/test/dummy/README.rdoc +0 -261
  32. data/test/dummy/Rakefile +0 -7
  33. data/test/dummy/app/assets/javascripts/application.js +0 -15
  34. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  35. data/test/dummy/app/controllers/application_controller.rb +0 -3
  36. data/test/dummy/app/helpers/application_helper.rb +0 -2
  37. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  38. data/test/dummy/config.ru +0 -4
  39. data/test/dummy/config/application.rb +0 -59
  40. data/test/dummy/config/boot.rb +0 -10
  41. data/test/dummy/config/database.yml +0 -25
  42. data/test/dummy/config/environment.rb +0 -5
  43. data/test/dummy/config/environments/development.rb +0 -37
  44. data/test/dummy/config/environments/production.rb +0 -67
  45. data/test/dummy/config/environments/test.rb +0 -37
  46. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  47. data/test/dummy/config/initializers/inflections.rb +0 -15
  48. data/test/dummy/config/initializers/mime_types.rb +0 -5
  49. data/test/dummy/config/initializers/secret_token.rb +0 -7
  50. data/test/dummy/config/initializers/session_store.rb +0 -8
  51. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  52. data/test/dummy/config/locales/en.yml +0 -5
  53. data/test/dummy/config/routes.rb +0 -58
  54. data/test/dummy/public/404.html +0 -26
  55. data/test/dummy/public/422.html +0 -26
  56. data/test/dummy/public/500.html +0 -25
  57. data/test/dummy/public/favicon.ico +0 -0
  58. data/test/dummy/script/rails +0 -6
  59. data/test/integration/navigation_test.rb +0 -10
  60. data/test/test_helper.rb +0 -15
@@ -1,326 +0,0 @@
1
- /**
2
- * CoTag Condo Rackspace Cloud Files Strategy
3
- * Direct to cloud resumable uploads for Rackspace Cloud Files
4
- *
5
- * Copyright (c) 2012 CoTag Media.
6
- *
7
- * @author Stephen von Takach <steve@cotag.me>
8
- * @copyright 2012 cotag.me
9
- *
10
- *
11
- * References:
12
- * *
13
- *
14
- **/
15
-
16
-
17
- (function(angular, undefined) {
18
- 'use strict';
19
-
20
- angular.module('Condo').
21
-
22
- factory('Condo.Rackspace', ['$q', 'Condo.Md5', function($q, md5) {
23
- var PENDING = 0,
24
- STARTED = 1,
25
- PAUSED = 2,
26
- UPLOADING = 3,
27
- COMPLETED = 4,
28
- ABORTED = 5,
29
-
30
-
31
- Rackspace = function (api, file) {
32
- var self = this,
33
- strategy = null,
34
- part_size = 2097152, // Multi-part uploads should be bigger then this
35
- pausing = false,
36
- defaultError = function(reason) {
37
- self.error = !pausing;
38
- pausing = false;
39
- self.pause(reason);
40
- },
41
-
42
- restart = function() {
43
- strategy = null;
44
- },
45
-
46
-
47
- completeUpload = function() {
48
- api.update().then(function(data) {
49
- self.progress = self.size; // Update to 100%
50
- self.state = COMPLETED;
51
- }, defaultError);
52
- },
53
-
54
-
55
- //
56
- // We need to sign our uploads so rackspace can confirm they are valid for us
57
- //
58
- build_request = function(part_number) {
59
- var current_part;
60
-
61
- if (file.size > part_size) { // If file bigger then 5mb we expect a chunked upload
62
- var endbyte = part_number * part_size;
63
- if (endbyte > file.size)
64
- endbyte = file.size;
65
- current_part = file.slice((part_number - 1) * part_size, endbyte);
66
- } else {
67
- current_part = file;
68
- }
69
-
70
- return md5.hash(current_part).then(function(val) {
71
- return {
72
- data: current_part,
73
- data_id: val,
74
- part_number: part_number
75
- }
76
- }, function(reason){
77
- return $q.reject(reason);
78
- });
79
- },
80
-
81
- //
82
- // Direct file upload strategy
83
- //
84
- RackspaceDirect = function(data) {
85
- //
86
- // resume
87
- // abort
88
- // pause
89
- //
90
- var $this = this,
91
- finalising = false;
92
-
93
- //
94
- // Update the parent
95
- //
96
- self.state = UPLOADING;
97
-
98
-
99
- //
100
- // This will only be called when the upload has finished and we need to inform the application
101
- //
102
- this.resume = function() {
103
- self.state = UPLOADING;
104
- completeUpload();
105
- }
106
-
107
- this.pause = function() {
108
- api.abort();
109
-
110
- if(!finalising) {
111
- restart(); // Should occur before events triggered
112
- self.progress = 0;
113
- }
114
- };
115
-
116
-
117
- //
118
- // AJAX for upload goes here
119
- //
120
- data['data'] = file;
121
- api.process_request(data, function(progress) {
122
- self.progress = progress;
123
- }).then(function(result) {
124
- finalising = true;
125
- $this.resume(); // Resume informs the application that the upload is complete
126
- }, function(reason) {
127
- self.progress = 0;
128
- defaultError(reason);
129
- });
130
- }, // END DIRECT
131
-
132
-
133
- //
134
- // Chunked upload strategy--------------------------------------------------
135
- //
136
- RackspaceChunked = function (data, first_chunk) {
137
- //
138
- // resume
139
- // abort
140
- // pause
141
- //
142
- var last_part = 0,
143
-
144
- //
145
- // Get the next part signature
146
- //
147
- next_part = function(part_number) {
148
- //
149
- // Check if we are past the end of the file
150
- //
151
- if ((part_number - 1) * part_size < file.size) {
152
-
153
- self.progress = (part_number - 1) * part_size; // Update the progress
154
-
155
- build_request(part_number).then(function(result) {
156
- if (self.state != UPLOADING)
157
- return; // upload was paused or aborted as we were reading the file
158
-
159
- api.update({
160
- resumable_id: part_number,
161
- file_id: result.data_id,
162
- part: part_number
163
- }).then(function(data) {
164
- set_part(data, result);
165
- }, defaultError);
166
-
167
- }, defaultError); // END BUILD_REQUEST
168
-
169
- } else {
170
- //
171
- // We're after the final commit
172
- //
173
- api.edit('finish').
174
- then(function(request) {
175
- api.process_request(request).then(completeUpload, defaultError);
176
- }, defaultError);
177
- }
178
- },
179
-
180
-
181
- //
182
- // Send a part to rackspace
183
- //
184
- set_part = function(request, part_info) {
185
- request['data'] = part_info.data;
186
- api.process_request(request, function(progress) {
187
- self.progress = (part_info.part_number - 1) * part_size + progress;
188
- }).then(function(result) {
189
- last_part = part_info.part_number;
190
- next_part(last_part + 1);
191
- }, function(reason) {
192
- self.progress = (part_info.part_number - 1) * part_size;
193
- defaultError(reason);
194
- });
195
- };
196
-
197
-
198
- self.state = UPLOADING;
199
-
200
- this.resume = function() {
201
- self.state = UPLOADING;
202
- next_part(last_part + 1);
203
- };
204
-
205
- this.pause = function() {
206
- api.abort();
207
- };
208
-
209
-
210
- //
211
- // We need to check if we are resuming or starting an upload
212
- //
213
- if(data.type == 'parts') {
214
- next_part(data.current_part);
215
- } else {
216
- set_part(data, first_chunk);
217
- }
218
- }; // END CHUNKED
219
-
220
-
221
- //
222
- // Variables required for all drivers
223
- //
224
- this.state = PENDING;
225
- this.progress = 0;
226
- this.message = 'pending';
227
- this.name = file.name;
228
- this.size = file.size;
229
- this.error = false;
230
-
231
-
232
- //
233
- // Support file slicing
234
- //
235
- if (typeof(file.slice) != 'function')
236
- file.slice = file.webkitSlice || file.mozSlice;
237
-
238
-
239
- this.start = function(){
240
- if(strategy == null) { // We need to create the upload
241
-
242
- pausing = false;
243
- this.error = false;
244
- this.message = null;
245
- this.state = STARTED;
246
- strategy = {}; // This function shouldn't be called twice so we need a state (TODO:: fix this)
247
-
248
- build_request(1).then(function(result) {
249
- if (self.state != STARTED)
250
- return; // upload was paused or aborted as we were reading the file
251
-
252
- api.create({file_id: result.data_id}).
253
- then(function(data) {
254
- if(data.type == 'direct_upload') {
255
- strategy = new RackspaceDirect(data);
256
- } else {
257
- strategy = new RackspaceChunked(data, result);
258
- }
259
- }, defaultError);
260
-
261
- }, defaultError); // END BUILD_REQUEST
262
-
263
-
264
- } else if (this.state == PAUSED) { // We need to resume the upload if it is paused
265
-
266
- pausing = false;
267
- this.error = false;
268
- this.message = null;
269
- strategy.resume();
270
- }
271
- };
272
-
273
- this.pause = function(reason) {
274
- if(strategy != null && this.state == UPLOADING) { // Check if the upload is uploading
275
- this.state = PAUSED;
276
- pausing = true;
277
- strategy.pause();
278
- } else if (this.state <= STARTED) {
279
- this.state = PAUSED;
280
- restart();
281
- }
282
- if(this.state == PAUSED)
283
- this.message = reason;
284
- };
285
-
286
- this.abort = function(reason) {
287
- if(strategy != null && this.state < COMPLETED) { // Check the upload has not finished
288
- var old_state = this.state;
289
-
290
- this.state = ABORTED;
291
- api.abort();
292
-
293
-
294
- //
295
- // As we may not have successfully deleted the upload
296
- // or we aborted before we received a response from create
297
- //
298
- restart(); // nullifies strategy
299
-
300
-
301
- //
302
- // if we have an upload_id then we should destroy the upload
303
- // we won't worry if this fails as it should be automatically cleaned up by the back end
304
- //
305
- if(old_state > STARTED) {
306
- api.destroy();
307
- }
308
-
309
- this.message = reason;
310
- }
311
- };
312
- }; // END RACKSPACE
313
-
314
-
315
- return {
316
- new_upload: function(api, file) {
317
- return new Rackspace(api, file);
318
- }
319
- };
320
- }]).
321
-
322
- config(['Condo.ApiProvider', function (ApiProvider) {
323
- ApiProvider.register('RackspaceCloudFiles', 'Condo.Rackspace');
324
- }]);
325
-
326
- })(angular);
@@ -1,86 +0,0 @@
1
- (function(angular, undefined) {
2
- 'use strict';
3
-
4
- angular.module('Condo').
5
-
6
- factory('Condo.Md5', ['$rootScope', '$q', 'Condo.Broadcast', function($rootScope, $q, broadcaster) {
7
-
8
- var hasher,
9
- queue = [],
10
- ready = false,
11
- processing = undefined,
12
-
13
- //
14
- // Resolves the hashing promise
15
- //
16
- recievedMessage = function(e) {
17
- if(e.data.success) {
18
- processing.result.resolve(e.data.result);
19
- } else {
20
- processing.result.reject(e.data.result);
21
- }
22
-
23
- processing = undefined;
24
- processNext();
25
-
26
- if(!$rootScope.$$phase) {
27
- $rootScope.$apply(); // This triggers the promise response
28
- }
29
- },
30
-
31
- //
32
- // starts processing the next item if the queue is not empty
33
- //
34
- processNext = function() {
35
- if(ready && processing === undefined && queue.length > 0) {
36
- processing = queue.pop();
37
- hasher.postMessage(processing.blob);
38
- }
39
- };
40
-
41
-
42
- if(!!window.Worker) {
43
- hasher = new Worker('<%= asset_path("condo/md5/hash.worker.js") %>');
44
- hasher.onmessage = recievedMessage;
45
- hasher.onerror = function(e) {
46
- ready = false;
47
- broadcaster.publish('coNotice', {
48
- type: 'error',
49
- number: 1
50
- });
51
- };
52
- ready = true;
53
- } else {
54
- $.getScript('<%= asset_path("condo/md5/hash.worker.emulator.js") %>', function() {
55
- hasher = new CondoHashWorkerEmulator(recievedMessage);
56
- ready = true;
57
- processNext(); // It is possible
58
- }).fail(function(jqxhr, settings, exception) {
59
- broadcaster.publish('coNotice', {
60
- type: 'error',
61
- number: 1
62
- });
63
- });
64
- }
65
-
66
-
67
-
68
- return {
69
- //
70
- // Will queue a start message and return the hash result
71
- //
72
- hash: function(blob) {
73
- var result = $q.defer();
74
-
75
- queue.push({
76
- blob: blob,
77
- result: result
78
- });
79
- processNext();
80
-
81
- return result.promise;
82
- }
83
- };
84
- }]);
85
- })(angular);
86
-
@@ -1,184 +0,0 @@
1
- /*
2
- * Copyright (c) 2010 Nick Galbreath
3
- * http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript
4
- *
5
- * Permission is hereby granted, free of charge, to any person
6
- * obtaining a copy of this software and associated documentation
7
- * files (the "Software"), to deal in the Software without
8
- * restriction, including without limitation the rights to use,
9
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- * copies of the Software, and to permit persons to whom the
11
- * Software is furnished to do so, subject to the following
12
- * conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be
15
- * included in all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
- * OTHER DEALINGS IN THE SOFTWARE.
25
- */
26
-
27
- /* base64 encode/decode compatible with window.btoa/atob
28
- *
29
- * window.atob/btoa is a Firefox extension to convert binary data (the "b")
30
- * to base64 (ascii, the "a").
31
- *
32
- * It is also found in Safari and Chrome. It is not available in IE.
33
- *
34
- * if (!window.btoa) window.btoa = base64.encode
35
- * if (!window.atob) window.atob = base64.decode
36
- *
37
- * The original spec's for atob/btoa are a bit lacking
38
- * https://developer.mozilla.org/en/DOM/window.atob
39
- * https://developer.mozilla.org/en/DOM/window.btoa
40
- *
41
- * window.btoa and base64.encode takes a string where charCodeAt is [0,255]
42
- * If any character is not [0,255], then an DOMException(5) is thrown.
43
- *
44
- * window.atob and base64.decode take a base64-encoded string
45
- * If the input length is not a multiple of 4, or contains invalid characters
46
- * then an DOMException(5) is thrown.
47
- */
48
-
49
-
50
- window.base64 = (function(undefined) {
51
- 'use strict';
52
-
53
- var base64 = {};
54
- base64.PADCHAR = '=';
55
- base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
56
-
57
- base64.makeDOMException = function() {
58
- // sadly in FF,Safari,Chrome you can't make a DOMException
59
- var e, tmp;
60
-
61
- try {
62
- return new DOMException(DOMException.INVALID_CHARACTER_ERR);
63
- } catch (tmp) {
64
- // not available, just passback a duck-typed equiv
65
- // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error
66
- // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/prototype
67
- var ex = new Error("DOM Exception 5");
68
-
69
- // ex.number and ex.description is IE-specific.
70
- ex.code = ex.number = 5;
71
- ex.name = ex.description = "INVALID_CHARACTER_ERR";
72
-
73
- // Safari/Chrome output format
74
- ex.toString = function() { return 'Error: ' + ex.name + ': ' + ex.message; };
75
- return ex;
76
- }
77
- }
78
-
79
- base64.getbyte64 = function(s,i) {
80
- // This is oddly fast, except on Chrome/V8.
81
- // Minimal or no improvement in performance by using a
82
- // object with properties mapping chars to value (eg. 'A': 0)
83
- var idx = base64.ALPHA.indexOf(s.charAt(i));
84
- if (idx === -1) {
85
- throw base64.makeDOMException();
86
- }
87
- return idx;
88
- }
89
-
90
- base64.decode = function(s) {
91
- // convert to string
92
- s = '' + s;
93
- var getbyte64 = base64.getbyte64;
94
- var pads, i, b10;
95
- var imax = s.length
96
- if (imax === 0) {
97
- return s;
98
- }
99
-
100
- if (imax % 4 !== 0) {
101
- throw base64.makeDOMException();
102
- }
103
-
104
- pads = 0
105
- if (s.charAt(imax - 1) === base64.PADCHAR) {
106
- pads = 1;
107
- if (s.charAt(imax - 2) === base64.PADCHAR) {
108
- pads = 2;
109
- }
110
- // either way, we want to ignore this last block
111
- imax -= 4;
112
- }
113
-
114
- var x = [];
115
- for (i = 0; i < imax; i += 4) {
116
- b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) |
117
- (getbyte64(s,i+2) << 6) | getbyte64(s,i+3);
118
- x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff));
119
- }
120
-
121
- switch (pads) {
122
- case 1:
123
- b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6);
124
- x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff));
125
- break;
126
- case 2:
127
- b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12);
128
- x.push(String.fromCharCode(b10 >> 16));
129
- break;
130
- }
131
- return x.join('');
132
- }
133
-
134
- base64.getbyte = function(s,i) {
135
- var x = s.charCodeAt(i);
136
- if (x > 255) {
137
- throw base64.makeDOMException();
138
- }
139
- return x;
140
- }
141
-
142
- base64.encode = function(s) {
143
- if (arguments.length !== 1) {
144
- throw new SyntaxError("Not enough arguments");
145
- }
146
- var padchar = base64.PADCHAR;
147
- var alpha = base64.ALPHA;
148
- var getbyte = base64.getbyte;
149
-
150
- var i, b10;
151
- var x = [];
152
-
153
- // convert to string
154
- s = '' + s;
155
-
156
- var imax = s.length - s.length % 3;
157
-
158
- if (s.length === 0) {
159
- return s;
160
- }
161
- for (i = 0; i < imax; i += 3) {
162
- b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8) | getbyte(s,i+2);
163
- x.push(alpha.charAt(b10 >> 18));
164
- x.push(alpha.charAt((b10 >> 12) & 0x3F));
165
- x.push(alpha.charAt((b10 >> 6) & 0x3f));
166
- x.push(alpha.charAt(b10 & 0x3f));
167
- }
168
- switch (s.length - imax) {
169
- case 1:
170
- b10 = getbyte(s,i) << 16;
171
- x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
172
- padchar + padchar);
173
- break;
174
- case 2:
175
- b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8);
176
- x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
177
- alpha.charAt((b10 >> 6) & 0x3f) + padchar);
178
- break;
179
- }
180
- return x.join('');
181
- }
182
-
183
- return base64;
184
- })();