ぼざクリ タグ広場 https://hub.nizika.monster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

912 lines
28 KiB

  1. var sparkMd5 = {
  2. exports: {}
  3. };
  4. (function(module, exports) {
  5. (function(factory) {
  6. {
  7. module.exports = factory();
  8. }
  9. })((function(undefined$1) {
  10. var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
  11. function md5cycle(x, k) {
  12. var a = x[0], b = x[1], c = x[2], d = x[3];
  13. a += (b & c | ~b & d) + k[0] - 680876936 | 0;
  14. a = (a << 7 | a >>> 25) + b | 0;
  15. d += (a & b | ~a & c) + k[1] - 389564586 | 0;
  16. d = (d << 12 | d >>> 20) + a | 0;
  17. c += (d & a | ~d & b) + k[2] + 606105819 | 0;
  18. c = (c << 17 | c >>> 15) + d | 0;
  19. b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
  20. b = (b << 22 | b >>> 10) + c | 0;
  21. a += (b & c | ~b & d) + k[4] - 176418897 | 0;
  22. a = (a << 7 | a >>> 25) + b | 0;
  23. d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
  24. d = (d << 12 | d >>> 20) + a | 0;
  25. c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
  26. c = (c << 17 | c >>> 15) + d | 0;
  27. b += (c & d | ~c & a) + k[7] - 45705983 | 0;
  28. b = (b << 22 | b >>> 10) + c | 0;
  29. a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
  30. a = (a << 7 | a >>> 25) + b | 0;
  31. d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
  32. d = (d << 12 | d >>> 20) + a | 0;
  33. c += (d & a | ~d & b) + k[10] - 42063 | 0;
  34. c = (c << 17 | c >>> 15) + d | 0;
  35. b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
  36. b = (b << 22 | b >>> 10) + c | 0;
  37. a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
  38. a = (a << 7 | a >>> 25) + b | 0;
  39. d += (a & b | ~a & c) + k[13] - 40341101 | 0;
  40. d = (d << 12 | d >>> 20) + a | 0;
  41. c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
  42. c = (c << 17 | c >>> 15) + d | 0;
  43. b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
  44. b = (b << 22 | b >>> 10) + c | 0;
  45. a += (b & d | c & ~d) + k[1] - 165796510 | 0;
  46. a = (a << 5 | a >>> 27) + b | 0;
  47. d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
  48. d = (d << 9 | d >>> 23) + a | 0;
  49. c += (d & b | a & ~b) + k[11] + 643717713 | 0;
  50. c = (c << 14 | c >>> 18) + d | 0;
  51. b += (c & a | d & ~a) + k[0] - 373897302 | 0;
  52. b = (b << 20 | b >>> 12) + c | 0;
  53. a += (b & d | c & ~d) + k[5] - 701558691 | 0;
  54. a = (a << 5 | a >>> 27) + b | 0;
  55. d += (a & c | b & ~c) + k[10] + 38016083 | 0;
  56. d = (d << 9 | d >>> 23) + a | 0;
  57. c += (d & b | a & ~b) + k[15] - 660478335 | 0;
  58. c = (c << 14 | c >>> 18) + d | 0;
  59. b += (c & a | d & ~a) + k[4] - 405537848 | 0;
  60. b = (b << 20 | b >>> 12) + c | 0;
  61. a += (b & d | c & ~d) + k[9] + 568446438 | 0;
  62. a = (a << 5 | a >>> 27) + b | 0;
  63. d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
  64. d = (d << 9 | d >>> 23) + a | 0;
  65. c += (d & b | a & ~b) + k[3] - 187363961 | 0;
  66. c = (c << 14 | c >>> 18) + d | 0;
  67. b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
  68. b = (b << 20 | b >>> 12) + c | 0;
  69. a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
  70. a = (a << 5 | a >>> 27) + b | 0;
  71. d += (a & c | b & ~c) + k[2] - 51403784 | 0;
  72. d = (d << 9 | d >>> 23) + a | 0;
  73. c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
  74. c = (c << 14 | c >>> 18) + d | 0;
  75. b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
  76. b = (b << 20 | b >>> 12) + c | 0;
  77. a += (b ^ c ^ d) + k[5] - 378558 | 0;
  78. a = (a << 4 | a >>> 28) + b | 0;
  79. d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
  80. d = (d << 11 | d >>> 21) + a | 0;
  81. c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
  82. c = (c << 16 | c >>> 16) + d | 0;
  83. b += (c ^ d ^ a) + k[14] - 35309556 | 0;
  84. b = (b << 23 | b >>> 9) + c | 0;
  85. a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
  86. a = (a << 4 | a >>> 28) + b | 0;
  87. d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
  88. d = (d << 11 | d >>> 21) + a | 0;
  89. c += (d ^ a ^ b) + k[7] - 155497632 | 0;
  90. c = (c << 16 | c >>> 16) + d | 0;
  91. b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
  92. b = (b << 23 | b >>> 9) + c | 0;
  93. a += (b ^ c ^ d) + k[13] + 681279174 | 0;
  94. a = (a << 4 | a >>> 28) + b | 0;
  95. d += (a ^ b ^ c) + k[0] - 358537222 | 0;
  96. d = (d << 11 | d >>> 21) + a | 0;
  97. c += (d ^ a ^ b) + k[3] - 722521979 | 0;
  98. c = (c << 16 | c >>> 16) + d | 0;
  99. b += (c ^ d ^ a) + k[6] + 76029189 | 0;
  100. b = (b << 23 | b >>> 9) + c | 0;
  101. a += (b ^ c ^ d) + k[9] - 640364487 | 0;
  102. a = (a << 4 | a >>> 28) + b | 0;
  103. d += (a ^ b ^ c) + k[12] - 421815835 | 0;
  104. d = (d << 11 | d >>> 21) + a | 0;
  105. c += (d ^ a ^ b) + k[15] + 530742520 | 0;
  106. c = (c << 16 | c >>> 16) + d | 0;
  107. b += (c ^ d ^ a) + k[2] - 995338651 | 0;
  108. b = (b << 23 | b >>> 9) + c | 0;
  109. a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
  110. a = (a << 6 | a >>> 26) + b | 0;
  111. d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
  112. d = (d << 10 | d >>> 22) + a | 0;
  113. c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
  114. c = (c << 15 | c >>> 17) + d | 0;
  115. b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
  116. b = (b << 21 | b >>> 11) + c | 0;
  117. a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
  118. a = (a << 6 | a >>> 26) + b | 0;
  119. d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
  120. d = (d << 10 | d >>> 22) + a | 0;
  121. c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
  122. c = (c << 15 | c >>> 17) + d | 0;
  123. b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
  124. b = (b << 21 | b >>> 11) + c | 0;
  125. a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
  126. a = (a << 6 | a >>> 26) + b | 0;
  127. d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
  128. d = (d << 10 | d >>> 22) + a | 0;
  129. c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
  130. c = (c << 15 | c >>> 17) + d | 0;
  131. b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
  132. b = (b << 21 | b >>> 11) + c | 0;
  133. a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
  134. a = (a << 6 | a >>> 26) + b | 0;
  135. d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
  136. d = (d << 10 | d >>> 22) + a | 0;
  137. c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
  138. c = (c << 15 | c >>> 17) + d | 0;
  139. b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
  140. b = (b << 21 | b >>> 11) + c | 0;
  141. x[0] = a + x[0] | 0;
  142. x[1] = b + x[1] | 0;
  143. x[2] = c + x[2] | 0;
  144. x[3] = d + x[3] | 0;
  145. }
  146. function md5blk(s) {
  147. var md5blks = [], i;
  148. for (i = 0; i < 64; i += 4) {
  149. md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
  150. }
  151. return md5blks;
  152. }
  153. function md5blk_array(a) {
  154. var md5blks = [], i;
  155. for (i = 0; i < 64; i += 4) {
  156. md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
  157. }
  158. return md5blks;
  159. }
  160. function md51(s) {
  161. var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
  162. for (i = 64; i <= n; i += 64) {
  163. md5cycle(state, md5blk(s.substring(i - 64, i)));
  164. }
  165. s = s.substring(i - 64);
  166. length = s.length;
  167. tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
  168. for (i = 0; i < length; i += 1) {
  169. tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
  170. }
  171. tail[i >> 2] |= 128 << (i % 4 << 3);
  172. if (i > 55) {
  173. md5cycle(state, tail);
  174. for (i = 0; i < 16; i += 1) {
  175. tail[i] = 0;
  176. }
  177. }
  178. tmp = n * 8;
  179. tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
  180. lo = parseInt(tmp[2], 16);
  181. hi = parseInt(tmp[1], 16) || 0;
  182. tail[14] = lo;
  183. tail[15] = hi;
  184. md5cycle(state, tail);
  185. return state;
  186. }
  187. function md51_array(a) {
  188. var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
  189. for (i = 64; i <= n; i += 64) {
  190. md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
  191. }
  192. a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
  193. length = a.length;
  194. tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
  195. for (i = 0; i < length; i += 1) {
  196. tail[i >> 2] |= a[i] << (i % 4 << 3);
  197. }
  198. tail[i >> 2] |= 128 << (i % 4 << 3);
  199. if (i > 55) {
  200. md5cycle(state, tail);
  201. for (i = 0; i < 16; i += 1) {
  202. tail[i] = 0;
  203. }
  204. }
  205. tmp = n * 8;
  206. tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
  207. lo = parseInt(tmp[2], 16);
  208. hi = parseInt(tmp[1], 16) || 0;
  209. tail[14] = lo;
  210. tail[15] = hi;
  211. md5cycle(state, tail);
  212. return state;
  213. }
  214. function rhex(n) {
  215. var s = "", j;
  216. for (j = 0; j < 4; j += 1) {
  217. s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
  218. }
  219. return s;
  220. }
  221. function hex(x) {
  222. var i;
  223. for (i = 0; i < x.length; i += 1) {
  224. x[i] = rhex(x[i]);
  225. }
  226. return x.join("");
  227. }
  228. if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
  229. if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
  230. (function() {
  231. function clamp(val, length) {
  232. val = val | 0 || 0;
  233. if (val < 0) {
  234. return Math.max(val + length, 0);
  235. }
  236. return Math.min(val, length);
  237. }
  238. ArrayBuffer.prototype.slice = function(from, to) {
  239. var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
  240. if (to !== undefined$1) {
  241. end = clamp(to, length);
  242. }
  243. if (begin > end) {
  244. return new ArrayBuffer(0);
  245. }
  246. num = end - begin;
  247. target = new ArrayBuffer(num);
  248. targetArray = new Uint8Array(target);
  249. sourceArray = new Uint8Array(this, begin, num);
  250. targetArray.set(sourceArray);
  251. return target;
  252. };
  253. })();
  254. }
  255. function toUtf8(str) {
  256. if (/[\u0080-\uFFFF]/.test(str)) {
  257. str = unescape(encodeURIComponent(str));
  258. }
  259. return str;
  260. }
  261. function utf8Str2ArrayBuffer(str, returnUInt8Array) {
  262. var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
  263. for (i = 0; i < length; i += 1) {
  264. arr[i] = str.charCodeAt(i);
  265. }
  266. return returnUInt8Array ? arr : buff;
  267. }
  268. function arrayBuffer2Utf8Str(buff) {
  269. return String.fromCharCode.apply(null, new Uint8Array(buff));
  270. }
  271. function concatenateArrayBuffers(first, second, returnUInt8Array) {
  272. var result = new Uint8Array(first.byteLength + second.byteLength);
  273. result.set(new Uint8Array(first));
  274. result.set(new Uint8Array(second), first.byteLength);
  275. return returnUInt8Array ? result : result.buffer;
  276. }
  277. function hexToBinaryString(hex) {
  278. var bytes = [], length = hex.length, x;
  279. for (x = 0; x < length - 1; x += 2) {
  280. bytes.push(parseInt(hex.substr(x, 2), 16));
  281. }
  282. return String.fromCharCode.apply(String, bytes);
  283. }
  284. function SparkMD5() {
  285. this.reset();
  286. }
  287. SparkMD5.prototype.append = function(str) {
  288. this.appendBinary(toUtf8(str));
  289. return this;
  290. };
  291. SparkMD5.prototype.appendBinary = function(contents) {
  292. this._buff += contents;
  293. this._length += contents.length;
  294. var length = this._buff.length, i;
  295. for (i = 64; i <= length; i += 64) {
  296. md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
  297. }
  298. this._buff = this._buff.substring(i - 64);
  299. return this;
  300. };
  301. SparkMD5.prototype.end = function(raw) {
  302. var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
  303. for (i = 0; i < length; i += 1) {
  304. tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
  305. }
  306. this._finish(tail, length);
  307. ret = hex(this._hash);
  308. if (raw) {
  309. ret = hexToBinaryString(ret);
  310. }
  311. this.reset();
  312. return ret;
  313. };
  314. SparkMD5.prototype.reset = function() {
  315. this._buff = "";
  316. this._length = 0;
  317. this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
  318. return this;
  319. };
  320. SparkMD5.prototype.getState = function() {
  321. return {
  322. buff: this._buff,
  323. length: this._length,
  324. hash: this._hash.slice()
  325. };
  326. };
  327. SparkMD5.prototype.setState = function(state) {
  328. this._buff = state.buff;
  329. this._length = state.length;
  330. this._hash = state.hash;
  331. return this;
  332. };
  333. SparkMD5.prototype.destroy = function() {
  334. delete this._hash;
  335. delete this._buff;
  336. delete this._length;
  337. };
  338. SparkMD5.prototype._finish = function(tail, length) {
  339. var i = length, tmp, lo, hi;
  340. tail[i >> 2] |= 128 << (i % 4 << 3);
  341. if (i > 55) {
  342. md5cycle(this._hash, tail);
  343. for (i = 0; i < 16; i += 1) {
  344. tail[i] = 0;
  345. }
  346. }
  347. tmp = this._length * 8;
  348. tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
  349. lo = parseInt(tmp[2], 16);
  350. hi = parseInt(tmp[1], 16) || 0;
  351. tail[14] = lo;
  352. tail[15] = hi;
  353. md5cycle(this._hash, tail);
  354. };
  355. SparkMD5.hash = function(str, raw) {
  356. return SparkMD5.hashBinary(toUtf8(str), raw);
  357. };
  358. SparkMD5.hashBinary = function(content, raw) {
  359. var hash = md51(content), ret = hex(hash);
  360. return raw ? hexToBinaryString(ret) : ret;
  361. };
  362. SparkMD5.ArrayBuffer = function() {
  363. this.reset();
  364. };
  365. SparkMD5.ArrayBuffer.prototype.append = function(arr) {
  366. var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
  367. this._length += arr.byteLength;
  368. for (i = 64; i <= length; i += 64) {
  369. md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
  370. }
  371. this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
  372. return this;
  373. };
  374. SparkMD5.ArrayBuffer.prototype.end = function(raw) {
  375. var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
  376. for (i = 0; i < length; i += 1) {
  377. tail[i >> 2] |= buff[i] << (i % 4 << 3);
  378. }
  379. this._finish(tail, length);
  380. ret = hex(this._hash);
  381. if (raw) {
  382. ret = hexToBinaryString(ret);
  383. }
  384. this.reset();
  385. return ret;
  386. };
  387. SparkMD5.ArrayBuffer.prototype.reset = function() {
  388. this._buff = new Uint8Array(0);
  389. this._length = 0;
  390. this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
  391. return this;
  392. };
  393. SparkMD5.ArrayBuffer.prototype.getState = function() {
  394. var state = SparkMD5.prototype.getState.call(this);
  395. state.buff = arrayBuffer2Utf8Str(state.buff);
  396. return state;
  397. };
  398. SparkMD5.ArrayBuffer.prototype.setState = function(state) {
  399. state.buff = utf8Str2ArrayBuffer(state.buff, true);
  400. return SparkMD5.prototype.setState.call(this, state);
  401. };
  402. SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
  403. SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
  404. SparkMD5.ArrayBuffer.hash = function(arr, raw) {
  405. var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
  406. return raw ? hexToBinaryString(ret) : ret;
  407. };
  408. return SparkMD5;
  409. }));
  410. })(sparkMd5);
  411. var SparkMD5 = sparkMd5.exports;
  412. const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
  413. class FileChecksum {
  414. static create(file, callback) {
  415. const instance = new FileChecksum(file);
  416. instance.create(callback);
  417. }
  418. constructor(file) {
  419. this.file = file;
  420. this.chunkSize = 2097152;
  421. this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
  422. this.chunkIndex = 0;
  423. }
  424. create(callback) {
  425. this.callback = callback;
  426. this.md5Buffer = new SparkMD5.ArrayBuffer;
  427. this.fileReader = new FileReader;
  428. this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
  429. this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
  430. this.readNextChunk();
  431. }
  432. fileReaderDidLoad(event) {
  433. this.md5Buffer.append(event.target.result);
  434. if (!this.readNextChunk()) {
  435. const binaryDigest = this.md5Buffer.end(true);
  436. const base64digest = btoa(binaryDigest);
  437. this.callback(null, base64digest);
  438. }
  439. }
  440. fileReaderDidError(event) {
  441. this.callback(`Error reading ${this.file.name}`);
  442. }
  443. readNextChunk() {
  444. if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
  445. const start = this.chunkIndex * this.chunkSize;
  446. const end = Math.min(start + this.chunkSize, this.file.size);
  447. const bytes = fileSlice.call(this.file, start, end);
  448. this.fileReader.readAsArrayBuffer(bytes);
  449. this.chunkIndex++;
  450. return true;
  451. } else {
  452. return false;
  453. }
  454. }
  455. }
  456. function getMetaValue(name) {
  457. const element = findElement(document.head, `meta[name="${name}"]`);
  458. if (element) {
  459. return element.getAttribute("content");
  460. }
  461. }
  462. function findElements(root, selector) {
  463. if (typeof root == "string") {
  464. selector = root;
  465. root = document;
  466. }
  467. const elements = root.querySelectorAll(selector);
  468. return toArray(elements);
  469. }
  470. function findElement(root, selector) {
  471. if (typeof root == "string") {
  472. selector = root;
  473. root = document;
  474. }
  475. return root.querySelector(selector);
  476. }
  477. function dispatchEvent(element, type, eventInit = {}) {
  478. const {disabled: disabled} = element;
  479. const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
  480. const event = document.createEvent("Event");
  481. event.initEvent(type, bubbles || true, cancelable || true);
  482. event.detail = detail || {};
  483. try {
  484. element.disabled = false;
  485. element.dispatchEvent(event);
  486. } finally {
  487. element.disabled = disabled;
  488. }
  489. return event;
  490. }
  491. function toArray(value) {
  492. if (Array.isArray(value)) {
  493. return value;
  494. } else if (Array.from) {
  495. return Array.from(value);
  496. } else {
  497. return [].slice.call(value);
  498. }
  499. }
  500. class BlobRecord {
  501. constructor(file, checksum, url, customHeaders = {}) {
  502. this.file = file;
  503. this.attributes = {
  504. filename: file.name,
  505. content_type: file.type || "application/octet-stream",
  506. byte_size: file.size,
  507. checksum: checksum
  508. };
  509. this.xhr = new XMLHttpRequest;
  510. this.xhr.open("POST", url, true);
  511. this.xhr.responseType = "json";
  512. this.xhr.setRequestHeader("Content-Type", "application/json");
  513. this.xhr.setRequestHeader("Accept", "application/json");
  514. this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  515. Object.keys(customHeaders).forEach((headerKey => {
  516. this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
  517. }));
  518. const csrfToken = getMetaValue("csrf-token");
  519. if (csrfToken != undefined) {
  520. this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
  521. }
  522. this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
  523. this.xhr.addEventListener("error", (event => this.requestDidError(event)));
  524. }
  525. get status() {
  526. return this.xhr.status;
  527. }
  528. get response() {
  529. const {responseType: responseType, response: response} = this.xhr;
  530. if (responseType == "json") {
  531. return response;
  532. } else {
  533. return JSON.parse(response);
  534. }
  535. }
  536. create(callback) {
  537. this.callback = callback;
  538. this.xhr.send(JSON.stringify({
  539. blob: this.attributes
  540. }));
  541. }
  542. requestDidLoad(event) {
  543. if (this.status >= 200 && this.status < 300) {
  544. const {response: response} = this;
  545. const {direct_upload: direct_upload} = response;
  546. delete response.direct_upload;
  547. this.attributes = response;
  548. this.directUploadData = direct_upload;
  549. this.callback(null, this.toJSON());
  550. } else {
  551. this.requestDidError(event);
  552. }
  553. }
  554. requestDidError(event) {
  555. this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
  556. }
  557. toJSON() {
  558. const result = {};
  559. for (const key in this.attributes) {
  560. result[key] = this.attributes[key];
  561. }
  562. return result;
  563. }
  564. }
  565. class BlobUpload {
  566. constructor(blob) {
  567. this.blob = blob;
  568. this.file = blob.file;
  569. const {url: url, headers: headers} = blob.directUploadData;
  570. this.xhr = new XMLHttpRequest;
  571. this.xhr.open("PUT", url, true);
  572. this.xhr.responseType = "text";
  573. for (const key in headers) {
  574. this.xhr.setRequestHeader(key, headers[key]);
  575. }
  576. this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
  577. this.xhr.addEventListener("error", (event => this.requestDidError(event)));
  578. }
  579. create(callback) {
  580. this.callback = callback;
  581. this.xhr.send(this.file.slice());
  582. }
  583. requestDidLoad(event) {
  584. const {status: status, response: response} = this.xhr;
  585. if (status >= 200 && status < 300) {
  586. this.callback(null, response);
  587. } else {
  588. this.requestDidError(event);
  589. }
  590. }
  591. requestDidError(event) {
  592. this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
  593. }
  594. }
  595. let id = 0;
  596. class DirectUpload {
  597. constructor(file, url, delegate, customHeaders = {}) {
  598. this.id = ++id;
  599. this.file = file;
  600. this.url = url;
  601. this.delegate = delegate;
  602. this.customHeaders = customHeaders;
  603. }
  604. create(callback) {
  605. FileChecksum.create(this.file, ((error, checksum) => {
  606. if (error) {
  607. callback(error);
  608. return;
  609. }
  610. const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
  611. notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
  612. blob.create((error => {
  613. if (error) {
  614. callback(error);
  615. } else {
  616. const upload = new BlobUpload(blob);
  617. notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
  618. upload.create((error => {
  619. if (error) {
  620. callback(error);
  621. } else {
  622. callback(null, blob.toJSON());
  623. }
  624. }));
  625. }
  626. }));
  627. }));
  628. }
  629. }
  630. function notify(object, methodName, ...messages) {
  631. if (object && typeof object[methodName] == "function") {
  632. return object[methodName](...messages);
  633. }
  634. }
  635. class DirectUploadController {
  636. constructor(input, file) {
  637. this.input = input;
  638. this.file = file;
  639. this.directUpload = new DirectUpload(this.file, this.url, this);
  640. this.dispatch("initialize");
  641. }
  642. start(callback) {
  643. const hiddenInput = document.createElement("input");
  644. hiddenInput.type = "hidden";
  645. hiddenInput.name = this.input.name;
  646. this.input.insertAdjacentElement("beforebegin", hiddenInput);
  647. this.dispatch("start");
  648. this.directUpload.create(((error, attributes) => {
  649. if (error) {
  650. hiddenInput.parentNode.removeChild(hiddenInput);
  651. this.dispatchError(error);
  652. } else {
  653. hiddenInput.value = attributes.signed_id;
  654. }
  655. this.dispatch("end");
  656. callback(error);
  657. }));
  658. }
  659. uploadRequestDidProgress(event) {
  660. const progress = event.loaded / event.total * 100;
  661. if (progress) {
  662. this.dispatch("progress", {
  663. progress: progress
  664. });
  665. }
  666. }
  667. get url() {
  668. return this.input.getAttribute("data-direct-upload-url");
  669. }
  670. dispatch(name, detail = {}) {
  671. detail.file = this.file;
  672. detail.id = this.directUpload.id;
  673. return dispatchEvent(this.input, `direct-upload:${name}`, {
  674. detail: detail
  675. });
  676. }
  677. dispatchError(error) {
  678. const event = this.dispatch("error", {
  679. error: error
  680. });
  681. if (!event.defaultPrevented) {
  682. alert(error);
  683. }
  684. }
  685. directUploadWillCreateBlobWithXHR(xhr) {
  686. this.dispatch("before-blob-request", {
  687. xhr: xhr
  688. });
  689. }
  690. directUploadWillStoreFileWithXHR(xhr) {
  691. this.dispatch("before-storage-request", {
  692. xhr: xhr
  693. });
  694. xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
  695. }
  696. }
  697. const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
  698. class DirectUploadsController {
  699. constructor(form) {
  700. this.form = form;
  701. this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
  702. }
  703. start(callback) {
  704. const controllers = this.createDirectUploadControllers();
  705. const startNextController = () => {
  706. const controller = controllers.shift();
  707. if (controller) {
  708. controller.start((error => {
  709. if (error) {
  710. callback(error);
  711. this.dispatch("end");
  712. } else {
  713. startNextController();
  714. }
  715. }));
  716. } else {
  717. callback();
  718. this.dispatch("end");
  719. }
  720. };
  721. this.dispatch("start");
  722. startNextController();
  723. }
  724. createDirectUploadControllers() {
  725. const controllers = [];
  726. this.inputs.forEach((input => {
  727. toArray(input.files).forEach((file => {
  728. const controller = new DirectUploadController(input, file);
  729. controllers.push(controller);
  730. }));
  731. }));
  732. return controllers;
  733. }
  734. dispatch(name, detail = {}) {
  735. return dispatchEvent(this.form, `direct-uploads:${name}`, {
  736. detail: detail
  737. });
  738. }
  739. }
  740. const processingAttribute = "data-direct-uploads-processing";
  741. const submitButtonsByForm = new WeakMap;
  742. let started = false;
  743. function start() {
  744. if (!started) {
  745. started = true;
  746. document.addEventListener("click", didClick, true);
  747. document.addEventListener("submit", didSubmitForm, true);
  748. document.addEventListener("ajax:before", didSubmitRemoteElement);
  749. }
  750. }
  751. function didClick(event) {
  752. const button = event.target.closest("button, input");
  753. if (button && button.type === "submit" && button.form) {
  754. submitButtonsByForm.set(button.form, button);
  755. }
  756. }
  757. function didSubmitForm(event) {
  758. handleFormSubmissionEvent(event);
  759. }
  760. function didSubmitRemoteElement(event) {
  761. if (event.target.tagName == "FORM") {
  762. handleFormSubmissionEvent(event);
  763. }
  764. }
  765. function handleFormSubmissionEvent(event) {
  766. const form = event.target;
  767. if (form.hasAttribute(processingAttribute)) {
  768. event.preventDefault();
  769. return;
  770. }
  771. const controller = new DirectUploadsController(form);
  772. const {inputs: inputs} = controller;
  773. if (inputs.length) {
  774. event.preventDefault();
  775. form.setAttribute(processingAttribute, "");
  776. inputs.forEach(disable);
  777. controller.start((error => {
  778. form.removeAttribute(processingAttribute);
  779. if (error) {
  780. inputs.forEach(enable);
  781. } else {
  782. submitForm(form);
  783. }
  784. }));
  785. }
  786. }
  787. function submitForm(form) {
  788. let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
  789. if (button) {
  790. const {disabled: disabled} = button;
  791. button.disabled = false;
  792. button.focus();
  793. button.click();
  794. button.disabled = disabled;
  795. } else {
  796. button = document.createElement("input");
  797. button.type = "submit";
  798. button.style.display = "none";
  799. form.appendChild(button);
  800. button.click();
  801. form.removeChild(button);
  802. }
  803. submitButtonsByForm.delete(form);
  804. }
  805. function disable(input) {
  806. input.disabled = true;
  807. }
  808. function enable(input) {
  809. input.disabled = false;
  810. }
  811. function autostart() {
  812. if (window.ActiveStorage) {
  813. start();
  814. }
  815. }
  816. setTimeout(autostart, 1);
  817. class AttachmentUpload {
  818. constructor(attachment, element) {
  819. this.attachment = attachment;
  820. this.element = element;
  821. this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this);
  822. }
  823. start() {
  824. this.directUpload.create(this.directUploadDidComplete.bind(this));
  825. this.dispatch("start");
  826. }
  827. directUploadWillStoreFileWithXHR(xhr) {
  828. xhr.upload.addEventListener("progress", (event => {
  829. const progress = event.loaded / event.total * 100;
  830. this.attachment.setUploadProgress(progress);
  831. if (progress) {
  832. this.dispatch("progress", {
  833. progress: progress
  834. });
  835. }
  836. }));
  837. }
  838. directUploadDidComplete(error, attributes) {
  839. if (error) {
  840. this.dispatchError(error);
  841. } else {
  842. this.attachment.setAttributes({
  843. sgid: attributes.attachable_sgid,
  844. url: this.createBlobUrl(attributes.signed_id, attributes.filename)
  845. });
  846. this.dispatch("end");
  847. }
  848. }
  849. createBlobUrl(signedId, filename) {
  850. return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
  851. }
  852. dispatch(name, detail = {}) {
  853. detail.attachment = this.attachment;
  854. return dispatchEvent(this.element, `direct-upload:${name}`, {
  855. detail: detail
  856. });
  857. }
  858. dispatchError(error) {
  859. const event = this.dispatch("error", {
  860. error: error
  861. });
  862. if (!event.defaultPrevented) {
  863. alert(error);
  864. }
  865. }
  866. get directUploadUrl() {
  867. return this.element.dataset.directUploadUrl;
  868. }
  869. get blobUrlTemplate() {
  870. return this.element.dataset.blobUrlTemplate;
  871. }
  872. }
  873. addEventListener("trix-attachment-add", (event => {
  874. const {attachment: attachment, target: target} = event;
  875. if (attachment.file) {
  876. const upload = new AttachmentUpload(attachment, target);
  877. upload.start();
  878. }
  879. }));