Arca base64 Autodecoder V2

아카라이브 Base64 자동 복호화

当前为 2023-12-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Arca base64 Autodecoder V2
  3. // @version 1.1
  4. // @author Laria
  5. // @match https://arca.live/b/*/*
  6. // @description 아카라이브 Base64 자동 복호화
  7. // @icon https://www.google.com/s2/favicons?sz=64&domain=arca.live
  8. // @run-at document-end
  9. // @namespace https://greasyfork.org/users/1235854
  10. // ==/UserScript==
  11.  
  12. /*
  13. * 1.0 - Release
  14. * 1.1 - Invalid character update (replace -> replaceAll)
  15. */
  16.  
  17. const regArr = [
  18. /(aHR0cDovL|aHR0cHM6Ly)(\w|=|\+|\/)*(?=[^\+=\w\/])/g,
  19. /(YUhSMGNEb3ZM|YUhSMGNITTZMe)(\w|=|\+|\/)*(?=[^\+=\w\/])/g,
  20. /(WVVoU01HTkViM1pN|WVVoU01HTklUVFpNZ)(\w|=|\+|\/)*(?=[^\+=\w\/])/g,
  21. ]
  22. const regInvalid = /[^\w\+\/=]/;
  23.  
  24.  
  25. var Base64 = {
  26. _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  27. decode : function (input) {
  28. var output = "";
  29. var chr1, chr2, chr3;
  30. var enc1, enc2, enc3, enc4;
  31. var i = 0;
  32.  
  33. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  34.  
  35. while (i < input.length) {
  36. enc1 = this._keyStr.indexOf(input.charAt(i++));
  37. enc2 = this._keyStr.indexOf(input.charAt(i++));
  38. enc3 = this._keyStr.indexOf(input.charAt(i++));
  39. enc4 = this._keyStr.indexOf(input.charAt(i++));
  40.  
  41. chr1 = (enc1 << 2) | (enc2 >> 4);
  42. chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
  43. chr3 = ((enc3 & 3) << 6) | enc4;
  44.  
  45. output = output + String.fromCharCode(chr1);
  46.  
  47. if (enc3 != 64) {
  48. output = output + String.fromCharCode(chr2);
  49. }
  50. if (enc4 != 64) {
  51. output = output + String.fromCharCode(chr3);
  52. }
  53. }
  54.  
  55. output = Base64._utf8_decode(output);
  56. return output;
  57. },
  58. // private method for UTF-8 decoding
  59. _utf8_decode : function (utftext) {
  60. var string = "";
  61. var i = 0;
  62. var c = 0;
  63. var c1 = 0;
  64. var c2 = 0;
  65. var c3 = 0;
  66.  
  67. while ( i < utftext.length ) {
  68. c = utftext.charCodeAt(i);
  69. if (c < 128) {
  70. string += String.fromCharCode(c);
  71. i++;
  72. }
  73. else if((c > 191) && (c < 224)) {
  74. c2 = utftext.charCodeAt(i+1);
  75. string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
  76. i += 2;
  77. }
  78. else {
  79. c2 = utftext.charCodeAt(i+1);
  80. c3 = utftext.charCodeAt(i+2);
  81. string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  82. i += 3;
  83. }
  84. }
  85. return string;
  86. }
  87. }
  88.  
  89. var hindex = 0; //total index
  90. const max_iter = 3; //max try decode iteration attamp, def:3
  91.  
  92. var lastSelected = document;
  93. var lastSelectedTime = Date.now();
  94.  
  95. function createLink(orig, index, url, depth) {
  96. return '<a href="' + url
  97. + '" target="_blank" rel="noreferrer">' + index.toString()
  98. + '번째 링크 (base64 깊이: ' + depth.toString()
  99. + ')</a>'
  100. + '<br>[ <a>' + orig.toString() + '</a> ]';
  101. }
  102.  
  103. function replacerGen(numIter) {
  104. return function(match) {
  105. try {
  106. return_f = ""; //return msg
  107. console.log(match)
  108. var converted = Base64.decode(match);
  109. for(var i=0; i<numIter; i++) {
  110. converted = Base64.decode(converted);
  111. }
  112. hindex++;
  113.  
  114. converted = decodeURI(encodeURI(converted).replaceAll('%00', '')); //remove invalid string - �
  115.  
  116. converted = converted.split(/\r?\n/);
  117. if (converted.length > 1) {
  118. return_f+='[ ' + match.toString() + ' ]';
  119. nindex = 1;
  120. converted.forEach(function(k) {
  121. if (k != "") {
  122. console.log(k)
  123. return_f+='<br>' + createLink('링크 자동 분할 : ' + nindex.toString() + '번째', hindex, k, numIter+1);
  124. hindex++;
  125. nindex++;
  126. }
  127. });
  128. hindex--; //last components
  129. } else return_f+=createLink(match, hindex, converted, numIter+1);
  130.  
  131. return return_f
  132. } catch(e) {
  133. console.log(e);
  134. console.log('base64 변환 실패 : ' + match);
  135. }
  136. return '[base64 변환 실패 : ' + match + ']';
  137. }
  138. }
  139.  
  140. //function disabled
  141. function selClicked(event) {
  142. var sel = document.getSelection().toString();
  143. if (!sel.match(regInvalid)
  144. && sel.length >= 10
  145. && lastSelectedTime + 200 < Date.now()) {
  146. try {
  147. var converted = Base64.decode(sel);
  148. } catch (e) {
  149. return;
  150. } finally {
  151. this.innerHTML = this.innerHTML.replace(sel, converted);
  152. this.removeEventListener('click', selClicked);
  153. }
  154. }
  155. }
  156.  
  157. (function() {
  158. 'use strict';
  159.  
  160. var article = document.getElementsByClassName("article-content")[0];
  161. for(var i=0; i<max_iter; i++) {
  162. article.innerHTML = article.innerHTML.replaceAll(regArr[i], replacerGen(i));
  163. }
  164.  
  165. var comments = document.getElementsByClassName("list-area");
  166. if(comments.length != 0) {
  167. for(var i=0; i<max_iter; i++) {
  168. comments[0].innerHTML = comments[0].innerHTML.replaceAll(regArr[i], replacerGen(i));
  169. }
  170. }
  171. /*
  172. document.addEventListener('selectionchange', function() {
  173. var sel = document.getSelection().anchorNode;
  174. if(sel) {
  175. sel = sel.parentElement;
  176. if(sel != lastSelected) {
  177. lastSelected.removeEventListener('click', selClicked);
  178. sel.addEventListener('click', selClicked);
  179. lastSelected = sel;
  180. lastSelectedTime = Date.now();
  181. }
  182. }
  183. })*/
  184. })();