From 4f13c42b6e23b16004bb8daedf05e2f007f0a6e0 Mon Sep 17 00:00:00 2001 From: rift <117926989+Riftriot@users.noreply.github.com> Date: Wed, 20 Dec 2023 21:26:58 -0600 Subject: [PATCH] FEAT: ADD RAMMER(HELL)HEAD --- package.json | 1 + src/ProxyFrame.tsx | 27 +++++- src/RammerheadEncode.tsx | 176 +++++++++++++++++++++++++++++++++++++++ src/index.tsx | 2 +- 4 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 src/RammerheadEncode.tsx diff --git a/package.json b/package.json index dca1297..90f2215 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "scripts": { "dev": "concurrently \"vite\" \"bare-server-node --port 8080\"", "build": "vite build", + "bstart": "npm run build && tsx server.ts", "preview": "vite preview", "format": "prettier --write ." }, diff --git a/src/ProxyFrame.tsx b/src/ProxyFrame.tsx index c3615a6..a7009cb 100644 --- a/src/ProxyFrame.tsx +++ b/src/ProxyFrame.tsx @@ -1,7 +1,28 @@ -export function ProxyFrame(props: { id: string }) { +import { RammerheadEncode } from "./RammerheadEncode"; +import { useEffect, useState } from "preact/hooks"; + +export function ProxyFrame(props: { url: string }) { // pass the URL encoded with encodeURIcomponent + var localProxy = localStorage.getItem("proxy") || "automatic"; + var [ProxiedUrl, setProxiedUrl] = useState(undefined); + + var decodedUrl = decodeURIComponent(props.url); + + useEffect(() => { + if (localProxy === "rammerhead") { + RammerheadEncode(decodedUrl).then((result: string) => { + console.log("ProxyHref inside:", result); + setProxiedUrl(result); + }); + } + }, [localProxy]); + + console.log(ProxiedUrl); + return (
-

{props.id}

+

{props.url}

+

{localProxy}

+

{ProxiedUrl}

- ); + ); // @TODO: Routing (iframe, ab, direct, etc.) } diff --git a/src/RammerheadEncode.tsx b/src/RammerheadEncode.tsx new file mode 100644 index 0000000..3b8e333 --- /dev/null +++ b/src/RammerheadEncode.tsx @@ -0,0 +1,176 @@ +export function RammerheadEncode(baseUrl) { // Hellhead + const mod = (n, m) => ((n % m) + m) % m; + const baseDictionary = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~-"; + const shuffledIndicator = "_rhs"; + const generateDictionary = function () { + let str = ""; + const split = baseDictionary.split(""); + while (split.length > 0) { + str += split.splice(Math.floor(Math.random() * split.length), 1)[0]; + } + return str; + }; + interface StrShuffler { + dictionary: any; + } + class StrShuffler { + constructor(dictionary = generateDictionary()) { + this.dictionary = dictionary; + } + shuffle(str) { + if (str.startsWith(shuffledIndicator)) { + return str; + } + let shuffledStr = ""; + for (let i = 0; i < str.length; i++) { + const char = str.charAt(i); + const idx = baseDictionary.indexOf(char); + if (char === "%" && str.length - i >= 3) { + shuffledStr += char; + shuffledStr += str.charAt(++i); + shuffledStr += str.charAt(++i); + } else if (idx === -1) { + shuffledStr += char; + } else { + shuffledStr += this.dictionary.charAt( + mod(idx + i, baseDictionary.length) + ); + } + } + return shuffledIndicator + shuffledStr; + } + unshuffle(str) { + if (!str.startsWith(shuffledIndicator)) { + return str; + } + + str = str.slice(shuffledIndicator.length); + + let unshuffledStr = ""; + for (let i = 0; i < str.length; i++) { + const char = str.charAt(i); + const idx = this.dictionary.indexOf(char); + if (char === "%" && str.length - i >= 3) { + unshuffledStr += char; + unshuffledStr += str.charAt(++i); + unshuffledStr += str.charAt(++i); + } else if (idx === -1) { + unshuffledStr += char; + } else { + unshuffledStr += baseDictionary.charAt( + mod(idx - i, baseDictionary.length) + ); + } + } + return unshuffledStr; + } + } + function get(url, callback, shush = false) { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.send(); + + request.onerror = function () { + if (!shush) console.log("Cannot communicate with the server"); + }; + request.onload = function () { + if (request.status === 200) { + callback(request.responseText); + } else { + if (!shush) + console.log( + 'unexpected server response to not match "200". Server says "' + + request.responseText + + '"' + ); + } + }; + } + var api = { + newsession(callback) { + get("/newsession", callback); + }, + sessionexists(id, callback) { + get("/sessionexists?id=" + encodeURIComponent(id), function (res) { + if (res === "exists") return callback(true); + if (res === "not found") return callback(false); + console.log("unexpected response from server. received" + res); + }); + }, + shuffleDict(id, callback) { + console.log("Shuffling", id); + get("/api/shuffleDict?id=" + encodeURIComponent(id), function (res) { + callback(JSON.parse(res)); + }); + } + }; + var localStorageKey = "rammerhead_sessionids"; + var localStorageKeyDefault = "rammerhead_default_sessionid"; + var sessionIdsStore = { + get() { + var rawData = localStorage.getItem(localStorageKey); + if (!rawData) return []; + try { + var data = JSON.parse(rawData); + if (!Array.isArray(data)) throw "getout"; + return data; + } catch (e) { + return []; + } + }, + set(data) { + if (!data || !Array.isArray(data)) throw new TypeError("must be array"); + localStorage.setItem(localStorageKey, JSON.stringify(data)); + }, + getDefault() { + var sessionId = localStorage.getItem(localStorageKeyDefault); + if (sessionId) { + var data = sessionIdsStore.get(); + data.filter(function (e) { + return e.id === sessionId; + }); + if (data.length) return data[0]; + } + return null; + }, + setDefault(id) { + localStorage.setItem(localStorageKeyDefault, id); + } + }; + function addSession(id) { + var data = sessionIdsStore.get(); + data.unshift({ id: id, createdOn: new Date().toLocaleString() }); + sessionIdsStore.set(data); + } + function getSessionId() { + return new Promise((resolve) => { + var id = localStorage.getItem("session-string"); + api.sessionexists(id, function (value) { + if (!value) { + console.log("Session validation failed"); + api.newsession(function (id) { + addSession(id); + localStorage.setItem("session-string", id); + console.log(id); + console.log("^ new id"); + resolve(id); + }); + } else { + resolve(id); + } + }); + }); + } + var ProxyHref; + + return getSessionId().then((id) => { + return new Promise((resolve, reject) => { + api.shuffleDict(id, function (shuffleDict) { + var shuffler = new StrShuffler(shuffleDict); + ProxyHref = "/" + id + "/" + shuffler.shuffle(baseUrl); + resolve(ProxyHref); + }); + }); + }); +} diff --git a/src/index.tsx b/src/index.tsx index 8a2bb2d..9f2a946 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -18,7 +18,7 @@ export function App() { - +