condo 1.0.6 → 2.0.0

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 (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
- })();