Decode Hex, Base64
当前为
// ==UserScript==
// @name Decode Hex strings on Voz
// @namespace Decode Hex strings on Voz
// @version 2.0
// @icon https://www.google.com/s2/favicons?sz=64&domain=voz.vn
// @author kylyte
// @description Decode Hex, Base64
// @match https://voz.vn/t/*
// @run-at document-idle
// @license GPL-3.0
// ==/UserScript==
(function() {
'use strict';
function decodeHex(hexString) {
if (!/^[0-9A-Fa-f]+$/.test(hexString)) return hexString;
let hexStr = '';
try {
for (let i = 0; i < hexString.length; i += 2) {
hexStr += String.fromCharCode(parseInt(hexString.substr(i, 2), 16));
}
return /^[\w\s.,!?@#$%^&*()_+=[\]{}|;:'",<>\-\/`~]*$/.test(hexStr) ? hexStr : hexString;
} catch {
return hexString;
}
}
function decodeBase64(base64String) {
if (!/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/.test(base64String)) return base64String;
try {
let binaryString = atob(base64String);
return /^[\w\s.,!?@#$%^&*()_+=[\]{}|;:'",<>\-\/`~]*$/.test(binaryString) ? binaryString : base64String;
} catch {
return base64String;
}
}
function decodeContent(elements, regex, decodeFunc) {
for (let element of elements) {
if (element.classList.contains('decoded')) continue;
let content = element.innerHTML;
let matches = content.match(regex);
if (matches) {
matches.forEach(match => {
content = content.replace(new RegExp(escapeRegExp(match), 'g'), decodeFunc(match));
});
element.innerHTML = content;
element.classList.add('decoded');
}
}
}
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function main() {
let elements = document.getElementsByClassName('bbCodeBlock-content');
decodeContent(elements, /([0-9A-Fa-f]{2}){8,}/g, decodeHex);
decodeContent(elements, /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/m, decodeBase64);
}
main();
new MutationObserver(() => main()).observe(document.documentElement, {
childList: true,
subtree: true
});
})();