Arca base64 autodecoder

아카라이브 Base64 자동 복호화

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Arca base64 autodecoder
// @version      1.11
// @author       Laria
// @match        https://arca.live/b/*/*
// @description  아카라이브 Base64 자동 복호화
// @icon         https://www.google.com/s2/favicons?sz=64&domain=arca.live
// @run-at       document-end
// @namespace https://greasyfork.org/users/1235854
// ==/UserScript==

/*
 * 1.0 - Release
 * 1.1 - Invalid character update (replace -> replaceAll)
 * 1.11 - Improved show multiple links
*/

const regArr = [
    /(aHR0cDovL|aHR0cHM6Ly)(\w|=|\+|\/)*(?=[^\+=\w\/])/g,
    /(YUhSMGNEb3ZM|YUhSMGNITTZMe)(\w|=|\+|\/)*(?=[^\+=\w\/])/g,
    /(WVVoU01HTkViM1pN|WVVoU01HTklUVFpNZ)(\w|=|\+|\/)*(?=[^\+=\w\/])/g,
]
const regInvalid = /[^\w\+\/=]/;


var Base64 = {
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {
            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }

        output = Base64._utf8_decode(output);
        return output;
    },
    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = 0;
        var c1 = 0;
        var c2 = 0;
        var c3 = 0;

        while ( i < utftext.length ) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }
}

var hindex = 0; //total index
const max_iter = 3; //max try decode iteration attamp, def:3

var lastSelected = document;
var lastSelectedTime = Date.now();

function createLink(orig, index, url, depth) {
    return '<a href="' + url
           + '" target="_blank" rel="noreferrer">' + index.toString()
           + '번째 링크 (base64 깊이: ' + depth.toString()
           + ')</a>'
           + '<br>[ <a>' + orig.toString() + '</a> ]';
}

function replacerGen(numIter) {
    return function(match) {
        try {
            return_f = ""; //return msg
            console.log(match)
            var converted = Base64.decode(match);
            for(var i=0; i<numIter; i++) {
                converted = Base64.decode(converted);
            }
            hindex++;

            converted = decodeURI(encodeURI(converted).replaceAll('%00', ''));  //remove invalid string - �

            converted = converted.split(/\r?\n/);
            if (converted.length > 1) {
              return_f+='[ ' + match.toString() + ' ]';
              nindex = 1;
              converted.forEach(function(k) {
                if (k != "") {
                  console.log(k)
                  return_f+='<br>' + createLink('링크 자동 분할 : ' + nindex.toString() + '번째', hindex, k, numIter+1);
                  hindex++;
                  nindex++;
                }
              });
              hindex--; //last components
              return_f = '분할된 링크 총 ' + nindex + '개 ' + return_f;
            } else return_f+=createLink(match, hindex, converted, numIter+1);

            return return_f
        } catch(e) {
            console.log(e);
            console.log('base64 변환 실패 : ' + match);
        }
        return '[base64 변환 실패 : ' + match + ']';
    }
}

//function disabled
function selClicked(event) {
    var sel = document.getSelection().toString();
    if (!sel.match(regInvalid)
        && sel.length >= 10
        && lastSelectedTime + 200 < Date.now()) {
        try {
            var converted = Base64.decode(sel);
        } catch (e) {
            return;
        } finally {
            this.innerHTML = this.innerHTML.replace(sel, converted);
            this.removeEventListener('click', selClicked);
        }
    }
}

(function() {
    'use strict';

    var article = document.getElementsByClassName("article-content")[0];
    for(var i=0; i<max_iter; i++) {
        article.innerHTML = article.innerHTML.replaceAll(regArr[i], replacerGen(i));
    }

    var comments = document.getElementsByClassName("list-area");
    if(comments.length != 0) {
        for(var i=0; i<max_iter; i++) {
            comments[0].innerHTML = comments[0].innerHTML.replaceAll(regArr[i], replacerGen(i));
        }
    }
    /*
    document.addEventListener('selectionchange', function() {
        var sel = document.getSelection().anchorNode;
        if(sel) {
            sel = sel.parentElement;
            if(sel != lastSelected) {
                lastSelected.removeEventListener('click', selClicked);
                sel.addEventListener('click', selClicked);
                lastSelected = sel;
                lastSelectedTime = Date.now();
            }
        }
    })*/
})();