115备份小工具

改自115转存助手ui优化版3.5,先感谢一下作者,其次我太懒了,不想写新的

目前為 2023-12-25 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name 115备份小工具
  3. // @name:zh 115备份小工具
  4. // @description 改自115转存助手ui优化版3.5,先感谢一下作者,其次我太懒了,不想写新的
  5. // @author 115211
  6. // @namespace null
  7. // @version 3.0.0
  8. // @match https://115.com/*
  9. // @exclude https://115.com/s/*
  10. // @license MIT
  11.  
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM_log
  14. // @grant GM_setValue
  15. // @grant GM_getValue
  16. // @grant GM_setClipboard
  17. // @grant unsafeWindow
  18. // @grant GM_registerMenuCommand
  19. // @grant GM_addStyle
  20. // @grant GM_info
  21.  
  22. // @connect proapi.115.com
  23. // @connect webapi.115.com
  24. // @connect 115.com
  25. // @connect *
  26.  
  27. // @require https://cdn.jsdelivr.net/npm/underscore@1.13.6/underscore-min.js
  28. // @require https://cdn.jsdelivr.net/npm/sweetalert2@11.7.20/dist/sweetalert2.min.js
  29. // @require https://cdn.jsdelivr.net/npm/node-forge@0.10.0/dist/forge.min.js
  30. // @require https://cdn.jsdelivr.net/npm/emoutils@2.0.0/dist/umd/emoutils.min.js
  31. // @require https://cdn.jsdelivr.net/npm/blueimp-md5@2.19.0/js/md5.min.js
  32. // @require https://cdn.jsdelivr.net/npm/big-integer@1.6.51/BigInteger.min.js
  33. // ==/UserScript==
  34.  
  35.  
  36. /*针对网络问题,只能将不稳定的依赖库放置于此*/
  37.  
  38. /*jssha@2.3.1/src/sha.js*/
  39. /*
  40. A JavaScript implementation of the SHA family of hashes, as
  41. defined in FIPS PUB 180-4 and FIPS PUB 202, as well as the corresponding
  42. HMAC implementation as defined in FIPS PUB 198a
  43.  
  44. Copyright Brian Turek 2008-2017
  45. Distributed under the BSD License
  46. See http://caligatio.github.com/jsSHA/ for more information
  47.  
  48. Several functions taken from Paul Johnston
  49. */
  50. 'use strict';
  51. (function(Y) {
  52. function C(c, a, b) {
  53. var e = 0,
  54. h = [],
  55. n = 0,
  56. g, l, d, f, m, q, u, r, I = !1,
  57. v = [],
  58. w = [],
  59. t, y = !1,
  60. z = !1,
  61. x = -1;
  62. b = b || {};
  63. g = b.encoding || 'UTF8';
  64. t = b.numRounds || 1;
  65. if (t !== parseInt(t, 10) || 1 > t) throw Error(
  66. 'numRounds must a integer >= 1');
  67. if ('SHA-1' === c) m = 512, q = K, u = Z, f = 160, r = function(a) {
  68. return a.slice();
  69. };
  70. else if (0 === c.lastIndexOf('SHA-', 0))
  71. if (q = function(a, b) {
  72. return L(a, b, c);
  73. }, u = function(a, b, h, e) {
  74. var k, f;
  75. if ('SHA-224' === c || 'SHA-256' === c) k = (b + 65 >>> 9 << 4) +
  76. 15, f = 16;
  77. else if ('SHA-384' === c || 'SHA-512' === c) k = (b + 129 >>> 10 <<
  78. 5) + 31, f = 32;
  79. else throw Error('Unexpected error in SHA-2 implementation');
  80. for (; a.length <= k;) a.push(0);
  81. a[b >>> 5] |= 128 << 24 - b % 32;
  82. b = b + h;
  83. a[k] = b & 4294967295;
  84. a[k - 1] = b / 4294967296 | 0;
  85. h = a.length;
  86. for (b = 0; b < h; b += f) e = L(a.slice(b, b + f), e, c);
  87. if ('SHA-224' === c) a = [e[0], e[1], e[2], e[3], e[4], e[5], e[6]];
  88. else if ('SHA-256' === c) a = e;
  89. else if ('SHA-384' === c) a = [
  90. e[0].a,
  91. e[0].b,
  92. e[1].a,
  93. e[1].b,
  94. e[2].a,
  95. e[2].b,
  96. e[3].a,
  97. e[3].b,
  98. e[4].a,
  99. e[4].b,
  100. e[5].a,
  101. e[5].b];
  102. else if ('SHA-512' === c) a = [
  103. e[0].a,
  104. e[0].b,
  105. e[1].a,
  106. e[1].b,
  107. e[2].a,
  108. e[2].b,
  109. e[3].a,
  110. e[3].b,
  111. e[4].a,
  112. e[4].b,
  113. e[5].a,
  114. e[5].b,
  115. e[6].a,
  116. e[6].b,
  117. e[7].a,
  118. e[7].b,
  119. ];
  120. else throw Error('Unexpected error in SHA-2 implementation');
  121. return a;
  122. }, r = function(a) {
  123. return a.slice();
  124. }, 'SHA-224' === c) m = 512, f = 224;
  125. else if ('SHA-256' === c) m = 512, f = 256;
  126. else if ('SHA-384' === c) m = 1024, f = 384;
  127. else if ('SHA-512' === c) m = 1024, f = 512;
  128. else throw Error('Chosen SHA variant is not supported');
  129. else if (0 === c.lastIndexOf('SHA3-', 0) || 0 ===
  130. c.lastIndexOf('SHAKE', 0)) {
  131. var F = 6;
  132. q = D;
  133. r = function(a) {
  134. var c = [],
  135. e;
  136. for (e = 0; 5 > e; e += 1) c[e] = a[e].slice();
  137. return c;
  138. };
  139. x = 1;
  140. if ('SHA3-224' ===
  141. c) m = 1152, f = 224;
  142. else if ('SHA3-256' === c) m = 1088, f = 256;
  143. else if ('SHA3-384' === c) m = 832, f = 384;
  144. else if ('SHA3-512' === c) m = 576, f = 512;
  145. else if ('SHAKE128' === c) m = 1344, f = -1, F = 31, z = !0;
  146. else if ('SHAKE256' === c) m = 1088, f = -1, F = 31, z = !0;
  147. else throw Error('Chosen SHA variant is not supported');
  148. u = function(a, c, e, b, h) {
  149. e = m;
  150. var k = F,
  151. f, g = [],
  152. n = e >>> 5,
  153. l = 0,
  154. d = c >>> 5;
  155. for (f = 0; f < d && c >= e; f += n) b = D(a.slice(f, f + n),
  156. b), c -= e;
  157. a = a.slice(f);
  158. for (c %= e; a.length < n;) a.push(0);
  159. f = c >>> 3;
  160. a[f >> 2] ^= k << f % 4 * 8;
  161. a[n - 1] ^= 2147483648;
  162. for (b = D(a, b); 32 * g.length < h;) {
  163. a = b[l %
  164. 5][l / 5 | 0];
  165. g.push(a.b);
  166. if (32 * g.length >= h) break;
  167. g.push(a.a);
  168. l += 1;
  169. 0 === 64 * l % e && D(null, b);
  170. }
  171. return g;
  172. };
  173. } else throw Error('Chosen SHA variant is not supported');
  174. d = M(a, g, x);
  175. l = A(c);
  176. this.setHMACKey = function(a, b, h) {
  177. var k;
  178. if (!0 === I) throw Error('HMAC key already set');
  179. if (!0 === y) throw Error('Cannot set HMAC key after calling update');
  180. if (!0 === z) throw Error('SHAKE is not supported for HMAC');
  181. g = (h || {}).encoding || 'UTF8';
  182. b = M(b, g, x)(a);
  183. a = b.binLen;
  184. b = b.value;
  185. k = m >>> 3;
  186. h = k / 4 - 1;
  187. if (k < a / 8) {
  188. for (b = u(b, a, 0, A(c), f); b.length <= h;) b.push(0);
  189. b[h] &= 4294967040;
  190. } else if (k > a / 8) {
  191. for (; b.length <= h;) b.push(0);
  192. b[h] &= 4294967040;
  193. }
  194. for (a = 0; a <= h; a += 1) v[a] = b[a] ^ 909522486, w[a] = b[a] ^
  195. 1549556828;
  196. l = q(v, l);
  197. e = m;
  198. I = !0;
  199. };
  200. this.update = function(a) {
  201. var c, b, k, f = 0,
  202. g = m >>> 5;
  203. c = d(a, h, n);
  204. a = c.binLen;
  205. b = c.value;
  206. c = a >>> 5;
  207. for (k = 0; k < c; k += g) f + m <= a &&
  208. (l = q(b.slice(k, k + g), l), f += m);
  209. e += f;
  210. h = b.slice(f >>> 5);
  211. n = a % m;
  212. y = !0;
  213. };
  214. this.getHash = function(a, b) {
  215. var k, g, d, m;
  216. if (!0 === I) throw Error('Cannot call getHash after setting HMAC key');
  217. d = N(b);
  218. if (!0 === z) {
  219. if (-1 === d.shakeLen) throw Error(
  220. 'shakeLen must be specified in options');
  221. f = d.shakeLen;
  222. }
  223. switch (a) {
  224. case 'HEX':
  225. k = function(a) {
  226. return O(a, f, x, d);
  227. };
  228. break;
  229. case 'B64':
  230. k = function(a) {
  231. return P(a, f, x, d);
  232. };
  233. break;
  234. case 'BYTES':
  235. k = function(a) {
  236. return Q(a, f, x);
  237. };
  238. break;
  239. case 'ARRAYBUFFER':
  240. try {
  241. g = new ArrayBuffer(0);
  242. } catch (p) {
  243. throw Error('ARRAYBUFFER not supported by this environment');
  244. }
  245. k = function(a) {
  246. return R(a, f, x);
  247. };
  248. break;
  249. default:
  250. throw Error('format must be HEX, B64, BYTES, or ARRAYBUFFER');
  251. }
  252. m = u(h.slice(), n, e, r(l), f);
  253. for (g = 1; g < t; g += 1) !0 === z && 0 !== f % 32 &&
  254. (m[m.length - 1] &= 16777215 >>> 24 - f % 32), m = u(m, f,
  255. 0, A(c), f);
  256. return k(m);
  257. };
  258. this.getHMAC = function(a, b) {
  259. var k, g, d, p;
  260. if (!1 === I) throw Error(
  261. 'Cannot call getHMAC without first setting HMAC key');
  262. d = N(b);
  263. switch (a) {
  264. case 'HEX':
  265. k = function(a) {
  266. return O(a, f, x, d);
  267. };
  268. break;
  269. case 'B64':
  270. k = function(a) {
  271. return P(a, f, x, d);
  272. };
  273. break;
  274. case 'BYTES':
  275. k = function(a) {
  276. return Q(a, f, x);
  277. };
  278. break;
  279. case 'ARRAYBUFFER':
  280. try {
  281. k = new ArrayBuffer(0);
  282. } catch (v) {
  283. throw Error('ARRAYBUFFER not supported by this environment');
  284. }
  285. k = function(a) {
  286. return R(a, f, x);
  287. };
  288. break;
  289. default:
  290. throw Error('outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER');
  291. }
  292. g = u(h.slice(), n, e, r(l), f);
  293. p = q(w, A(c));
  294. p = u(g, f, m, p, f);
  295. return k(p);
  296. };
  297. }
  298.  
  299. function b(c, a) {
  300. this.a = c;
  301. this.b = a;
  302. }
  303.  
  304. function O(c, a, b, e) {
  305. var h = '';
  306. a /= 8;
  307. var n, g, d;
  308. d = -1 === b ? 3 : 0;
  309. for (n = 0; n < a; n += 1) g = c[n >>> 2] >>> 8 *
  310. (d + n % 4 * b), h += '0123456789abcdef'.charAt(g >>> 4 & 15) +
  311. '0123456789abcdef'.charAt(g & 15);
  312. return e.outputUpper ? h.toUpperCase() : h;
  313. }
  314.  
  315. function P(c, a, b, e) {
  316. var h = '',
  317. n = a / 8,
  318. g, d, p, f;
  319. f = -1 === b ? 3 : 0;
  320. for (g = 0; g < n; g += 3)
  321. for (d = g + 1 < n ? c[g + 1 >>> 2] : 0, p = g + 2 < n ?
  322. c[g + 2 >>> 2] :
  323. 0, p = (c[g >>> 2] >>> 8 * (f + g % 4 * b) & 255) << 16 |
  324. (d >>> 8 * (f + (g + 1) % 4 * b) & 255) << 8 | p >>> 8 * (f +
  325. (g + 2) % 4 * b) & 255, d = 0; 4 > d; d += 1) 8 * g + 6 * d <= a ?
  326. h += 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(
  327. p >>> 6 * (3 - d) & 63) :
  328. h += e.b64Pad;
  329. return h;
  330. }
  331.  
  332. function Q(c, a, b) {
  333. var e = '';
  334. a /= 8;
  335. var h, d, g;
  336. g = -1 === b ? 3 : 0;
  337. for (h = 0; h < a; h += 1) d = c[h >>> 2] >>> 8 * (g + h % 4 * b) &
  338. 255, e += String.fromCharCode(d);
  339. return e;
  340. }
  341.  
  342. function R(c, a, b) {
  343. a /= 8;
  344. var e, h = new ArrayBuffer(a),
  345. d, g;
  346. g = new Uint8Array(h);
  347. d = -1 === b ? 3 : 0;
  348. for (e = 0; e < a; e += 1) g[e] = c[e >>> 2] >>> 8 * (d + e % 4 * b) & 255;
  349. return h;
  350. }
  351.  
  352. function N(c) {
  353. var a = {
  354. outputUpper: !1,
  355. b64Pad: '=',
  356. shakeLen: -1,
  357. };
  358. c = c || {};
  359. a.outputUpper = c.outputUpper || !1;
  360. !0 === c.hasOwnProperty('b64Pad') && (a.b64Pad = c.b64Pad);
  361. if (!0 === c.hasOwnProperty('shakeLen')) {
  362. if (0 !== c.shakeLen % 8) throw Error('shakeLen must be a multiple of 8');
  363. a.shakeLen = c.shakeLen;
  364. }
  365. if ('boolean' !== typeof a.outputUpper) throw Error(
  366. 'Invalid outputUpper formatting option');
  367. if ('string' !== typeof a.b64Pad) throw Error(
  368. 'Invalid b64Pad formatting option');
  369. return a;
  370. }
  371.  
  372. function M(c, a, b) {
  373. switch (a) {
  374. case 'UTF8':
  375. case 'UTF16BE':
  376. case 'UTF16LE':
  377. break;
  378. default:
  379. throw Error('encoding must be UTF8, UTF16BE, or UTF16LE');
  380. }
  381. switch (c) {
  382. case 'HEX':
  383. c = function(a, c, d) {
  384. var g = a.length,
  385. l, p, f, m, q, u;
  386. if (0 !== g % 2) throw Error(
  387. 'String of HEX type must be in byte increments');
  388. c = c || [0];
  389. d = d || 0;
  390. q = d >>> 3;
  391. u = -1 === b ? 3 : 0;
  392. for (l = 0; l < g; l += 2) {
  393. p = parseInt(a.substr(l, 2), 16);
  394. if (isNaN(p)) throw Error(
  395. 'String of HEX type contains invalid characters');
  396. m = (l >>> 1) + q;
  397. for (f = m >>> 2; c.length <= f;) c.push(0);
  398. c[f] |= p << 8 * (u + m % 4 * b);
  399. }
  400. return {
  401. value: c,
  402. binLen: 4 * g + d,
  403. };
  404. };
  405. break;
  406. case 'TEXT':
  407. c = function(c, h, d) {
  408. var g, l, p = 0,
  409. f, m, q, u, r, t;
  410. h = h || [0];
  411. d = d || 0;
  412. q = d >>> 3;
  413. if ('UTF8' === a)
  414. for (t = -1 ===
  415. b ? 3 : 0, f = 0; f < c.length; f += 1)
  416. for (g = c.charCodeAt(f), l = [], 128 > g ?
  417. l.push(g) :
  418. 2048 > g ?
  419. (l.push(192 | g >>> 6), l.push(128 | g & 63)) :
  420. 55296 > g || 57344 <= g ?
  421. l.push(224 | g >>> 12, 128 | g >>> 6 & 63,
  422. 128 | g & 63) :
  423. (f += 1, g = 65536 +
  424. ((g & 1023) << 10 | c.charCodeAt(f) &
  425. 1023), l.push(240 | g >>> 18,
  426. 128 | g >>> 12 & 63, 128 | g >>> 6 & 63,
  427. 128 | g & 63)), m = 0; m < l.length; m += 1) {
  428. r = p + q;
  429. for (u = r >>> 2; h.length <= u;) h.push(0);
  430. h[u] |= l[m] << 8 * (t + r % 4 * b);
  431. p += 1;
  432. } else if ('UTF16BE' === a || 'UTF16LE' === a)
  433. for (t = -1 === b ? 2 : 0, l = 'UTF16LE' === a && 1 !== b ||
  434. 'UTF16LE' !== a && 1 === b, f = 0; f < c.length; f += 1) {
  435. g = c.charCodeAt(f);
  436. !0 === l && (m = g & 255, g = m << 8 | g >>> 8);
  437. r = p + q;
  438. for (u = r >>> 2; h.length <= u;) h.push(0);
  439. h[u] |= g << 8 * (t + r % 4 * b);
  440. p += 2;
  441. }
  442. return {
  443. value: h,
  444. binLen: 8 * p + d,
  445. };
  446. };
  447. break;
  448. case 'B64':
  449. c = function(a, c, d) {
  450. var g = 0,
  451. l, p, f, m, q, u, r, t;
  452. if (-1 === a.search(/^[a-zA-Z0-9=+\/]+$/)) throw Error(
  453. 'Invalid character in base-64 string');
  454. p = a.indexOf('=');
  455. a = a.replace(/\=/g, '');
  456. if (-1 !== p && p < a.length) throw Error(
  457. 'Invalid \'=\' found in base-64 string');
  458. c = c || [0];
  459. d = d || 0;
  460. u = d >>> 3;
  461. t = -1 === b ? 3 : 0;
  462. for (p = 0; p < a.length; p += 4) {
  463. q = a.substr(p, 4);
  464. for (f = m = 0; f <
  465. q.length; f += 1) l = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.indexOf(
  466. q[f]),
  467. m |= l << 18 - 6 * f;
  468. for (f = 0; f < q.length - 1; f += 1) {
  469. r = g + u;
  470. for (l = r >>> 2; c.length <= l;) c.push(0);
  471. c[l] |= (m >>> 16 - 8 * f & 255) << 8 * (t + r % 4 * b);
  472. g += 1;
  473. }
  474. }
  475. return {
  476. value: c,
  477. binLen: 8 * g + d,
  478. };
  479. };
  480. break;
  481. case 'BYTES':
  482. c = function(a, c, d) {
  483. var g, l, p, f, m, q;
  484. c = c || [0];
  485. d = d || 0;
  486. p = d >>> 3;
  487. q = -1 === b ? 3 : 0;
  488. for (l = 0; l < a.length; l += 1) g = a.charCodeAt(l), m = l +
  489. p, f = m >>> 2, c.length <= f && c.push(0), c[f] |= g << 8 *
  490. (q + m % 4 * b);
  491. return {
  492. value: c,
  493. binLen: 8 * a.length + d,
  494. };
  495. };
  496. break;
  497. case 'ARRAYBUFFER':
  498. try {
  499. c = new ArrayBuffer(0);
  500. } catch (e) {
  501. throw Error('ARRAYBUFFER not supported by this environment');
  502. }
  503. c =
  504. function(a, c, d) {
  505. var g, l, p, f, m, q;
  506. c = c || [0];
  507. d = d || 0;
  508. l = d >>> 3;
  509. m = -1 === b ? 3 : 0;
  510. q = new Uint8Array(a);
  511. for (g = 0; g < a.byteLength; g += 1) f = g + l, p = f >>>
  512. 2, c.length <= p && c.push(0), c[p] |= q[g] << 8 *
  513. (m + f % 4 * b);
  514. return {
  515. value: c,
  516. binLen: 8 * a.byteLength + d,
  517. };
  518. };
  519. break;
  520. default:
  521. throw Error('format must be HEX, TEXT, B64, BYTES, or ARRAYBUFFER');
  522. }
  523. return c;
  524. }
  525.  
  526. function y(c, a) {
  527. return c << a | c >>> 32 - a;
  528. }
  529.  
  530. function S(c, a) {
  531. return 32 < a ?
  532. (a -= 32, new b(c.b << a | c.a >>> 32 - a, c.a << a | c.b >>> 32 - a)) :
  533. 0 !== a ?
  534. new b(c.a << a | c.b >>> 32 - a, c.b << a | c.a >>> 32 - a) :
  535. c;
  536. }
  537.  
  538. function w(c, a) {
  539. return c >>>
  540. a | c << 32 - a;
  541. }
  542.  
  543. function t(c, a) {
  544. var k = null,
  545. k = new b(c.a, c.b);
  546. return k = 32 >= a ?
  547. new b(k.a >>> a | k.b << 32 - a & 4294967295,
  548. k.b >>> a | k.a << 32 - a & 4294967295) :
  549. new b(k.b >>> a - 32 | k.a << 64 - a & 4294967295,
  550. k.a >>> a - 32 | k.b << 64 - a & 4294967295);
  551. }
  552.  
  553. function T(c, a) {
  554. var k = null;
  555. return k = 32 >= a ?
  556. new b(c.a >>> a, c.b >>> a | c.a << 32 - a & 4294967295) :
  557. new b(0, c.a >>> a - 32);
  558. }
  559.  
  560. function aa(c, a, b) {
  561. return c & a ^ ~c & b;
  562. }
  563.  
  564. function ba(c, a, k) {
  565. return new b(c.a & a.a ^ ~c.a & k.a, c.b & a.b ^ ~c.b & k.b);
  566. }
  567.  
  568. function U(c, a, b) {
  569. return c & a ^ c & b ^ a & b;
  570. }
  571.  
  572. function ca(c, a, k) {
  573. return new b(c.a & a.a ^ c.a & k.a ^ a.a &
  574. k.a, c.b & a.b ^ c.b & k.b ^ a.b & k.b);
  575. }
  576.  
  577. function da(c) {
  578. return w(c, 2) ^ w(c, 13) ^ w(c, 22);
  579. }
  580.  
  581. function ea(c) {
  582. var a = t(c, 28),
  583. k = t(c, 34);
  584. c = t(c, 39);
  585. return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b);
  586. }
  587.  
  588. function fa(c) {
  589. return w(c, 6) ^ w(c, 11) ^ w(c, 25);
  590. }
  591.  
  592. function ga(c) {
  593. var a = t(c, 14),
  594. k = t(c, 18);
  595. c = t(c, 41);
  596. return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b);
  597. }
  598.  
  599. function ha(c) {
  600. return w(c, 7) ^ w(c, 18) ^ c >>> 3;
  601. }
  602.  
  603. function ia(c) {
  604. var a = t(c, 1),
  605. k = t(c, 8);
  606. c = T(c, 7);
  607. return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b);
  608. }
  609.  
  610. function ja(c) {
  611. return w(c, 17) ^ w(c, 19) ^ c >>> 10;
  612. }
  613.  
  614. function ka(c) {
  615. var a = t(c, 19),
  616. k = t(c, 61);
  617. c = T(c, 6);
  618. return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b);
  619. }
  620.  
  621. function G(c, a) {
  622. var b = (c & 65535) + (a & 65535);
  623. return ((c >>> 16) + (a >>> 16) + (b >>> 16) & 65535) << 16 | b & 65535;
  624. }
  625.  
  626. function la(c, a, b, e) {
  627. var h = (c & 65535) + (a & 65535) + (b & 65535) + (e & 65535);
  628. return ((c >>> 16) + (a >>> 16) + (b >>> 16) + (e >>> 16) + (h >>> 16) &
  629. 65535) << 16 | h & 65535;
  630. }
  631.  
  632. function H(c, a, b, e, h) {
  633. var d = (c & 65535) + (a & 65535) + (b & 65535) + (e & 65535) + (h & 65535);
  634. return ((c >>> 16) + (a >>> 16) + (b >>> 16) + (e >>> 16) + (h >>> 16) +
  635. (d >>> 16) & 65535) << 16 | d & 65535;
  636. }
  637.  
  638. function ma(c, a) {
  639. var d, e, h;
  640. d = (c.b & 65535) + (a.b & 65535);
  641. e = (c.b >>> 16) +
  642. (a.b >>> 16) + (d >>> 16);
  643. h = (e & 65535) << 16 | d & 65535;
  644. d = (c.a & 65535) + (a.a & 65535) + (e >>> 16);
  645. e = (c.a >>> 16) + (a.a >>> 16) + (d >>> 16);
  646. return new b((e & 65535) << 16 | d & 65535, h);
  647. }
  648.  
  649. function na(c, a, d, e) {
  650. var h, n, g;
  651. h = (c.b & 65535) + (a.b & 65535) + (d.b & 65535) + (e.b & 65535);
  652. n = (c.b >>> 16) + (a.b >>> 16) + (d.b >>> 16) + (e.b >>> 16) + (h >>> 16);
  653. g = (n & 65535) << 16 | h & 65535;
  654. h = (c.a & 65535) + (a.a & 65535) + (d.a & 65535) + (e.a & 65535) +
  655. (n >>> 16);
  656. n = (c.a >>> 16) + (a.a >>> 16) + (d.a >>> 16) + (e.a >>> 16) + (h >>> 16);
  657. return new b((n & 65535) << 16 | h & 65535, g);
  658. }
  659.  
  660. function oa(c, a, d, e, h) {
  661. var n, g, l;
  662. n = (c.b &
  663. 65535) + (a.b & 65535) + (d.b & 65535) + (e.b & 65535) + (h.b & 65535);
  664. g = (c.b >>> 16) + (a.b >>> 16) + (d.b >>> 16) + (e.b >>> 16) +
  665. (h.b >>> 16) + (n >>> 16);
  666. l = (g & 65535) << 16 | n & 65535;
  667. n = (c.a & 65535) + (a.a & 65535) + (d.a & 65535) + (e.a & 65535) +
  668. (h.a & 65535) + (g >>> 16);
  669. g = (c.a >>> 16) + (a.a >>> 16) + (d.a >>> 16) + (e.a >>> 16) +
  670. (h.a >>> 16) + (n >>> 16);
  671. return new b((g & 65535) << 16 | n & 65535, l);
  672. }
  673.  
  674. function B(c, a) {
  675. return new b(c.a ^ a.a, c.b ^ a.b);
  676. }
  677.  
  678. function A(c) {
  679. var a = [],
  680. d;
  681. if ('SHA-1' === c) a = [
  682. 1732584193,
  683. 4023233417,
  684. 2562383102,
  685. 271733878,
  686. 3285377520];
  687. else if (0 === c.lastIndexOf('SHA-', 0)) switch (a = [
  688. 3238371032,
  689. 914150663,
  690. 812702999,
  691. 4144912697,
  692. 4290775857,
  693. 1750603025,
  694. 1694076839,
  695. 3204075428], d = [
  696. 1779033703,
  697. 3144134277,
  698. 1013904242,
  699. 2773480762,
  700. 1359893119,
  701. 2600822924,
  702. 528734635,
  703. 1541459225], c) {
  704. case 'SHA-224':
  705. break;
  706. case 'SHA-256':
  707. a = d;
  708. break;
  709. case 'SHA-384':
  710. a = [
  711. new b(3418070365, a[0]),
  712. new b(1654270250, a[1]),
  713. new b(2438529370, a[2]),
  714. new b(355462360, a[3]),
  715. new b(1731405415, a[4]),
  716. new b(41048885895, a[5]),
  717. new b(3675008525, a[6]),
  718. new b(1203062813, a[7])];
  719. break;
  720. case 'SHA-512':
  721. a = [
  722. new b(d[0], 4089235720),
  723. new b(d[1], 2227873595),
  724. new b(d[2], 4271175723),
  725. new b(d[3], 1595750129),
  726. new b(d[4], 2917565137),
  727. new b(d[5], 725511199),
  728. new b(d[6], 4215389547),
  729. new b(d[7], 327033209),
  730. ];
  731. break;
  732. default:
  733. throw Error('Unknown SHA variant');
  734. } else if (0 === c.lastIndexOf('SHA3-', 0) || 0 ===
  735. c.lastIndexOf('SHAKE', 0))
  736. for (c = 0; 5 > c; c += 1) a[c] = [
  737. new b(0, 0),
  738. new b(0, 0),
  739. new b(0, 0),
  740. new b(0, 0),
  741. new b(0, 0)];
  742. else throw Error('No SHA variants supported');
  743. return a;
  744. }
  745.  
  746. function K(c, a) {
  747. var b = [],
  748. e, d, n, g, l, p, f;
  749. e = a[0];
  750. d = a[1];
  751. n = a[2];
  752. g = a[3];
  753. l = a[4];
  754. for (f = 0; 80 > f; f += 1) b[f] = 16 > f ? c[f] : y(b[f -
  755. 3] ^ b[f - 8] ^ b[f - 14] ^ b[f - 16], 1), p = 20 > f ?
  756. H(y(e, 5), d & n ^ ~d & g, l, 1518500249, b[f]) :
  757. 40 > f ?
  758. H(y(e, 5), d ^ n ^ g, l, 1859775393, b[f]) :
  759. 60 > f ?
  760. H(y(e, 5), U(d, n, g), l, 2400959708, b[f]) :
  761. H(y(e, 5), d ^ n ^ g, l, 3395469782, b[f]), l = g, g = n, n = y(
  762. d, 30), d = e, e = p;
  763. a[0] = G(e, a[0]);
  764. a[1] = G(d, a[1]);
  765. a[2] = G(n, a[2]);
  766. a[3] = G(g, a[3]);
  767. a[4] = G(l, a[4]);
  768. return a;
  769. }
  770.  
  771. function Z(c, a, b, e) {
  772. var d;
  773. for (d = (a + 65 >>> 9 << 4) + 15; c.length <= d;) c.push(0);
  774. c[a >>> 5] |= 128 << 24 - a % 32;
  775. a += b;
  776. c[d] = a & 4294967295;
  777. c[d - 1] = a / 4294967296 | 0;
  778. a = c.length;
  779. for (d = 0; d < a; d += 16) e = K(c.slice(d, d + 16), e);
  780. return e;
  781. }
  782.  
  783. function L(c,
  784. a, k) {
  785. var e, h, n, g, l, p, f, m, q, u, r, t, v, w, y, A, z, x, F, B, C, D,
  786. E = [],
  787. J;
  788. if ('SHA-224' === k || 'SHA-256' ===
  789. k) u = 64, t = 1, D = Number, v = G, w = la, y = H, A = ha, z = ja, x = da, F = fa, C = U, B = aa, J = d;
  790. else if ('SHA-384' === k || 'SHA-512' ===
  791. k) u = 80, t = 2, D = b, v = ma, w = na, y = oa, A = ia, z = ka, x = ea, F = ga, C = ca, B = ba, J = V;
  792. else throw Error('Unexpected error in SHA-2 implementation');
  793. k = a[0];
  794. e = a[1];
  795. h = a[2];
  796. n = a[3];
  797. g = a[4];
  798. l = a[5];
  799. p = a[6];
  800. f = a[7];
  801. for (r = 0; r < u; r += 1) 16 > r ?
  802. (q = r * t, m = c.length <= q ? 0 : c[q], q = c.length <= q + 1 ?
  803. 0 :
  804. c[q + 1], E[r] = new D(m, q)) :
  805. E[r] = w(z(E[r - 2]), E[r - 7], A(E[r - 15]), E[r -
  806. 16]), m = y(f, F(g), B(g, l, p), J[r], E[r]), q = v(x(k),
  807. C(k, e, h)), f = p, p = l, l = g, g = v(n,
  808. m), n = h, h = e, e = k, k = v(m, q);
  809. a[0] = v(k, a[0]);
  810. a[1] = v(e, a[1]);
  811. a[2] = v(h, a[2]);
  812. a[3] = v(n, a[3]);
  813. a[4] = v(g, a[4]);
  814. a[5] = v(l, a[5]);
  815. a[6] = v(p, a[6]);
  816. a[7] = v(f, a[7]);
  817. return a;
  818. }
  819.  
  820. function D(c, a) {
  821. var d, e, h, n, g = [],
  822. l = [];
  823. if (null !== c)
  824. for (e = 0; e < c.length; e += 2) a[(e >>> 1) % 5][(e >>> 1) / 5 | 0] = B(
  825. a[(e >>> 1) % 5][(e >>> 1) / 5 | 0], new b(c[e + 1], c[e]));
  826. for (d = 0; 24 > d; d += 1) {
  827. n = A('SHA3-');
  828. for (e = 0; 5 > e; e += 1) {
  829. h = a[e][0];
  830. var p = a[e][1],
  831. f = a[e][2],
  832. m = a[e][3],
  833. q = a[e][4];
  834. g[e] = new b(h.a ^ p.a ^ f.a ^
  835. m.a ^ q.a, h.b ^ p.b ^ f.b ^ m.b ^ q.b);
  836. }
  837. for (e = 0; 5 > e; e += 1) l[e] = B(g[(e + 4) % 5], S(g[(e + 1) % 5], 1));
  838. for (e = 0; 5 > e; e += 1)
  839. for (h = 0; 5 > h; h += 1) a[e][h] = B(a[e][h], l[e]);
  840. for (e = 0; 5 > e; e += 1)
  841. for (h = 0; 5 > h; h += 1) n[h][(2 * e + 3 * h) % 5] = S(a[e][h],
  842. W[e][h]);
  843. for (e = 0; 5 > e; e += 1)
  844. for (h = 0; 5 > h; h += 1) a[e][h] = B(n[e][h],
  845. new b(~n[(e + 1) % 5][h].a & n[(e + 2) % 5][h].a,
  846. ~n[(e + 1) % 5][h].b & n[(e + 2) % 5][h].b));
  847. a[0][0] = B(a[0][0], X[d]);
  848. }
  849. return a;
  850. }
  851.  
  852. var d, V, W, X;
  853. d = [
  854. 1116352408,
  855. 1899447441,
  856. 3049323471,
  857. 3921009573,
  858. 961987163,
  859. 1508970993,
  860. 2453635748,
  861. 2870763221,
  862. 3624381080,
  863. 310598401,
  864. 607225278,
  865. 1426881987,
  866. 1925078388,
  867. 2162078206,
  868. 2614888103,
  869. 3248222580,
  870. 3835390401,
  871. 4022224774,
  872. 264347078,
  873. 604807628,
  874. 770255983,
  875. 1249150122,
  876. 1555081692,
  877. 1996064986,
  878. 2554220882,
  879. 2821834349,
  880. 2952996808,
  881. 3210313671,
  882. 3336571891,
  883. 3584528711,
  884. 113926993,
  885. 338241895,
  886. 666307205,
  887. 773529912,
  888. 1294757372,
  889. 1396182291,
  890. 1695183700,
  891. 1986661051,
  892. 2177026350,
  893. 2456956037,
  894. 2730485921,
  895. 2820302411,
  896. 3259730800,
  897. 3345764771,
  898. 3516065817,
  899. 3600352804,
  900. 4094571909,
  901. 275423344,
  902. 430227734,
  903. 506948616,
  904. 659060556,
  905. 883997877,
  906. 958139571,
  907. 1322822218,
  908. 1537002063,
  909. 1747873779,
  910. 1955562222,
  911. 2024104815,
  912. 2227730452,
  913. 2361852424,
  914. 2428436474,
  915. 2756734187,
  916. 3204031479,
  917. 3329325298,
  918. ];
  919. V = [
  920. new b(d[0], 3609767458),
  921. new b(d[1], 602891725),
  922. new b(d[2], 3964484399),
  923. new b(d[3], 2173295548),
  924. new b(d[4], 4081628472),
  925. new b(d[5], 3053834265),
  926. new b(d[6], 2937671579),
  927. new b(d[7], 3664609560),
  928. new b(d[8], 2734883394),
  929. new b(d[9], 1164996542),
  930. new b(d[10], 1323610764),
  931. new b(d[11], 3590304994),
  932. new b(d[12], 4068182383),
  933. new b(d[13], 991336113),
  934. new b(d[14], 633803317),
  935. new b(d[15], 3479774868),
  936. new b(d[16], 2666613458),
  937. new b(d[17], 944711139),
  938. new b(d[18], 2341262773),
  939. new b(d[19], 2007800933),
  940. new b(d[20], 1495990901),
  941. new b(d[21], 1856431235),
  942. new b(d[22], 3175218132),
  943. new b(d[23], 2198950837),
  944. new b(d[24], 3999719339),
  945. new b(d[25], 766784016),
  946. new b(d[26], 2566594879),
  947. new b(d[27], 3203337956),
  948. new b(d[28], 1034457026),
  949. new b(d[29], 2466948901),
  950. new b(d[30], 3758326383),
  951. new b(d[31], 168717936),
  952. new b(d[32], 1188179964),
  953. new b(d[33], 1546045734),
  954. new b(d[34], 1522805485),
  955. new b(d[35], 2643833823),
  956. new b(d[36], 2343527390),
  957. new b(d[37], 1014477480),
  958. new b(d[38], 1206759142),
  959. new b(d[39], 344077627),
  960. new b(d[40], 1290863460),
  961. new b(d[41], 3158454273),
  962. new b(d[42], 3505952657),
  963. new b(d[43], 106217008),
  964. new b(d[44], 3606008344),
  965. new b(d[45], 1432725776),
  966. new b(d[46], 1467031594),
  967. new b(d[47], 851169720),
  968. new b(d[48], 3100823752),
  969. new b(d[49], 1363258195),
  970. new b(d[50], 3750685593),
  971. new b(d[51], 3785050280),
  972. new b(d[52], 3318307427),
  973. new b(d[53], 3812723403),
  974. new b(d[54], 2003034995),
  975. new b(d[55], 3602036899),
  976. new b(d[56], 1575990012),
  977. new b(d[57], 1125592928),
  978. new b(d[58], 2716904306),
  979. new b(d[59], 442776044),
  980. new b(d[60], 593698344),
  981. new b(d[61],
  982. 3733110249),
  983. new b(d[62], 2999351573),
  984. new b(d[63], 3815920427),
  985. new b(3391569614, 3928383900),
  986. new b(3515267271, 566280711),
  987. new b(3940187606, 3454069534),
  988. new b(4118630271, 4000239992),
  989. new b(116418474, 1914138554),
  990. new b(174292421, 2731055270),
  991. new b(289380356, 3203993006),
  992. new b(460393269, 320620315),
  993. new b(685471733, 587496836),
  994. new b(852142971, 1086792851),
  995. new b(1017036298, 365543100),
  996. new b(1126000580, 2618297676),
  997. new b(1288033470, 3409855158),
  998. new b(1501505948, 4234509866),
  999. new b(1607167915, 987167468),
  1000. new b(1816402316,
  1001. 1246189591),
  1002. ];
  1003. X = [
  1004. new b(0, 1),
  1005. new b(0, 32898),
  1006. new b(2147483648, 32906),
  1007. new b(2147483648, 2147516416),
  1008. new b(0, 32907),
  1009. new b(0, 2147483649),
  1010. new b(2147483648, 2147516545),
  1011. new b(2147483648, 32777),
  1012. new b(0, 138),
  1013. new b(0, 136),
  1014. new b(0, 2147516425),
  1015. new b(0, 2147483658),
  1016. new b(0, 2147516555),
  1017. new b(2147483648, 139),
  1018. new b(2147483648, 32905),
  1019. new b(2147483648, 32771),
  1020. new b(2147483648, 32770),
  1021. new b(2147483648, 128),
  1022. new b(0, 32778),
  1023. new b(2147483648, 2147483658),
  1024. new b(2147483648, 2147516545),
  1025. new b(2147483648, 32896),
  1026. new b(0, 2147483649),
  1027. new b(2147483648, 2147516424),
  1028. ];
  1029. W = [
  1030. [0, 36, 3, 41, 18],
  1031. [1, 44, 10, 45, 2],
  1032. [62, 6, 43, 15, 61],
  1033. [28, 55, 25, 21, 56],
  1034. [27, 20, 39, 8, 14],
  1035. ];
  1036. 'function' === typeof define && define.amd ?
  1037. define(function() {
  1038. return C;
  1039. }) :
  1040. 'undefined' !== typeof exports ?
  1041. ('undefined' !== typeof module && module.exports &&
  1042. (module.exports = C), exports = C) :
  1043. Y.jsSHA = C;
  1044. })(this);
  1045.  
  1046. var CreateDownloadTask, CreateDownloadTask_, browserInterface, bytesToString,
  1047. cloneInto, g_key_l, g_key_s, g_kts, m115_asym_decode, m115_asym_encode,
  1048. m115_decode, m115_encode, m115_getkey, m115_sym_decode, m115_sym_encode,
  1049. ref, stringToBytes, xor115_enc;
  1050.  
  1051. class MyRsa {
  1052. constructor() {
  1053. // this.n = BigInt('0x8686980c0f5a24c4b9d43020cd2c22703ff3f450756529058b1cf88f09b8602136477198a6e2683149659bd122c33592fdb5ad47944ad1ea4d36c6b172aad6338c3bb6ac6227502d010993ac967d1aef00f0c8e038de2e4d3bc2ec368af2e9f10a6f1eda4f7262f136420c07c331b871bf139f74f3010e3c4fe57df3afb71683')
  1054. // this.e = BigInt('0x10001')
  1055. this.n = bigInt(
  1056. '8686980c0f5a24c4b9d43020cd2c22703ff3f450756529058b1cf88f09b8602136477198a6e2683149659bd122c33592fdb5ad47944ad1ea4d36c6b172aad6338c3bb6ac6227502d010993ac967d1aef00f0c8e038de2e4d3bc2ec368af2e9f10a6f1eda4f7262f136420c07c331b871bf139f74f3010e3c4fe57df3afb71683',
  1057. 16);
  1058. this.e = bigInt('10001', 16);
  1059. };
  1060.  
  1061. a2hex(byteArray) {
  1062. var hexString = '';
  1063. var nextHexByte;
  1064. for (var i = 0; i < byteArray.length; i++) {
  1065. nextHexByte = byteArray[i].toString(16);
  1066. if (nextHexByte.length < 2) {
  1067. nextHexByte = '0' + nextHexByte;
  1068. }
  1069. hexString += nextHexByte;
  1070. }
  1071. return hexString;
  1072. }
  1073.  
  1074. hex2a(hex) {
  1075. var str = '';
  1076. for (var i = 0; i < hex.length; i += 2) {
  1077. str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
  1078. }
  1079. return str;
  1080. }
  1081.  
  1082. pkcs1pad2(s, n) {
  1083. if (n < s.length + 11) {
  1084. return null;
  1085. }
  1086. var ba = [];
  1087. var i = s.length - 1;
  1088. while (i >= 0 && n > 0) {
  1089. ba[--n] = s.charCodeAt(i--);
  1090. }
  1091. ba[--n] = 0;
  1092. while (n > 2) { // random non-zero pad
  1093. ba[--n] = 0xff;
  1094. }
  1095. ba[--n] = 2;
  1096. ba[--n] = 0;
  1097. var c = this.a2hex(ba);
  1098. return bigInt(c, 16);
  1099. }
  1100.  
  1101. pkcs1unpad2(a) {
  1102. var b = a.toString(16);
  1103. if (b.length % 2 !== 0) {
  1104. b = '0' + b;
  1105. }
  1106. var c = this.hex2a(b);
  1107. var i = 1;
  1108. while (c.charCodeAt(i) !== 0) {
  1109. i++;
  1110. }
  1111. return c.slice(i + 1);
  1112. }
  1113.  
  1114. encrypt(text) {
  1115. var m = this.pkcs1pad2(text, 0x80);
  1116. var c = m.modPow(this.e, this.n);
  1117. var h = c.toString(16);
  1118. while (h.length < 0x80 * 2) {
  1119. h = '0' + h;
  1120. }
  1121. return h;
  1122. };
  1123.  
  1124. decrypt(text) {
  1125. var ba = [];
  1126. var i = 0;
  1127. while (i < text.length) {
  1128. ba[i] = text.charCodeAt(i);
  1129. i += 1;
  1130. }
  1131. var a = bigInt(this.a2hex(ba), 16);
  1132. var c = a.modPow(this.e, this.n);
  1133. var d = this.pkcs1unpad2(c);
  1134. return d;
  1135. };
  1136. }
  1137.  
  1138. var new_rsa = new MyRsa();
  1139.  
  1140. g_kts = [
  1141. 240,
  1142. 229,
  1143. 105,
  1144. 174,
  1145. 191,
  1146. 220,
  1147. 191,
  1148. 138,
  1149. 26,
  1150. 69,
  1151. 232,
  1152. 190,
  1153. 125,
  1154. 166,
  1155. 115,
  1156. 184,
  1157. 222,
  1158. 143,
  1159. 231,
  1160. 196,
  1161. 69,
  1162. 218,
  1163. 134,
  1164. 196,
  1165. 155,
  1166. 100,
  1167. 139,
  1168. 20,
  1169. 106,
  1170. 180,
  1171. 241,
  1172. 170,
  1173. 56,
  1174. 1,
  1175. 53,
  1176. 158,
  1177. 38,
  1178. 105,
  1179. 44,
  1180. 134,
  1181. 0,
  1182. 107,
  1183. 79,
  1184. 165,
  1185. 54,
  1186. 52,
  1187. 98,
  1188. 166,
  1189. 42,
  1190. 150,
  1191. 104,
  1192. 24,
  1193. 242,
  1194. 74,
  1195. 253,
  1196. 189,
  1197. 107,
  1198. 151,
  1199. 143,
  1200. 77,
  1201. 143,
  1202. 137,
  1203. 19,
  1204. 183,
  1205. 108,
  1206. 142,
  1207. 147,
  1208. 237,
  1209. 14,
  1210. 13,
  1211. 72,
  1212. 62,
  1213. 215,
  1214. 47,
  1215. 136,
  1216. 216,
  1217. 254,
  1218. 254,
  1219. 126,
  1220. 134,
  1221. 80,
  1222. 149,
  1223. 79,
  1224. 209,
  1225. 235,
  1226. 131,
  1227. 38,
  1228. 52,
  1229. 219,
  1230. 102,
  1231. 123,
  1232. 156,
  1233. 126,
  1234. 157,
  1235. 122,
  1236. 129,
  1237. 50,
  1238. 234,
  1239. 182,
  1240. 51,
  1241. 222,
  1242. 58,
  1243. 169,
  1244. 89,
  1245. 52,
  1246. 102,
  1247. 59,
  1248. 170,
  1249. 186,
  1250. 129,
  1251. 96,
  1252. 72,
  1253. 185,
  1254. 213,
  1255. 129,
  1256. 156,
  1257. 248,
  1258. 108,
  1259. 132,
  1260. 119,
  1261. 255,
  1262. 84,
  1263. 120,
  1264. 38,
  1265. 95,
  1266. 190,
  1267. 232,
  1268. 30,
  1269. 54,
  1270. 159,
  1271. 52,
  1272. 128,
  1273. 92,
  1274. 69,
  1275. 44,
  1276. 155,
  1277. 118,
  1278. 213,
  1279. 27,
  1280. 143,
  1281. 204,
  1282. 195,
  1283. 184,
  1284. 245];
  1285.  
  1286. g_key_s = [0x29, 0x23, 0x21, 0x5E];
  1287.  
  1288. g_key_l = [120, 6, 173, 76, 51, 134, 93, 24, 76, 1, 63, 70];
  1289.  
  1290. m115_getkey = function(length, key) {
  1291. var i;
  1292. if (key != null) {
  1293. return (function() {
  1294. var j, ref, results;
  1295. results = [];
  1296. for (i = j = 0, ref = length; (0 <= ref ? j < ref : j > ref); i = 0 <=
  1297. ref ? ++j : --j) {
  1298. results.push(((key[i] + g_kts[length * i]) & 0xff) ^
  1299. g_kts[length * (length - 1 - i)]);
  1300. }
  1301. return results;
  1302. })();
  1303. }
  1304. if (length === 12) {
  1305. return g_key_l.slice(0);
  1306. }
  1307. return g_key_s.slice(0);
  1308. };
  1309.  
  1310. xor115_enc = function(src, srclen, key, keylen) {
  1311. var i, j, k, mod4, ref, ref1, ref2, ret;
  1312. mod4 = srclen % 4;
  1313. ret = [];
  1314. if (mod4 !== 0) {
  1315. for (i = j = 0, ref = mod4; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ?
  1316. ++j :
  1317. --j) {
  1318. ret.push(src[i] ^ key[i % keylen]);
  1319. }
  1320. }
  1321. for (i = k = ref1 = mod4, ref2 = srclen; (ref1 <= ref2 ?
  1322. k < ref2 :
  1323. k > ref2); i = ref1 <= ref2 ? ++k : --k) {
  1324. ret.push(src[i] ^ key[(i - mod4) % keylen]);
  1325. }
  1326. return ret;
  1327. };
  1328.  
  1329. m115_sym_encode = function(src, srclen, key1, key2) {
  1330. var k1, k2, ret;
  1331. k1 = m115_getkey(4, key1);
  1332. k2 = m115_getkey(12, key2);
  1333. ret = xor115_enc(src, srclen, k1, 4);
  1334. ret.reverse();
  1335. ret = xor115_enc(ret, srclen, k2, 12);
  1336. return ret;
  1337. };
  1338.  
  1339. m115_sym_decode = function(src, srclen, key1, key2) {
  1340. var k1, k2, ret;
  1341. k1 = m115_getkey(4, key1);
  1342. k2 = m115_getkey(12, key2);
  1343. ret = xor115_enc(src, srclen, k2, 12);
  1344. ret.reverse();
  1345. ret = xor115_enc(ret, srclen, k1, 4);
  1346. return ret;
  1347. };
  1348.  
  1349. stringToBytes = function(s) {
  1350. var i, j, ref, ret;
  1351. ret = [];
  1352. for (i = j = 0, ref = s.length; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ?
  1353. ++j :
  1354. --j) {
  1355. ret.push(s.charCodeAt(i));
  1356. }
  1357. return ret;
  1358. };
  1359.  
  1360. bytesToString = function(b) {
  1361. var i, j, len, ret;
  1362. ret = '';
  1363. for (j = 0, len = b.length; j < len; j++) {
  1364. i = b[j];
  1365. ret += String.fromCharCode(i);
  1366. }
  1367. return ret;
  1368. };
  1369.  
  1370. m115_asym_encode = function(src, srclen) {
  1371. var i, j, m, ref, ret;
  1372. m = 128 - 11;
  1373. ret = '';
  1374. for (i = j = 0, ref = Math.floor((srclen + m - 1) / m); (0 <= ref ?
  1375. j < ref :
  1376. j > ref); i = 0 <= ref ? ++j : --j) {
  1377. ret += new_rsa.encrypt(
  1378. bytesToString(src.slice(i * m, Math.min((i + 1) * m, srclen))));
  1379. }
  1380. return window.btoa(new_rsa.hex2a(ret));
  1381. };
  1382.  
  1383. m115_asym_decode = function(src, srclen) {
  1384. var i, j, m, ref, ret;
  1385. m = 128;
  1386. ret = '';
  1387. for (i = j = 0, ref = Math.floor((srclen + m - 1) / m); (0 <= ref ?
  1388. j < ref :
  1389. j > ref); i = 0 <= ref ? ++j : --j) {
  1390. ret += new_rsa.decrypt(
  1391. bytesToString(src.slice(i * m, Math.min((i + 1) * m, srclen))));
  1392. }
  1393. return stringToBytes(ret);
  1394. };
  1395.  
  1396. m115_encode = function(src, tm) {
  1397. var key, tmp, zz;
  1398. key = stringToBytes(md5(`!@###@#${tm}DFDR@#@#`));
  1399. tmp = stringToBytes(src);
  1400. console.log(tmp);
  1401. tmp = m115_sym_encode(tmp, tmp.length, key, null);
  1402. console.log(tmp);
  1403. tmp = key.slice(0, 16).concat(tmp);
  1404. return {
  1405. data: m115_asym_encode(tmp, tmp.length),
  1406. key,
  1407. };
  1408. };
  1409.  
  1410. m115_decode = function(src, key) {
  1411. console.log(src, key);
  1412. var tmp;
  1413. tmp = stringToBytes(window.atob(src));
  1414. tmp = m115_asym_decode(tmp, tmp.length);
  1415. return bytesToString(
  1416. m115_sym_decode(tmp.slice(16), tmp.length - 16, key, tmp.slice(0, 16)));
  1417. };
  1418.  
  1419. /*GM_config_zh-CN.js*/
  1420.  
  1421. // ==UserScript==
  1422. // @name GM_config_zh-CN
  1423. // @author Mike Medley & zxf10608
  1424. // @version 1.3.7
  1425. // @description GM_config_中文版
  1426. // @grant GM_getValue
  1427. // @grant GM_setValue
  1428. // @grant GM_deleteValue
  1429. // @exclude *
  1430. // @license LGPL 3
  1431. // ==/UserScript==
  1432.  
  1433. /*
  1434. 优化说明
  1435. 1、改成中文 "确定"、"取消" 按钮。
  1436. 2、select 新增了 textContents 数组。
  1437. 3、新增了skin: 'tab'换页切换菜单样式
  1438. 4、更新部分翻译
  1439. 5、优化字体显示效果
  1440. 6、优化同一行内CSS样式
  1441. */
  1442.  
  1443. // The GM_config constructor
  1444. function GM_configStruct() {
  1445. // call init() if settings were passed to constructor
  1446. if (arguments.length) {
  1447. GM_configInit(this, arguments);
  1448. this.onInit();
  1449. }
  1450. }
  1451.  
  1452. // This is the initializer function
  1453. function GM_configInit(config, args) {
  1454. // Initialize instance variables
  1455. if (typeof config.fields == 'undefined') {
  1456. config.fields = {};
  1457. config.onInit = config.onInit || function() {
  1458. };
  1459. config.onOpen = config.onOpen || function() {
  1460. };
  1461. config.onSave = config.onSave || function() {
  1462. };
  1463. config.onClose = config.onClose || function() {
  1464. };
  1465. config.onReset = config.onReset || function() {
  1466. };
  1467. config.isOpen = false;
  1468. config.title = '用户脚本设置';
  1469. config.css = {
  1470. basic: [
  1471. '#GM_config * { font-family: arial,tahoma,myriad pro,sans-serif; }',
  1472. '#GM_config { background: #FFF; }',
  1473. '#GM_config input[type=\'radio\'] { margin-right: 8px; }',
  1474. '#GM_config .indent40 { margin-left: 40%; }',
  1475. '#GM_config .field_label { font-size: 14px; font-weight: bold; margin-right: 6px; }',
  1476. '#GM_config .radio_label { font-size: 14px; }',
  1477. '#GM_config .block { display: block; }',
  1478. '#GM_config .saveclose_buttons { margin: 16px 10px 10px; padding: 2px 12px; }',
  1479. '#GM_config .reset, #GM_config .reset a,' +
  1480. ' #GM_config_buttons_holder { color: #000; text-align: right; }',
  1481. '#GM_config .config_header { font-size: 20pt; margin: 0; }',
  1482. '#GM_config .config_desc, #GM_config .section_desc, #GM_config .reset { font-size: 9pt; }',
  1483. '#GM_config .center { text-align: center; }',
  1484. '#GM_config .section_header_holder { margin-top: 8px; }',
  1485. '#GM_config .config_var { margin: 0 0 4px; }',
  1486. '#GM_config .section_header { background: #414141; border: 1px solid #000; color: #FFF;' +
  1487. ' font-size: 12pt; margin: 0; }',
  1488. '#GM_config .section_desc { background: #EFEFEF; border: 1px solid #CCC; color: #575757;' +
  1489. ' font-size: 10pt; margin: 0 0 6px; }',
  1490. // newer
  1491. '#GM_config input[type=\'number\'] { width: 60px; }',
  1492. '#GM_config .nav-tabs { margin: 10 0}',
  1493. '#GM_config .nav-tabs > div { display: inline; padding: 3px 10px; }',
  1494. '#pv-prefs .section_header_holder { padding-left: 10px; }',
  1495. ].join('\n') + '\n',
  1496. skin_tab: [
  1497. '#GM_config { background: #EEE; }',
  1498. '#GM_config textarea { width: 98%; height: 45px; margin-top: 5px; }',
  1499. '#GM_config .field_label { display: inline-block; font-weight: normal; }',
  1500. // 在同一行内的设置
  1501. '#GM_config .inline input[type=\'checkbox\'] {margin: 3px 3px 3px 0px;}',
  1502. '#GM_config .inline .config_var { margin-left: 15px; }',
  1503. // 内容样式
  1504. '#GM_config .config_var { font-size: 14px; padding: 5px; margin: 0; }',
  1505. '#GM_config .config_header a { text-decoration: none; color: #000; }',
  1506. '#GM_config .nav-tabs { margin: 20 0}',
  1507. '#GM_config .nav-tabs > div { font-size: 15px; color: #999; cursor: pointer; padding: 10px 20px; }',
  1508. '#GM_config .nav-tabs > .active { cursor: default; color: #FFF; }',
  1509. '#GM_config .nav-tabs > div:hover { color: #FFF; }',
  1510. ].join('\n') + '\n',
  1511. skin_1: [ // 仿 Mouseover Popup Image Viewer 样式
  1512. '#GM_config { background: #EEE; }',
  1513. '#GM_config textarea { width: 98%; height: 45px; margin-top: 5px; }',
  1514. '#GM_config .config_var { font-size: 12px; }',
  1515. '#GM_config .inline .config_var { margin-left: 15px; }',
  1516. '#GM_config .field_label { display: inline-block; font-weight: normal; }',
  1517. '#GM_config { padding: 20px 30px; margin: 0; }',
  1518. '#GM_config .config_header { margin-bottom: 10px; }',
  1519. '#GM_config div.config_var { padding: 7px 0; }',
  1520. ].join('\n') + '\n',
  1521. basicPrefix: 'GM_config',
  1522. stylish: '',
  1523. };
  1524. }
  1525.  
  1526. if (args.length == 1 &&
  1527. typeof args[0].id == 'string' &&
  1528. typeof args[0].appendChild != 'function') var settings = args[0];
  1529. else {
  1530. // Provide backwards-compatibility with argument style intialization
  1531. var settings = {};
  1532.  
  1533. // loop through GM_config.init() arguments
  1534. for (var i = 0, l = args.length, arg; i < l; ++i) {
  1535. arg = args[i];
  1536.  
  1537. // An element to use as the config window
  1538. if (typeof arg.appendChild == 'function') {
  1539. settings.frame = arg;
  1540. continue;
  1541. }
  1542.  
  1543. switch (typeof arg) {
  1544. case 'object':
  1545. for (var j in arg) { // could be a callback functions or settings object
  1546. if (typeof arg[j] != 'function') { // we are in the settings object
  1547. if (typeof arg[j] == 'string') {
  1548. settings.frameStyle = arg;
  1549. } else {
  1550. settings.fields = arg; // store settings object
  1551. }
  1552. break; // leave the loop
  1553. } // otherwise it must be a callback function
  1554. if (!settings.events) settings.events = {};
  1555. settings.events[j] = arg[j];
  1556. }
  1557. break;
  1558. case 'function': // passing a bare function is set to open callback
  1559. settings.events = {
  1560. open: arg,
  1561. };
  1562. break;
  1563. case 'string': // could be custom CSS or the title string
  1564. // if (/[\w\.]+\s*\{\s*[\w-]+\s*:\s*\w+[\s|\S]*\}/.test(arg))
  1565. if (/[\w\.]+\s*\{\s*[\w-]+\s*:[\s|\S]*\}/.test(arg))
  1566. settings.css = arg;
  1567. else if (arg)
  1568. settings.title = arg;
  1569. break;
  1570. }
  1571. }
  1572. }
  1573.  
  1574. /* Initialize everything using the new settings object */
  1575. // Set the id
  1576. if (settings.id) config.id = settings.id;
  1577. else if (typeof config.id == 'undefined') config.id = 'GM_config';
  1578.  
  1579. // Set the title
  1580. if (settings.title) config.title = settings.title;
  1581.  
  1582. // Set the custom css
  1583. if (settings.css) config.css.stylish = settings.css;
  1584.  
  1585. if (settings.skin) {
  1586. var skin = config.css['skin_' + settings.skin];
  1587. if (skin) {
  1588. config.css.basic += skin;
  1589. }
  1590. }
  1591.  
  1592. // Set the frame
  1593. if (settings.frame) config.frame = settings.frame;
  1594. if (settings.frameStyle) config.frameStyle = settings.frameStyle;
  1595.  
  1596. config.isTabs = settings.isTabs;
  1597.  
  1598. // Set the event callbacks
  1599. if (settings.events) {
  1600. var events = settings.events;
  1601. for (var e in events)
  1602. config['on' + e.charAt(0).toUpperCase() + e.slice(1)] = events[e];
  1603. }
  1604.  
  1605. // Create the fields
  1606. if (settings.fields) {
  1607. var stored = config.read(), // read the stored settings
  1608. fields = settings.fields,
  1609. customTypes = settings.types || {};
  1610.  
  1611. for (var id in fields) {
  1612. var field = fields[id];
  1613.  
  1614. // for each field definition create a field object
  1615. if (field)
  1616. config.fields[id] = new GM_configField(field, stored[id], id,
  1617. customTypes[field.type]);
  1618. else if (config.fields[id]) delete config.fields[id];
  1619. }
  1620. }
  1621.  
  1622. // If the id has changed we must modify the default style
  1623. if (config.id != config.css.basicPrefix) {
  1624. config.css.basic = config.css.basic.replace(
  1625. new RegExp('#' + config.css.basicPrefix, 'gm'), '#' + config.id);
  1626. config.css.basicPrefix = config.id;
  1627. }
  1628. }
  1629.  
  1630. GM_configStruct.prototype = {
  1631. // Support old method of initalizing
  1632. init: function() {
  1633. GM_configInit(this, arguments);
  1634. this.onInit();
  1635. },
  1636.  
  1637. // call GM_config.open() from your script to open the menu
  1638. open: function() {
  1639. // Die if the menu is already open on this page
  1640. // You can have multiple instances but you can't open the same instance twice
  1641. var match = document.getElementById(this.id);
  1642. if (match &&
  1643. (match.tagName == 'IFRAME' || match.childNodes.length > 0)) return;
  1644.  
  1645. // Sometimes "this" gets overwritten so create an alias
  1646. var config = this;
  1647.  
  1648. // Function to build the mighty config window :)
  1649. function buildConfigWin(body, head) {
  1650. var create = config.create,
  1651. fields = config.fields,
  1652. configId = config.id,
  1653. bodyWrapper = create('div', {
  1654. id: configId + '_wrapper',
  1655. });
  1656.  
  1657. // Append the style which is our default style plus the user style
  1658. head.appendChild(
  1659. create('style', {
  1660. type: 'text/css',
  1661. textContent: config.css.basic + config.css.stylish,
  1662. }));
  1663.  
  1664. // Add header and title
  1665. bodyWrapper.appendChild(create('div', {
  1666. id: configId + '_header',
  1667. className: 'config_header block center',
  1668. }, config.title));
  1669.  
  1670. // Append elements
  1671. var section = bodyWrapper,
  1672. secNum = 0; // Section count
  1673. var lastParentNode = null;
  1674.  
  1675. // loop through fields
  1676. for (var id in fields) {
  1677. var field = fields[id],
  1678. settings = field.settings;
  1679.  
  1680. if (settings.section) { // the start of a new section
  1681. section = bodyWrapper.appendChild(create('div', {
  1682. className: 'section_header_holder',
  1683. id: configId + '_section_' + secNum,
  1684. }));
  1685.  
  1686. if (Object.prototype.toString.call(settings.section) !==
  1687. '[object Array]')
  1688. settings.section = [settings.section];
  1689.  
  1690. if (settings.section[0])
  1691. section.appendChild(create('div', {
  1692. className: 'section_header center',
  1693. id: configId + '_section_header_' + secNum,
  1694. }, settings.section[0]));
  1695.  
  1696. if (settings.section[1])
  1697. section.appendChild(create('p', {
  1698. className: 'section_desc center',
  1699. id: configId + '_section_desc_' + secNum,
  1700. }, settings.section[1]));
  1701. ++secNum;
  1702. }
  1703.  
  1704. if (settings.line == 'start' && lastParentNode) { // 切换到下一行
  1705. lastParentNode = null;
  1706. }
  1707.  
  1708. // Create field elements and append to current section
  1709. (lastParentNode || section).appendChild(
  1710. (field.wrapper = field.toNode(configId, lastParentNode)));
  1711.  
  1712. if (settings.line == 'start') {
  1713. lastParentNode = field.wrapper;
  1714. lastParentNode.classList.add('inline');
  1715. } else if (settings.line == 'end') {
  1716. lastParentNode = null;
  1717. }
  1718. }
  1719.  
  1720. // Add save and close buttons
  1721. bodyWrapper.appendChild(create('div', {
  1722. id: configId + '_buttons_holder',
  1723. },
  1724.  
  1725. create('button', {
  1726. id: configId + '_saveBtn',
  1727. textContent: '确定',
  1728. title: '部分选项需要刷新页面才能生效',
  1729. className: 'saveclose_buttons',
  1730. onclick: function() {
  1731. config.save();
  1732. config.close();
  1733. },
  1734. }),
  1735.  
  1736. create('button', {
  1737. id: configId + '_closeBtn',
  1738. textContent: '取消',
  1739. title: '取消本次设置,所有选项还原',
  1740. className: 'saveclose_buttons',
  1741. onclick: function() {
  1742. config.close();
  1743. },
  1744. }),
  1745.  
  1746. create('div', {
  1747. className: 'reset_holder block',
  1748. },
  1749.  
  1750. // Reset link
  1751. create('a', {
  1752. id: configId + '_resetLink',
  1753. textContent: '恢复默认设置',
  1754. href: '#',
  1755. title: '恢复所有设置的内容为默认值',
  1756. className: 'reset',
  1757. onclick: function(e) {
  1758. e.preventDefault();
  1759. config.reset();
  1760. },
  1761. }),
  1762. )));
  1763.  
  1764. body.appendChild(bodyWrapper); // Paint everything to window at once
  1765. config.center(); // Show and center iframe
  1766. window.addEventListener('resize', config.center, false); // Center frame on resize
  1767.  
  1768. // Call the open() callback function
  1769. config.onOpen(config.frame.contentDocument || config.frame.ownerDocument,
  1770. config.frame.contentWindow || window,
  1771. config.frame);
  1772.  
  1773. if (config.isTabs) {
  1774. config.toTabs();
  1775. }
  1776.  
  1777. // Close frame on window close
  1778. window.addEventListener('beforeunload', function() {
  1779. config.close();
  1780. }, false);
  1781.  
  1782. // Now that everything is loaded, make it visible
  1783. config.frame.style.display = 'block';
  1784. config.isOpen = true;
  1785. }
  1786.  
  1787. // Change this in the onOpen callback using this.frame.setAttribute('style', '')
  1788. var defaultStyle = 'bottom: auto; border: 1px solid #000; display: none; height: 75%;' +
  1789. ' left: 0; margin: 0; max-height: 95%; max-width: 95%; opacity: 0;' +
  1790. ' overflow: auto; padding: 0; position: fixed; right: auto; top: 0;' +
  1791. ' width: 75%; z-index: 999999999;';
  1792.  
  1793. // Either use the element passed to init() or create an iframe
  1794. if (this.frame) {
  1795. this.frame.id = this.id; // Allows for prefixing styles with the config id
  1796. this.frame.setAttribute('style', defaultStyle);
  1797. buildConfigWin(this.frame,
  1798. this.frame.ownerDocument.getElementsByTagName('head')[0]);
  1799. } else {
  1800. // Create frame
  1801. document.body.appendChild((this.frame = this.create('iframe', {
  1802. id: this.id,
  1803. style: defaultStyle,
  1804. })));
  1805.  
  1806. if (this.frameStyle) {
  1807. Object.keys(this.frameStyle).forEach(function(key) {
  1808. config.frame.style[key] = config.frameStyle[key];
  1809. });
  1810. }
  1811.  
  1812. // In WebKit src can't be set until it is added to the page
  1813. this.frame.src = 'about:blank';
  1814. // we wait for the iframe to load before we can modify it
  1815. this.frame.addEventListener('load', function(e) {
  1816. var frame = config.frame;
  1817. var body = frame.contentDocument.getElementsByTagName('body')[0];
  1818. body.id = config.id; // Allows for prefixing styles with the config id
  1819. buildConfigWin(body,
  1820. frame.contentDocument.getElementsByTagName('head')[0]);
  1821. }, false);
  1822. }
  1823. },
  1824.  
  1825. save: function() {
  1826. var forgotten = this.write();
  1827. this.onSave(forgotten); // Call the save() callback function
  1828. },
  1829.  
  1830. close: function() {
  1831. if (!this.frame) return;
  1832. // If frame is an iframe then remove it
  1833. if (this.frame.contentDocument) {
  1834. this.remove(this.frame);
  1835. this.frame = null;
  1836. } else { // else wipe its content
  1837. this.frame.innerHTML = '';
  1838. this.frame.style.display = 'none';
  1839. }
  1840.  
  1841. // Null out all the fields so we don't leak memory
  1842. var fields = this.fields;
  1843. for (var id in fields) {
  1844. var field = fields[id];
  1845. field.wrapper = null;
  1846. field.node = null;
  1847. }
  1848.  
  1849. this.onClose(); // Call the close() callback function
  1850. this.isOpen = false;
  1851. },
  1852.  
  1853. set: function(name, val) {
  1854. this.fields[name].value = val;
  1855.  
  1856. if (this.fields[name].node) {
  1857. this.fields[name].reload();
  1858. }
  1859. },
  1860.  
  1861. get: function(name, getLive) {
  1862. var field = this.fields[name],
  1863. fieldVal = null;
  1864.  
  1865. if (getLive && field.node) {
  1866. fieldVal = field.toValue();
  1867. }
  1868.  
  1869. return fieldVal != null ? fieldVal : field.value;
  1870. },
  1871.  
  1872. write: function(store, obj) {
  1873. if (!obj) {
  1874. var values = {},
  1875. forgotten = {},
  1876. fields = this.fields;
  1877.  
  1878. for (var id in fields) {
  1879. var field = fields[id];
  1880. var value = field.toValue();
  1881.  
  1882. if (field.save) {
  1883. if (value != null) {
  1884. values[id] = value;
  1885. field.value = value;
  1886. } else
  1887. values[id] = field.value;
  1888. } else
  1889. forgotten[id] = value;
  1890. }
  1891. }
  1892. try {
  1893. this.setValue(store || this.id, this.stringify(obj || values));
  1894. } catch (e) {
  1895. this.log('GM_config failed to save settings!');
  1896. }
  1897.  
  1898. return forgotten;
  1899. },
  1900.  
  1901. read: function(store) {
  1902. try {
  1903. var rval = this.parser(this.getValue(store || this.id, '{}'));
  1904. } catch (e) {
  1905. this.log('GM_config failed to read saved settings!');
  1906. var rval = {};
  1907. }
  1908. return rval;
  1909. },
  1910.  
  1911. reset: function() {
  1912. var fields = this.fields;
  1913.  
  1914. // Reset all the fields
  1915. for (var id in fields) fields[id].reset();
  1916.  
  1917. this.onReset(); // Call the reset() callback function
  1918. },
  1919.  
  1920. create: function() {
  1921. switch (arguments.length) {
  1922. case 1:
  1923. var A = document.createTextNode(arguments[0]);
  1924. break;
  1925. default:
  1926. var A = document.createElement(arguments[0]),
  1927. B = arguments[1];
  1928. for (var b in B) {
  1929. if (b.indexOf('on') == 0)
  1930. A.addEventListener(b.substring(2), B[b], false);
  1931. else if (',style,accesskey,id,name,src,href,which,for'.indexOf(',' +
  1932. b.toLowerCase()) != -1)
  1933. A.setAttribute(b, B[b]);
  1934. else if (typeof B[b] != 'undefined')
  1935. A[b] = B[b];
  1936. }
  1937. if (typeof arguments[2] == 'string')
  1938. A.innerHTML = arguments[2];
  1939. else
  1940. for (var i = 2, len = arguments.length; i < len; ++i)
  1941. A.appendChild(arguments[i]);
  1942. }
  1943. return A;
  1944. },
  1945.  
  1946. center: function() {
  1947. var node = this.frame;
  1948. if (!node) return;
  1949. var style = node.style,
  1950. beforeOpacity = style.opacity;
  1951. if (style.display == 'none') style.opacity = '0';
  1952. style.display = '';
  1953. style.top = Math.floor((window.innerHeight / 2) - (node.offsetHeight / 2)) +
  1954. 'px';
  1955. style.left = Math.floor((window.innerWidth / 2) - (node.offsetWidth / 2)) +
  1956. 'px';
  1957. style.opacity = '1';
  1958. },
  1959.  
  1960. remove: function(el) {
  1961. if (el && el.parentNode) el.parentNode.removeChild(el);
  1962. },
  1963.  
  1964. toTabs: function() { // 转为 tab 的形式
  1965. var body = this.frame.tagName == 'IFRAME' ?
  1966. this.frame.contentWindow.document :
  1967. this.frame,
  1968. configId = this.id;
  1969. var $ = function(id) {
  1970. return body.getElementById(configId + '_' + id);
  1971. };
  1972.  
  1973. var headers = body.querySelectorAll('.section_header');
  1974. if (!headers.length) return;
  1975.  
  1976. var anch = this.create('div', {
  1977. // id: configId + '_tab_holder',
  1978. className: 'nav-tabs',
  1979. });
  1980.  
  1981. for (var i = 0, header; i < headers.length; i++) {
  1982. header = headers[i];
  1983. if (i == 0) {
  1984. header.classList.add('active');
  1985. }
  1986. anch.appendChild(header);
  1987. }
  1988.  
  1989. anch.addEventListener('click', this.toggleTab.bind(this), false);
  1990.  
  1991. $('section_0').parentNode.insertBefore(anch, $('section_0'));
  1992.  
  1993. var curTab = localStorage.getItem('picviewerCE.config.curTab') || 0;
  1994. this.toggleTab(parseInt(curTab, 10));
  1995. },
  1996. toggleTab: function(e) {
  1997. var body = this.frame.tagName == 'IFRAME' ?
  1998. this.frame.contentWindow.document :
  1999. this.frame,
  2000. configId = this.id;
  2001.  
  2002. var curTab = typeof e == 'number' ? e : /\_(\d+)/.exec(e.target.id)[1];
  2003.  
  2004. [].forEach.call(body.querySelectorAll('.section_header'),
  2005. function(header, i) {
  2006. if (i == curTab) {
  2007. header.classList.add('active');
  2008. } else {
  2009. header.classList.remove('active');
  2010. }
  2011. });
  2012.  
  2013. [].forEach.call(body.querySelectorAll('.section_header_holder'),
  2014. function(holder, i) {
  2015. holder.style.display = (i == curTab) ? 'block' : 'none';
  2016. });
  2017.  
  2018. localStorage.setItem('picviewerCE.config.curTab', curTab);
  2019. },
  2020. };
  2021.  
  2022. // Define a bunch of API stuff
  2023. (function() {
  2024. var isGM = typeof GM_getValue != 'undefined' &&
  2025. typeof GM_getValue('a', 'b') != 'undefined',
  2026. setValue, getValue, stringify, parser;
  2027.  
  2028. // Define value storing and reading API
  2029. if (!isGM) {
  2030. setValue = function(name, value) {
  2031. return localStorage.setItem(name, value);
  2032. };
  2033. getValue = function(name, def) {
  2034. var s = localStorage.getItem(name);
  2035. return s == null ? def : s;
  2036. };
  2037.  
  2038. // We only support JSON parser outside GM
  2039. stringify = JSON.stringify;
  2040. parser = JSON.parse;
  2041. } else {
  2042. setValue = GM_setValue;
  2043. getValue = GM_getValue;
  2044. stringify = typeof JSON == 'undefined' ?
  2045. function(obj) {
  2046. return obj.toSource();
  2047. } : JSON.stringify;
  2048. parser = typeof JSON == 'undefined' ?
  2049. function(jsonData) {
  2050. return (new Function('return ' + jsonData + ';'))();
  2051. } : JSON.parse;
  2052. }
  2053.  
  2054. GM_configStruct.prototype.isGM = isGM;
  2055. GM_configStruct.prototype.setValue = setValue;
  2056. GM_configStruct.prototype.getValue = getValue;
  2057. GM_configStruct.prototype.stringify = stringify;
  2058. GM_configStruct.prototype.parser = parser;
  2059. GM_configStruct.prototype.log = window.console ?
  2060. console.log : (isGM && typeof GM_log != 'undefined' ?
  2061. GM_log : (window.opera ?
  2062. opera.postError : function() {
  2063. /* no logging */
  2064. }
  2065. ));
  2066. })();
  2067.  
  2068. function GM_configDefaultValue(type, options) {
  2069. var value;
  2070.  
  2071. if (type && type.indexOf('unsigned ') == 0)
  2072. type = type.substring(9);
  2073.  
  2074. switch (type) {
  2075. case 'radio':
  2076. case 'select':
  2077. value = options[0];
  2078. break;
  2079. case 'checkbox':
  2080. value = false;
  2081. break;
  2082. case 'int':
  2083. case 'integer':
  2084. case 'float':
  2085. case 'number':
  2086. value = 0;
  2087. break;
  2088. default:
  2089. value = '';
  2090. }
  2091.  
  2092. return value;
  2093. }
  2094.  
  2095. function GM_configField(settings, stored, id, customType) {
  2096. // Store the field's settings
  2097. this.settings = settings;
  2098. this.id = id;
  2099. this.node = null;
  2100. this.wrapper = null;
  2101. this.save = typeof settings.save == 'undefined' ? true : settings.save;
  2102.  
  2103. // Buttons are static and don't have a stored value
  2104. if (settings.type == 'button') this.save = false;
  2105. if (settings.type == 'span') this.save = false;
  2106.  
  2107. // if a default value wasn't passed through init() then
  2108. // if the type is custom use its default value
  2109. // else use default value for type
  2110. // else use the default value passed through init()
  2111. this['default'] = typeof settings['default'] == 'undefined' ?
  2112. customType ?
  2113. customType['default'] :
  2114. GM_configDefaultValue(settings.type, settings.options) :
  2115. settings['default'];
  2116.  
  2117. // Store the field's value
  2118. this.value = typeof stored == 'undefined' ? this['default'] : stored;
  2119.  
  2120. // Setup methods for a custom type
  2121. if (customType) {
  2122. this.toNode = customType.toNode;
  2123. this.toValue = customType.toValue;
  2124. this.reset = customType.reset;
  2125. }
  2126. }
  2127.  
  2128. GM_configField.prototype = {
  2129. create: GM_configStruct.prototype.create,
  2130.  
  2131. toNode: function(configId, lastParentNode) {
  2132. var field = this.settings,
  2133. value = this.value,
  2134. options = field.options,
  2135. type = field.type,
  2136. id = this.id,
  2137. labelPos = field.labelPos,
  2138. create = this.create;
  2139.  
  2140. function addLabel(pos, labelEl, parentNode, beforeEl) {
  2141. if (!beforeEl) {
  2142. beforeEl = lastParentNode ?
  2143. parentNode.lastChild :
  2144. parentNode.firstChild; // oneLine 的修正
  2145. }
  2146.  
  2147. switch (pos) {
  2148. case 'right':
  2149. case 'below':
  2150. if (pos == 'below')
  2151. parentNode.appendChild(create('br', {}));
  2152. parentNode.appendChild(labelEl);
  2153. break;
  2154. default:
  2155. if (pos == 'above')
  2156. parentNode.insertBefore(create('br', {}), beforeEl);
  2157. parentNode.insertBefore(labelEl, beforeEl);
  2158. }
  2159. }
  2160.  
  2161. var retNode = create('div', {
  2162. className: 'config_var',
  2163. id: configId + '_' + id + '_var',
  2164. title: field.title || '',
  2165. }),
  2166. firstProp;
  2167.  
  2168. // Retrieve the first prop
  2169. for (var i in field) {
  2170. firstProp = i;
  2171. break;
  2172. }
  2173.  
  2174. var label = field.label && type != 'button' ?
  2175. create('label', {
  2176. id: configId + '_' + id + '_field_label',
  2177. for: configId + '_field_' + id,
  2178. className: 'field_label',
  2179. }, field.label) : null;
  2180.  
  2181. switch (type) {
  2182. case 'span':
  2183. label = null;
  2184.  
  2185. this.node = create('span', {
  2186. innerHTML: field.label,
  2187. className: 'field_label',
  2188. title: field.title,
  2189. style: field.style,
  2190. });
  2191. retNode = this.node;
  2192. break;
  2193. case 'textarea':
  2194. retNode.appendChild((this.node = create('textarea', {
  2195. innerHTML: value,
  2196. id: configId + '_field_' + id,
  2197. className: 'block' + (field.className ? (' ' + field.className) : ''),
  2198. cols: (field.cols ? field.cols : 20),
  2199. rows: (field.rows ? field.rows : 2),
  2200. placeholder: field.placeholder,
  2201. })));
  2202. break;
  2203. case 'radio':
  2204. var wrap = create('div', {
  2205. id: configId + '_field_' + id,
  2206. className: field.className,
  2207. });
  2208. this.node = wrap;
  2209.  
  2210. for (var i = 0, len = options.length; i < len; ++i) {
  2211. var radLabel = create('label', {
  2212. className: 'radio_label',
  2213. }, options[i]);
  2214.  
  2215. var rad = wrap.appendChild(create('input', {
  2216. value: options[i],
  2217. type: 'radio',
  2218. name: id,
  2219. checked: options[i] == value,
  2220. }));
  2221.  
  2222. var radLabelPos = labelPos &&
  2223. (labelPos == 'left' || labelPos == 'right') ?
  2224. labelPos : firstProp == 'options' ? 'left' : 'right';
  2225.  
  2226. addLabel(radLabelPos, radLabel, wrap, rad);
  2227. }
  2228.  
  2229. retNode.appendChild(wrap);
  2230. break;
  2231. case 'select':
  2232. var wrap = create('select', {
  2233. id: configId + '_field_' + id,
  2234. });
  2235. this.node = wrap;
  2236.  
  2237. for (var i = 0, len = options.length; i < len; ++i) {
  2238. var option = options[i];
  2239. wrap.appendChild(create('option', {
  2240. value: option,
  2241. selected: option == value,
  2242. }, option));
  2243. }
  2244.  
  2245. retNode.appendChild(wrap);
  2246. break;
  2247. default: // fields using input elements
  2248. var props = {
  2249. id: configId + '_field_' + id,
  2250. type: type,
  2251. value: type == 'button' ? field.label : value,
  2252. };
  2253.  
  2254. switch (type) {
  2255. case 'checkbox':
  2256. props.checked = value;
  2257. break;
  2258. case 'button':
  2259. props.size = field.size ? field.size : 25;
  2260. if (field.script) field.click = field.script;
  2261. if (field.click) props.onclick = field.click;
  2262. break;
  2263. case 'hidden':
  2264. break;
  2265. default:
  2266. // type = text, int, or float
  2267. props.type = 'text';
  2268. props.size = field.size ? field.size : 25;
  2269. }
  2270.  
  2271. retNode.appendChild((this.node = create('input', props)));
  2272. }
  2273.  
  2274. if (label) {
  2275. // If the label is passed first, insert it before the field
  2276. // else insert it after
  2277. if (!labelPos)
  2278. labelPos = firstProp == 'label' || type == 'radio' ?
  2279. 'left' : 'right';
  2280.  
  2281. addLabel(labelPos, label, retNode);
  2282. }
  2283.  
  2284. return retNode;
  2285. },
  2286.  
  2287. toValue: function() {
  2288. var node = this.node,
  2289. field = this.settings,
  2290. type = field.type,
  2291. unsigned = false,
  2292. rval = null;
  2293.  
  2294. if (!node) return rval;
  2295.  
  2296. if (type.indexOf('unsigned ') == 0) {
  2297. type = type.substring(9);
  2298. unsigned = true;
  2299. }
  2300.  
  2301. switch (type) {
  2302. case 'checkbox':
  2303. rval = node.checked;
  2304. break;
  2305. case 'select':
  2306. rval = node[node.selectedIndex].value;
  2307. break;
  2308. case 'radio':
  2309. var radios = node.getElementsByTagName('input');
  2310. for (var i = 0, len = radios.length; i < len; ++i)
  2311. if (radios[i].checked)
  2312. rval = radios[i].value;
  2313. break;
  2314. case 'button':
  2315. break;
  2316. case 'int':
  2317. case 'integer':
  2318. case 'float':
  2319. case 'number':
  2320. var num = Number(node.value);
  2321. var warn = '输入字符 "' + field.label + '" 要求必须为' +
  2322. (unsigned ? ' 正 ' : 'n ') + '整数值';
  2323.  
  2324. if (isNaN(num) || (type.substr(0, 3) == 'int' &&
  2325. Math.ceil(num) != Math.floor(num)) ||
  2326. (unsigned && num < 0)) {
  2327. alert(warn + '.');
  2328. return null;
  2329. }
  2330.  
  2331. if (!this._checkNumberRange(num, warn))
  2332. return null;
  2333. rval = num;
  2334. break;
  2335. default:
  2336. rval = node.value;
  2337. break;
  2338. }
  2339.  
  2340. return rval; // value read successfully
  2341. },
  2342.  
  2343. reset: function() {
  2344. var node = this.node,
  2345. field = this.settings,
  2346. type = field.type;
  2347.  
  2348. if (!node) return;
  2349.  
  2350. switch (type) {
  2351. case 'checkbox':
  2352. node.checked = this['default'];
  2353. break;
  2354. case 'select':
  2355. for (var i = 0, len = node.options.length; i < len; ++i)
  2356. if (node.options[i].value == this['default'])
  2357. node.selectedIndex = i;
  2358. break;
  2359. case 'radio':
  2360. var radios = node.getElementsByTagName('input');
  2361. for (var i = 0, len = radios.length; i < len; ++i)
  2362. if (radios[i].value == this['default'])
  2363. radios[i].checked = true;
  2364. break;
  2365. case 'button':
  2366. break;
  2367. default:
  2368. node.value = this['default'];
  2369. break;
  2370. }
  2371. },
  2372.  
  2373. remove: function(el) {
  2374. GM_configStruct.prototype.remove(el || this.wrapper);
  2375. this.wrapper = null;
  2376. this.node = null;
  2377. },
  2378.  
  2379. reload: function() {
  2380. var wrapper = this.wrapper;
  2381. if (wrapper) {
  2382. var fieldParent = wrapper.parentNode;
  2383. fieldParent.insertBefore((this.wrapper = this.toNode()), wrapper);
  2384. this.remove(wrapper);
  2385. }
  2386. },
  2387.  
  2388. _checkNumberRange: function(num, warn) {
  2389. var field = this.settings;
  2390. if (typeof field.min == 'number' && num < field.min) {
  2391. alert(warn + ' greater than or equal to ' + field.min + '.');
  2392. return null;
  2393. }
  2394.  
  2395. if (typeof field.max == 'number' && num > field.max) {
  2396. alert(warn + ' less than or equal to ' + field.max + '.');
  2397. return null;
  2398. }
  2399. return true;
  2400. },
  2401. };
  2402.  
  2403. // Create default instance of GM_config
  2404. var GM_config = new GM_configStruct();
  2405.  
  2406. /*waitForKeyElements*/
  2407.  
  2408. /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
  2409. that detects and handles AJAXed content.
  2410.  
  2411. Usage example:
  2412. waitForKeyElements ("div.comments", commentCallbackFunction);
  2413.  
  2414. //--- Page-specific function to do what we want when the node is found.
  2415. function commentCallbackFunction (jNode) {
  2416. jNode.text ("This comment changed by waitForKeyElements().");
  2417. }
  2418.  
  2419. IMPORTANT: This function requires your script to have loaded jQuery.
  2420. */
  2421.  
  2422. function waitForKeyElements(
  2423. selectorTxt,
  2424. /* Required: The jQuery selector string that
  2425. specifies the desired element(s).
  2426. */
  2427. actionFunction,
  2428. /* Required: The code to run when elements are
  2429. found. It is passed a jNode to the matched
  2430. element.
  2431. */
  2432. bWaitOnce,
  2433. /* Optional: If false, will continue to scan for
  2434. new elements even after the first match is
  2435. found.
  2436. */
  2437. iframeSelector,
  2438. /* Optional: If set, identifies the iframe to
  2439. search.
  2440. */
  2441. ) {
  2442. var targetNodes, btargetsFound;
  2443.  
  2444. if (typeof iframeSelector == 'undefined')
  2445. targetNodes = $(selectorTxt);
  2446. else
  2447. targetNodes = $(iframeSelector).contents().find(selectorTxt);
  2448.  
  2449. if (targetNodes && targetNodes.length > 0) {
  2450. btargetsFound = true;
  2451. /*--- Found target node(s). Go through each and act if they
  2452. are new.
  2453. */
  2454. targetNodes.each(function() {
  2455. var jThis = $(this);
  2456. var alreadyFound = jThis.data('alreadyFound') || false;
  2457.  
  2458. if (!alreadyFound) {
  2459. //--- Call the payload function.
  2460. var cancelFound = actionFunction(jThis);
  2461. if (cancelFound)
  2462. btargetsFound = false;
  2463. else
  2464. jThis.data('alreadyFound', true);
  2465. }
  2466. });
  2467. } else {
  2468. btargetsFound = false;
  2469. }
  2470.  
  2471. //--- Get the timer-control variable for this selector.
  2472. var controlObj = waitForKeyElements.controlObj || {};
  2473. var controlKey = selectorTxt.replace(/[^\w]/g, '_');
  2474. var timeControl = controlObj[controlKey];
  2475.  
  2476. //--- Now set or clear the timer as appropriate.
  2477. if (btargetsFound && bWaitOnce && timeControl) {
  2478. //--- The only condition where we need to clear the timer.
  2479. clearInterval(timeControl);
  2480. delete controlObj[controlKey];
  2481. } else {
  2482. //--- Set a timer, if needed.
  2483. if (!timeControl) {
  2484. timeControl = setInterval(function() {
  2485. waitForKeyElements(selectorTxt,
  2486. actionFunction,
  2487. bWaitOnce,
  2488. iframeSelector,
  2489. );
  2490. },
  2491. 300,
  2492. );
  2493. controlObj[controlKey] = timeControl;
  2494. }
  2495. }
  2496. waitForKeyElements.controlObj = controlObj;
  2497. }
  2498.  
  2499. (function() {
  2500. 'use strict';
  2501.  
  2502. //版本信息
  2503. const TIPS = {
  2504. CurrentVersion: "1",
  2505. LastUpdateDate: "2023.12.12",
  2506. VersionTips: "秒传工具获取",
  2507. UpdateUrl: "https://115211.xyz/forum.php?mod=viewthread&tid=1",
  2508. Sha1FileInputDetails: "",
  2509. };
  2510.  
  2511. const WORKSETTINGS = {
  2512. WorkingItemsNumber: 4, //同时执行任务数
  2513. SleepLittleTime: 500, //短暂休眠,毫秒,暂时在转存中使用
  2514. SleepMoreTime: 1000, //长时休眠,毫秒,暂时在提取中使用
  2515. SleepMuchMoreTime: 8000, //超长休眠,暂时未使用
  2516. ANumber: 27, //随机数,暂时未使用
  2517. };
  2518.  
  2519. GM_addStyle(`
  2520. @keyframes hue {
  2521. from {
  2522. filter: hue-rotate(0);
  2523. }
  2524.  
  2525. to {
  2526. filter: hue-rotate(360deg);
  2527. }
  2528. }
  2529.  
  2530. .rainbow-text {
  2531. display: inline-block;
  2532. color: red;
  2533. animation: hue 6s linear infinite;
  2534. background-image: linear-gradient(to right bottom, rgb(255,0,0), rgb(255,255,0),rgb(255,0,255));
  2535. -webkit-background-clip: text;
  2536. }
  2537.  
  2538. .my115Info{
  2539. color:red
  2540. }
  2541. .btnInGrid{
  2542. height:20px;
  2543. width:20px;
  2544. margin-left:-22px;
  2545. margin-top:36px;
  2546. border:0px;
  2547. border-color:transparent;
  2548. background-color:transparent;
  2549. }
  2550.  
  2551. .btnInGrid i{
  2552. margin:3px -3px
  2553. }
  2554.  
  2555. li:hover .btnInGrid{
  2556. background-color:#2777F8 !important
  2557. }
  2558.  
  2559.  
  2560.  
  2561. /* Style The Dropdown Button */
  2562. .my115Dropbtn {
  2563. background-color: #2777F8;
  2564. color: white;
  2565. font-size: 16px;
  2566. border: none;
  2567. cursor: pointer;
  2568. }
  2569.  
  2570. /* The container <div> - needed to position the dropdown content */
  2571. .my115Dropdown {
  2572. position: relative;
  2573. display: inline-block;
  2574. }
  2575.  
  2576. /* Dropdown Content (Hidden by Default) */
  2577. .my115Dropdown-content {
  2578. display: none;
  2579. position: absolute;
  2580. background-color: #f9f9f9;
  2581. min-width: 230px;
  2582. box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  2583. z-index: 1;
  2584. margin-top: 32px;
  2585. }
  2586.  
  2587. /* Links inside the dropdown */
  2588. .my115Dropdown-content a {
  2589. color: black;
  2590. padding: 12px 16px;
  2591. text-decoration: none;
  2592. display: block;
  2593. cursor: pointer;
  2594. margin:4px;
  2595. }
  2596.  
  2597. /* Change color of dropdown links on hover */
  2598. .my115Dropdown-content a:hover{
  2599. background-color: #2777F8;
  2600. color:white;
  2601. }
  2602.  
  2603. /* Show the dropdown menu on hover */
  2604. .my115Dropdown:hover .my115Dropdown-content {
  2605. display: block;
  2606. }
  2607.  
  2608. /* Change the background color of the dropdown button when the dropdown content is shown */
  2609. .my115Dropdown:hover .my115Dropbtn {
  2610. background-color: #3e8e41;
  2611. }
  2612.  
  2613. `);
  2614.  
  2615. function getEnviromentInfo() {
  2616. return `
  2617. [gm]:${GM_info.scriptHandler}
  2618. [gmVersion]:${GM_info.version}
  2619. [ua]:${navigator.userAgent}
  2620. [version]:${TIPS.CurrentVersion}
  2621. `;
  2622. }
  2623.  
  2624. function config() {
  2625. console.log('脚本与环境信息:(如果报bug,请附带上如下信息)');
  2626. let env = getEnviromentInfo();
  2627. console.log(env);
  2628.  
  2629. var windowCss = '#Cfg4ne .nav-tabs {margin: 20 2} #Cfg4ne .config_var textarea{width: 310px; height: 50px;} #Cfg4ne .inline {padding-bottom:0px;} #Cfg4ne .config_header a:hover {color:#1e90ff;} #Cfg4ne .config_var {margin-left: 6%;margin-right: 6%;} #Cfg4ne input[type="checkbox"] {margin: 3px 3px 3px 0px;} #Cfg4ne input[type="text"] {width: 60px;} #Cfg4ne {background-color: lightgray;} #Cfg4ne .reset_holder {float: left; position: relative; bottom: -1em;} #Cfg4ne .saveclose_buttons {margin: .7em;} #Cfg4ne .section_desc {font-size: 10pt;}';
  2630.  
  2631. GM_registerMenuCommand('设置', opencfg);
  2632.  
  2633. function opencfg() {
  2634. GM_config.open();
  2635. };
  2636.  
  2637. GM_config.init({
  2638. id: 'Cfg4ne',
  2639. title: GM_config.create('a', {
  2640. href: TIPS.UpdateUrl,
  2641. target: '_blank',
  2642. className: 'setTitle',
  2643. textContent: `${TIPS.VersionTips}设置`,
  2644. title: `作者:Never4Ever 版本:${TIPS.CurrentVersion}点击访问主页`,
  2645. }),
  2646. isTabs: true,
  2647. skin: 'tab',
  2648. css: windowCss,
  2649. frameStyle: {
  2650. height: '490px',
  2651. width: '750px',
  2652. zIndex: '2147483648',
  2653. },
  2654. fields: {
  2655. createRootFolderDefaultValue: {
  2656. section: ['', '转存助手一些功能设置,发包参数暂未开放,敬请期待!'],
  2657. label: '“sha1转存时,强制在保存处新建根目录”这项默认选中',
  2658. labelPos: 'right',
  2659. type: 'checkbox',
  2660. default: true,
  2661. },
  2662.  
  2663. createChildFolderVisible: {
  2664. label: '显示“sha1转存时,不创建任何子目录”选项;不显示则强制创建子目录',
  2665. labelPos: 'right',
  2666. type: 'checkbox',
  2667. default: false,
  2668. },
  2669. createItemSha1: {
  2670. label: '列表模式下:悬浮条显示”获取sha1链接“',
  2671. labelPos: 'right',
  2672. type: 'checkbox',
  2673. default: true,
  2674. },
  2675. createItemSha1InThumb: {
  2676. label: '缩略图模式下:显示”获取sha1链接“',
  2677. labelPos: 'right',
  2678. type: 'checkbox',
  2679. default: true,
  2680. },
  2681. advancedRename: {
  2682. label: '在目录的悬浮工具条处显示“去除分隔符”选项',
  2683. labelPos: 'right',
  2684. type: 'checkbox',
  2685. default: false,
  2686. },
  2687. autoUseSeparator: {
  2688. label: '自动给文件名添加分隔符进行上传,以防文件名违规',
  2689. labelPos: 'right',
  2690. type: 'checkbox',
  2691. default: true,
  2692. },
  2693. autoUseSeparatorToRename: {
  2694. label: '上传结束,自动给文件名去除分隔符,还原原文件名',
  2695. labelPos: 'right',
  2696. type: 'checkbox',
  2697. default: true,
  2698. },
  2699. separator: {
  2700. label: '分隔符方案(推荐生僻字;如果分隔符失效,请自行修改):',
  2701. type: 'text',
  2702. default: '變',
  2703. },
  2704. uploadNumber: {
  2705. //section: ['时间参数设置', '注意:参数设置过快,会引起115服务器无响应,为稳定运行参数未启用!'],
  2706. //label: '转存同时工作任务数:',
  2707. labelPos: 'left',
  2708. type: 'hidden',
  2709. default: '4',
  2710. },
  2711. uploadSleepTime: {
  2712. //label: '转存间隔时间(毫秒):',
  2713. labelPos: 'left',
  2714. type: 'hidden',
  2715. default: '500',
  2716. },
  2717. downloadNumber: {
  2718. //label: '提取同时工作任务数:',
  2719. labelPos: 'left',
  2720. type: 'hidden',
  2721. default: '4',
  2722. },
  2723. downloadSleepTime: {
  2724. //label: '提取间隔时间(毫秒):',
  2725. labelPos: 'left',
  2726. type: 'hidden',
  2727. default: '1300',
  2728. },
  2729. createFolderSleepTime: {
  2730. //label: '目录创建间隔时间(毫秒):',
  2731. labelPos: 'left',
  2732. type: 'hidden',
  2733. default: '300',
  2734. },
  2735. checkUpdate: {
  2736. //section: ['帮助&更新&反馈', '常见错误以及对本脚本进行更新检查与bug反馈'],
  2737. label: '前往github主页',
  2738. labelPos: 'right',
  2739. type: 'button',
  2740. click: function() {
  2741. window.open(TIPS.UpdateUrl, '_blank');
  2742. },
  2743. },
  2744.  
  2745. },
  2746.  
  2747. events: {
  2748. save: function() {
  2749. GM_config.close();
  2750. location.reload();
  2751. },
  2752. },
  2753. });
  2754.  
  2755. GM_registerMenuCommand('脚本与环境信息', jsInfo);
  2756.  
  2757. function jsInfo() {
  2758. postSha1Messgae(createMessage(MessageType.JSINFO, env));
  2759. }
  2760. };
  2761. config();
  2762.  
  2763. var currentConfig = {
  2764. createRootFolderDefaultValue: 'createRootFolderDefaultValue',
  2765. createChildFolderVisible: 'createChildFolderVisible',
  2766. advancedRename: 'advancedRename',
  2767. autoUseSeparator: 'autoUseSeparator',
  2768. autoUseSeparatorToRename: 'autoUseSeparatorToRename',
  2769. separator: 'separator',
  2770. uploadNumber: 'uploadNumber',
  2771. uploadSleepTime: 'uploadSleepTime',
  2772. downloadNumber: 'downloadNumber',
  2773. downloadSleepTime: 'downloadSleepTime',
  2774. createFolderSleepTime: 'createFolderSleepTime',
  2775. createItemSha1: 'createItemSha1',
  2776. createItemSha1InThumb: 'createItemSha1InThumb',
  2777.  
  2778. };
  2779.  
  2780. var offlineTaskButton = `
  2781. <div class="my115Dropdown" id="my115Dropdown">
  2782. <div class="my115Dropbtn">
  2783. <a href="https://115211.xyz/forum.php?mod=viewthread&tid=1" target="_blank" class="button btn-line btn-upload"><i class="icon-operate ifo-linktask"></i><span>获取秒传工具</span><em style="display:none;" class="num-dot"></em></a>
  2784. </div>
  2785. </div>
  2786. `;
  2787.  
  2788. if (!$('#my115Dropdown').length > 0) {
  2789.  
  2790. $('.left-tvf').eq(0).append(offlineTaskButton);
  2791. }
  2792.  
  2793. window.cookie = document.cookie;
  2794.  
  2795. //todo:添加的功能入口
  2796. //列表模式下,项目悬工具条
  2797. waitForKeyElements('div.file-opr', AddShareSHA1Btn);
  2798. //添加任务的弹窗
  2799. waitForKeyElements('div.dialog-bottom', AddDownloadSha1Btn);
  2800. //搜索下的状态
  2801. waitForKeyElements('div.lstc-search', AddShareButtonForSearchItem);
  2802. //缩略图模式下
  2803. waitForKeyElements(`#js_cantain_box .list-thumb li[rel="item"]`,
  2804. AddCeateSha1ButtonInGrid);
  2805. //文件路径旁边的”选中获取项sha1“
  2806. waitForKeyElements('div#js_top_header_file_path_box',
  2807. CreateSha1ButtonForSelectedItems);
  2808. //隐藏截图中的uid
  2809. waitForKeyElements('div[class^="fp-"]', HandleUidDiv);
  2810.  
  2811. function HandleUidDiv(node) {
  2812. node.hide();
  2813. console.log('set uiddiv');
  2814. }
  2815.  
  2816. //#region 20201230新的提取api相关
  2817.  
  2818. function PostData(dict) {
  2819. var k, tmp, v;
  2820. tmp = [];
  2821. for (k in dict) {
  2822. v = dict[k];
  2823. tmp.push(k + '=' + v);
  2824. }
  2825. return tmp.join('&');
  2826. };
  2827.  
  2828. function UrlData(dict) {
  2829. var k, tmp, v;
  2830. tmp = [];
  2831. for (k in dict) {
  2832. v = dict[k];
  2833. tmp.push((encodeURIComponent(k)) + '=' + (encodeURIComponent(v)));
  2834. }
  2835. return tmp.join('&');
  2836. };
  2837.  
  2838. function GetSig(userid, fileid, target, userkey) {
  2839. var sha1, tmp;
  2840. sha1 = new jsSHA('SHA-1', 'TEXT');
  2841. sha1.update('' + userid + fileid + fileid + target + '0');
  2842. tmp = sha1.getHash('HEX');
  2843. sha1 = new jsSHA('SHA-1', 'TEXT');
  2844. sha1.update('' + userkey + tmp + '000000');
  2845. return sha1.getHash('HEX', {
  2846. outputUpper: true,
  2847. });
  2848. }
  2849.  
  2850. function download(filename, content, contentType) {
  2851. if (!contentType) contentType = 'application/octet-stream';
  2852. var a = document.createElement('a');
  2853. var blob = new Blob([content], {
  2854. 'type': contentType,
  2855. });
  2856. a.href = window.URL.createObjectURL(blob);
  2857. a.download = filename;
  2858. a.click();
  2859. }
  2860.  
  2861. function RenewCookie() {
  2862. var arryCookie = window.cookie.split(';');
  2863. arryCookie.forEach(function(kv) {
  2864. document.cookie = kv +
  2865. ';expires=Thu, 01 Jan 2100 00:00:00 UTC;;domain=.115.com';
  2866. });
  2867. }
  2868.  
  2869. function DeleteCookie(resp) {
  2870. try {
  2871. var reg = /set-cookie: .+;/g;
  2872. var setcookie = reg.exec(resp)[0].split(';');
  2873. var filecookie = setcookie[0].slice(11) +
  2874. '; expires=Thu, 01 Jan 1970 00:00:00 UTC;' + setcookie[3] +
  2875. ';domain=.115.com';
  2876. document.cookie = filecookie;
  2877. RenewCookie();
  2878. return filecookie;
  2879. } catch (err) {
  2880. return null;
  2881. }
  2882. }
  2883.  
  2884. //#endregion
  2885.  
  2886. function hereDoc(f) {
  2887. return f.toString().
  2888. replace(/^[^\/]+\/\*!?\s?/, '').
  2889. replace(/\*\/[^\/]+$/, '');
  2890. }
  2891.  
  2892. const TaskType = {
  2893. DOWNLOAD: 'Download', //提取
  2894. UPLOAD: 'Upload', //转存
  2895. };
  2896.  
  2897. const MessageType = {
  2898. BEGIN: 0,
  2899. PROCESSING: 1,
  2900. END: 2,
  2901. ERROR: 3,
  2902. CLOSE: 4,
  2903. CANCEL: 5,
  2904. BEGIN4UPLOAD: 6,
  2905. END4UPLOAD: 7,
  2906. NOTIFYINFO: 8,
  2907. BEGIN4CONTINUETASK: 9,
  2908. SHOWCANCEl: 10,
  2909. HIDECANCEL: 11,
  2910. FILEDOWNLOAD: 12,
  2911. MSGERROR: 13,
  2912. JSINFO: 14,
  2913. };
  2914.  
  2915. function createMessage(messageType, msg, id) {
  2916. return {
  2917. messageType: messageType,
  2918. msg: msg,
  2919. targetID: id,
  2920. };
  2921. }
  2922.  
  2923. String.prototype.format = function() {
  2924. if (arguments.length == 0) {
  2925. return this;
  2926. }
  2927. for (var s = this, i = 0; i < arguments.length; i++) {
  2928. s = s.replace(new RegExp('\\{' + i + '\\}', 'g'), arguments[i]);
  2929. }
  2930. return s;
  2931. };
  2932.  
  2933. var getTamplateLines = function() {
  2934. /*
  2935. <div >
  2936. <div class="itemContent" style="color: red;text-align: left;margin: 10px 0;">
  2937. </div>
  2938. <hr />
  2939. <div style="height:140px;overflow-x: hidden;overflow-y: auto;">
  2940. <ul class="errorList" style="font-size: small;text-align: left;font-style: italic; "></ul>
  2941. </div>
  2942. </div>
  2943. */
  2944. };
  2945.  
  2946. //post from iframe
  2947. function postSha1Messgae(message) {
  2948. var postData = {
  2949. eventID: '115sha1',
  2950. data: message,
  2951. };
  2952.  
  2953. var text = JSON.stringify(postData);
  2954. window.parent.postMessage(text, 'https://115.com/');
  2955.  
  2956. }
  2957.  
  2958. function setTaskCancel() {
  2959. GM_setValue('setTaskCancel', true);
  2960. }
  2961.  
  2962. function resetTaskCancelFlag() {
  2963. GM_setValue('setTaskCancel', false);
  2964. }
  2965.  
  2966. function getTaskCancelFlag() {
  2967. return GM_getValue('setTaskCancel');
  2968. }
  2969.  
  2970. const footerString = `<p class="rainbow-text"><span style="color:#2777F8">[${TIPS.CurrentVersion}]</span>: 操作时,<span class="my115Info">确保本页面置顶</span>,防止脚本休眠!!
  2971. <br><span class="my115Info">无</span>115会员,<span class="my115Info">提取速度</span>受限,<span class="my115Info">转存文件大小</span>不超过5GB!!</p>`;
  2972. //解决提取时的alert不能全屏的问题
  2973. if (window.top === window.self) {
  2974. $(function() {
  2975. var $itemContent = null;
  2976. var $errorList = null;
  2977. var getTamplate = hereDoc(getTamplateLines);
  2978.  
  2979. $(window).on('message', function(e) {
  2980. var dataInfo = typeof e.originalEvent.data == 'string' ?
  2981. JSON.parse(e.originalEvent.data) :
  2982. e.originalEvent.data;
  2983. if (dataInfo.eventID != '115sha1' || e.originalEvent.origin !=
  2984. 'https://115.com') return;
  2985. var message = typeof dataInfo.data == 'string' ?
  2986. JSON.parse(dataInfo.data) :
  2987. dataInfo.data;
  2988.  
  2989. //ui:
  2990. if (message.messageType == MessageType.BEGIN) {
  2991. Swal.fire({
  2992. title: '正在操作中...',
  2993. html: getTamplate,
  2994. allowOutsideClick: false,
  2995. allowEscapeKey: false,
  2996. confirmButtonText: `完成`,
  2997. showCancelButton: true,
  2998. cancelButtonText: `取消操作`,
  2999. footer: footerString,
  3000. willOpen: function() {
  3001. Swal.getCancelButton().style.display = 'none';
  3002. Swal.showLoading(Swal.getConfirmButton());
  3003. var $swalContent1 = $(Swal.getHtmlContainer());
  3004. $errorList = $swalContent1.find('.errorList');
  3005. $itemContent = $swalContent1.find('.itemContent');
  3006. },
  3007. }).then((result) => {
  3008. if (result.dismiss === Swal.DismissReason.cancel) {
  3009. setTaskCancel();
  3010. console.log('Download Cancel Task');
  3011. Swal.fire({
  3012. title: '已取消,等待进行中的任务结束...',
  3013. html: getTamplate,
  3014. allowOutsideClick: false,
  3015. allowEscapeKey: false,
  3016. confirmButtonText: `完成`,
  3017. footer: footerString,
  3018. willOpen: function() {
  3019. Swal.showLoading(Swal.getConfirmButton());
  3020. var $swalContent1 = $(Swal.getHtmlContainer());
  3021. let html = $errorList.eq[0];
  3022. $errorList = $swalContent1.find('.errorList');
  3023. $errorList.append(html);
  3024. $itemContent = $swalContent1.find('.itemContent');
  3025. },
  3026. });
  3027. }
  3028. });
  3029.  
  3030. } else if (message.messageType == MessageType.PROCESSING) {
  3031. $itemContent.html(message.msg);
  3032. } else if (message.messageType == MessageType.ERROR) {
  3033. $errorList.append('<li><div display: flex;"><p>' + message.msg +
  3034. '</p><p style="font-style: italic;"><\p><\div><\li><li><hr/></li>');
  3035. } else if (message.messageType == MessageType.END) {
  3036. $itemContent.html(message.msg);
  3037. Swal.getTitle().textContent = '操作完成!';
  3038. Swal.getCancelButton().style.display = 'none';
  3039. Swal.getFooter().style.display = 'none';
  3040. Swal.hideLoading();
  3041.  
  3042. } else if (message.messageType == MessageType.CLOSE) {
  3043. Swal.close();
  3044. } else if (message.messageType == MessageType.BEGIN4UPLOAD) {
  3045. Swal.fire({
  3046. title: '正在操作中...',
  3047. html: getTamplate,
  3048. allowOutsideClick: false,
  3049. allowEscapeKey: false,
  3050. confirmButtonText: `完成`,
  3051. denyButtonText: `打开目录`,
  3052. showCancelButton: true,
  3053. cancelButtonText: '取消操作',
  3054. footer: footerString,
  3055. willOpen: function() {
  3056. Swal.getCancelButton().style.display = 'none';
  3057. Swal.getDenyButton().style.display = 'none';
  3058. Swal.showLoading(Swal.getConfirmButton());
  3059. var $swalContent1 = $(Swal.getHtmlContainer());
  3060. $errorList = $swalContent1.find('.errorList');
  3061. $itemContent = $swalContent1.find('.itemContent');
  3062. },
  3063. }).then(result => {
  3064. if (result.dismiss === Swal.DismissReason.cancel) {
  3065. setTaskCancel();
  3066. console.log('Upload Cancel Task');
  3067. console.log(window.parent.document.myData);
  3068. Swal.fire({
  3069. title: '已取消,等待进行中的任务完成...',
  3070. html: getTamplate,
  3071. allowOutsideClick: false,
  3072. allowEscapeKey: false,
  3073. confirmButtonText: `完成`,
  3074. denyButtonText: `打开目录`,
  3075. showCancelButton: false,
  3076. cancelButtonText: '取消操作',
  3077. willOpen: function() {
  3078.  
  3079. Swal.getDenyButton().style.display = 'none';
  3080. Swal.showLoading(Swal.getConfirmButton());
  3081. var $swalContent1 = $(Swal.getHtmlContainer());
  3082. $errorList = $swalContent1.find('.errorList');
  3083. $itemContent = $swalContent1.find('.itemContent');
  3084. },
  3085. });
  3086.  
  3087. }
  3088. });
  3089. } else if (message.messageType == MessageType.END4UPLOAD) {
  3090. $itemContent.html(message.msg);
  3091. Swal.getTitle().textContent = '操作完成!';
  3092. Swal.getCancelButton().style.display = 'none';
  3093. Swal.getDenyButton().style.display = 'block';
  3094. Swal.getDenyButton().addEventListener('click', e => {
  3095. console.log('DenyButton click');
  3096. console.log(message);
  3097. window.location.href = 'https://115.com/?cid=' +
  3098. message.targetID +
  3099. '&offset=0&tab=&mode=wangpan';
  3100. });
  3101. Swal.getFooter().style.display = 'none';
  3102. Swal.hideLoading();
  3103. } else if (message.messageType == MessageType.BEGIN4CONTINUETASK) {
  3104. let taskFile = '';
  3105. Swal.fire({
  3106. title: '导入任务文件,继续任务',
  3107. html: `<div style="text-align: left;">
  3108. 选择任务文件(.7task):<input id="continuedTaskFile" type="file" accept=".7task" ></input>
  3109. <div style="font-size:14px;color:red;margin:10px;text-align: left;">*在没有移动相关的文件以及文件夹,包括目标的所有目录层级,导入任务可继续</div>
  3110. </div>`,
  3111. focusConfirm: false,
  3112. confirmButtonText: `开始继续任务`,
  3113. }).then(t => {
  3114. if (t.isConfirmed && taskFile) {
  3115. ContinuedTask(taskFile);
  3116. }
  3117. });
  3118.  
  3119. document.getElementById('continuedTaskFile').
  3120. addEventListener('change', e => {
  3121. taskFile = e.target.files[0];
  3122. });
  3123.  
  3124. } else if (message.messageType == MessageType.SHOWCANCEl) {
  3125. if (Swal.getCancelButton()) {
  3126. //Swal.getCancelButton().style.display = "block";
  3127. }
  3128. } else if (message.messageType == MessageType.HIDECANCEL) {
  3129. if (Swal.getCancelButton()) {
  3130. Swal.getCancelButton().style.display = 'none';
  3131. }
  3132.  
  3133. } else if (message.messageType == MessageType.FILEDOWNLOAD) {
  3134. console.log(message.msg);
  3135. let size = parseInt(message.msg.onlineFile.size);
  3136. if (size > 2 * 1024 * 1024) {
  3137. postSha1Messgae(createMessage(MessageType.MSGERROR,
  3138. '暂不支持大于2MB的 text|json 文件!'));
  3139. } else {
  3140. Swal.fire({
  3141. title: '正在下载文件...',
  3142. html: `<p>${message.msg.onlineFile.name}</p><p id="processInSwal"></p>`,
  3143. allowOutsideClick: false,
  3144. allowEscapeKey: false,
  3145. confirmButtonText: `完成`,
  3146. showCancelButton: false,
  3147. willOpen: function() {
  3148. Swal.showLoading(Swal.getConfirmButton());
  3149. downloadAFile(message.msg.onlineFile, text => {
  3150. $(Swal.getHtmlContainer()).
  3151. find('#processInSwal').
  3152. html(text);
  3153. }).then(r => {
  3154. if (r.state) {
  3155. console.log(r.text);
  3156. message.msg.config.text = r.text;
  3157.  
  3158. UploadFilesBySha1Links(message.msg.config);
  3159. }
  3160. });
  3161.  
  3162. },
  3163. });
  3164. }
  3165.  
  3166. } else if (message.messageType == MessageType.MSGERROR) {
  3167. Swal.fire({
  3168. icon: 'error',
  3169. text: message.msg,
  3170. });
  3171. } else if (message.messageType == MessageType.JSINFO) {
  3172. Swal.fire({
  3173. icon: 'info',
  3174. text: '脚本与环境信息:(如果报bug,请附带上如下信息)\r\n' + message.msg,
  3175. });
  3176. }
  3177.  
  3178. });
  3179. });
  3180. }
  3181.  
  3182. function delay(ms) {
  3183.  
  3184. if (ms == 0) {
  3185. ms = 1000 * (Math.floor(Math.random() * (11 - 4)) + 4);
  3186. }
  3187. return new Promise(resolve => setTimeout(resolve, ms));
  3188. }
  3189.  
  3190. //#region 115 api
  3191. //get UploadInfo
  3192. //return {state:false,user_id:0,userkey:'0',error:''}
  3193. async function getUploadInfo() {
  3194. const r = await $.ajax({
  3195. url: 'https://proapi.115.com/app/uploadinfo',
  3196. dataType: 'json',
  3197. xhrFields: {
  3198. withCredentials: true,
  3199. },
  3200. });
  3201. return r;
  3202. }
  3203.  
  3204. //add a folder
  3205. //return {state: false, error: "该目录名称已存在。", errno: 20004, errtype: "war"}
  3206. //return {state: true, error: "", errno: "", aid: 1, cid: "2020455078010511975", …}
  3207. async function addFolder(pid, folderName) {
  3208. const postData = PostData({
  3209. pid: pid,
  3210. cname: encodeURIComponent(folderName),
  3211. });
  3212.  
  3213. const r = await $.ajax({
  3214. type: 'POST',
  3215. url: 'https://webapi.115.com/files/add',
  3216. headers: {
  3217. 'Content-Type': 'application/x-www-form-urlencoded',
  3218. //'Origin': 'https://115.com'
  3219. },
  3220. xhrFields: {
  3221. withCredentials: true,
  3222. },
  3223. dataType: 'json',
  3224. data: postData,
  3225. });
  3226.  
  3227. return r;
  3228. }
  3229.  
  3230. //return {data: Array(30), count: 53, data_source: "DB", sys_count: 0, offset: 0, page_size:115, …}
  3231. //return Array type:
  3232. // [folder]:{cid: "", aid: "1", pid: "", n: "", m: 0, …}
  3233. // [file]: {fid: "", uid: 1447812, aid: 1, cid: "", n: "",pc:"",sha:"",s:0,t:"" …}
  3234. async function getDirectChildItemsByOffset(cid, offset) {
  3235. var tUrl = 'https://webapi.115.com/files?aid=1&cid=' + cid +
  3236. '&o=file_name&asc=1&offset=' + offset +
  3237. '&show_dir=1&limit=1150&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&fc_mix=&type=&star=&is_share=&suffix=&custom_order=';
  3238. // var tUrl = "https://aps.115.com/natsort/files.php?aid=1&cid=" + cid + "&o=file_name&asc=1&offset=" + offset + "&show_dir=1&limit=1150&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&fc_mix=0&type=&star=&is_share=&suffix=&custom_order=";
  3239. const result = await $.ajax({
  3240. type: 'GET',
  3241. url: tUrl,
  3242. dataType: 'json',
  3243. xhrFields: {
  3244. withCredentials: true,
  3245. },
  3246. });
  3247. return result;
  3248. }
  3249.  
  3250. //直接子项目少于1200
  3251. async function getDirectChildItemsByOffsetlt1200(cid, offset) {
  3252. //var tUrl = 'https://webapi.115.com/files?aid=1&cid='+cid+'&o=file_name&asc=1&offset='+offset+'&show_dir=1&limit=1150&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&fc_mix=&type=&star=&is_share=&suffix=&custom_order=';
  3253. var tUrl = 'https://aps.115.com/natsort/files.php?aid=1&cid=' + cid +
  3254. '&o=file_name&asc=1&offset=' + offset +
  3255. '&show_dir=1&limit=1150&code=&scid=&snap=0&natsort=1&record_open_time=1&source=&format=json&fc_mix=0&type=&star=&is_share=&suffix=&custom_order=';
  3256. const result = await $.ajax({
  3257. type: 'GET',
  3258. url: tUrl,
  3259. dataType: 'json',
  3260. xhrFields: {
  3261. withCredentials: true,
  3262. },
  3263. });
  3264. return result;
  3265. }
  3266.  
  3267. //return AllDirect items :{id:"",parentID:cid,isFolder:false,name:"",size:0,pc:"",sha:"",paths[] };
  3268. async function getAllDirectItems(cid, folderProcessCallback) {
  3269. var items = new Array();
  3270. var index = 0;
  3271. var flag = true;
  3272. var pageIndex = 1;
  3273. var first = true;
  3274. var isLT1200 = false;
  3275.  
  3276. while (flag) {
  3277. if (getTaskCancelFlag()) break;
  3278.  
  3279. folderProcessCallback(pageIndex);
  3280. var result = null;
  3281. //1200数量,不同的api;这么写减少发包
  3282. if (first) {
  3283. result = await getDirectChildItemsByOffset(cid, index);
  3284. console.log(`first >1200 :${result.state},${result.count}`);
  3285. if (!result.state) {
  3286. result = await getDirectChildItemsByOffsetlt1200(cid, index);
  3287. console.log(`first <1200 :${result.state},${result.count}`);
  3288. isLT1200 = true;
  3289. }
  3290. first = false;
  3291. } else {
  3292. if (isLT1200) result = await getDirectChildItemsByOffsetlt1200(cid,
  3293. index);
  3294. else result = await getDirectChildItemsByOffset(cid, index);
  3295. }
  3296.  
  3297. var totalCount = parseInt(result.count);
  3298. if (totalCount >= 1) {
  3299. result.data.forEach(function(item) {
  3300. var pItem = {
  3301. id: '',
  3302. parentID: cid,
  3303. isFolder: false,
  3304. name: '',
  3305. size: '',
  3306. pickCode: '',
  3307. sha1: '',
  3308. paths: new Array(),
  3309. preid: '',
  3310. needToRemoved: false,
  3311. };
  3312.  
  3313. if (item.fid) //文件 fid,cid
  3314. {
  3315. pItem.isFolder = false;
  3316. pItem.id = item.fid;
  3317. pItem.name = item.n;
  3318. pItem.pickCode = item.pc;
  3319. pItem.sha1 = item.sha;
  3320. pItem.size = item.s;
  3321. } else //目录 cid,pid
  3322. {
  3323. pItem.isFolder = true;
  3324. pItem.id = item.cid;
  3325. pItem.name = item.n;
  3326. pItem.pickCode = item.pc;
  3327. }
  3328.  
  3329. var itemIndex = items.findIndex(
  3330. q => q.name == pItem.name && q.pickCode == pItem.pickCode &&
  3331. q.sha1 == pItem.sha1 &&
  3332. (_.isEqual(q.paths, pItem.paths)));
  3333. if (itemIndex == -1) items.push(pItem);
  3334. else {
  3335. //可能存在同一个目录下,两个文件一模一样,
  3336. //相同文件处理:不然循环条件退不出
  3337. //fix:pickcode不一样,先保存着吧
  3338. pItem.needToRemoved = true;
  3339. items.push(pItem);
  3340. }
  3341. });
  3342. }
  3343.  
  3344. console.log('_______________totalCount ' + totalCount);
  3345. console.log(items.length);
  3346. //当获取到比pagesize小时,获取结束,1200时有个坑。。。
  3347. if (totalCount <= items.length) {
  3348. break;
  3349. } else {
  3350. await delay(500);
  3351. index = items.length;
  3352. pageIndex = pageIndex + 1;
  3353. }
  3354. }
  3355.  
  3356. console.log('cid: {0}, count: {1}'.format(cid, items.length));
  3357.  
  3358. var noNullItems = items.filter(q => !q.needToRemoved);
  3359. console.log(
  3360. 'cid: {0}, 除去完全重复count: {1}'.format(cid, noNullItems.length));
  3361.  
  3362. return noNullItems;
  3363. }
  3364.  
  3365. //return {file_name:"",pick_code:"",sha1:"",count:"",size:"",folder_count:"",paths:[]}
  3366. //return paths:[]层级目录
  3367. async function getFolderInfo(cid) {
  3368. var pUrl = 'https://webapi.115.com/category/get?aid=1&cid=' + cid;
  3369. const result = await $.ajax({
  3370. type: 'GET',
  3371. url: pUrl,
  3372. dataType: 'json',
  3373. xhrFields: {
  3374. withCredentials: true,
  3375. },
  3376. });
  3377. console.log(result);
  3378. var pItem = {
  3379. fileCount: parseInt(result.count),
  3380. folderCount: parseInt(result.folder_count),
  3381. id: cid,
  3382. parentID: '',
  3383. isFolder: true,
  3384. name: result.file_name,
  3385. size: result.size,
  3386. pickCode: result.pick_code,
  3387. sha1: '',
  3388. paths: result.paths,
  3389. preid: '',
  3390. };
  3391.  
  3392. return pItem;
  3393. }
  3394.  
  3395. // get fileArray:{id:"",parentID:cid,isFolder:false,name:"",size:0,pc:"",sha:"",paths[] };
  3396. async function getAllFiles(
  3397. cid, fileArray, topCid, folderProcessCallback) {
  3398. var thisFolder = await getFolderInfo(cid);
  3399. folderProcessCallback(thisFolder.name, 0);
  3400. //空目录,跳过遍历
  3401.  
  3402. if (getTaskCancelFlag()) return;
  3403. if (thisFolder.fileCount == 0) return;
  3404. folderProcessCallback(thisFolder.name);
  3405. var directItems = await getAllDirectItems(thisFolder.id, pageIndex => {
  3406. folderProcessCallback(thisFolder.name, pageIndex);
  3407. });
  3408. //空目录,跳过遍历
  3409. if (directItems.length == 0) return;
  3410. var files = directItems.filter(t => !t.isFolder);
  3411. files.forEach(f => {
  3412. var index = thisFolder.paths.findIndex(
  3413. q => q.file_id.toString() == topCid);
  3414. var paths = new Array();
  3415. if (index != -1) {
  3416. paths = thisFolder.paths.slice(index).map(q => q.file_name);
  3417. }
  3418. paths.push(thisFolder.name);
  3419. f.paths = paths.slice(1);
  3420.  
  3421. fileArray.push(f);
  3422. });
  3423.  
  3424. var folders = directItems.filter(t => t.isFolder);
  3425. for (var folder of folders) {
  3426. if (getTaskCancelFlag()) break;
  3427. await getAllFiles(folder.id, fileArray, topCid,
  3428. folderProcessCallback);
  3429. await delay(200);
  3430. }
  3431.  
  3432. }
  3433.  
  3434. //批量重命名 fileArray [{id:id,name:ddd}]
  3435. //{"state":true,"error":"","errno":0,"data":{"2187365717527997108":"14214.mp4"}}
  3436. async function renameFiles(fileArray) {
  3437. console.log('renameFiles fileArray');
  3438. console.log(fileArray);
  3439. let datas = fileArray.map((value, index, array) => {
  3440. let dataKey = `files_new_name[${value.id}]`;
  3441. let dataValue = value.name;
  3442. return `${encodeURIComponent(dataKey)}=${encodeURIComponent(
  3443. dataValue)}`;
  3444. }).join('&');
  3445.  
  3446. let renameUrl = 'https://webapi.115.com/files/batch_rename';
  3447. const result = await $.ajax({
  3448. type: 'POST',
  3449. url: renameUrl,
  3450. headers: {
  3451. 'Content-Type': 'application/x-www-form-urlencoded',
  3452. //'Origin': 'https://115.com'
  3453. },
  3454. dataType: 'json',
  3455. xhrFields: {
  3456. withCredentials: true,
  3457. },
  3458. data: datas,
  3459. });
  3460.  
  3461. return result;
  3462. }
  3463.  
  3464. async function getUploadHistory(offset, limit) {
  3465. let historyFiles = [];
  3466. let pUrl = `https://webapi.115.com/history/list?type=4&offset=${offset}&limit=${limit}`;
  3467. const result = await $.ajax({
  3468. type: 'GET',
  3469. url: pUrl,
  3470. dataType: 'json',
  3471. xhrFields: {
  3472. withCredentials: true,
  3473. },
  3474. });
  3475.  
  3476. let files = result.data.list;
  3477. for (const aFile of files) {
  3478. historyFiles.push({
  3479. sha1: aFile.sha1,
  3480. id: aFile.file_id,
  3481. createTime: aFile.create_time,
  3482. pickCode: aFile.pick_code, //可能不一样
  3483. name: aFile.file_name,
  3484. parentID: aFile.parent_id,
  3485. });
  3486. }
  3487.  
  3488. return historyFiles;
  3489. }
  3490.  
  3491. async function getLastUploadFiles(
  3492. count, delayTime = 200, processCallback) {
  3493. let files = [];
  3494. let offset = 0;
  3495. let limit = 115;
  3496. let leftCount = count;
  3497. while (leftCount >= limit) {
  3498. processCallback(`正在获取第${offset + 1}-${offset + limit + 1}个文件数据...`);
  3499. let result = await getUploadHistory(offset, limit);
  3500. result.forEach(f => files.push(f));
  3501. offset = offset + limit;
  3502. leftCount = leftCount - limit;
  3503. await delay(delayTime);
  3504. }
  3505. if (leftCount > 0) {
  3506. processCallback(
  3507. `正在获取第${offset + 1}-${offset + leftCount + 1}个文件数据...`);
  3508. let result = await getUploadHistory(offset, leftCount);
  3509. result.forEach(f => files.push(f));
  3510. }
  3511.  
  3512. return files;
  3513. }
  3514.  
  3515. //获取生成sha1需要preid
  3516. //return: {state:,error:,fileItem:}
  3517. function getFileItemPreid(fileItem) {
  3518. console.log('getFileItemPreid');
  3519. console.log(fileItem);
  3520. const f = fileItem;
  3521. let fileSize = parseInt(fileItem.size);
  3522. if (fileSize == 0) {
  3523. return new Promise((resolve, reject) => {
  3524. const errorMsg = '{0} 文件大小为0,已经跳过!'.format(f.filename);
  3525. console.error('errorMsg');
  3526. resolve({
  3527. state: false,
  3528. error: '文件大小为0,已经跳过!',
  3529. fileItem: fileItem,
  3530. });
  3531. });
  3532. }
  3533.  
  3534. const r = new Promise((resolve, reject) => {
  3535. var data, key, tm, tmus;
  3536. tmus = (new Date()).getTime();
  3537. tm = Math.floor(tmus / 1000);
  3538. var test = JSON.stringify({
  3539. pickcode: fileItem.pickCode,
  3540. });
  3541. console.log(
  3542. '111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111');
  3543. console.log(fileItem.pickCode, test, tm);
  3544. ({data, key} = m115_encode(test, tm));
  3545. console.log("开始")
  3546. //开始做种
  3547. GM_xmlhttpRequest({
  3548. method: "POST",
  3549. url: 'https://proapi.115.com/app/chrome/downurl?t=' + tm,
  3550. headers: {
  3551. 'Content-Type': 'application/x-www-form-urlencoded',
  3552. 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)'
  3553. },
  3554. responseType: 'json',
  3555. data: PostData({
  3556. data: encodeURIComponent(data)
  3557. }),
  3558. onload: function(r) {
  3559. if (r.status == 200) {
  3560. var download_info = r.response;
  3561.  
  3562. if (download_info.state && download_info.data) {
  3563. console.log(download_info.data, key)
  3564. var json = m115_decode(download_info.data, key);
  3565. console.log(
  3566. '666666666666666666666666666666666666666666666666666666666666666666666')
  3567. var url = JSON.parse(json)[fileItem.id]['url']['url'];
  3568. //todo:不能下载的文件处理
  3569. if (!url.startsWith("http://cdnfhnfdfs.115.com") &&
  3570. url.startsWith('http:///')) {
  3571. console.error(`error url:${url}`);
  3572. url = url.replace("http:///",
  3573. "http://cdnfhnfdfs.115.com/")
  3574. }
  3575.  
  3576. //获取文件下载链接
  3577. console.log(url);
  3578. var base64 = new Base64()
  3579.  
  3580. console.log(base64.encode(url))
  3581.  
  3582. GM_xmlhttpRequest({
  3583. method: 'POST',
  3584. url: 'https://api.115211.xyz/api/seed',
  3585. headers: {
  3586. 'Content-Type': 'application/x-www-form-urlencoded',
  3587. 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
  3588. },
  3589. responseType: 'json',
  3590. data: PostData({
  3591. name: fileItem.name,
  3592. size: fileItem.size,
  3593. sha1: fileItem.sha1,
  3594. url: base64.encode(url)
  3595. }),
  3596. onload: function(res) {
  3597. console.log(res)
  3598. let resInfo = res.response;
  3599. if (resInfo.status == 2) {
  3600. //秒传成功
  3601. // var pre_buff = response.response;
  3602. // var data = new Uint8Array(pre_buff);
  3603. // var sha1 = new jsSHA('SHA-1', 'ARRAYBUFFER');
  3604. // sha1.update(data.slice(0, 128 * 1024));
  3605. // var preid = sha1.getHash('HEX', {
  3606. // outputUpper: true
  3607. // });
  3608. fileItem.preid = "0EEE99A4ED0A1844DA8B6FEF7306067F6156E4B5";
  3609. resolve({
  3610. state: true,
  3611. error: "",
  3612. fileItem: fileItem
  3613. });
  3614. }else{
  3615.  
  3616. }
  3617. }
  3618. })
  3619. }
  3620. }
  3621. }
  3622. })
  3623.  
  3624.  
  3625.  
  3626.  
  3627.  
  3628.  
  3629.  
  3630. // GM_xmlhttpRequest({
  3631. // method: "POST",
  3632. // url: 'https://proapi.115.com/app/chrome/downurl?t='+tm,
  3633. // headers: {
  3634. // 'Content-Type': 'application/x-www-form-urlencoded',
  3635. // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 115Browser/23.9.3.6'
  3636. // 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
  3637. // },
  3638. // responseType: 'json',
  3639. // data: PostData({
  3640. // data: encodeURIComponent(data)
  3641. // }),
  3642. // onload: function (r) {
  3643. // if (r.status == 200) {
  3644. // var download_info = r.response;
  3645. //
  3646. //
  3647. // if (download_info.state && download_info.data) {
  3648. // try {
  3649. // console.log(download_info.data,key)
  3650. // var json = m115_decode(download_info.data,key);
  3651. // console.log(json)
  3652. // console.log(JSON.parse(json))
  3653. // console.log('666666666666666666666666666666666666666666666666666666666666666666666')
  3654. // var url = JSON.parse(json)[fileItem.id]['url']['url'];
  3655. // //todo:不能下载的文件处理
  3656. // if (!url.startsWith("http://cdnfhnfdfs.115.com") && url.startsWith('http:///')) {
  3657. // console.error(`error url:${url}`);
  3658. // url = url.replace("http:///", "http://cdnfhnfdfs.115.com/")
  3659. // }
  3660. //
  3661. // //获取文件下载链接
  3662. // console.log(url);
  3663. // var resp = r.responseHeaders
  3664. // var setCookie = DeleteCookie(resp)
  3665. // var fileCookie = null;
  3666. // if (setCookie) {
  3667. // fileCookie = setCookie;
  3668. // }
  3669. //
  3670. // GM_xmlhttpRequest({
  3671. // method: "GET",
  3672. // url: url,
  3673. // timeout: 12000,
  3674. // headers: {
  3675. // "Range": "bytes=0-131072",
  3676. // "Cookie": fileCookie,
  3677. // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 115Browser/23.9.3.6'
  3678. // 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
  3679. // },
  3680. // responseType: 'arraybuffer',
  3681. // onload: function (response) {
  3682. // if (response.status === 206) {
  3683. // var pre_buff = response.response;
  3684. // var data = new Uint8Array(pre_buff);
  3685. // var sha1 = new jsSHA('SHA-1', 'ARRAYBUFFER');
  3686. // sha1.update(data.slice(0, 128 * 1024));
  3687. // var preid = sha1.getHash('HEX', {
  3688. // outputUpper: true
  3689. // });
  3690. // fileItem.preid = preid;
  3691. // resolve({
  3692. // state: true,
  3693. // error: "",
  3694. // fileItem: fileItem
  3695. // });
  3696. // } else if (response.status === 403) {
  3697. // console.error("Forbidden, 已经用40个0代替");
  3698. // fileItem.preid = "0000000000000000000000000000000000000000";
  3699. // resolve({
  3700. // state: true,
  3701. // error: "",
  3702. // fileItem: fileItem
  3703. // });
  3704. // } else {
  3705. // //fix v3.3: 修复404文件无法下载导致卡ui问题 @指环王
  3706. // console.error("可能文件无法下载或者网络问题");
  3707. // console.log(response);
  3708. // resolve({
  3709. // state: false,
  3710. // error: "下载出错,可能文件无法下载或者网络问题",
  3711. // fileItem: fileItem
  3712. // });
  3713. // }
  3714. // },
  3715. // ontimeout: function (res) {
  3716. // console.error("下载超时,可能文件无法下载或者网络问题");
  3717. // console.log(res);
  3718. // resolve({
  3719. // state: false,
  3720. // error: "下载超时,可能文件无法下载或者网络问题",
  3721. // fileItem: fileItem
  3722. // });
  3723. // }
  3724. // });
  3725. // } catch (error) {
  3726. // console.error(error);
  3727. // resolve({
  3728. // state: false,
  3729. // error: "在提取中发生错误...",
  3730. // fileItem: fileItem
  3731. // });
  3732. // }
  3733. // } else {
  3734. // console.log(download_info);
  3735. // resolve({
  3736. // state: false,
  3737. // error: download_info.msg,
  3738. // fileItem: fileItem
  3739. // });
  3740. // }
  3741. //
  3742. // } else {
  3743. // console.error(response.response);
  3744. // resolve({
  3745. // state: false,
  3746. // error: "在提取中发生错误...",
  3747. // fileItem: fileItem
  3748. // });
  3749. // }
  3750. // }
  3751. // });
  3752. })
  3753. ;
  3754. return r;
  3755. }
  3756.  
  3757. var utf8ArrayToStr = (function() {
  3758. var charCache = new Array(128); // Preallocate the cache for the common single byte chars
  3759. var charFromCodePt = String.fromCodePoint || String.fromCharCode;
  3760. var result = [];
  3761.  
  3762. return function(array) {
  3763. var codePt, byte1;
  3764. var buffLen = array.length;
  3765.  
  3766. result.length = 0;
  3767.  
  3768. for (var i = 0; i < buffLen;) {
  3769. byte1 = array[i++];
  3770.  
  3771. if (byte1 <= 0x7F) {
  3772. codePt = byte1;
  3773. } else if (byte1 <= 0xDF) {
  3774. codePt = ((byte1 & 0x1F) << 6) | (array[i++] & 0x3F);
  3775. } else if (byte1 <= 0xEF) {
  3776. codePt = ((byte1 & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) |
  3777. (array[i++] & 0x3F);
  3778. } else if (String.fromCodePoint) {
  3779. codePt = ((byte1 & 0x07) << 18) | ((array[i++] & 0x3F) << 12) |
  3780. ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
  3781. } else {
  3782. codePt = 63; // Cannot convert four byte code points, so use "?" instead
  3783. i += 3;
  3784. }
  3785.  
  3786. result.push(charCache[codePt] ||
  3787. (charCache[codePt] = charFromCodePt(codePt)));
  3788. }
  3789.  
  3790. return result.join('');
  3791. };
  3792. })();
  3793.  
  3794. function downloadAFile(fileItem, progressCallback = function(text) {
  3795. }) {
  3796. console.log('downloadAFile');
  3797. console.log(fileItem);
  3798. console.log(
  3799. '999999999999999999999999999999999999999999999999999999999999999999');
  3800. const r = new Promise((resolve, reject) => {
  3801. var data, key, tm, tmus;
  3802. tmus = (new Date()).getTime();
  3803. tm = Math.floor(tmus / 1000);
  3804. var test = JSON.stringify({
  3805. pickcode: fileItem.pickCode,
  3806. });
  3807. console.log(fileItem.pickCode, test, tm);
  3808. ({data, key} = m115_encode(test, tm));
  3809. GM_xmlhttpRequest({
  3810. method: 'POST',
  3811. url: 'https://proapi.115.com/app/chrome/downurl?t=' + tm,
  3812. headers: {
  3813. 'Content-Type': 'application/x-www-form-urlencoded',
  3814. // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 115Browser/23.9.3.6',
  3815. 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
  3816. },
  3817. responseType: 'json',
  3818. data: PostData({
  3819. data: encodeURIComponent(data),
  3820. }),
  3821. onload: function(r) {
  3822. if (r.status == 200) {
  3823. var download_info = r.response;
  3824. if (download_info.state && download_info.data) {
  3825. try {
  3826. var json = m115_decode(download_info.data, key);
  3827. //console.log(json)
  3828. var url = JSON.parse(json)[fileItem.id]['url']['url'];
  3829. //todo:不能下载的文件处理
  3830. if (!url.startsWith('http://cdnfhnfdfs.115.com') &&
  3831. url.startsWith('http:///')) {
  3832. console.error(`error url:${url}`);
  3833. url = url.replace('http:///',
  3834. 'http://cdnfhnfdfs.115.com/');
  3835. }
  3836.  
  3837. console.log(url);
  3838. var resp = r.responseHeaders;
  3839. var setCookie = DeleteCookie(resp);
  3840. var fileCookie = null;
  3841. if (setCookie) {
  3842. fileCookie = setCookie;
  3843. }
  3844.  
  3845. GM_xmlhttpRequest({
  3846. method: 'GET',
  3847. url: url,
  3848. headers: {
  3849. 'Content-Type': 'application/octet-stream',
  3850. 'Cookie': fileCookie,
  3851. // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 115Browser/23.9.3.6',
  3852. 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
  3853. },
  3854. responseType: 'arraybuffer',
  3855. onload: function(response) {
  3856. if (response.status === 200) {
  3857. let str = utf8ArrayToStr(
  3858. new Uint8Array(response.response));
  3859. resolve({
  3860. state: true,
  3861. error: '',
  3862. text: str,
  3863. });
  3864. } else {
  3865.  
  3866. console.error(response);
  3867. resolve({
  3868. state: false,
  3869. error: `response.status:${response.status}`,
  3870. text: '',
  3871. });
  3872.  
  3873. }
  3874.  
  3875. },
  3876. onprogress: function(event) {
  3877. let textMsg = `${event.loaded} of ${event.total} bytes, ${(event.loaded /
  3878. event.total).toFixed(4) * 100}%`;
  3879. console.log(textMsg);
  3880. progressCallback(textMsg);
  3881. },
  3882.  
  3883. });
  3884. } catch (error) {
  3885. console.error(error);
  3886. resolve({
  3887. state: false,
  3888. error: `${error}`,
  3889. text: '',
  3890. });
  3891.  
  3892. }
  3893. } else {
  3894. console.log(download_info);
  3895. resolve({
  3896. state: false,
  3897. error: download_info.msg,
  3898. text: '',
  3899. });
  3900. }
  3901.  
  3902. } else {
  3903. console.log('下载第一阶段');
  3904. console.error(response.response);
  3905. resolve({
  3906. state: false,
  3907. error: `在下载中发生错误...${response.status}`,
  3908. text: '',
  3909. });
  3910. }
  3911. },
  3912. });
  3913. });
  3914. return r;
  3915. }
  3916.  
  3917. //windows平台上限制的字符:/\|":*?<> 其他平台比windows宽泛一些
  3918. function repalceValidatedName(name) {
  3919. return name.replace(/</g, '[').
  3920. replace(/>/g, ']').
  3921. replace(/\|/g, '_').
  3922. replace(/:/g, '_').
  3923. replace(/\//g, '_').
  3924. replace(/\\/g, '_').
  3925. replace(/\*/g, '_').
  3926. replace(/"/g, '\'').
  3927. replace(/\?/g, '_');
  3928. }
  3929.  
  3930. //格式化sha1 链接
  3931. //return type: {state:succeed,msg:""}
  3932. // false:msg->出错信息
  3933. //true: msg->sha1链接
  3934. function convertToSha1Link(fileItem, isSimpleFormat) {
  3935. var succeed = false;
  3936. var msg = '格式生成失败!';
  3937. if (fileItem.name && fileItem.size && fileItem.sha1 && fileItem.preid) {
  3938. var serverId = 50660199;
  3939. var paths = '';
  3940. //生成最终的115SHA1链接
  3941. // var sha1Link = "115://" + repalceValidatedName(fileItem.name) + "|" + fileItem.size + "|" + fileItem.sha1 + "|" + fileItem.preid;
  3942. var sha1Link = '211://' + repalceValidatedName(fileItem.name) + '|' +
  3943. fileItem.size + '|' + fileItem.sha1 + '|' + serverId;
  3944. if (!isSimpleFormat) {
  3945. if (fileItem.paths.length > 0) {
  3946. //console.log(fileItem.paths);
  3947. //fix: v3.3 目录中的‘|’或者‘#’替换为‘/’,防止脚本导出再导入时破坏目录结构
  3948. //fix: v3.4 windows平台上不能限制的字符:/\|":*?<> 替换;去掉了老版本的#分隔符
  3949. paths = fileItem.paths.map(t => repalceValidatedName(t)).
  3950. join('/');
  3951. // msg = sha1Link + '|' + paths;
  3952. }
  3953. }
  3954. msg = sha1Link + '|' + paths + '|' + fileItem.pickCode;
  3955. ;
  3956. succeed = true;
  3957. }
  3958.  
  3959. return {
  3960. state: succeed,
  3961. msg: msg,
  3962. };
  3963. }
  3964.  
  3965. // 从sha1link 转换为 FileItem
  3966. //return type:{state:succeed,fileItem:{}}
  3967. //true: fileItem, false:null
  3968. function convertFromSha1Link(sha1Link) {
  3969. var succeed = false;
  3970. var item = {};
  3971. if (sha1Link) {
  3972. if (sha1Link.startsWith('115://')) {
  3973. sha1Link = sha1Link.substring(6);
  3974. }
  3975. //v3.4 add 转存时,文件名、文件夹名替换非法字符
  3976. var infos = sha1Link.split('|');
  3977. if (infos.length >= 4) {
  3978. item.id = '';
  3979. item.pickCode = '';
  3980. item.name = repalceValidatedName(infos[0]);
  3981. item.size = infos[1];
  3982. item.sha1 = infos[2];
  3983. item.preid = infos[3];
  3984. item.parentID = '';
  3985. item.paths = new Array();
  3986. if (infos.length > 4) {
  3987. //fix: v3.4 移除了此兼容,因为开放了#作为目录名
  3988. // if (infos.length == 5 && infos[4].includes('#')) {
  3989. //兼容 #字符分割
  3990.  
  3991. // item.paths = infos[4].split('#');
  3992. //} else {
  3993. item.paths = infos.slice(4).map(t => repalceValidatedName(t));
  3994. //}
  3995. }
  3996. item.extension = '';
  3997. item.formatedName = '';
  3998. succeed = true;
  3999. }
  4000. }
  4001.  
  4002. return {
  4003. state: succeed,
  4004. fileItem: item,
  4005. };
  4006. }
  4007.  
  4008. function createUploadFile(urlData, postData) {
  4009. return new Promise((resolve, reject) => {
  4010. GM_xmlhttpRequest({
  4011. method: 'POST',
  4012. url: 'http://uplb.115.com/3.0/initupload.php?' + urlData,
  4013. data: postData,
  4014. responseType: 'json',
  4015. headers: {
  4016. 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
  4017. // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 115Browser/25.0.0.3',
  4018. 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
  4019. //'Origin': 'https://115.com'
  4020. },
  4021. onload: function(response) {
  4022. let data = {
  4023. state: false,
  4024. error: '',
  4025. pickCode: '',
  4026. };
  4027. if (response.status === 200 && response.response.status === 2) {
  4028. data.state = true;
  4029. data.pickCode = response.response.pickcode;
  4030. } else {
  4031. console.error(response);
  4032. let error = '或许sha1链接不匹配(?)';
  4033. if (response.status === 405) {
  4034. error = '频繁请求,被115限制 ([!]立即停止,尝试停止操作半小时或者重新登录(不可用)):' +
  4035. response.statusText;
  4036. } else if (response.response &&
  4037. response.response.message) error = response.response.message;
  4038. else if (response.response &&
  4039. response.response.statusmsg) error = '可能参数不正确(?):' +
  4040. response.response.statusmsg;
  4041. data.error = error;
  4042. }
  4043. resolve(data);
  4044. },
  4045. });
  4046.  
  4047. });
  4048. }
  4049.  
  4050. //return:{state:false,error:"",fileItem:};
  4051. function uploadFile(targetFolder, fileItem, uploadInfo) {
  4052.  
  4053. let fCid = `U_1_${targetFolder}`;
  4054. let appVersion = '25.0.0.3';
  4055. const secret = 'Qclm8MGWUv59TnrR0XPg';
  4056. console.log(fCid);
  4057. let time = (new Date()).getTime();
  4058. let ts = Math.floor(time / 1000);
  4059. console.log(fileItem);
  4060. console.log(uploadInfo);
  4061.  
  4062. console.log();
  4063. console.log(
  4064. `${secret}${fileItem.sha1}${fileItem.size}${fileItem.preid}${uploadInfo.user_id}${ts}${md5(
  4065. uploadInfo.user_id)}${appVersion}`);
  4066. let uploadToken = md5(
  4067. `${secret}${fileItem.sha1}${fileItem.size}${fileItem.preid}${uploadInfo.user_id}${ts}${md5(
  4068. uploadInfo.user_id)}${appVersion}`);
  4069.  
  4070. let urlData = UrlData({
  4071. isp: 0,
  4072. appid: 0,
  4073. topupload: 0,
  4074. rt: 0,
  4075. appversion: appVersion,
  4076. format: 'json',
  4077. sig: GetSig(uploadInfo.user_id, fileItem.sha1, fCid,
  4078. uploadInfo.userkey),
  4079. t: ts,
  4080. token: uploadToken,
  4081. });
  4082.  
  4083. let postData = PostData({
  4084. preid: fileItem.preid,
  4085. fileid: fileItem.sha1,
  4086. quickid: fileItem.sha1,
  4087. app_ver: appVersion,
  4088. filename: encodeURIComponent(fileItem.formatedName),
  4089. filesize: fileItem.size,
  4090. exif: '',
  4091. target: fCid,
  4092. userid: uploadInfo.user_id,
  4093.  
  4094. });
  4095. console.log(urlData);
  4096. console.log(postData);
  4097.  
  4098. // const r = createUploadFile(urlData, postData);
  4099.  
  4100. // const x = r.then(t => {
  4101. // return new Promise((resole, reject) => {
  4102. // fileItem.state = t.state;
  4103. // fileItem.pickCode = t.pickCode;
  4104. // resole({
  4105. // state: t.state,
  4106. // error: t.error,
  4107. // fileItem: fileItem
  4108. // });
  4109. // })
  4110. // });
  4111.  
  4112. // return x;
  4113. }
  4114.  
  4115. //设置列表视图
  4116. function setListView() {
  4117. GM_xmlhttpRequest({
  4118. method: 'POST',
  4119. url: 'https://115.com/?ct=user_setting&ac=set',
  4120. headers: {
  4121. 'Content-Type': 'application/x-www-form-urlencoded',
  4122. },
  4123. data: PostData({
  4124. setting: '{"view_file":"list"}',
  4125. }),
  4126. responseType: 'json',
  4127. onload: function(response) {
  4128. if (response.status === 200) {
  4129. }
  4130. },
  4131. });
  4132. }
  4133.  
  4134. //#endregion
  4135.  
  4136. //更新父ID
  4137. async function updateParentID(
  4138. cid, cname, thisLevel, maxLevel, items, sleepTime,
  4139. createFolderCallback) {
  4140. if (thisLevel == maxLevel) return;
  4141. let files = new Array();
  4142. if (thisLevel == 0) {
  4143. files = items;
  4144. } else {
  4145. files = items.filter(f => f.paths[thisLevel - 1] == cname);
  4146. }
  4147.  
  4148. let childFiles = files.filter(q => q.paths.length == thisLevel);
  4149. let childFolderNames = files.map(q => q.paths[thisLevel]).
  4150. filter(q => q).
  4151. filter((x, i, a) => a.indexOf(x) == i);
  4152.  
  4153. console.log(`childFiles ${childFiles.length}`);
  4154. //upload file:
  4155. for (let file of childFiles) {
  4156. file.parentID = cid;
  4157. //console.log(file.parentID);
  4158. }
  4159.  
  4160. //create folder:
  4161. for (let folderName of childFolderNames) {
  4162.  
  4163. let r = await createRootFolder(cid, folderName, 10, sleepTime,
  4164. callbackMsg => {
  4165. createFolderCallback && createFolderCallback({
  4166. state: true,
  4167. folderName: folderName,
  4168. error: callbackMsg,
  4169. });
  4170. });
  4171.  
  4172. //fix: v3.4 有同名文件夹,处理跟根目录相同处理。如果超过重试次数的逻辑未处理
  4173. //let r = await addFolder(cid, folderName);
  4174. console.log(r);
  4175.  
  4176. if (r.state) {
  4177. await updateParentID(r.cid, folderName, thisLevel + 1, maxLevel,
  4178. files, createFolderCallback);
  4179. } else { //ui 目录创建失败
  4180. //todo: !!!尚未解决这个
  4181. console.error(`updateParentID 如果出现这个,说明重复名字的文件夹也太太太多了`);
  4182. }
  4183.  
  4184. await delay(sleepTime);
  4185. }
  4186.  
  4187. }
  4188.  
  4189. function internelFormat(folder, files, folderParents) {
  4190. var paths = folderParents.slice(0);
  4191. paths.push(folder.dir_name);
  4192.  
  4193. for (var file of folder.files) {
  4194.  
  4195. var link = file + '|' + paths.slice(1).join('|');
  4196. files.push(link);
  4197. }
  4198.  
  4199. for (var childFolder of folder.dirs) {
  4200.  
  4201. internelFormat(childFolder, files, paths);
  4202. }
  4203. }
  4204.  
  4205. //格式化为普通json
  4206. //{state:true,error:"",text:""}
  4207. function formatJsonToCommon(text) {
  4208.  
  4209. try {
  4210. var root = JSON.parse(text);
  4211. console.log(root);
  4212. var files = new Array();
  4213. var paths = new Array();
  4214. internelFormat(root, files, paths);
  4215.  
  4216. return {
  4217. state: true,
  4218. error: '',
  4219. text: files.join('\r\n'),
  4220. rootFolder: root.dir_name,
  4221. };
  4222. } catch (error) {
  4223. return {
  4224. state: false,
  4225. error: error,
  4226. text: '',
  4227. };
  4228. }
  4229.  
  4230. }
  4231.  
  4232. //解析Sha1链接到文件数组
  4233. //解析inline text sha1 links,并根据配置设置分隔符;返回FileArray
  4234. function parseSha1LinksToFileArray(text, nameSeparator, errorCallback) {
  4235. let textLines = text.split(/\r?\n/);
  4236.  
  4237. let files = new Array();
  4238. for (let line of textLines) {
  4239. let fLine = line.trim();
  4240. if (!fLine) continue;
  4241. let r = convertFromSha1Link(fLine);
  4242. if (r.state) {
  4243. let nameStrings = r.fileItem.name.split('.');
  4244. let extension = nameStrings.pop();
  4245. r.fileItem.extension = extension;
  4246. //根据配置重新设置文件名
  4247. if (nameSeparator) {
  4248. //使用emoutils.js库来分割,带有emoji的文件名
  4249. let fileName = emojiUtils.toArray(nameStrings.join('.')).
  4250. map(c => c + nameSeparator).
  4251. join('').
  4252. slice(0, -1);
  4253. r.fileItem.formatedName = fileName + '.' + extension;
  4254. } else {
  4255. r.fileItem.formatedName = r.fileItem.name;
  4256. }
  4257. files.push(r.fileItem);
  4258. } else {
  4259. errorCallback && errorCallback(`${fLine} 格式错误?`);
  4260. }
  4261.  
  4262. }
  4263.  
  4264. return files;
  4265. }
  4266.  
  4267. //fix: v3.4 时间日期中含有"/",":"导致目录或者文件下载失败
  4268. function getCurrentTimeString() {
  4269. let time = new Date();
  4270. let timeString = `${time.toLocaleString()} (${time.getMilliseconds()})`;
  4271. return timeString.replace(/\//g, '.').replace(/:/g, '.');
  4272. }
  4273.  
  4274. //在targetCid下创建目录,成功则返回新目录cid,否则返回原cid;返回’-1‘,target已经被移除或者删除
  4275. async function createRootFolder(
  4276. targetCid, folderName, retryTimes, sleepTime, processCallback) {
  4277. let cid = targetCid;
  4278. let newFolderName = folderName;
  4279.  
  4280. if (folderName == '') {
  4281.  
  4282. newFolderName = `auto_create@${getCurrentTimeString()}`;
  4283. }
  4284.  
  4285. for (let i = 0; i < retryTimes; i++) {
  4286.  
  4287. if (i != 0) {
  4288.  
  4289. newFolderName = `${folderName == '' ?
  4290. 'auto_create' :
  4291. folderName}@${getCurrentTimeString()}`;
  4292. }
  4293.  
  4294. processCallback && processCallback(`正在自动创建目录${newFolderName}...`);
  4295. let tr = await addFolder(targetCid, newFolderName);
  4296. if (tr.state) {
  4297. cid = tr.cid;
  4298. processCallback && processCallback(`自动创建目录${newFolderName}成功!`);
  4299. break;
  4300. } else {
  4301.  
  4302. processCallback && processCallback(
  4303. `自动创建目录${newFolderName}失败!原因:${tr.error},将自动尝试新的名字...`);
  4304. if (tr.error.includes('云端目录不存在') ||
  4305. tr.error.includes('文件不存在或已删除')) {
  4306. cid = '-1'; //父目录不存在时的提示
  4307. break;
  4308. }
  4309. await delay(sleepTime);
  4310. }
  4311. }
  4312.  
  4313. let state = cid != '-1';
  4314. let error = state ? '' : '云端目录之前已经删除,请重新选择保存位置!';
  4315. //todo:父目录不存在时的提示
  4316. return {
  4317. cid: cid,
  4318. folderName: newFolderName,
  4319. state: state,
  4320. error: error,
  4321. };
  4322. }
  4323.  
  4324. //上传超时文件
  4325. function uploadFileWithTimeOut(timeOut, fileParentID, file, uploadInfo) {
  4326. console.log('uploadFileWithTimeOut');
  4327. let to = delay(timeOut).then(t => {
  4328. return {
  4329. state: false,
  4330. error: `等待上传结果超时,此乃警告!成功与否,看最后统计结果!`,
  4331. fileItem: file,
  4332. };
  4333. });
  4334. let up = uploadFile(fileParentID, file, uploadInfo);
  4335.  
  4336. return Promise.race([to, up]);
  4337. }
  4338.  
  4339. //上传过程
  4340. async function processUpload(
  4341. allFiles, workingNumber, sleepTime, resultCallback) {
  4342. let fileArray = allFiles.filter(q => !q.state);
  4343. let index = 1;
  4344. let fileLength = allFiles.length;
  4345. let completed = fileLength - fileArray.length;
  4346. let promisArray = new Array();
  4347. let uploadInfo = await getUploadInfo();
  4348. let msg;
  4349. for (let file of fileArray) {
  4350. if (getTaskCancelFlag()) {
  4351. console.log('转存取消');
  4352. //postSha1Messgae(createMessage(MessageType.PROCESSING, "已取消,正在等待进行中的任务结束..."));
  4353. break;
  4354. }
  4355. console.log(file);
  4356.  
  4357. //let r = uploadFile(file.parentID, file, uploadInfo).then(t => {
  4358. let r = uploadFileWithTimeOut(8000, file.parentID, file, uploadInfo).
  4359. then(t => {
  4360. completed = completed + 1;
  4361. if (t.state) {
  4362. msg = `<div align="right"><b>${completed}</b> | <b>${fileLength}</b></div><hr>【 <b>${t.fileItem.name}</b> 】上传成功.`;
  4363. } else {
  4364. let uploadError = `【 <b>${t.fileItem.name}</b> 】: ${t.error}`;
  4365. resultCallback && resultCallback({
  4366. state: false,
  4367. msg: uploadError,
  4368. });
  4369. msg = `<div align="right"><b>${completed}</b> | <b>${fileLength}</b></div><hr>${uploadError}`;
  4370. }
  4371. resultCallback && resultCallback({
  4372. state: true,
  4373. msg: msg,
  4374. });
  4375. });
  4376.  
  4377. promisArray.push(r);
  4378.  
  4379. if (index % workingNumber == 0) {
  4380. await delay(sleepTime);
  4381. }
  4382.  
  4383. if (index % 128 == 0) {
  4384. await Promise.all(promisArray);
  4385. let seconds = 3;
  4386. for (let i = 0; i < seconds; i++) {
  4387. resultCallback && resultCallback({
  4388. state: true,
  4389. msg: `防止115服务器限制,暂停发包。<br><br>${seconds - i}秒后继续....`,
  4390. });
  4391. await delay(1000);
  4392. }
  4393. promisArray = new Array();
  4394. }
  4395. index = index + 1;
  4396. }
  4397.  
  4398. await delay(500);
  4399. await Promise.all(promisArray);
  4400.  
  4401. return fileArray;
  4402. }
  4403.  
  4404. // v3.3 转存时获取文件从历史上传中获取,如果文件夹众多,此方案速度优势明显,但不允许多页面操作
  4405. async function processRenameByUsingHistory(
  4406. files, separator, sleepTime, resultCallback) {
  4407.  
  4408. let history = await getLastUploadFiles(files.length, sleepTime, t => {
  4409. resultCallback({
  4410. state: true,
  4411. msg: t,
  4412. });
  4413. });
  4414.  
  4415. resultCallback({
  4416. state: true,
  4417. msg: '正在等待重命名...如果文件较多,请等待;或者停止,等以后手动操作去除分隔符。',
  4418. });
  4419. //fix: v3.3.1 修复含有重复文件的时候,未所有完成重命名的bug
  4420. history.forEach(q => q.isMarked = false);
  4421. for (const file of files) {
  4422. //console.log("file")
  4423. //console.log(file)
  4424. let thisFile = history.find(
  4425. q => q.sha1 == file.sha1 && q.parentID == file.parentID &&
  4426. q.name ==
  4427. file.formatedName && !q.isMarked);
  4428. //console.log("thisFile")
  4429. //console.log(thisFile)
  4430. if (thisFile) {
  4431. file.id = thisFile.id;
  4432. thisFile.isMarked = true;
  4433. } else {
  4434. console.error(`历史记录里未找到 ${file.name}`);
  4435. }
  4436. }
  4437.  
  4438. let selectedFiles = files.filter(
  4439. f => f.formatedName.search(separator) != -1 && f.id).map(f => {
  4440. let fo = {
  4441. id: f.id,
  4442. name: f.formatedName.split(separator).join(''),
  4443. };
  4444. return fo;
  4445. });
  4446. console.log(selectedFiles);
  4447. let i, j, temporary, chunk = 115;
  4448. for (i = 0, j = selectedFiles.length; i < j; i += chunk) {
  4449. temporary = selectedFiles.slice(i, i + chunk);
  4450. resultCallback && resultCallback({
  4451. state: true,
  4452. msg: `正在重命名第${i + 1}到${i + temporary.length}个文件...`,
  4453. });
  4454. let renameResult = await renameFiles(temporary);
  4455. if (renameResult.state === true) {
  4456. resultCallback && resultCallback({
  4457. state: true,
  4458. msg: `重命名第${i + 1}到${i + temporary.length}个文件成功!`,
  4459. });
  4460. } else {
  4461. resultCallback && resultCallback({
  4462. state: false,
  4463. msg: renameResult.error,
  4464. });
  4465. resultCallback && resultCallback({
  4466. state: true,
  4467. msg: `重命名第${i + 1}到${i + 1 + temporary.length}个文件中有失败!!!`,
  4468. });
  4469. }
  4470. await delay(sleepTime);
  4471. }
  4472.  
  4473. }
  4474.  
  4475. //过程重命名
  4476. async function processRename(
  4477. targetFolderCid, separator, sleepTime, resultCallback) {
  4478. let onlineFiles = new Array();
  4479. await getAllFiles(targetFolderCid, onlineFiles, targetFolderCid,
  4480. (fname, pIndex) => {
  4481. if (pIndex > 1) {
  4482. resultCallback && resultCallback({
  4483. state: true,
  4484. msg: `正在获取 ${fname}】 下第 ${pIndex} 页的内容...`,
  4485. });
  4486. } else {
  4487. resultCallback && resultCallback({
  4488. state: true,
  4489. msg: `正在获取 ${fname}】 下的内容...`,
  4490. });
  4491. }
  4492. });
  4493.  
  4494. let selectedFiles = onlineFiles.filter(
  4495. f => f.name.search(separator) != -1).map(f => {
  4496. let fo = {
  4497. id: f.id,
  4498. name: f.name.split(separator).join(''),
  4499. };
  4500. return fo;
  4501. });
  4502.  
  4503. let i, j, temporary, chunk = 115;
  4504. for (i = 0, j = selectedFiles.length; i < j; i += chunk) {
  4505. temporary = selectedFiles.slice(i, i + chunk);
  4506. resultCallback && resultCallback({
  4507. state: true,
  4508. msg: `正在重命名第${i + 1}到${i + temporary.length}个文件...`,
  4509. });
  4510. let renameResult = await renameFiles(temporary);
  4511. if (renameResult.state === true) {
  4512. resultCallback && resultCallback({
  4513. state: true,
  4514. msg: `重命名第${i + 1}到${i + temporary.length}个文件成功!`,
  4515. });
  4516. } else {
  4517. resultCallback && resultCallback({
  4518. state: false,
  4519. msg: renameResult.error,
  4520. });
  4521. resultCallback && resultCallback({
  4522. state: true,
  4523. msg: `重命名第${i + 1}到${i + 1 + temporary.length}个文件中有失败!!!`,
  4524. });
  4525. }
  4526. await delay(sleepTime);
  4527. }
  4528.  
  4529. }
  4530.  
  4531. //通过sha1链接转存文件
  4532. //uploadSetting:{targetCid,text,rootFolder:{needToCreate:true,folderName:""},itemNameSeparator:{needToSeparate:true,separator:""}}
  4533. async function UploadFilesBySha1Links(
  4534. config, continuedTaskSetting = null) {
  4535.  
  4536. let uploadConfig = continuedTaskSetting == null ?
  4537. config :
  4538. continuedTaskSetting.uploadConfig;
  4539. let folderSleepTime = uploadConfig.folderSetting.sleepTime;
  4540. let nameSeparator = '';
  4541. let newTargetCid = '-1';
  4542. let files;
  4543. let fileName = '';
  4544.  
  4545. if (continuedTaskSetting == null) {
  4546. //fix: v3.4 在线获取内容可能有空格,修复解析出错
  4547. let formatedText = uploadConfig.text.trim();
  4548. if (!formatedText) return;
  4549. postSha1Messgae(
  4550. createMessage(MessageType.BEGIN4UPLOAD, '正在解析sha1链接...'));
  4551.  
  4552. //解析json,转为inline text;并且从json中获取root folder name
  4553. if (formatedText.startsWith('{') && formatedText.endsWith('}')) {
  4554. let r = formatJsonToCommon(formatedText);
  4555. if (r.state) {
  4556. uploadConfig.folderSetting.rootFolder.folderName = r.rootFolder;
  4557. formatedText = r.text;
  4558. } else {
  4559. console.error('json 解析失败');
  4560. postSha1Messgae(
  4561. createMessage(MessageType.END4UPLOAD, 'json解析失败!是不是格式不匹配!'));
  4562. return;
  4563. //json 解析失败,提示,,
  4564. }
  4565. }
  4566.  
  4567. //解析inline text sha1 links,并根据配置设置分隔符
  4568.  
  4569. if (uploadConfig.itemNameSeparator.needToSeparate &&
  4570. uploadConfig.itemNameSeparator.separator) {
  4571. nameSeparator = uploadConfig.itemNameSeparator.separator;
  4572. }
  4573.  
  4574. files = parseSha1LinksToFileArray(formatedText, nameSeparator,
  4575. errorMsg => {
  4576. postSha1Messgae(createMessage(MessageType.ERROR, errorMsg));
  4577. });
  4578.  
  4579. if (files.length == 0) {
  4580. postSha1Messgae(createMessage(MessageType.END, `未获取到有效的链接!`));
  4581. return;
  4582. }
  4583.  
  4584. postSha1Messgae(
  4585. createMessage(MessageType.PROCESSING, `获取到链接个数:${files.length}`));
  4586. await delay(500);
  4587.  
  4588. //根目录设置
  4589. //根据配置重新设置targetCid
  4590. newTargetCid = uploadConfig.targetCid;
  4591.  
  4592. if (uploadConfig.folderSetting.rootFolder.needToCreate === true) {
  4593. let rootFolderName = uploadConfig.folderSetting.rootFolder.folderName;
  4594. let root = await createRootFolder(newTargetCid, rootFolderName, 11,
  4595. folderSleepTime * 2, msg => {
  4596. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  4597. });
  4598.  
  4599. fileName = root.folderName;
  4600. newTargetCid = root.cid;
  4601. await delay(500);
  4602. }
  4603. console.log(`newTargetCid: ${newTargetCid}`);
  4604.  
  4605. if (newTargetCid == '-1') {
  4606. console.log('选择的保存处文件夹已经被删除或者移动');
  4607. postSha1Messgae(createMessage(MessageType.END,
  4608. '自动创建根目录出错: <br/>选择的保存处文件夹,已经被删除或者移动,请重新选择保存位置!'));
  4609. return;
  4610. }
  4611.  
  4612. //子目录设置
  4613. files.forEach(f => {
  4614. f.parentID = newTargetCid;
  4615. });
  4616.  
  4617. if (uploadConfig.folderSetting.notCreateAnyChildFolder === false) //可以创建目录
  4618. {
  4619. console.log('需要创建子目录');
  4620. //根据配置设置每个文件的parent id
  4621. //最大的层次
  4622. let maxLevel = Math.max.apply(Math, files.map(e => e.length));
  4623. let level = 0;
  4624. //cid更新
  4625. postSha1Messgae(
  4626. createMessage(MessageType.PROCESSING, `正在配置子目录的生成...`));
  4627. await updateParentID(newTargetCid, '',
  4628. level, maxLevel, files, folderSleepTime * 1.5, t => {
  4629. let st = t.state ? '成功.' : '失败!!! ' + t.error;
  4630. let msg = `创建子目录 <b>${t.folderName}</b> ${st}`;
  4631. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  4632. if (!t.state) postSha1Messgae(
  4633. createMessage(MessageType.ERROR, msg));
  4634. });
  4635.  
  4636. }
  4637. } else {
  4638. newTargetCid = continuedTaskSetting.targetCid;
  4639. files = continuedTaskSetting.data;
  4640. fileName = continuedTaskSetting.fileName;
  4641. }
  4642.  
  4643. window.parent.document.myData = files;
  4644. postSha1Messgae(createMessage(MessageType.SHOWCANCEl));
  4645. console.log(files.length);
  4646. //文件上传
  4647. await processUpload(files, uploadConfig.upload.workingNumber,
  4648. uploadConfig.upload.sleepTime, result => {
  4649. if (result.state === true) {
  4650. postSha1Messgae(
  4651. createMessage(MessageType.PROCESSING, result.msg));
  4652. } else {
  4653. postSha1Messgae(createMessage(MessageType.ERROR, result.msg));
  4654. }
  4655. });
  4656. let isTaskCanceled = getTaskCancelFlag();
  4657.  
  4658. postSha1Messgae(createMessage(MessageType.HIDECANCEL));
  4659.  
  4660. //根据配置,重命名文件
  4661. if (uploadConfig.itemNameSeparator.needToSeparate &&
  4662. uploadConfig.itemNameSeparator.needToRemoveSeparator &&
  4663. uploadConfig.itemNameSeparator.separator &&
  4664. !isTaskCanceled) {
  4665. postSha1Messgae(
  4666. createMessage(MessageType.PROCESSING, '开始获取文件,并自动重命名...'));
  4667. await delay(folderSleepTime);
  4668. console.log(files);
  4669. await processRenameByUsingHistory(files,
  4670. uploadConfig.itemNameSeparator.separator, folderSleepTime,
  4671. result => {
  4672. if (result.state === true) {
  4673. postSha1Messgae(
  4674. createMessage(MessageType.PROCESSING, result.msg));
  4675. } else {
  4676. postSha1Messgae(createMessage(MessageType.ERROR, result.msg));
  4677. }
  4678. });
  4679. // await processRename(newTargetCid, uploadConfig.itemNameSeparator.separator, folderSleepTime, result => {
  4680. // if (result.state === true) {
  4681. // postSha1Messgae(createMessage(MessageType.PROCESSING, result.msg));
  4682. // } else {
  4683. // postSha1Messgae(createMessage(MessageType.ERROR, result.msg));
  4684. // }
  4685. // });
  4686.  
  4687. postSha1Messgae(
  4688. createMessage(MessageType.PROCESSING, '文件批量去除分隔符(重命名)完成!'));
  4689. await delay(folderSleepTime * 2);
  4690. }
  4691.  
  4692. var fails = files.filter(q => !q.state);
  4693. var failText = fails.map(function(p) {
  4694. var r = convertToSha1Link(p, false);
  4695. return r.msg;
  4696. }).join('\r\n');
  4697.  
  4698. if (failText) GM_setClipboard(failText);
  4699. if (isTaskCanceled) {
  4700. //todo:取消转存
  4701. let file_name = fileName + '_转存_未完成.7task';
  4702. let data = files.map(f => {
  4703. `let tempFile={
  4704. parentID:f.parentID,
  4705. name:f.name,
  4706. size:f.size,
  4707. sha1:f.sha1,
  4708. preid:f.preid,
  4709. };`;
  4710. let tempFile = [
  4711. f.parentID,
  4712. f.name,
  4713. f.formatedName,
  4714. f.size,
  4715. f.sha1,
  4716. f.preid,
  4717. f.state,
  4718. ];
  4719. return tempFile;
  4720. });
  4721. uploadConfig.text = '';
  4722. let taskJson = {
  4723. taskType: TaskType.UPLOAD,
  4724. targetCid: newTargetCid,
  4725. fileName: fileName,
  4726. data: data,
  4727. uploadConfig: uploadConfig,
  4728. };
  4729. let text = JSON.stringify(taskJson);
  4730. download(file_name, text);
  4731.  
  4732. }
  4733.  
  4734. let msg = `完成上传!成功 <b>${(files.length -
  4735. fails.length)}</b> ,失败或者取消 <b>${fails.length}</b>\
  4736. <br><br>如果有失败,已将失败sha1链接复制到剪贴板!如果转存失败,请检查sha1链接格式或者在 chrome 上尝试转存。\
  4737. 获取最新版,或者遇到问题去此反馈,感谢 !点击-> <a href="${TIPS.UpdateUrl}" target="_blank">${TIPS.VersionTips}</a>`;
  4738. postSha1Messgae(
  4739. createMessage(MessageType.END4UPLOAD, msg, newTargetCid));
  4740.  
  4741. }
  4742.  
  4743. //获取文件项Preid与超时
  4744. function getFileItemPreidWithTimeOut(timeOut, file) {
  4745. console.log('getFileItemPreidWithTimeOut');
  4746. let to = delay(timeOut).then(t => {
  4747. return {
  4748. state: false,
  4749. error: `等待提取结果超时,此乃警告,成功与否看最后结果!`,
  4750. fileItem: file,
  4751. };
  4752. });
  4753. let up = getFileItemPreid(file);
  4754. // console.log('文件的Preid',up)
  4755. return Promise.race([to, up]);
  4756. }
  4757.  
  4758. function GetFileItemByliNode(liNode) {
  4759.  
  4760. var pItem = {
  4761. id: '',
  4762. parentID: '',
  4763. isFolder: false,
  4764. name: '',
  4765. size: 0,
  4766. pickCode: '',
  4767. sha1: '',
  4768. paths: [],
  4769. preid: '',
  4770. selected: false,
  4771.  
  4772. };
  4773.  
  4774. var type = liNode.getAttribute('file_type');
  4775. pItem.name = liNode.getAttribute('title');
  4776. pItem.parentID = liNode.getAttribute('p_id');
  4777.  
  4778. var isSelected = liNode.getAttribute('class');
  4779. if (isSelected == 'selected') pItem.selected = true;
  4780.  
  4781. if (type == '0') {
  4782. pItem.id = liNode.getAttribute('cate_id');
  4783. pItem.isFolder = true;
  4784. } else {
  4785. pItem.size = liNode.getAttribute('file_size');
  4786. pItem.sha1 = liNode.getAttribute('sha1');
  4787. pItem.pickCode = liNode.getAttribute('pick_code');
  4788. pItem.id = liNode.getAttribute('file_id');
  4789. }
  4790.  
  4791. return pItem;
  4792. }
  4793.  
  4794. const FILESIZE = 128 * 1024;
  4795.  
  4796. //内部创建Sha1链接
  4797. async function InnerCreateSha1Links(allFiles, txtName) {
  4798. var msg = '';
  4799. var index = 1;
  4800. var completedIndex = 1;
  4801. var promisArray = new Array();
  4802.  
  4803. for (let file of allFiles) {
  4804. let fileSize = parseInt(file.size);
  4805. file.size = fileSize;
  4806. if (!file.preid && file.size <= FILESIZE) {
  4807. file.preid = file.sha1;
  4808. }
  4809. }
  4810.  
  4811. let files = allFiles.filter(f => !f.preid);
  4812. completedIndex = allFiles.length - files.length;
  4813. var gt1200files = files.length >= 1200;
  4814. console.log(`>=1200: ${gt1200files}`);
  4815. //postSha1Messgae(createMessage(MessageType.PROCESSING, `总计${allFiles.length},已完成${completedIndex}`));
  4816. postSha1Messgae(createMessage(MessageType.SHOWCANCEl));
  4817. for (var file of files) {
  4818.  
  4819. let taskCancelFlag = getTaskCancelFlag();
  4820. console.log(taskCancelFlag);
  4821. if (taskCancelFlag === true) {
  4822. console.log('创建SHA1链接任务已取消');
  4823. break;
  4824. }
  4825.  
  4826. const f = file;
  4827. var time = Date.parse(new Date()) / 1000;
  4828. //请求做种
  4829.  
  4830. // Seed(file,time)
  4831.  
  4832. // 获取文件Preid
  4833. const r = getFileItemPreidWithTimeOut(20000, f).then((t) => {
  4834. console.log(t)
  4835. if (t.state) {
  4836. msg = '<div align="right"><b>{0}</b> | <b>{1}</b></div><hr>获取【 <b>{2}</b> 】的sha1链接成功'.format(
  4837. completedIndex, allFiles.length, t.fileItem.name);
  4838. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  4839. } else {
  4840. msg = '<div align="right"><b>{0}</b> | <b>{1}</b></div><hr>获取【 <b>{2}</b> 】的sha1链接:{3}'.format(
  4841. completedIndex, allFiles.length, t.fileItem.name, t.error);
  4842. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  4843. var filePath = t.fileItem.paths.join(' > ');
  4844. console.log(filePath);
  4845. if (filePath) msg = '{0},原因:{1},路径:{2}'.format(t.fileItem.name,
  4846. t.error, filePath);
  4847. else msg = '{0},原因:{1}'.format(t.fileItem.name, t.error);
  4848.  
  4849. postSha1Messgae(createMessage(MessageType.ERROR, msg));
  4850. }
  4851. completedIndex = completedIndex + 1;
  4852. });
  4853.  
  4854. promisArray.push(r);
  4855.  
  4856. //自己改代码吧,怎么弄提取逻辑。。太慢,耗时长;太快,115容易没反应
  4857. if (index % WORKSETTINGS.WorkingItemsNumber == 0) {
  4858. await delay(WORKSETTINGS.SleepMoreTime * 1.5);
  4859. if (index % (WORKSETTINGS.WorkingItemsNumber * 9) == 0) {
  4860. await Promise.all(promisArray);
  4861. let seconds = 2;
  4862. for (let i = 0; i < seconds; i++) {
  4863. postSha1Messgae(createMessage(MessageType.PROCESSING,
  4864. `防止115服务器限制,暂停发包中。<br><br>${seconds - i}秒后继续...`));
  4865. await delay(1000);
  4866. }
  4867. promisArray = new Array();
  4868. }
  4869. }
  4870.  
  4871. //
  4872. index = index + 1;
  4873. }
  4874.  
  4875. await Promise.all(promisArray);
  4876.  
  4877. var succeedArray = allFiles.filter(q => q.preid);
  4878. if (succeedArray.length == 1) {
  4879. var result = convertToSha1Link(succeedArray[0], false);
  4880. postSha1Messgae(createMessage(MessageType.CLOSE, ''));
  4881.  
  4882. setTimeout(s => {
  4883. prompt('复制分享链接到剪贴板', s);
  4884. }, 100, result.msg);
  4885.  
  4886. } else {
  4887.  
  4888. if (succeedArray.length > 1) {
  4889.  
  4890. let file_name = txtName + '_sha1.txt';
  4891. let text = '';
  4892.  
  4893. if (getTaskCancelFlag()) {
  4894. file_name = txtName + '_提取_未完成.7task';
  4895. let data = allFiles.map(f => {
  4896. `let tempFile={
  4897. id:f.id,
  4898. parentID:f.parentID,
  4899. name:f.name,
  4900. size:f.size,
  4901. paths:f.paths,
  4902. pickCode:f.pickCode,
  4903. sha1:f.sha1,
  4904. preid:f.preid,
  4905. };`;
  4906. let tempFile = [
  4907. f.id,
  4908. f.parentID,
  4909. f.name,
  4910. f.size,
  4911. f.paths,
  4912. f.pickCode,
  4913. f.sha1,
  4914. f.preid,
  4915. ];
  4916. return tempFile;
  4917. });
  4918. let taskJson = {
  4919. taskType: TaskType.DOWNLOAD,
  4920. fileName: txtName,
  4921. data: data,
  4922. };
  4923. text = JSON.stringify(taskJson);
  4924. //todo:取消任务
  4925.  
  4926. } else {
  4927. text = allFiles.filter(q => q.preid).map(function(p) {
  4928. var r = convertToSha1Link(p, false);
  4929. return r.msg;
  4930. }).join('\r\n');
  4931. }
  4932. download(file_name, text);
  4933. }
  4934.  
  4935. msg = `
  4936. 完成【 <b>${txtName}</b> 】提取!<hr><br>
  4937. 总共<b>${allFiles.length}</b> ,取消或者失败 <b>${allFiles.length -
  4938. succeedArray.length}</b>。<br>
  4939. 取消后,若未移动文件夹,可导入继续提取。<br>
  4940. 点击-> <a href="${TIPS.UpdateUrl}" target="_blank">${TIPS.VersionTips}</a>,获取最新版与反馈!
  4941. `;
  4942. console.log(msg);
  4943. postSha1Messgae(createMessage(MessageType.END, msg));
  4944. }
  4945. }
  4946. async function CreateSha1LinksAll(items, taskName) {
  4947. //ui: 获取文件中...
  4948. var msg = '正在获取文件...';
  4949. postSha1Messgae(createMessage(MessageType.BEGIN, msg));
  4950. var files = new Array();
  4951. for (let item of items) {
  4952. if (getTaskCancelFlag()) break;
  4953.  
  4954. if (!item.isFolder) {
  4955. files.push(item);
  4956. } else {
  4957. msg = `正在获取 ${item.name} 下的内容...`;
  4958. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  4959. let children = new Array();
  4960. await getAllFiles(item.id, children, item.id, (fname, pIndex) => {
  4961. if (pIndex > 1) {
  4962. msg = `正在获取 ${fname}】 下第 ${pIndex} 页的内容...`;
  4963. } else {
  4964. msg = `正在获取 ${fname}】 下的内容...`;
  4965. }
  4966. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  4967. });
  4968.  
  4969. for (let f of children) {
  4970. f.paths.unshift(item.name);
  4971. files.push(f);
  4972. }
  4973.  
  4974. }
  4975. }
  4976.  
  4977. if (!files || files.length == 0) {
  4978. postSha1Messgae(createMessage(MessageType.END, `未选中任何内容???`));
  4979. return;
  4980. }
  4981.  
  4982. postSha1Messgae(createMessage(MessageType.PROCESSING,
  4983. `获取到 【<b>${taskName}</b>】 的内容 ${files.length} 项`));
  4984. await delay(100);
  4985. if (getTaskCancelFlag()) {
  4986. postSha1Messgae(createMessage(MessageType.END, '已经取消任务!'));
  4987. } else InnerCreateSha1Links(files, taskName);
  4988. }
  4989.  
  4990. //创建SHA1链接
  4991. async function CreateSha1Links(item) {
  4992. //ui: 获取文件中...
  4993. var msg = '正在获取文件...';
  4994. postSha1Messgae(createMessage(MessageType.BEGIN, msg));
  4995. var files = new Array();
  4996.  
  4997. if (!item.isFolder) {
  4998. files.push(item);
  4999. } else {
  5000. msg = `正在获取 ${item.name} 下的内容...`;
  5001. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  5002.  
  5003. await getAllFiles(item.id, files, item.id, (fname, pIndex) => {
  5004. if (pIndex > 1) {
  5005. msg = '正在获取 【{0}】 下第 {1} 页的内容...'.format(fname, pIndex);
  5006. } else {
  5007. msg = '正在获取 【{0}】 下的内容...'.format(fname);
  5008. }
  5009. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  5010. });
  5011.  
  5012. if (!files || files.length == 0) {
  5013. postSha1Messgae(createMessage(MessageType.END,
  5014. '【<b>{0}</b> 】空目录???'.format(item.name)));
  5015. return;
  5016. }
  5017. }
  5018.  
  5019. postSha1Messgae(createMessage(MessageType.PROCESSING,
  5020. '获取到 【<b>{0}</b>】 的内容 {1} 项'.format(item.name, files.length)));
  5021. await delay(100);
  5022. if (getTaskCancelFlag()) {
  5023. postSha1Messgae(createMessage(MessageType.END, '已经取消任务!'));
  5024. } else InnerCreateSha1Links(files, item.name);
  5025. }
  5026.  
  5027. const autoCreateRootFolderTips = {
  5028. msg: `sha1转存时,强制在保存处新建根目录`,
  5029. details: `选择时:&#013;&#010;1.新建根目录名来自sha1转存文件名或者json中的根元素。\
  5030. &#013;&#010;2.如果没有,则当前时间为文件名生成。`,
  5031. };
  5032.  
  5033. const autoCreateRootFolderString =
  5034. `<div class="linktask-quota" style="height: 40px;display: block">\
  5035. <a>${autoCreateRootFolderTips.msg}</a>\
  5036. <div class="help" title=" ${autoCreateRootFolderTips.details}"><a></a></div>\
  5037. <span>&nbsp;&nbsp;</span><div class="option-switch" style="top:10px;left:10px">\
  5038. <input type="checkbox" checked="true" id="neAutoCreateRootfolder" onclick="function f() {return false}">\
  5039. <label for><i>开启</i><s>关闭</s><b>切换</b></label></div>`;
  5040.  
  5041. const notCreateAnyChildFolderTips = {
  5042. msg: `sha1转存时,不创建任何子目录`,
  5043. details: `选中时,不会自动创建任何子目录。此项与根目录不会影响!`,
  5044. };
  5045.  
  5046. const notCreateAnyChildFolderString =
  5047. `<div id="neNotCreateAnyChildFolderParent" class="linktask-quota" style="height: 40px;display: block">\
  5048. <a>${notCreateAnyChildFolderTips.msg}</a>\
  5049. <div class="help" title=" ${notCreateAnyChildFolderTips.details}"><a></a></div>\
  5050. <span>&nbsp;&nbsp;</span><div class="option-switch" style="top:10px;left:10px">\
  5051. <input type="checkbox" checked="true" id="neNotCreateAnyChildFolder" onclick="function f() {return false}">\
  5052. <label for><i>开启</i><s>关闭</s><b>切换</b></label></div>`;
  5053.  
  5054. const selectFileTips = {
  5055. msg: `或者导入sha1链接文件(txt/json)`,
  5056. details: `如果不能正确显示选择文件按钮,可能是与其他脚本或者插件冲突!!`,
  5057. };
  5058. const selectFileString = `<div id="neFile">
  5059. <div id="neFileOnline">
  5060. <span style="display:flex;margin-top: 10px;">已经选择在线文件:<p style="color:red" id="neOnlineFileName"></p></span>
  5061. </div>
  5062. <div id="neFileUpload" >
  5063. <div class="linktask-quota" style="margin-top: 10px;">\
  5064. <a>${selectFileTips.msg}</a>\
  5065. <div class="help" title="${selectFileTips.details}"><a></a></div>\
  5066. <span>&nbsp;&nbsp;</span><input type="file" id="neSelectFile" accept=".txt,.json" style="display:block;color:#2777F8;visibility: visible;"></input></div>
  5067. </div>
  5068. </div>`;
  5069.  
  5070. const otherSettingString = `<div class="linktask-quota" style="margin-top: 10px;display:none;">\
  5071. 分隔符或者其他选项:<a id="neSetting1" href="javascript:;" style="color:#2777F8">点此设置</a>。\
  5072. </div>`;
  5073.  
  5074. const headerString = `<div id="ne115tipsforheader">${TIPS.VersionTips}(${TIPS.LastUpdateDate}),\
  5075. <a style="color:red;" target="_blank" href=${TIPS.UpdateUrl}>更新&反馈点此!</a>\
  5076. <a href="javascript:;" style="color:#2777F8" id="neSetting2">分隔符等设置点此!</a></div>`;
  5077.  
  5078. const beginUploadBySha1String = `<div class="con" id="downsha1"><a class="button" target="_blank" href="https://115211.xyz/forum.php?mod=viewthread&tid=1">开始sha1转存</a></div>`;
  5079.  
  5080. //当前页面所在的目录信息
  5081. function getCurrentFolderDisplayed() {
  5082. let defaultFolder = {
  5083. id: '0',
  5084. name: '根目录',
  5085. };
  5086. let iframes = document.querySelectorAll('iframe');
  5087. for (let item of iframes) {
  5088. let filePath = item.contentWindow.document.body.querySelector(
  5089. '[rel=header_page_local]');
  5090. if (filePath) {
  5091. let folders = filePath.querySelectorAll('.folder');
  5092. let lastFolder = folders[folders.length - 1];
  5093. defaultFolder.name = lastFolder.getAttribute('titletext');
  5094. let search = new URLSearchParams(window.location.search);
  5095. defaultFolder.id = search.get('cid');
  5096. break;
  5097. }
  5098. }
  5099.  
  5100. return defaultFolder;
  5101. }
  5102.  
  5103. //fix: v3.3 修复“添加任务弹窗可能无法关闭”
  5104. function AddDownloadSha1Btn(jNode) {
  5105.  
  5106. document.querySelector(`a[btn="close"]`).
  5107. addEventListener('click', e => {
  5108. window.parent.document.tryUploadItem = null;
  5109. });
  5110.  
  5111. let onlineFile = null;
  5112.  
  5113. var file = '';
  5114.  
  5115. var dialog = document.getElementsByClassName(
  5116. 'dialog-box dialog-mini offline-box window-current')[0];
  5117. dialog.style.width = '720px';
  5118. dialog.style.top = '10px';
  5119. if (document.getElementById('ne115tipsforheader') == null) {
  5120. $(headerString).appendTo('.dialog-header[rel$=\'title_box\']');
  5121.  
  5122. $('#neSetting2')[0].addEventListener('click', e => {
  5123. document.querySelector(`a[btn="close"]`).click();
  5124. GM_config.open();
  5125. });
  5126. }
  5127.  
  5128. var textArea = document.querySelector('#js_offline_new_add');
  5129. if (textArea) {
  5130. textArea.style.height = '100px';
  5131. }
  5132.  
  5133. if (document.getElementById('neSelectFile') == null) {
  5134. var div = document.getElementsByClassName(
  5135. 'dialog-input input-offline');
  5136.  
  5137. console.log(div);
  5138. var $selectFile = $(selectFileString);
  5139. var $autoCreateRootFolder = $(autoCreateRootFolderString);
  5140. var $notCreateAnyChildFolder = $(notCreateAnyChildFolderString);
  5141. var $otherSetting = $(otherSettingString);
  5142. div[0].style.display = 'grid';
  5143. div[0].appendChild($selectFile[0]);
  5144. div[0].appendChild($autoCreateRootFolder[0]);
  5145.  
  5146. div[0].appendChild($notCreateAnyChildFolder[0]);
  5147. div[0].appendChild($otherSetting[0]);
  5148.  
  5149. //界面选项设置
  5150. //根目录自动创建默认值:
  5151. document.getElementById(
  5152. 'neAutoCreateRootfolder').checked = GM_config.get(
  5153. currentConfig.createRootFolderDefaultValue);
  5154. //是否显示不创建任何目录:
  5155. document.getElementById(
  5156. 'neNotCreateAnyChildFolderParent').style.display = GM_config.get(
  5157. currentConfig.createChildFolderVisible) === true ?
  5158. 'block' :
  5159. 'none';
  5160. document.getElementById('neNotCreateAnyChildFolder').checked = false;
  5161.  
  5162. $selectFile[0].addEventListener('change', e => {
  5163. console.log(e.target.files);
  5164. if (e.target.files) {
  5165. file = e.target.files[0];
  5166. } else {
  5167. file = '';
  5168. }
  5169. });
  5170.  
  5171. $('#neSetting1')[0].addEventListener('click', e => {
  5172. document.querySelector(`a[btn="close"]`).click();
  5173. GM_config.open();
  5174. });
  5175.  
  5176. } else {
  5177.  
  5178. //界面选项设置
  5179. document.getElementById('neSelectFile').value = '';
  5180. file = '';
  5181. //根目录自动创建默认值:
  5182. document.getElementById(
  5183. 'neAutoCreateRootfolder').checked = GM_config.get(
  5184. currentConfig.createRootFolderDefaultValue);
  5185. //是否显示不创建任何目录:
  5186. document.getElementById(
  5187. 'neNotCreateAnyChildFolderParent').style.display = GM_config.get(
  5188. currentConfig.createChildFolderVisible) === true ?
  5189. 'block' :
  5190. 'none';
  5191. document.getElementById('neNotCreateAnyChildFolder').checked = false;
  5192. }
  5193.  
  5194. if (document.getElementById('downsha1') == null) {
  5195.  
  5196. resetTaskCancelFlag();
  5197.  
  5198. var $btn = $(beginUploadBySha1String);
  5199. jNode[0].appendChild($btn[0]);
  5200. $btn[0].addEventListener('click', e => {
  5201.  
  5202. let cid = $(`li[rel="bts_select_item"][class="selected"]`).
  5203. attr('file_id');
  5204. if (cid == '') {
  5205. //目录不存在,比如把 “云下载” 目录删除
  5206. cid = '0';
  5207. }
  5208.  
  5209. let notCreateAnyChildFolder = document.getElementById(
  5210. 'neNotCreateAnyChildFolder').checked;
  5211. let autoCreateRootfolder = document.getElementById(
  5212. 'neAutoCreateRootfolder').checked;
  5213.  
  5214. let links = document.getElementById('js_offline_new_add').value;
  5215. let config = {
  5216. targetCid: cid,
  5217. text: '',
  5218. folderSetting: {
  5219. notCreateAnyChildFolder: notCreateAnyChildFolder,
  5220. sleepTime: GM_config.get(currentConfig.createFolderSleepTime),
  5221. rootFolder: {
  5222. needToCreate: autoCreateRootfolder,
  5223. folderName: '',
  5224. },
  5225. },
  5226. itemNameSeparator: {
  5227. needToSeparate: GM_config.get(currentConfig.autoUseSeparator),
  5228. needToRemoveSeparator: GM_config.get(
  5229. currentConfig.autoUseSeparatorToRename),
  5230. separator: GM_config.get(currentConfig.separator),
  5231. },
  5232. upload: {
  5233. workingNumber: GM_config.get(currentConfig.uploadNumber),
  5234. sleepTime: GM_config.get(currentConfig.uploadSleepTime),
  5235. },
  5236. };
  5237.  
  5238. onlineFile = window.parent.document.tryUploadItem;
  5239. if (onlineFile) {
  5240. document.querySelector(`a[btn="close"]`).click();
  5241. console.log('选择了在线文件:');
  5242. config.folderSetting.rootFolder.folderName = onlineFile.name.split(
  5243. '.').slice(0, -1).join('.');
  5244.  
  5245. postSha1Messgae(createMessage(MessageType.FILEDOWNLOAD, {
  5246. onlineFile: onlineFile,
  5247. config: config,
  5248. }));
  5249. window.parent.document.tryUploadItem = null;
  5250.  
  5251. } else if (file) {
  5252. console.log('选择了文件:');
  5253. console.log(file);
  5254. let reader = new FileReader();
  5255. reader.addEventListener('load', function(t) {
  5256. //fix: v3.3 导入的文件名带"."
  5257. config.folderSetting.rootFolder.folderName = file.name.split(
  5258. '.').
  5259. slice(0, -1).
  5260. join('.');
  5261. config.text = t.target.result;
  5262. file = '';
  5263. UploadFilesBySha1Links(config);
  5264. });
  5265. reader.readAsText(file);
  5266. document.querySelector(`a[btn="close"]`).click();
  5267. //(document.getElementsByClassName('close')[2].click());
  5268.  
  5269. } else if (links) {
  5270.  
  5271. console.log('选择了文本框中输入:');
  5272. // var text = { FileName: "", Content: links };
  5273. config.folderSetting.rootFolder.folderName = '';
  5274. config.text = links;
  5275.  
  5276. document.querySelector(`a[btn="close"]`).click();
  5277. //closeButton.click();
  5278. UploadFilesBySha1Links(config);
  5279.  
  5280. }
  5281.  
  5282. });
  5283. }
  5284.  
  5285. let save = document.querySelector('.bt-task-safe');
  5286. if (save != null && document.querySelector('#saveTip') == null) {
  5287. save.insertAdjacentHTML('afterend',
  5288. `<div id="saveTip"><p style="margin-left:20px;margin-top:-20px;">转存也在此处选择位置。<span style="color:red;">因115页面结构以及接口调整,暂时下线【默认保存至当前位置】</span></p></div>`);
  5289. }
  5290.  
  5291. if (window.parent.document.tryUploadItem) {
  5292. document.getElementById('neFileOnline').style.display = 'block';
  5293. document.getElementById('neFileUpload').style.display = 'none';
  5294. document.getElementById(
  5295. 'neOnlineFileName').innerText = window.parent.document.tryUploadItem.name;
  5296. } else {
  5297. document.getElementById('neFileOnline').style.display = 'none';
  5298. document.getElementById('neFileUpload').style.display = 'block';
  5299. }
  5300.  
  5301. let currentFolder = getCurrentFolderDisplayed();
  5302. console.log(currentFolder);
  5303.  
  5304. /*
  5305. let ul = document.querySelector('ul[rel="select_item_ul"]');
  5306. if (ul) {
  5307. //弹窗时可能数据还在获取,延迟修改
  5308. //fix: v3.3.1 优化”脚本修改比自带的快“
  5309. //fix: v3.4 再次延长,优化”脚本修改比自带的快“
  5310. delay(1000).then(t => {
  5311. const lis = ul.querySelectorAll("li");
  5312. let folderIncluded = null;
  5313.  
  5314. for (const li of lis) {
  5315.  
  5316. if(li.className&&li.className.includes("selected"))
  5317. {
  5318. li.classList.remove("selected")
  5319. }
  5320.  
  5321. console.log(li.attributes['file_id'])
  5322. if (li.attributes['file_id'].value == currentFolder.id) {
  5323. folderIncluded = li;
  5324. }
  5325. };
  5326.  
  5327. console.log(folderIncluded)
  5328. if(folderIncluded){
  5329. folderIncluded.classList.add("selected");
  5330. }
  5331. else{
  5332. const li = `<li rel="bts_select_item" class="selected" file_id="${currentFolder.id}"><a href="javascript:;"><span>${currentFolder.name}</span></a></li>`;
  5333. ul.insertAdjacentHTML("afterbegin", li);
  5334. }
  5335.  
  5336.  
  5337.  
  5338. const em= document.querySelector('em[rel="downFileResult"]');
  5339. if(em){
  5340. em.textContent=currentFolder.name;
  5341. }
  5342. });
  5343.  
  5344. }
  5345. */
  5346.  
  5347. }
  5348.  
  5349. // function formatCommonToJson(children, root) {
  5350. // let childFiles = children.filter(f => f.Paths.length == 0);
  5351. // root.files = Array();
  5352. // root.dirs = Array();
  5353. // childFiles.forEach(c => root.files.push({ Name: c.Name }));
  5354.  
  5355. // let selectedChildren = children.filter(f => f.Paths.length > 0);
  5356.  
  5357. // let childFolders = selectedChildren.map(q => q.Paths[0]).filter((v, i, a) => a.indexOf(v) === i);
  5358. // childFolders.forEach(f => root.dirs.push({ dir_name: f }));
  5359.  
  5360. // root.dirs.forEach(d => {
  5361. // let newChildren = selectedChildren.filter(f => f.Paths[0] == d.dir_name)
  5362. // .map(c => {
  5363. // let a = { Name: c.Name, Paths: c.Paths.slice(1) };
  5364. // return a;
  5365. // })
  5366. // ConverterAdvanced(newChildren, d);
  5367. // });
  5368. // }
  5369.  
  5370. //在网格中添加创建Sha1按钮
  5371. function AddCeateSha1ButtonInGrid(jNode) {
  5372. //add: v3.4 增加设置是否显示 缩略图模式下获取sha1
  5373. if (!GM_config.get(currentConfig.createItemSha1InThumb)) return;
  5374. let $li = jNode.find('[class~="file-thumb"]');
  5375. //fix: v3.3.1 修正文件夹如果设置封面,获取sha1链接按钮会覆盖的bug
  5376. let $button = $(
  5377. '<button class="btnInGrid" title="获取sha1链接"><i class="icon-operate-light ifol-download" style="height:14px;width:14px;position:inherit"></i></button>');
  5378. $button.appendTo($li);
  5379. $button.click(function(e) {
  5380. e.stopPropagation();
  5381. let pItem = GetFileItemByliNode(jNode[0]);
  5382. console.log('生成sha1');
  5383. console.log(pItem);
  5384. //生成sha1
  5385. resetTaskCancelFlag();
  5386. CreateSha1Links(pItem);
  5387. });
  5388.  
  5389. }
  5390.  
  5391. function renameInToolTip(element, pItem) {
  5392. var $btn1 = $('<a><i></i><span>去除分隔符</span></a>');
  5393. $btn1.prependTo(element);
  5394. $btn1[0].addEventListener('click', async e => {
  5395. let separator = GM_config.get(currentConfig.separator);
  5396. let sleepTime = GM_config.get(currentConfig.createFolderSleepTime);
  5397. postSha1Messgae(createMessage(MessageType.BEGIN4UPLOAD, ''));
  5398. postSha1Messgae(createMessage(MessageType.PROCESSING,
  5399. `即将开始重命名 ${pItem.name}】 下所有文件:<br><br>去除分隔符:${separator}`));
  5400. await delay(1000);
  5401. await processRename(pItem.id, separator, sleepTime, result => {
  5402. if (result.state === true) {
  5403. postSha1Messgae(
  5404. createMessage(MessageType.PROCESSING, result.msg));
  5405. } else {
  5406. postSha1Messgae(createMessage(MessageType.ERROR, result.msg));
  5407. }
  5408. });
  5409.  
  5410. postSha1Messgae(
  5411. createMessage(MessageType.END4UPLOAD, `对目录 ${pItem.name}】下的文件重命名完成!\
  5412. <br><br>获取最新版,或者遇到问题去此反馈,感谢 !点击->\
  5413. <a href="${TIPS.UpdateUrl}" target="_blank">${TIPS.VersionTips}</a>`,
  5414. pItem.id));
  5415. });
  5416. }
  5417.  
  5418. //使用在线文件上传工具提示
  5419. function createSha1InToolTip(toopTip, pItem) {
  5420. var $btn = $(
  5421. '<a ><i></i><div style="background:white"><span>获取SHA1链接</span></div></a>');
  5422.  
  5423. $btn.prependTo(toopTip);
  5424. $btn[0].addEventListener('click', e => {
  5425. console.log('生成sha1');
  5426. console.log(pItem);
  5427. //生成sha1
  5428. resetTaskCancelFlag();
  5429. CreateSha1Links(pItem);
  5430. });
  5431. }
  5432.  
  5433. function usingOnlineFileToUploadInToolTip(toopTip, pItem) {
  5434.  
  5435. let temps = pItem.name.split('.');
  5436. let extension = temps[temps.length - 1].toLowerCase();
  5437. if (extension == 'json' || extension == 'txt') {
  5438. let $btn1 = $(
  5439. '<a menu="offline_task" title="暂不支持大于2MB的文本文件操作"><i></i><div style="background:white"><span>尝试转存</span></div></a>');
  5440. $btn1.prependTo(toopTip);
  5441. //尝试转存
  5442. $btn1[0].addEventListener('click', e => {
  5443. window.parent.document.tryUploadItem = pItem;
  5444. });
  5445. }
  5446. }
  5447.  
  5448. //fix:v3.3 修复在回收站显示提取的bug
  5449. function AddShareSHA1Btn(jNode) {
  5450.  
  5451. var parentNode = jNode[0].parentNode;
  5452. var pItem = GetFileItemByliNode(parentNode);
  5453. if (!pItem.name) return;
  5454.  
  5455. jNode[0].style.left = '180px';
  5456. //目录,去除分隔符
  5457. if (pItem.isFolder && GM_config.get(currentConfig.advancedRename)) {
  5458. renameInToolTip(jNode[0], pItem);
  5459. }
  5460.  
  5461. //add: v3.4 增加设置是否显示 列表模式下获取sha1
  5462. if (GM_config.get(currentConfig.createItemSha1)) {
  5463. createSha1InToolTip(jNode[0], pItem);
  5464. }
  5465.  
  5466. if (!pItem.isFolder) {
  5467. usingOnlineFileToUploadInToolTip(jNode[0], pItem);
  5468. }
  5469.  
  5470. //生成json格式
  5471. // if(pItem.isFolder)
  5472. // {
  5473. // var $btn1 = $('<a><i></i><span>获取SHA1(json)</span></a>');
  5474. // $btn1.prependTo(jNode[0]);
  5475. // $btn1[0].addEventListener('click', e => {
  5476. // console.log(pItem);
  5477. // //生成sha1
  5478. // resetTaskCancelFlag();
  5479. // CreateSha1Links(pItem);
  5480. // })
  5481. // }
  5482.  
  5483. }
  5484.  
  5485. //获取搜索列表
  5486. async function GetSearchList(isOnlySelected) {
  5487. resetTaskCancelFlag();
  5488.  
  5489. var msg = '正在获取文件...';
  5490. postSha1Messgae(createMessage(MessageType.BEGIN, msg));
  5491.  
  5492. var doc = document.getElementsByClassName('search-iframe')[0];
  5493. if (!doc) doc = document;
  5494. var lis = doc.querySelectorAll(
  5495. '.list-cell.lstc-search > .list-contents > ul > li');
  5496. if (!lis) return;
  5497. console.log(lis);
  5498. var files = new Array();
  5499. for (var li of lis) {
  5500. var fileItem = GetFileItemByliNode(li);
  5501. files.push(fileItem);
  5502. }
  5503. console.log('0: search items{0}'.format(files.length));
  5504. if (isOnlySelected) {
  5505. console.log('search items onlySelected');
  5506. files = files.filter(q => q.selected);
  5507. }
  5508.  
  5509. console.log('1: search items{0}'.format(files.length));
  5510.  
  5511. console.log(document.URL);
  5512. var url = new URL(document.URL);
  5513. var key = url.searchParams.get('search_value');
  5514. key = key ? key : '搜索结果';
  5515. files = files.filter(q => !q.isFolder);
  5516. msg = '获取到符合搜索的文件数:{0}'.format(files.length);
  5517. postSha1Messgae(createMessage(MessageType.PROCESSING, msg));
  5518. await delay(200);
  5519. await InnerCreateSha1Links(files, key);
  5520.  
  5521. }
  5522.  
  5523. //为选中的项目创建Sha1按钮
  5524. function CreateSha1ButtonForSelectedItems(element) {
  5525. if (document.getElementById('my115CreateSha1ForSelected')) return;
  5526.  
  5527. let div = `<div id="my115CreateSha1ForSelected" style="margin-left:20px;cursor:pointer">
  5528. <a hef="javascript=:;" class="button btn-line">
  5529. <i class="icon-operate ifo-share"></i>
  5530. <span>获取选中项的SHA1链接</span>
  5531. </a>
  5532. </div>`;
  5533. element[0].insertAdjacentHTML('beforeend', div);
  5534. document.getElementById('my115CreateSha1ForSelected').
  5535. addEventListener('mousedown', async e => {
  5536. //生成转传sha1
  5537.  
  5538. //停止传播
  5539. e.stopPropagation();
  5540. let seletedElements = new Array();
  5541. //列表模式下:
  5542. let selectedItemsInList = document.querySelectorAll(
  5543. '.list-contents > ul > li');
  5544. console.log(`列表模式下,选中:${selectedItemsInList.length}`);
  5545. selectedItemsInList.forEach(ele => seletedElements.push(ele));
  5546. //缩略图模式下:
  5547. selectedItemsInList = document.querySelectorAll(
  5548. '.list-thumb > ul > li');
  5549. console.log(`缩略图模式下,选中:${selectedItemsInList.length}`);
  5550. selectedItemsInList.forEach(ele => seletedElements.push(ele));
  5551.  
  5552. console.log(`选中:${seletedElements.length}`);
  5553. let items = new Array();
  5554. for (let item of seletedElements) {
  5555. let sItem = GetFileItemByliNode(item);
  5556. if (sItem.selected) items.push(sItem);
  5557. }
  5558.  
  5559. if (items.length == 0) return;
  5560. if (items.length == 1) {
  5561. //创建Sha1单个链接
  5562. await CreateSha1Links(items[0]);
  5563. } else {
  5564. //创建Sha1所有链接
  5565. await CreateSha1LinksAll(items,
  5566. `${items[0].name}等${items.length}个`);
  5567. }
  5568.  
  5569. });
  5570. }
  5571.  
  5572. //为搜索项添加共享按钮
  5573. function AddShareButtonForSearchItem(node) {
  5574.  
  5575. document.getElementById('my115Dropdown').style.display = 'none';
  5576.  
  5577. //每一项
  5578. var lis = node[0].getElementsByTagName('li');
  5579. for (var li of lis) {
  5580. var pItem = GetFileItemByliNode(li);
  5581. var $btn = $('<div class="file-opr" style="left:200px"></div>');
  5582. $btn.appendTo(li);
  5583. }
  5584.  
  5585. //针对当前页面
  5586. $('.left-tvf > a.btn-upload').css('top', '10px');
  5587. if (document.getElementById('btn_selected_sha1') == null) {
  5588. var $btn_selected = $(`<a href="javascript:;" id="btn_selected_sha1" class="button btn-line" style="top:10px">
  5589. <i class="icon-operate ifo-share"></i>
  5590. <span>提取本页选中文件(不包括文件夹)</span>
  5591. <em style="display:none;" class="num-dot"></em>
  5592. </a>`);
  5593. $('.left-tvf').eq(0).append($btn_selected);
  5594.  
  5595. $btn_selected[0].addEventListener('click', e => {
  5596. GetSearchList(true);
  5597. });
  5598. }
  5599.  
  5600. if (document.getElementById('btn_all_sha1') == null) {
  5601. var $btn_all = $(`<a href="javascript:;" id="btn_all_sha1" class="button btn-line" style="top:10px">
  5602. <i class="icon-operate ifo-share"></i>
  5603. <span>提取本页所有文件(不包括文件夹)</span>
  5604. <em style="display:none;" class="num-dot"></em>
  5605. </a>`);
  5606. $('.left-tvf').eq(0).append($btn_all);
  5607.  
  5608. $btn_all[0].addEventListener('click', e => {
  5609. GetSearchList(false);
  5610. });
  5611. }
  5612.  
  5613. }
  5614.  
  5615. //继续任务
  5616. function ContinuedTask(taskJsonFileName) {
  5617. console.log('ContinuedTask');
  5618. postSha1Messgae(createMessage(MessageType.BEGIN, '正在继续任务...'));
  5619. resetTaskCancelFlag();
  5620. let reader = new FileReader();
  5621. reader.addEventListener('load', function(t) {
  5622. try {
  5623.  
  5624. postSha1Messgae(
  5625. createMessage(MessageType.PROCESSING, '正在解析继续任务配置...'));
  5626. let taskJson = JSON.parse(t.target.result);
  5627.  
  5628. console.log(
  5629. `${taskJson.taskType}, ${taskJson.fileName}, ${taskJson.data.length}`);
  5630. let canContinued = true;
  5631. if (taskJson.data.length > 0) {
  5632.  
  5633. } else {
  5634. canContinued = false;
  5635. }
  5636. if (canContinued) {
  5637. if (taskJson.taskType == TaskType.DOWNLOAD) {
  5638. postSha1Messgae(createMessage(MessageType.PROCESSING,
  5639. `正在开始对【${taskJson.fileName}】继续提取...请稍等!`));
  5640. `
  5641. 提取:
  5642. let tempFile=[
  5643. f.id,f.parentID,f.name,f.size,f.paths,f.pickCode,f.sha1,f.preid,
  5644. ];
  5645. `;
  5646. let allFiles = taskJson.data.map(f => {
  5647. return {
  5648. id: f[0],
  5649. parentID: f[1],
  5650. name: f[2],
  5651. size: f[3],
  5652. paths: f[4],
  5653. pickCode: f[5],
  5654. sha1: f[6],
  5655. preid: f[7],
  5656. };
  5657. });
  5658. InnerCreateSha1Links(allFiles, taskJson.fileName);
  5659. } else if (taskJson.taskType == TaskType.UPLOAD) {
  5660. postSha1Messgae(
  5661. createMessage(MessageType.BEGIN4UPLOAD, '正在解析sha1链接...'));
  5662. `转化格式
  5663. 转存:
  5664. let tempFile = [
  5665. f.parentID,f.name, f.formatedName, f.size, f.sha1, f.preid,f.state
  5666. ]
  5667. `;
  5668. let allFiles = taskJson.data.map(f => {
  5669. return {
  5670. id: '',
  5671. parentID: f[0],
  5672. name: f[1],
  5673. formatedName: f[2],
  5674. size: f[3],
  5675. pickCode: '',
  5676. sha1: f[4],
  5677. preid: f[5],
  5678. state: f[6],
  5679. };
  5680. });
  5681.  
  5682. taskJson.data = allFiles;
  5683.  
  5684. UploadFilesBySha1Links(null, taskJson);
  5685.  
  5686. }
  5687. } else {
  5688. let msg = `
  5689. 获取的继续任务:【 <b>${taskJson.fileName}</b> 】,配置有误!<br>
  5690. 可能不是正确的配置文件, 或者不适用于此版本的配置!
  5691. `;
  5692. postSha1Messgae(createMessage(MessageType.END, msg));
  5693. }
  5694.  
  5695. } catch (error) {
  5696. console.error(error);
  5697. }
  5698.  
  5699. });
  5700. reader.readAsText(taskJsonFileName);
  5701.  
  5702. }
  5703.  
  5704.  
  5705.  
  5706. /**
  5707. *
  5708. * Base64 encode / decode
  5709. *
  5710. * @author haitao.tu
  5711. * @date 2010-04-26
  5712. * @email tuhaitao@foxmail.com
  5713. *
  5714. */
  5715. function Base64() {
  5716. // private property
  5717. var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  5718. // public method for encoding
  5719. this.encode = function (input) {
  5720. var output = "";
  5721. var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  5722. var i = 0;
  5723. input = _utf8_encode(input);
  5724. while (i < input.length) {
  5725. chr1 = input.charCodeAt(i++);
  5726. chr2 = input.charCodeAt(i++);
  5727. chr3 = input.charCodeAt(i++);
  5728. enc1 = chr1 >> 2;
  5729. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  5730. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  5731. enc4 = chr3 & 63;
  5732. if (isNaN(chr2)) {
  5733. enc3 = enc4 = 64;
  5734. } else if (isNaN(chr3)) {
  5735. enc4 = 64;
  5736. }
  5737. output = output +
  5738. _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
  5739. _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
  5740. }
  5741. return output;
  5742. }
  5743. // public method for decoding
  5744. this.decode = function (input) {
  5745. var output = "";
  5746. var chr1, chr2, chr3;
  5747. var enc1, enc2, enc3, enc4;
  5748. var i = 0;
  5749. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  5750. while (i < input.length) {
  5751. enc1 = _keyStr.indexOf(input.charAt(i++));
  5752. enc2 = _keyStr.indexOf(input.charAt(i++));
  5753. enc3 = _keyStr.indexOf(input.charAt(i++));
  5754. enc4 = _keyStr.indexOf(input.charAt(i++));
  5755. chr1 = (enc1 << 2) | (enc2 >> 4);
  5756. chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
  5757. chr3 = ((enc3 & 3) << 6) | enc4;
  5758. output = output + String.fromCharCode(chr1);
  5759. if (enc3 != 64) {
  5760. output = output + String.fromCharCode(chr2);
  5761. }
  5762. if (enc4 != 64) {
  5763. output = output + String.fromCharCode(chr3);
  5764. }
  5765. }
  5766. output = _utf8_decode(output);
  5767. return output;
  5768. }
  5769. // private method for UTF-8 encoding
  5770. var _utf8_encode = function (string) {
  5771. string = string.replace(/\r\n/g,"\n");
  5772. var utftext = "";
  5773. for (var n = 0; n < string.length; n++) {
  5774. var c = string.charCodeAt(n);
  5775. if (c < 128) {
  5776. utftext += String.fromCharCode(c);
  5777. } else if((c > 127) && (c < 2048)) {
  5778. utftext += String.fromCharCode((c >> 6) | 192);
  5779. utftext += String.fromCharCode((c & 63) | 128);
  5780. } else {
  5781. utftext += String.fromCharCode((c >> 12) | 224);
  5782. utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  5783. utftext += String.fromCharCode((c & 63) | 128);
  5784. }
  5785. }
  5786. return utftext;
  5787. }
  5788. // private method for UTF-8 decoding
  5789. var _utf8_decode = function (utftext) {
  5790. var string = "";
  5791. var i = 0;
  5792. var c = c1 = c2 = 0;
  5793. while ( i < utftext.length ) {
  5794. c = utftext.charCodeAt(i);
  5795. if (c < 128) {
  5796. string += String.fromCharCode(c);
  5797. i++;
  5798. } else if((c > 191) && (c < 224)) {
  5799. c2 = utftext.charCodeAt(i+1);
  5800. string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
  5801. i += 2;
  5802. } else {
  5803. c2 = utftext.charCodeAt(i+1);
  5804. c3 = utftext.charCodeAt(i+2);
  5805. string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  5806. i += 3;
  5807. }
  5808. }
  5809. return string;
  5810. }
  5811. }
  5812.  
  5813.  
  5814.  
  5815.  
  5816. }
  5817.  
  5818. )
  5819. ();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址