Changed auth-token to cookie, moved mother script to js file, fixed wit file naming

This commit is contained in:
polwex 2025-03-17 21:10:43 +07:00
parent f9266b8491
commit cd4bf0c99e
6 changed files with 424 additions and 475 deletions

View File

@ -1,59 +0,0 @@
interface contacts {
enum capability {
read-name-only,
read,
add,
remove,
}
variant request {
/// requires ReadNameOnly capability
/// lazy-load-blob: none.
get-names,
/// requires Read capability
/// lazy-load-blob: none.
get-all-contacts,
/// requires Read capability
/// lazy-load-blob: none.
get-contact(string),
/// requires Add capability
/// lazy-load-blob: none.
add-contact(string),
/// requires Add capability
/// lazy-load-blob: none.
/// tuple<node, field, value>
add-field(tuple<string, string, string>),
/// requires Remove capability
/// lazy-load-blob: none.
remove-contact(string),
/// requires Remove capability
/// lazy-load-blob: none.
/// tuple<node, field>
remove-field(tuple<string, string>),
}
variant response {
/// lazy-load-blob: none.
get-names(list<string>),
/// lazy-load-blob: required; JSON all-contacts dict in blob.
get-all-contacts,
/// lazy-load-blob: required; JSON contact dict in blob.
get-contact,
/// lazy-load-blob: none.
add-contact,
/// lazy-load-blob: none.
add-field,
/// lazy-load-blob: none.
remove-contact,
/// lazy-load-blob: none.
remove-field,
/// any failed request will receive this response
/// lazy-load-blob: none.
err(string),
}
}
world contacts-sys-v0 {
import contacts;
include process-v1;
}

View File

@ -0,0 +1,6 @@
interface loginex{}
world loginex-sys-v0 {
import loginex;
include process-v1;
}

View File

@ -1,12 +1,11 @@
use crate::hyperware::process::contacts;
use anyhow;
use hyperware_process_lib::http::client::send_request_await_response;
use hyperware_process_lib::http::server::{send_response, HttpBindingConfig, WsBindingConfig};
use hyperware_process_lib::http::{Method, StatusCode};
use hyperware_process_lib::logging::{info, init_logging, Level};
use hyperware_process_lib::{
await_message, call_init, eth, get_blob, get_typed_state, homepage, http, hypermap, kiprintln,
set_state, Address, Capability, LazyLoadBlob, Message, Request,
await_message, call_init, get_blob, get_typed_state, homepage, http, kiprintln, set_state,
Address, Capability, Message, Request,
};
use process_macros::SerdeJsonInto;
use serde::{Deserialize, Serialize};
@ -25,7 +24,7 @@ const WEB2_LOGIN_NONCE: &str = "lorem ipsum";
wit_bindgen::generate!({
path: "target/wit",
world: "contacts-sys-v0",
world: "loginex-sys-v0",
generate_unused_types: true,
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto],
});
@ -33,12 +32,12 @@ wit_bindgen::generate!({
#[derive(Debug, Serialize, Deserialize)]
enum FrontendRequest {
Sign,
CheckAuth,
CheckCookie,
Logout,
Debug(String),
}
#[derive(Debug, Serialize, Deserialize)]
enum LoginRequest {
enum SignerRequest {
Sign(SignRequest),
Verify { from: Address, data: SignResponse },
}
@ -59,7 +58,7 @@ const ICON: &str = include_str!("icon");
#[derive(Debug, Serialize, Deserialize)]
struct ProxyStateV1 {
// TODO this should probably be generic and go on login:sys:sys
pub auth: Option<String>,
pub cookie: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
@ -73,22 +72,24 @@ enum VersionedState {
impl VersionedState {
fn load() -> Self {
get_typed_state(|bytes| serde_json::from_slice(bytes))
.unwrap_or(Self::V1(ProxyStateV1 { auth: None }))
.unwrap_or(Self::V1(ProxyStateV1 { cookie: None }))
}
fn _save(&self) {
set_state(&serde_json::to_vec(&self).expect("Failed to serialize state!"));
}
fn save_auth(&self, auth: String) {
let ns = Self::V1(ProxyStateV1 { auth: Some(auth) });
fn save_cookie(&self, cookie: String) {
let ns = Self::V1(ProxyStateV1 {
cookie: Some(cookie),
});
set_state(&serde_json::to_vec(&ns).expect("Failed to serialize state!"));
}
fn wipe_auth(&self) {
let ns = Self::V1(ProxyStateV1 { auth: None });
fn wipe_cookie(&self) {
let ns = Self::V1(ProxyStateV1 { cookie: None });
set_state(&serde_json::to_vec(&ns).expect("Failed to serialize state!"));
}
fn get_auth(&self) -> Option<String> {
fn get_cookie(&self) -> Option<String> {
match self {
Self::V1(ps) => ps.auth.clone(),
Self::V1(ps) => ps.cookie.clone(),
}
}
}
@ -101,8 +102,8 @@ fn initialize(our: Address) {
homepage::add_to_homepage("Login", Some(ICON), Some("/"), None);
let mut state = VersionedState::load();
let auth = state.get_auth();
kiprintln!("auth {:#?}", auth);
let cookie = state.get_cookie();
kiprintln!("cookie{:#?}", cookie);
let mut http_server = http::server::HttpServer::new(5);
let http_config = HttpBindingConfig::default().secure_subdomain(false);
@ -207,7 +208,7 @@ fn handle_login_request(
match request {
FrontendRequest::Sign => {
let target = Address::new(our.node(), ("login", "login", "sys"));
let lr = LoginRequest::Sign(SignRequest {
let lr = SignerRequest::Sign(SignRequest {
site: WEB2_URL.to_string(),
nonce: Some(WEB2_LOGIN_NONCE.to_string()),
time: get_now(),
@ -221,16 +222,16 @@ fn handle_login_request(
// Send signature to designated endpoint on Web2 app
attempt_login(our, state, res)?;
}
FrontendRequest::CheckAuth => {
let auth = state.get_auth();
let json = match auth {
FrontendRequest::CheckCookie => {
let cookie = state.get_cookie();
let json = match cookie {
None => serde_json::Value::Null,
Some(s) => json!(s),
};
send_response(StatusCode::OK, None, serde_json::to_vec(&json)?)
}
FrontendRequest::Logout => {
state.wipe_auth();
state.wipe_cookie();
let json = serde_json::to_vec(&json!(true))?;
send_response(StatusCode::OK, None, json);
}
@ -271,17 +272,17 @@ fn attempt_login(
)?;
}
Some(_) => {
let auth_header = res.headers().get("x-hyperware-auth");
match auth_header {
let cookie_header = res.headers().get("set-cookie");
match cookie_header {
None => {
send_json_response(
StatusCode::OK,
&json!({"error": "No auth string found in response"}),
)?;
}
Some(av) => {
let auth_string = av.to_str()?;
state.save_auth(auth_string.to_string());
Some(cookie_value) => {
let cookie = cookie_value.to_str()?;
state.save_cookie(cookie.to_string());
send_json_response(StatusCode::OK, &json!({"ok": "go ahead"}))?;
}
}
@ -295,9 +296,9 @@ fn handle_page_request(
http_request: &http::server::IncomingHttpRequest,
) -> anyhow::Result<()> {
// TODO remove before release
let auth = state.get_auth();
let cookie = state.get_cookie();
// let auth = Some(String::new());
match auth {
match cookie {
None => {
let package = our.package_id();
let process = our.process();
@ -311,27 +312,27 @@ fn handle_page_request(
);
Ok(())
}
Some(auth_token) => proxy::run_proxy(http_request, WEB2_URL, &auth_token),
Some(cookie) => proxy::run_proxy(http_request, WEB2_URL, &cookie),
}
}
fn _invalid_node(
hypermap: &hypermap::Hypermap,
node: &str,
) -> Option<(contacts::Response, Option<LazyLoadBlob>)> {
if hypermap
.get(&node)
.map(|(tba, _, _)| tba != eth::Address::ZERO)
.unwrap_or(false)
{
None
} else {
Some((
contacts::Response::Err("Node name invalid or does not exist".to_string()),
None,
))
}
}
// fn _invalid_node(
// hypermap: &hypermap::Hypermap,
// node: &str,
// ) -> Option<(contacts::Response, Option<LazyLoadBlob>)> {
// if hypermap
// .get(&node)
// .map(|(tba, _, _)| tba != eth::Address::ZERO)
// .unwrap_or(false)
// {
// None
// } else {
// Some((
// contacts::Response::Err("Node name invalid or does not exist".to_string()),
// None,
// ))
// }
// }
fn send_json_response<T: serde::Serialize>(status: StatusCode, data: &T) -> anyhow::Result<()> {
let json_data = serde_json::to_vec(data)?;

View File

@ -0,0 +1,366 @@
console.log("mother script running");
// Store original functions
const originalFetch = window.fetch;
const originalXHROpen = XMLHttpRequest.prototype.open;
const originalCreateElement = document.createElement;
function getURL(resource){
if (typeof resource === "string") {
const isURL = URL.canParse(resource);
if (isURL) return URL.parse(resource)
else {
const urlTry = (window.location.origin + resource);
if (URL.canParse(urlTry)) return URL.parse(urlTry)
else return null
}
}
else if ("pathname" in resource) return resource
else if ("method" in resource) return URL.parse(resource.url)
else {
console.warn("weird fetch", resource);
return null
}
}
function reRouteToHyperware(url){
console.log("Rewriting URL:", url);
if (url.origin === window.location.origin)
url.pathname = HYPERWARE_APP_PATH + url.pathname;
else console.warn("external fetch?", url.href);
return url
}
// Log all network activity for debugging
window.fetch = async function(resource, options) {
const url1 = getURL(resource);
if (!url) return
const url = reRouteToHyperware(url1);
const res = await originalFetch(url, options);
const resc = res.clone();
const headers = {};
for (let [k, v] of resc.headers.entries()){
headers[k] = v;
}
console.warn({url, status: resc.status, headers});
return res
};
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
console.log("XHR intercepted:", url);
let newUrl = url;
if (url.includes('/_next/') || url.includes('/static/chunks/')) {
console.log("Rewriting XHR URL:", url);
newUrl = HYPERWARE_APP_PATH + url;
}
// return originalXHROpen.call(this, method, newUrl, ...rest);
};
// Most important: intercept script tag creation since webpack uses this
document.createElement = function(tagName) {
const element = originalCreateElement.call(document, tagName);
console.log("dynamic element created", tagName);
const ltn = tagName.toLowerCase();
if (ltn === 'link' || ltn === "a") {
let originalHref = '';
Object.defineProperty(element, 'href', {
get: function() {
return originalHref;
},
set: function(value) {
console.log("setting href", {new: value, old: element.getAttribute("href")});
const uri = typeof value === "string" ? value : value.toString();
const url = getURL(uri);
originalHref = url;
return url;
}
});
}
if (['script', 'img', 'video', 'audio', 'track', 'iframe'].includes(ltn)) {
// Add a property setter interceptor for the src attribute
let originalSrc = '';
Object.defineProperty(element, 'src', {
get: function() {
return originalSrc;
},
set: function(value) {
const uri = typeof value === "string" ? value : value.toString();
console.log("setting src", {new: value, old: element.src});
// if (uri.includes("vercel")){
// console.log({element});
// return ""
// }
const url = getURL(uri);
if (!url) return
originalSrc = url
return url;
}
});
}
if (ltn === 'img') {
const originalSetAttribute = element.setAttribute;
element.setAttribute = function(name, value) {
let newValue = value;
console.log("setting img", {name, value});
if (name === "src" || name === "href"){
const uri = typeof value === "string" ? value : value.toString();
const url1 = getURL(uri);
if (url1) newValue = reRouteToHyperware(url1);
}
return originalSetAttribute.call(this, name, newValue);
};
}
if (ltn === 'meta') {
const originalSetAttribute = element.setAttribute;
element.setAttribute = function(name, value) {
if (name === 'http-equiv' && value.toLowerCase() === 'refresh') {
console.warn("META REFRESH DETECTED");
console.trace("Meta refresh stack trace");
debugger;
}
return originalSetAttribute.call(this, name, value);
};
}
else console.log("element created", {tagName, element});
return element;
};
// Add monitoring of script tags to see what's happening
function observeMutations(){
let oldHref = document.location.href;
// let oldHref2 = window.location.href;
const body = document.querySelector("body");
const observer = new MutationObserver(mutations => {
if (oldHref !== document.location.href){
console.warn("mutation", {new: document.location.href, old: oldHref});
// console.warn("mutationw", {neww: window.location.href, oldw: oldHref2});
};
for (let mutation of mutations){
console.log(mutation.type, mutation)
for (let node of mutation.addedNodes){
const attrs = node.getAttributeNames();
const data = Array.from(attrs).reduce((acc, item) => ({...acc, [item]: node.getAttribute(item)}), {});
data.outerHTML = node.outerHTML;
data.tagName = node.tagName;
fuckNext();
}
}
});
observer.observe(body, {childList: true, subtree: true, attributes: true, attributeOldValue: true})
}
// next router crap
let fuckingNext = false;
// Wait for Next.js to initialize
const fuckNext = () => {
if (fuckingNext) return
if (window.next && window.next.router) {
console.log("next router", window.next.router);
// Store original router methods
const originalPush = window.next.router.push;
const originalReplace = window.next.router.replace;
const originalPrefetch = window.next.router.prefetch;
// Override router methods
window.next.router.push = function() {
console.log("Router push intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {}); // Return a never-resolving promise
};
window.next.router.replace = function() {
console.log("Router replace intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {});
};
window.next.router.refresh= function() {
console.log("Router refresh intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {});
};
window.next.router.prefetch = function() {
console.log("Router prefetch intercepted:", arguments);
return originalPrefetch.call(arguments)
};
window.next.router.hmrRefresh = function() {
console.log("Router hmrRefresh intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {});
};
window.next.router.forward = function() {
console.log("Router forward intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {});
};
window.next.router.back= function() {
console.log("Router back intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {});
};
console.log("Next.js router methods intercepted");
fuckingNext = true;
} else {
console.log("Next.js router not found");
}
};
// Listeners
// Start observing when body is available
document.addEventListener("DOMContentLoaded",observeMutations);
navigation.addEventListener("navigate", (e) => {
console.log("navigation", e.destination)
console.log("navigation", e.info)
console.log("navigation", e.navigationType)
console.log("navigation", e.userInitiated)
console.log("navigation", e.canIntercept)
e.intercept({
async handler(){
console.log("intercepting navigation")
}
})
})
window.addEventListener("hashchange", (e) => {
console.warn("navigation", window.location)
})
window.addEventListener('beforeunload', function(e) {
remoteLog("unloading!!", e);
});
window.addEventListener('popstate', function(e) {
remoteLog("popstate", e);
});
window.addEventListener('pageswap', function(e) {
remoteLog("pageswap", e);
});
const originalListener = window.addEventListener;
window.addEventListener = function(type, listener, options) {
if (type === 'popstate') {
console.log("Popstate event listener added");
// Replace with no-op function
return originalListener.call(this, type, function(e) {
console.log("Popstate event prevented", e);
e.preventDefault();
e.stopImmediatePropagation();
}, options);
}
return originalListener.call(this, type, listener, options);
};
// // prevent redirects
// const originalLocationDescriptor = Object.getOwnPropertyDescriptor(window, 'location');
// // Override location to prevent redirects
// let interceptedLocation = { ...location };
// Object.defineProperty(window, 'location', {
// get: function() {
// return interceptedLocation;
// },
// set: function(value) {
// console.log("PREVENTED REDIRECT to:", value);
// console.trace("Redirect stack trace");
// // Don't actually set it, just log it
// return interceptedLocation;
// }
// });
// // Also overwrite properties on our fake location
// for (let prop in interceptedLocation) {
// if (typeof interceptedLocation[prop] !== 'function') {
// Object.defineProperty(interceptedLocation, prop, {
// get: function() {
// return location[prop];
// },
// set: function(value) {
// console.log(`PREVENTED location.${prop} change to:`, value);
// console.trace(`location.${prop} change stack trace`);
// // Don't actually apply the change
// }
// });
// }
// }
// Store logs in sessionStorage
const originalConsoleLog = console.warn;
console.warn= function(...args) {{
remoteLog(...args);
// originalConsoleLog.apply(this, args);
};
// console.log = function() {{
// const jon = JSON.stringify(arguments);
// remoteLog(jon);
// console.log(arguments)
// originalConsoleLog.apply(this, arguments);
// };
console.log("mother script finished loading");
async function remoteLog(...args){
const logObj = Array.from(args).reduce((acc, item, i) => ({...acc, [i.toString()]: safeStringify(item)}), {});
await originalFetch("http://localhost:8283", {
method: 'POST',
keepalive: true, // This allows the request to outlive the page
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
Debug: logObj
})
})}
function safeStringify(obj, depth = 0) {
if (depth > 3) return "[Object depth limit exceeded]";
try {
if (obj === null) return "null";
if (obj === undefined) return "undefined";
const type = typeof obj;
// Handle primitive types
if (type !== 'object' && type !== 'function') {
return String(obj);
}
// Handle special objects
if (obj instanceof Error) {
return `Error: ${obj.message}\n${obj.stack || ''}`;
}
if (obj instanceof HTMLElement) {
return `[${obj.tagName.toLowerCase()}${obj.id ? '#'+obj.id : ''}]`;
}
if (Array.isArray(obj)) {
const items = obj.map(item => safeStringify(item, depth + 1));
return `[${items.join(', ')}]`;
}
// Handle regular objects
const pairs = [];
for (const key in obj) {
try {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const value = safeStringify(obj[key], depth + 1);
pairs.push(`${key}: ${value}`);
// Limit number of properties to avoid huge objects
if (pairs.length >= 10) {
pairs.push("...");
break;
}
}
} catch (e) {
pairs.push(`${key}: [Error during serialization]`);
}
}
return `{${pairs.join(', ')}`;
} catch (e) {
return `[Non-serializable: ${e.message}]`;
}
}
}

View File

@ -178,14 +178,14 @@ fn modify_html(html_bytes: &[u8], prefix: &str) -> anyhow::Result<Vec<u8>> {
pub fn run_proxy(
request: &IncomingHttpRequest,
web2_url: &str,
auth_token: &str,
cookie: &str,
) -> anyhow::Result<()> {
let blob = get_blob().unwrap();
let body = blob.bytes().to_vec();
let url = replace_domain(&request.url()?, web2_url)?;
let (first_path_segment, url) = split_first_path_segment(&url)?;
let mut headers = HashMap::new();
headers.insert("hypr-auth".to_string(), auth_token.to_string());
headers.insert("Cookie".to_string(), cookie.to_string());
kiprintln!("fetching\n{}", url.to_string());
let response = send_request_await_response(request.method()?, url, Some(headers), 6000, body)?;
let resheaders = response.headers();
@ -225,373 +225,8 @@ fn mother_script(prefix: &str) -> String {
let script_text = format!(
r#"
<script>
console.log("mother script running");
// Store original functions
const originalFetch = window.fetch;
const originalXHROpen = XMLHttpRequest.prototype.open;
const originalCreateElement = document.createElement;
function getURL(resource){{
if (typeof resource === "string") {{
const isURL = URL.canParse(resource);
if (isURL) return URL.parse(resource)
else {{
const urlTry = (window.location.origin + resource);
if (URL.canParse(urlTry)) return URL.parse(urlTry)
else return null
}}
}}
else if ("pathname" in resource) return resource
else if ("method" in resource) return URL.parse(resource.url)
else {{
console.warn("weird fetch", resource);
return null
}}
}}
function reRouteToHyperware(url){{
console.log("Rewriting URL:", url);
if (url.origin === window.location.origin)
url.pathname = '{0}' + url.pathname;
else console.warn("external fetch?", url.href);
return url
}}
// Log all network activity for debugging
window.fetch = async function(resource, options) {{
const url1 = getURL(resource);
if (!url) return
const url = reRouteToHyperware(url1);
const res = await originalFetch(url, options);
const resc = res.clone();
const headers = {{}};
for (let [k, v] of resc.headers.entries()){{
headers[k] = v;
}}
console.warn({{url, status: resc.status, headers}});
return res
}};
XMLHttpRequest.prototype.open = function(method, url, ...rest) {{
console.log("XHR intercepted:", url);
let newUrl = url;
if (url.includes('/_next/') || url.includes('/static/chunks/')) {{
console.log("Rewriting XHR URL:", url);
newUrl = '{0}' + url;
}}
// return originalXHROpen.call(this, method, newUrl, ...rest);
}};
// Most important: intercept script tag creation since webpack uses this
document.createElement = function(tagName) {{
const element = originalCreateElement.call(document, tagName);
console.log("dynamic element created", tagName);
const ltn = tagName.toLowerCase();
if (ltn === 'link' || ltn === "a") {{
let originalHref = '';
Object.defineProperty(element, 'href', {{
get: function() {{
return originalHref;
}},
set: function(value) {{
console.log("setting href", {{new: value, old: element.getAttribute("href")}});
const uri = typeof value === "string" ? value : value.toString();
const url = getURL(uri);
originalHref = url;
return url;
}}
}});
}}
if (['script', 'img', 'video', 'audio', 'track', 'iframe'].includes(ltn)) {{
// Add a property setter interceptor for the src attribute
let originalSrc = '';
Object.defineProperty(element, 'src', {{
get: function() {{
return originalSrc;
}},
set: function(value) {{
const uri = typeof value === "string" ? value : value.toString();
console.log("setting src", {{new: value, old: element.src}});
// if (uri.includes("vercel")){{
// console.log({{element}});
// return ""
// }}
const url = getURL(uri);
if (!url) return
originalSrc = url
return url;
}}
}});
}}
if (ltn === 'img') {{
const originalSetAttribute = element.setAttribute;
element.setAttribute = function(name, value) {{
let newValue = value;
console.log("setting img", {{name, value}});
if (name === "src" || name === "href"){{
const uri = typeof value === "string" ? value : value.toString();
const url1 = getURL(uri);
if (url1) newValue = reRouteToHyperware(url1);
}}
return originalSetAttribute.call(this, name, newValue);
}};
}}
if (ltn === 'meta') {{
const originalSetAttribute = element.setAttribute;
element.setAttribute = function(name, value) {{
if (name === 'http-equiv' && value.toLowerCase() === 'refresh') {{
console.warn("META REFRESH DETECTED");
console.trace("Meta refresh stack trace");
debugger;
}}
return originalSetAttribute.call(this, name, value);
}};
}}
else console.log("element created", {{tagName, element}});
return element;
}};
// Add monitoring of script tags to see what's happening
function observeMutations(){{
let oldHref = document.location.href;
// let oldHref2 = window.location.href;
const body = document.querySelector("body");
const observer = new MutationObserver(mutations => {{
if (oldHref !== document.location.href){{
console.warn("mutation", {{new: document.location.href, old: oldHref}});
// console.warn("mutationw", {{neww: window.location.href, oldw: oldHref2}});
}};
for (let mutation of mutations){{
console.log(mutation.type, mutation)
for (let node of mutation.addedNodes){{
const attrs = node.getAttributeNames();
const data = Array.from(attrs).reduce((acc, item) => ({{...acc, [item]: node.getAttribute(item)}}), {{}});
data.outerHTML = node.outerHTML;
data.tagName = node.tagName;
fuckNext();
}}
}}
}});
observer.observe(body, {{childList: true, subtree: true, attributes: true, attributeOldValue: true}})
}}
// next router crap
let fuckingNext = false;
// Wait for Next.js to initialize
const fuckNext = () => {{
if (fuckingNext) return
if (window.next && window.next.router) {{
console.log("next router", window.next.router);
// Store original router methods
const originalPush = window.next.router.push;
const originalReplace = window.next.router.replace;
const originalPrefetch = window.next.router.prefetch;
// Override router methods
window.next.router.push = function() {{
console.log("Router push intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {{}}); // Return a never-resolving promise
}};
window.next.router.replace = function() {{
console.log("Router replace intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {{}});
}};
window.next.router.refresh= function() {{
console.log("Router refresh intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {{}});
}};
window.next.router.prefetch = function() {{
console.log("Router prefetch intercepted:", arguments);
return originalPrefetch.call(arguments)
}};
window.next.router.hmrRefresh = function() {{
console.log("Router hmrRefresh intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {{}});
}};
window.next.router.forward = function() {{
console.log("Router forward intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {{}});
}};
window.next.router.back= function() {{
console.log("Router back intercepted:", arguments);
// Return without calling the original to prevent navigation
return new Promise(() => {{}});
}};
console.log("Next.js router methods intercepted");
fuckingNext = true;
}} else {{
console.log("Next.js router not found");
}}
}};
// Listeners
// Start observing when body is available
document.addEventListener("DOMContentLoaded",observeMutations);
navigation.addEventListener("navigate", (e) => {{
console.log("navigation", e.destination)
console.log("navigation", e.info)
console.log("navigation", e.navigationType)
console.log("navigation", e.userInitiated)
console.log("navigation", e.canIntercept)
e.intercept({{
async handler(){{
console.log("intercepting navigation")
}}
}})
}})
window.addEventListener("hashchange", (e) => {{
console.warn("navigation", window.location)
}})
window.addEventListener('beforeunload', function(e) {{
remoteLog("unloading!!", e);
}});
window.addEventListener('popstate', function(e) {{
remoteLog("popstate", e);
}});
window.addEventListener('pageswap', function(e) {{
remoteLog("pageswap", e);
}});
const originalListener = window.addEventListener;
window.addEventListener = function(type, listener, options) {{
if (type === 'popstate') {{
console.log("Popstate event listener added");
// Replace with no-op function
return originalListener.call(this, type, function(e) {{
console.log("Popstate event prevented", e);
e.preventDefault();
e.stopImmediatePropagation();
}}, options);
}}
return originalListener.call(this, type, listener, options);
}};
// // prevent redirects
// const originalLocationDescriptor = Object.getOwnPropertyDescriptor(window, 'location');
// // Override location to prevent redirects
// let interceptedLocation = {{ ...location }};
// Object.defineProperty(window, 'location', {{
// get: function() {{
// return interceptedLocation;
// }},
// set: function(value) {{
// console.log("PREVENTED REDIRECT to:", value);
// console.trace("Redirect stack trace");
// // Don't actually set it, just log it
// return interceptedLocation;
// }}
// }});
// // Also overwrite properties on our fake location
// for (let prop in interceptedLocation) {{
// if (typeof interceptedLocation[prop] !== 'function') {{
// Object.defineProperty(interceptedLocation, prop, {{
// get: function() {{
// return location[prop];
// }},
// set: function(value) {{
// console.log(`PREVENTED location.${{prop}} change to:`, value);
// console.trace(`location.${{prop}} change stack trace`);
// // Don't actually apply the change
// }}
// }});
// }}
// }}
// Store logs in sessionStorage
const originalConsoleLog = console.warn;
console.warn= function(...args) {{{{
remoteLog(...args);
// originalConsoleLog.apply(this, args);
}}}};
// console.log = function() {{{{
// const jon = JSON.stringify(arguments);
// remoteLog(jon);
// console.log(arguments)
// originalConsoleLog.apply(this, arguments);
// }}}};
console.log("mother script finished loading");
async function remoteLog(...args){{
const logObj = Array.from(args).reduce((acc, item, i) => ({{...acc, [i.toString()]: safeStringify(item)}}), {{}});
await originalFetch("http://localhost:8283", {{
method: 'POST',
keepalive: true, // This allows the request to outlive the page
headers: {{'Content-Type': 'application/json'}},
body: JSON.stringify({{
Debug: logObj
}})
}})}}
function safeStringify(obj, depth = 0) {{
if (depth > 3) return "[Object depth limit exceeded]";
try {{
if (obj === null) return "null";
if (obj === undefined) return "undefined";
const type = typeof obj;
// Handle primitive types
if (type !== 'object' && type !== 'function') {{
return String(obj);
}}
// Handle special objects
if (obj instanceof Error) {{
return `Error: ${{obj.message}}\n${{obj.stack || ''}}`;
}}
if (obj instanceof HTMLElement) {{
return `[${{obj.tagName.toLowerCase()}}${{obj.id ? '#'+obj.id : ''}}]`;
}}
if (Array.isArray(obj)) {{
const items = obj.map(item => safeStringify(item, depth + 1));
return `[${{items.join(', ')}}]`;
}}
// Handle regular objects
const pairs = [];
for (const key in obj) {{
try {{
if (Object.prototype.hasOwnProperty.call(obj, key)) {{
const value = safeStringify(obj[key], depth + 1);
pairs.push(`${{key}}: ${{value}}`);
// Limit number of properties to avoid huge objects
if (pairs.length >= 10) {{
pairs.push("...");
break;
}}
}}
}} catch (e) {{
pairs.push(`${{key}}: [Error during serialization]`);
}}
}}
return `{{${{pairs.join(', ')}}}}`;
}} catch (e) {{
return `[Non-serializable: ${{e.message}}]`;
}}
}}
</script>
const HYPERWARE_APP_PATH = '{0}';
</script>
"#,
prefix
);

View File

@ -6,7 +6,7 @@ document.addEventListener("DOMContentLoaded", checkAuth);
async function checkAuth() {
const res = await call_app({ CheckAuth: null });
const res = await call_app({ CheckCookie: null });
const j = await res.json();
console.log({j})
if (j) {