condo 1.0.4 → 1.0.6

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 (32) hide show
  1. checksums.yaml +7 -0
  2. data/README.textile +133 -133
  3. data/app/assets/javascripts/condo.js +9 -6
  4. data/app/assets/javascripts/condo/amazon.js +403 -406
  5. data/app/assets/javascripts/condo/condo.js +184 -0
  6. data/app/assets/javascripts/condo/config.js +69 -80
  7. data/app/assets/javascripts/condo/google.js +338 -255
  8. data/app/assets/javascripts/condo/md5/hash.worker.emulator.js +23 -23
  9. data/app/assets/javascripts/condo/md5/hash.worker.js +11 -11
  10. data/app/assets/javascripts/condo/md5/hasher.js +119 -100
  11. data/app/assets/javascripts/condo/md5/spark-md5.js +276 -161
  12. data/app/assets/javascripts/condo/rackspace.js +326 -329
  13. data/app/assets/javascripts/condo/{abstract-md5.js.erb → services/abstract-md5.js.erb} +86 -93
  14. data/app/assets/javascripts/condo/{base64.js → services/base64.js} +2 -10
  15. data/app/assets/javascripts/condo/services/broadcaster.js +26 -0
  16. data/app/assets/javascripts/condo/services/uploader.js +302 -0
  17. data/app/assets/javascripts/core/core.js +4 -0
  18. data/app/assets/javascripts/core/services/1-safe-apply.js +17 -0
  19. data/app/assets/javascripts/core/services/2-messaging.js +171 -0
  20. data/lib/condo.rb +269 -269
  21. data/lib/condo/configuration.rb +137 -139
  22. data/lib/condo/errors.rb +8 -8
  23. data/lib/condo/strata/amazon_s3.rb +301 -301
  24. data/lib/condo/strata/google_cloud_storage.rb +315 -314
  25. data/lib/condo/strata/rackspace_cloud_files.rb +245 -223
  26. data/lib/condo/version.rb +1 -1
  27. metadata +21 -44
  28. data/app/assets/javascripts/condo/broadcaster.js +0 -60
  29. data/app/assets/javascripts/condo/controller.js +0 -194
  30. data/app/assets/javascripts/condo/uploader.js +0 -310
  31. data/test/dummy/db/test.sqlite3 +0 -0
  32. data/test/dummy/log/test.log +0 -25
@@ -1,23 +1,23 @@
1
- //= require condo/md5/spark-md5
2
- //= require condo/md5/hasher
3
-
4
-
5
- function CondoHashWorkerEmulator(callback) {
6
-
7
- // Create an API that looks like postMessage
8
- this.postMessage = function (data, portArray) {
9
- hasher.hash(data); // Clone the data if required JSON.parse(JSON.stringify(message)); // - Don't think it is required
10
- }
11
-
12
-
13
- this.terminate = function () {
14
- // No special clean-up needed.
15
- }
16
-
17
- function messageEvtEmulator(rawMessage) {
18
- callback({ data: rawMessage });
19
- }
20
-
21
- // Create an instance of downloader.
22
- var hasher = new CondoMD5Hasher(messageEvtEmulator);
23
- }
1
+ //= require condo/md5/spark-md5
2
+ //= require condo/md5/hasher
3
+
4
+
5
+ function CondoHashWorkerEmulator(callback) {
6
+
7
+ // Create an API that looks like postMessage
8
+ this.postMessage = function (data, portArray) {
9
+ hasher.hash(data); // Clone the data if required JSON.parse(JSON.stringify(message)); // - Don't think it is required
10
+ }
11
+
12
+
13
+ this.terminate = function () {
14
+ // No special clean-up needed.
15
+ }
16
+
17
+ function messageEvtEmulator(rawMessage) {
18
+ callback({ data: rawMessage });
19
+ }
20
+
21
+ // Create an instance of downloader.
22
+ var hasher = new CondoMD5Hasher(messageEvtEmulator, false);
23
+ }
@@ -1,11 +1,11 @@
1
- //= require condo/md5/spark-md5
2
- //= require condo/md5/hasher
3
-
4
-
5
- var hasher = new CondoMD5Hasher(postMessage); // Accepts the callback as the parameter
6
-
7
-
8
- // Hook-up worker input
9
- onmessage = function (e) {
10
- hasher.hash(e.data);
11
- }
1
+ //= require condo/md5/spark-md5
2
+ //= require condo/md5/hasher
3
+
4
+
5
+ var hasher = new CondoMD5Hasher(postMessage, true); // Accepts the callback as the parameter
6
+
7
+
8
+ // Hook-up worker input
9
+ onmessage = function (e) {
10
+ hasher.hash(e.data);
11
+ };
@@ -1,100 +1,119 @@
1
-
2
-
3
- var CondoMD5Hasher = (function(global) {
4
-
5
- var part_size = 1048576, // This is the amount of the file we read into memory as we are building the hash (1mb)
6
- async = true;
7
-
8
- //
9
- // Firefox does not have FileReader in webworkers? WTF
10
- // See issue #2
11
- //
12
- if (!!!global.FileReader) {
13
- async = false;
14
- global.FileReader = global.FileReaderSync;
15
- }
16
-
17
- //
18
- // Some browsers have a vendor prefix on slice
19
- //
20
- if (!!!Blob.prototype.slice) {
21
- Blob.prototype.slice = Blob.prototype.webkitSlice || Blob.prototype.mozSlice;
22
- }
23
-
24
- return function(callback) {
25
-
26
-
27
- //
28
- // responds with: {success: true|false, result: <Object>}
29
- //
30
- this.hash = function(blob) {
31
-
32
- var current_part,
33
- md5 = new global.SparkMD5(),
34
- reader = new global.FileReader(),
35
- part_number = 0,
36
- length = Math.ceil(blob.size / part_size),
37
- fail = function() {
38
- callback({
39
- success: false,
40
- result: 'file read failed'
41
- });
42
- },
43
- hashData = function(e) {
44
- md5.appendBinary(e.target.result);
45
- if(part_number * part_size >= blob.size) {
46
- callback({
47
- success: true,
48
- result: md5.end()
49
- });
50
- } else {
51
- processPart();
52
- }
53
- },
54
- processPart = function() {
55
- var endbyte = 0;
56
-
57
- part_number += 1;
58
-
59
- if (blob.size > part_size) { // If blob bigger then part_size we will slice it up
60
- endbyte = part_number * part_size;
61
- if (endbyte > blob.size)
62
- endbyte = blob.size;
63
-
64
- current_part = blob.slice((part_number - 1) * part_size, endbyte);
65
- } else {
66
- current_part = blob;
67
- }
68
-
69
- if(async)
70
- reader.readAsArrayBuffer(current_part);
71
- else {
72
- setTimeout(function() {
73
- try {
74
- hashData({
75
- target: {
76
- result: reader.readAsArrayBuffer(current_part)
77
- }
78
- });
79
- } catch (e) {
80
- fail();
81
- }
82
- }, 1);
83
- }
84
-
85
- };
86
-
87
-
88
- if(async) {
89
- reader.onload = hashData;
90
- reader.onerror = fail;
91
- reader.onabort = fail;
92
- }
93
-
94
-
95
- processPart();
96
- };
97
- };
98
-
99
- })(this);
100
-
1
+
2
+
3
+ var CondoMD5Hasher = (function(global) {
4
+
5
+ var part_size = 1048576, // This is the amount of the file we read into memory as we are building the hash (1mb)
6
+ async = true,
7
+ newReader = !!navigator.userAgent.toLowerCase().match(/opera/); // Opera bug (opera can only use a reader once)
8
+
9
+
10
+ //
11
+ // Firefox does not have FileReader in webworkers? WTF
12
+ // See issue #2
13
+ //
14
+ if (!!!global.FileReader) {
15
+ async = false;
16
+ global.FileReader = global.FileReaderSync;
17
+ }
18
+
19
+ //
20
+ // Some browsers have a vendor prefix on slice
21
+ //
22
+ if (!!!Blob.prototype.slice) {
23
+ Blob.prototype.slice = Blob.prototype.webkitSlice || Blob.prototype.mozSlice;
24
+ }
25
+
26
+ return function(callback, inWorker) {
27
+
28
+
29
+ //
30
+ // Opera claims to have async readers in webworkers however it is actually just
31
+ // a synchronous reader in disguise
32
+ //
33
+ if (newReader && inWorker) {
34
+ async = false;
35
+ global.FileReader = global.FileReaderSync || global.FileReader;
36
+ }
37
+
38
+
39
+ //
40
+ // responds with: {success: true|false, result: <Object>}
41
+ //
42
+ this.hash = function(blob) {
43
+
44
+ var current_part,
45
+ md5 = new global.SparkMD5.ArrayBuffer(),
46
+ part_number = 0,
47
+ length = Math.ceil(blob.size / part_size),
48
+ reader,
49
+
50
+ fail = function() {
51
+ callback({
52
+ success: false,
53
+ result: 'file read failed'
54
+ });
55
+ },
56
+
57
+ hashData = function(e) {
58
+ md5.append(e.target.result);
59
+ if(part_number * part_size >= blob.size) {
60
+ callback({
61
+ success: true,
62
+ result: md5.end()
63
+ });
64
+ } else {
65
+ if (newReader) configureReader();
66
+ processPart();
67
+ }
68
+ },
69
+
70
+ processPart = function() {
71
+ var endbyte = 0;
72
+
73
+ part_number += 1;
74
+
75
+ if (blob.size > part_size) { // If blob bigger then part_size we will slice it up
76
+ endbyte = part_number * part_size;
77
+ if (endbyte > blob.size)
78
+ endbyte = blob.size;
79
+
80
+ current_part = blob.slice((part_number - 1) * part_size, endbyte);
81
+ } else {
82
+ current_part = blob;
83
+ }
84
+
85
+ if(async)
86
+ reader.readAsArrayBuffer(current_part);
87
+ else {
88
+ setTimeout(function() {
89
+ try {
90
+ hashData({
91
+ target: {
92
+ result: reader.readAsArrayBuffer(current_part)
93
+ }
94
+ });
95
+ } catch (e) {
96
+ fail();
97
+ }
98
+ }, 0);
99
+ }
100
+
101
+ },
102
+
103
+ configureReader = function() {
104
+ reader = new global.FileReader();
105
+ if(async) {
106
+ reader.onload = hashData;
107
+ reader.onerror = fail;
108
+ reader.onabort = fail;
109
+ }
110
+ };
111
+
112
+
113
+ configureReader();
114
+ processPart();
115
+ };
116
+ };
117
+
118
+ })(this);
119
+
@@ -1,83 +1,6 @@
1
1
  /*jshint bitwise:false*/
2
2
  /*global unescape*/
3
3
 
4
- /**
5
- * SparkMD5 is a fast md5 implementation of the MD5 algorithm.
6
- * This script is based in the JKM md5 library which is the
7
- * fastest algorithm around (see: http://jsperf.com/md5-shootout/7).
8
- *
9
- * NOTE: Please disable Firebug while testing this script!
10
- * Firebug consumes a lot of memory and CPU and slows down by a great margin.
11
- * Opera Dragonfly also slows down by a great margin.
12
- * Safari/Chrome developer tools seems not to slow it down.
13
- *
14
- * Improvements over the JKM md5 library:
15
- *
16
- * - Functionality wrapped in a closure
17
- * - Object oriented library
18
- * - Incremental md5 (see bellow)
19
- * - Validates using jslint
20
- *
21
- * Incremental md5 performs a lot better for hashing large ammounts of data, such as
22
- * files. One could read files in chunks, using the FileReader & Blob's, and append
23
- * each chunk for md5 hashing while keeping memory usage low. See example bellow.
24
- *
25
- * @example
26
- *
27
- * Normal usage:
28
- *
29
- * var hexHash = SparkMD5.hash('Hi there'); // hex hash
30
- * var rawHash = SparkMD5.hash('Hi there', true); // raw hash
31
- *
32
- * Incremental usage:
33
- *
34
- * var spark = new SparkMD5();
35
- * spark.append('Hi');
36
- * spark.append(' there');
37
- * var hexHash = spark.end(); // hex hash
38
- * var rawHash = spark.end(true); // raw hash
39
- *
40
- * Hash a file incrementally:
41
- *
42
- * NOTE: If you test the code bellow using the file:// protocol in chrome you must start the browser with -allow-file-access-from-files argument.
43
- * Please see: http://code.google.com/p/chromium/issues/detail?id=60889
44
- *
45
- * document.getElementById("file").addEventListener("change", function() {
46
- *
47
- * var fileReader = new FileReader(),
48
- * blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
49
- * file = document.getElementById("file").files[0],
50
- * chunkSize = 2097152, // read in chunks of 2MB
51
- * chunks = Math.ceil(file.size / chunkSize),
52
- * currentChunk = 0,
53
- * spark = new SparkMD5();
54
- *
55
- * fileReader.onload = function(e) {
56
- * console.log("read chunk nr", currentChunk + 1, "of", chunks);
57
- * spark.appendBinary(e.target.result); // append binary string
58
- * currentChunk++;
59
- *
60
- * if (currentChunk < chunks) {
61
- * loadNext();
62
- * }
63
- * else {
64
- * console.log("finished loading");
65
- * console.info("computed hash", spark.end()); // compute hash
66
- * }
67
- * };
68
- *
69
- * function loadNext() {
70
- * var start = currentChunk * chunkSize,
71
- * end = start + chunkSize >= file.size ? file.size : start + chunkSize;
72
- *
73
- * fileReader.readAsBinaryString(blobSlice.call(file, start, end));
74
- * };
75
- *
76
- * loadNext();
77
- * });
78
- *
79
- * @TODO: Add native support for reading files? Maybe add it as an extension?
80
- */
81
4
  (function (factory) {
82
5
  if (typeof exports === 'object') {
83
6
  // Node/CommonJS
@@ -99,32 +22,6 @@
99
22
  }(function (undefined) {
100
23
 
101
24
  'use strict';
102
-
103
-
104
- /* converts strings to array buffers
105
- * From: http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
106
- */
107
- var str2ab = function (str) {
108
- var buf = new ArrayBuffer(str.length * 2), // 2 bytes for each char
109
- bufView = new Uint16Array(buf);
110
- for (var i = 0, strLen = str.length; i < strLen; i++) {
111
- bufView[i] = str.charCodeAt(i);
112
- }
113
- return buf;
114
- },
115
-
116
-
117
- abConcat = function(first, second)
118
- {
119
- var firstLength = first.length,
120
- result = new Uint8Array(firstLength + second.byteLength);
121
-
122
- result.set(first);
123
- result.set(new Uint8Array(second), firstLength);
124
-
125
- return result;
126
- },
127
-
128
25
 
129
26
  ////////////////////////////////////////////////////////////////////////////
130
27
 
@@ -135,8 +32,13 @@
135
32
  * @see http://www.myersdaily.org/joseph/javascript/md5-text.html
136
33
  * @see http://jsperf.com/md5-shootout/7
137
34
  */
138
-
139
- add32 = function (a, b) {
35
+
36
+ /* this function is much faster,
37
+ so if possible we use it. Some IEs
38
+ are the only ones I know of that
39
+ need the idiotic second function,
40
+ generated by an if clause. */
41
+ var add32 = function (a, b) {
140
42
  return (a + b) & 0xFFFFFFFF;
141
43
  },
142
44
 
@@ -145,23 +47,23 @@
145
47
  return add32((a << s) | (a >>> (32 - s)), b);
146
48
  },
147
49
 
148
- ff = function(a, b, c, d, x, s, t) {
50
+ ff = function (a, b, c, d, x, s, t) {
149
51
  return cmn((b & c) | ((~b) & d), a, b, x, s, t);
150
52
  },
151
53
 
152
- gg = function(a, b, c, d, x, s, t) {
54
+ gg = function (a, b, c, d, x, s, t) {
153
55
  return cmn((b & d) | (c & (~d)), a, b, x, s, t);
154
56
  },
155
57
 
156
- hh = function(a, b, c, d, x, s, t) {
58
+ hh = function (a, b, c, d, x, s, t) {
157
59
  return cmn(b ^ c ^ d, a, b, x, s, t);
158
60
  },
159
61
 
160
- ii = function(a, b, c, d, x, s, t) {
62
+ ii = function (a, b, c, d, x, s, t) {
161
63
  return cmn(c ^ (b | (~d)), a, b, x, s, t);
162
64
  },
163
65
 
164
- md5cycle = function(x, k) {
66
+ md5cycle = function (x, k) {
165
67
  var a = x[0],
166
68
  b = x[1],
167
69
  c = x[2],
@@ -241,16 +143,42 @@
241
143
  x[3] = add32(d, x[3]);
242
144
  },
243
145
 
244
- md5blk = function(s) { /* I figured global was faster. */
146
+ /* there needs to be support for Unicode here,
147
+ * unless we pretend that we can redefine the MD-5
148
+ * algorithm for multi-byte characters (perhaps
149
+ * by adding every four 16-bit characters and
150
+ * shortening the sum to 32 bits). Otherwise
151
+ * I suggest performing MD-5 as if every character
152
+ * was two bytes--e.g., 0040 0025 = @%--but then
153
+ * how will an ordinary MD-5 sum be matched?
154
+ * There is no way to standardize text to something
155
+ * like UTF-8 before transformation; speed cost is
156
+ * utterly prohibitive. The JavaScript standard
157
+ * itself needs to look at this: it should start
158
+ * providing access to strings as preformed UTF-8
159
+ * 8-bit unsigned value arrays.
160
+ */
161
+ md5blk = function (s) {
245
162
  var md5blks = [],
246
163
  i; /* Andy King said do it this way. */
164
+
165
+ for (i = 0; i < 64; i += 4) {
166
+ md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
167
+ }
168
+ return md5blks;
169
+ },
170
+
171
+ md5blk_array = function (a) {
172
+ var md5blks = [],
173
+ i; /* Andy King said do it this way. */
174
+
247
175
  for (i = 0; i < 64; i += 4) {
248
- md5blks[i >> 2] = s[i] + (s[i + 1] << 8) + (s[i + 2] << 16) + (s[i + 3] << 24);
176
+ md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
249
177
  }
250
178
  return md5blks;
251
179
  },
252
180
 
253
- md51 = function(s) {
181
+ md51 = function (s) {
254
182
  var n = s.length,
255
183
  state = [1732584193, -271733879, -1732584194, 271733878],
256
184
  i,
@@ -261,25 +189,61 @@
261
189
  hi;
262
190
 
263
191
  for (i = 64; i <= n; i += 64) {
264
- md5cycle(state, md5blk(s.subarray(i - 64, i)));
192
+ md5cycle(state, md5blk(s.substring(i - 64, i)));
193
+ }
194
+ s = s.substring(i - 64);
195
+ length = s.length;
196
+ tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
197
+ for (i = 0; i < length; i += 1) {
198
+ tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
199
+ }
200
+ tail[i >> 2] |= 0x80 << ((i % 4) << 3);
201
+ if (i > 55) {
202
+ md5cycle(state, tail);
203
+ for (i = 0; i < 16; i += 1) {
204
+ tail[i] = 0;
205
+ }
265
206
  }
266
-
267
- //
207
+
208
+ // Beware that the final length might not fit in 32 bits so we take care of that
209
+ tmp = n * 8;
210
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
211
+ lo = parseInt(tmp[2], 16);
212
+ hi = parseInt(tmp[1], 16) || 0;
213
+
214
+ tail[14] = lo;
215
+ tail[15] = hi;
216
+
217
+ md5cycle(state, tail);
218
+ return state;
219
+ },
220
+
221
+ md51_array = function (a) {
222
+ var n = a.length,
223
+ state = [1732584193, -271733879, -1732584194, 271733878],
224
+ i,
225
+ length,
226
+ tail,
227
+ tmp,
228
+ lo,
229
+ hi;
230
+
231
+ for (i = 64; i <= n; i += 64) {
232
+ md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
233
+ }
234
+
268
235
  // Not sure if it is a bug, however IE10 will always produce a sub array of length 1
269
236
  // containing the last element of the parent array if the sub array specified starts
270
237
  // beyond the length of the parent array - weird.
271
238
  // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
272
- //
273
- if((i - 64) < n)
274
- s = s.subarray(i - 64);
275
- else
276
- s = new Uint8Array(0);
277
-
278
- length = s.length;
239
+ a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
240
+
241
+ length = a.length;
279
242
  tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
280
243
  for (i = 0; i < length; i += 1) {
281
- tail[i >> 2] |= s[i] << ((i % 4) << 3);
244
+ tail[i >> 2] |= a[i] << ((i % 4) << 3);
282
245
  }
246
+
283
247
  tail[i >> 2] |= 0x80 << ((i % 4) << 3);
284
248
  if (i > 55) {
285
249
  md5cycle(state, tail);
@@ -298,12 +262,13 @@
298
262
  tail[15] = hi;
299
263
 
300
264
  md5cycle(state, tail);
265
+
301
266
  return state;
302
267
  },
303
268
 
304
269
  hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],
305
270
 
306
- rhex = function(n) {
271
+ rhex = function (n) {
307
272
  var s = '',
308
273
  j;
309
274
  for (j = 0; j < 4; j += 1) {
@@ -312,7 +277,7 @@
312
277
  return s;
313
278
  },
314
279
 
315
- hex = function(x) {
280
+ hex = function (x) {
316
281
  var i;
317
282
  for (i = 0; i < x.length; i += 1) {
318
283
  x[i] = rhex(x[i]);
@@ -320,10 +285,12 @@
320
285
  return x.join('');
321
286
  },
322
287
 
323
- md5 = function(s) {
288
+ md5 = function (s) {
324
289
  return hex(md51(s));
325
290
  },
326
291
 
292
+
293
+
327
294
  ////////////////////////////////////////////////////////////////////////////
328
295
 
329
296
  /**
@@ -335,21 +302,35 @@
335
302
  SparkMD5 = function () {
336
303
  // call reset to init the instance
337
304
  this.reset();
338
- };
339
-
305
+ };
306
+
307
+
308
+ // In some cases the fast add32 function cannot be used..
309
+ if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {
310
+ add32 = function (x, y) {
311
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF),
312
+ msw = (x >> 16) + (y >> 16) + (lsw >> 16);
313
+ return (msw << 16) | (lsw & 0xFFFF);
314
+ };
315
+ }
316
+
340
317
 
341
318
  /**
342
319
  * Appends a string.
343
- * Converts to a byte array.
320
+ * A conversion will be applied if an utf8 string is detected.
344
321
  *
345
322
  * @param {String} str The string to be appended
346
323
  *
347
324
  * @return {SparkMD5} The instance itself
348
325
  */
349
326
  SparkMD5.prototype.append = function (str) {
327
+ // converts the string to utf8 bytes if necessary
328
+ if (/[\u0080-\uFFFF]/.test(str)) {
329
+ str = unescape(encodeURIComponent(str));
330
+ }
350
331
 
351
- // convert to array then append as binary
352
- this.appendBinary(str2ab(str));
332
+ // then append as binary
333
+ this.appendBinary(str);
353
334
 
354
335
  return this;
355
336
  };
@@ -357,26 +338,22 @@
357
338
  /**
358
339
  * Appends a binary string.
359
340
  *
360
- * @param {ArrayBuffer} contents The binary string to be appended
341
+ * @param {String} contents The binary string to be appended
361
342
  *
362
343
  * @return {SparkMD5} The instance itself
363
344
  */
364
345
  SparkMD5.prototype.appendBinary = function (contents) {
365
- var buff = abConcat(this._buff, contents),
366
- length = buff.length,
346
+ this._buff += contents;
347
+ this._length += contents.length;
348
+
349
+ var length = this._buff.length,
367
350
  i;
368
-
369
- this._length += contents.byteLength;
370
-
351
+
371
352
  for (i = 64; i <= length; i += 64) {
372
- md5cycle(this._state, md5blk(buff.subarray(i - 64, i)));
353
+ md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));
373
354
  }
374
355
 
375
- // Avoids IE10 weirdness
376
- if((i - 64) < length)
377
- this._buff = buff.subarray(i - 64);
378
- else
379
- this._buff = new Uint8Array(0);
356
+ this._buff = this._buff.substr(i - 64);
380
357
 
381
358
  return this;
382
359
  };
@@ -393,16 +370,34 @@
393
370
  SparkMD5.prototype.end = function (raw) {
394
371
  var buff = this._buff,
395
372
  length = buff.length,
396
- tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
397
373
  i,
398
- ret,
374
+ tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
375
+ ret;
376
+
377
+ for (i = 0; i < length; i += 1) {
378
+ tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
379
+ }
380
+
381
+ this._finish(tail, length);
382
+ ret = !!raw ? this._state : hex(this._state);
383
+
384
+ this.reset();
385
+
386
+ return ret;
387
+ };
388
+
389
+ /**
390
+ * Finish the final calculation based on the tail.
391
+ *
392
+ * @param {Array} tail The tail (will be modified)
393
+ * @param {Number} length The length of the remaining buffer
394
+ */
395
+ SparkMD5.prototype._finish = function (tail, length) {
396
+ var i = length,
399
397
  tmp,
400
398
  lo,
401
399
  hi;
402
400
 
403
- for (i = 0; i < length; i += 1) {
404
- tail[i >> 2] |= buff[i] << ((i % 4) << 3);
405
- }
406
401
  tail[i >> 2] |= 0x80 << ((i % 4) << 3);
407
402
  if (i > 55) {
408
403
  md5cycle(this._state, tail);
@@ -421,12 +416,6 @@
421
416
  tail[14] = lo;
422
417
  tail[15] = hi;
423
418
  md5cycle(this._state, tail);
424
-
425
- ret = !!raw ? this._state : hex(this._state);
426
-
427
- this.reset();
428
-
429
- return ret;
430
419
  };
431
420
 
432
421
  /**
@@ -435,7 +424,7 @@
435
424
  * @return {SparkMD5} The instance itself
436
425
  */
437
426
  SparkMD5.prototype.reset = function () {
438
- this._buff = new Uint8Array(0);
427
+ this._buff = "";
439
428
  this._length = 0;
440
429
  this._state = [1732584193, -271733879, -1732584194, 271733878];
441
430
 
@@ -452,8 +441,10 @@
452
441
  delete this._length;
453
442
  };
454
443
 
444
+
455
445
  /**
456
- * Performs the md5 hash on a string as utf16
446
+ * Performs the md5 hash on a string.
447
+ * A conversion will be applied if utf8 string is detected.
457
448
  *
458
449
  * @param {String} str The string
459
450
  * @param {Boolean} raw True to get the raw result, false to get the hex result
@@ -461,21 +452,145 @@
461
452
  * @return {String|Array} The result
462
453
  */
463
454
  SparkMD5.hash = function (str, raw) {
464
- var hash = md51(new Uint8Array(str2ab(str)));
455
+ // converts the string to utf8 bytes if necessary
456
+ if (/[\u0080-\uFFFF]/.test(str)) {
457
+ str = unescape(encodeURIComponent(str));
458
+ }
459
+
460
+ var hash = md51(str);
465
461
 
466
462
  return !!raw ? hash : hex(hash);
467
463
  };
468
464
 
469
465
  /**
470
- * Performs the md5 hash on a typed array.
466
+ * Performs the md5 hash on a binary string.
471
467
  *
472
- * @param {ArrayBuffer} content The binary array
468
+ * @param {String} content The binary string
473
469
  * @param {Boolean} raw True to get the raw result, false to get the hex result
474
470
  *
475
471
  * @return {String|Array} The result
476
472
  */
477
473
  SparkMD5.hashBinary = function (content, raw) {
478
- var hash = md51(new Uint8Array(content));
474
+ var hash = md51(content);
475
+
476
+ return !!raw ? hash : hex(hash);
477
+ };
478
+
479
+ /**
480
+ * SparkMD5 OOP implementation for array buffers.
481
+ *
482
+ * Use this class to perform an incremental md5 ONLY for array buffers.
483
+ */
484
+ SparkMD5.ArrayBuffer = function () {
485
+ // call reset to init the instance
486
+ this.reset();
487
+ };
488
+
489
+ ////////////////////////////////////////////////////////////////////////////
490
+
491
+ /**
492
+ * Appends an array buffer.
493
+ *
494
+ * @param {ArrayBuffer} arr The array to be appended
495
+ *
496
+ * @return {SparkMD5.ArrayBuffer} The instance itself
497
+ */
498
+ SparkMD5.ArrayBuffer.prototype.append = function (arr) {
499
+ // TODO: we could avoid the concatenation here but the algorithm would be more complex
500
+ // if you find yourself needing extra performance, please make a PR.
501
+ var buff = this._concatArrayBuffer(this._buff, arr),
502
+ length = buff.length,
503
+ i;
504
+
505
+ this._length += arr.byteLength;
506
+
507
+ for (i = 64; i <= length; i += 64) {
508
+ md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));
509
+ }
510
+
511
+ // Avoids IE10 weirdness (documented above)
512
+ this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);
513
+
514
+ return this;
515
+ };
516
+
517
+ /**
518
+ * Finishes the incremental computation, reseting the internal state and
519
+ * returning the result.
520
+ * Use the raw parameter to obtain the raw result instead of the hex one.
521
+ *
522
+ * @param {Boolean} raw True to get the raw result, false to get the hex result
523
+ *
524
+ * @return {String|Array} The result
525
+ */
526
+ SparkMD5.ArrayBuffer.prototype.end = function (raw) {
527
+ var buff = this._buff,
528
+ length = buff.length,
529
+ tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
530
+ i,
531
+ ret;
532
+
533
+ for (i = 0; i < length; i += 1) {
534
+ tail[i >> 2] |= buff[i] << ((i % 4) << 3);
535
+ }
536
+
537
+ this._finish(tail, length);
538
+ ret = !!raw ? this._state : hex(this._state);
539
+
540
+ this.reset();
541
+
542
+ return ret;
543
+ };
544
+
545
+ SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
546
+
547
+ /**
548
+ * Resets the internal state of the computation.
549
+ *
550
+ * @return {SparkMD5.ArrayBuffer} The instance itself
551
+ */
552
+ SparkMD5.ArrayBuffer.prototype.reset = function () {
553
+ this._buff = new Uint8Array(0);
554
+ this._length = 0;
555
+ this._state = [1732584193, -271733879, -1732584194, 271733878];
556
+
557
+ return this;
558
+ };
559
+
560
+ /**
561
+ * Releases memory used by the incremental buffer and other aditional
562
+ * resources. If you plan to use the instance again, use reset instead.
563
+ */
564
+ SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
565
+
566
+ /**
567
+ * Concats two array buffers, returning a new one.
568
+ *
569
+ * @param {ArrayBuffer} first The first array buffer
570
+ * @param {ArrayBuffer} second The second array buffer
571
+ *
572
+ * @return {ArrayBuffer} The new array buffer
573
+ */
574
+ SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {
575
+ var firstLength = first.length,
576
+ result = new Uint8Array(firstLength + second.byteLength);
577
+
578
+ result.set(first);
579
+ result.set(new Uint8Array(second), firstLength);
580
+
581
+ return result;
582
+ };
583
+
584
+ /**
585
+ * Performs the md5 hash on an array buffer.
586
+ *
587
+ * @param {ArrayBuffer} arr The array buffer
588
+ * @param {Boolean} raw True to get the raw result, false to get the hex result
589
+ *
590
+ * @return {String|Array} The result
591
+ */
592
+ SparkMD5.ArrayBuffer.hash = function (arr, raw) {
593
+ var hash = md51_array(new Uint8Array(arr));
479
594
 
480
595
  return !!raw ? hash : hex(hash);
481
596
  };