condo 1.0.4 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
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
  };