This commit is contained in:
Jason 2022-02-19 00:10:57 -05:00
parent 82f5f76588
commit 2c06fed426
25 changed files with 1131 additions and 604 deletions

View file

@ -1,7 +1,15 @@
if (!self.__uv) {
__uvHook(self, {
prefix: '/sw/',
encodeUrl: Ultraviolet.codec.xor.encode,
decodeUrl: Ultraviolet.codec.xor.decode,
});
};
async function __uvHook(window, config = {}) {
if ('__uv' in window && window.__uv instanceof Ultraviolet) return false;
const worker = !window.window;
const master = '__uv';
const methodPrefix = '__uv$';
@ -9,23 +17,23 @@ async function __uvHook(window, config = {}) {
...config,
window,
});
const { client } = __uv;
const {
HTMLMediaElement,
HTMLScriptElement,
HTMLAudioElement,
HTMLVideoElement,
HTMLInputElement,
HTMLEmbedElement,
HTMLTrackElement,
HTMLAnchorElement,
HTMLScriptElement,
HTMLAudioElement,
HTMLVideoElement,
HTMLInputElement,
HTMLEmbedElement,
HTMLTrackElement,
HTMLAnchorElement,
HTMLIFrameElement,
HTMLAreaElement,
HTMLLinkElement,
HTMLLinkElement,
HTMLBaseElement,
HTMLFormElement,
HTMLImageElement,
HTMLImageElement,
HTMLSourceElement,
} = window;
@ -34,9 +42,10 @@ async function __uvHook(window, config = {}) {
enumerable: false,
});
__uv.meta.origin = location.origin;
__uv.meta.origin = location.origin;
__uv.location = client.location.emulate(
(href) => {
if (href === 'about:srcdoc') return new URL(href);
if (href.startsWith('blob:')) href = href.slice('blob:'.length);
return new URL(__uv.sourceUrl(href));
},
@ -51,8 +60,46 @@ async function __uvHook(window, config = {}) {
__uv.blobUrls = new window.Map();
__uv.referrer = '';
__uv.cookies = [];
__uv.localStorageObj = {};
__uv.sessionStorageObj = {};
let rawBase = window.document ? client.node.baseURI.get.call(window.document) : window.location.href;
if (__uv.location.href === 'about:srcdoc') {
__uv.meta = window.parent.__uv.meta;
};
// Storage wrappers
client.nativeMethods.defineProperty(client.storage.storeProto, '__uv$storageObj', {
get() {
if (this === client.storage.sessionStorage) return __uv.sessionStorageObj;
if (this === client.storage.localStorage) return __uv.localStorageObj;
},
enumerable: false,
});
if (window.localStorage) {
for (const key in window.localStorage) {
if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {
__uv.localStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.localStorage.getItem(key);
};
};
__uv.lsWrap = client.storage.emulate(client.storage.localStorage, __uv.localStorageObj);
};
if (window.sessionStorage) {
for (const key in window.sessionStorage) {
if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {
__uv.sessionStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.sessionStorage.getItem(key);
};
};
__uv.ssWrap = client.storage.emulate(client.storage.sessionStorage, __uv.sessionStorageObj);
};
let rawBase = window.document ? client.node.baseURI.get.call(window.document) : window.location.href;
let base = __uv.sourceUrl(rawBase);
client.nativeMethods.defineProperty(__uv.meta, 'base', {
@ -76,6 +123,8 @@ async function __uvHook(window, config = {}) {
function: methodPrefix + 'function',
string: methodPrefix + 'string',
eval: methodPrefix + 'eval',
parent: methodPrefix + 'parent',
top: methodPrefix + 'top',
};
__uv.filterKeys = [
@ -86,10 +135,13 @@ async function __uvHook(window, config = {}) {
__uv.methods.function,
__uv.methods.string,
__uv.methods.eval,
__uv.methods.parent,
__uv.methods.top,
methodPrefix + 'storageObj',
'Ultraviolet',
'__uvHook',
];
client.on('wrap', (target, wrapped) => {
client.nativeMethods.defineProperty(wrapped, 'name', client.nativeMethods.getOwnPropertyDescriptor(target, 'name'));
@ -106,7 +158,7 @@ async function __uvHook(window, config = {}) {
});
});
client.fetch.on('request', event => {
client.fetch.on('request', event => {
event.data.input = __uv.rewriteUrl(event.data.input);
});
@ -127,7 +179,7 @@ async function __uvHook(window, config = {}) {
event.data.value = __uv.sourceUrl(event.data.value);
});
// Workers
client.workers.on('worker', event => {
event.data.url = __uv.rewriteUrl(event.data.url);
@ -140,7 +192,7 @@ async function __uvHook(window, config = {}) {
client.workers.on('importScripts', event => {
for (const i in event.data.scripts) {
event.data.scripts[i] = __uv.rewriteUrl(event.data.scripts[i]);
};
};
});
client.workers.on('postMessage', event => {
@ -156,16 +208,16 @@ async function __uvHook(window, config = {}) {
// Navigator
client.navigator.on('sendBeacon', event => {
event.data.url = __uv.rewriteUrl(event.data.url);
event.data.url = __uv.rewriteUrl(event.data.url);
});
// Cookies
client.document.on('getCookie', event => {
event.data.value = __uv.cookieStr;
});
client.document.on('setCookie', event => {
Promise.resolve(__uv.cookie.setCookies(event.data.value, __uv.db, __uv.meta)).then(() => {
Promise.resolve(__uv.cookie.setCookies(event.data.value, __uv.db, __uv.meta)).then(() => {
__uv.cookie.db().then(db => {
__uv.cookie.getCookies(db).then(cookies => {
__uv.cookieStr = __uv.cookie.serialize(cookies, __uv.meta, true);
@ -187,7 +239,7 @@ async function __uvHook(window, config = {}) {
// HTML
client.element.on('setInnerHTML', event => {
switch(event.that.tagName) {
switch (event.that.tagName) {
case 'SCRIPT':
event.data.value = __uv.js.rewrite(event.data.value);
break;
@ -200,7 +252,7 @@ async function __uvHook(window, config = {}) {
});
client.element.on('getInnerHTML', event => {
switch(event.that.tagName) {
switch (event.that.tagName) {
case 'SCRIPT':
event.data.value = __uv.js.source(event.data.value);
break;
@ -213,8 +265,8 @@ async function __uvHook(window, config = {}) {
event.data.value = __uv.rewriteHtml(event.data.value, { document: event.that.tagName === 'HTML' });
});
client.element.on('getOuterHTML', event => {
switch(event.that.tagName) {
client.element.on('getOuterHTML', event => {
switch (event.that.tagName) {
case 'HEAD':
event.data.value = __uv.sourceHtml(
event.data.value.replace(/<head(.*)>(.*)<\/head>/s, '<op-head$1>$2</op-head>')
@ -230,17 +282,17 @@ async function __uvHook(window, config = {}) {
break;
};
//event.data.value = __uv.sourceHtml(event.data.value, { document: event.that.tagName === 'HTML' });
//event.data.value = __uv.sourceHtml(event.data.value, { document: event.that.tagName === 'HTML' });
});
client.document.on('write', event => {
if (!event.data.html.length) return false;
event.data.html = [ __uv.rewriteHtml(event.data.html.join('')) ];
event.data.html = [__uv.rewriteHtml(event.data.html.join(''))];
});
client.document.on('writeln', event => {
if (!event.data.html.length) return false;
event.data.html = [ __uv.rewriteHtml(event.data.html.join('')) ];
event.data.html = [__uv.rewriteHtml(event.data.html.join(''))];
});
client.element.on('insertAdjacentHTML', event => {
@ -260,10 +312,10 @@ async function __uvHook(window, config = {}) {
// History
client.history.on('replaceState', event => {
if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta);
if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta);
});
client.history.on('pushState', event => {
if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta);
if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta);
});
// Element get set attribute methods
@ -280,7 +332,7 @@ async function __uvHook(window, config = {}) {
let to = event.data.origin;
let call = __uv.call;
if (event.that) {
call = event.that.__uv$source.call;
};
@ -293,9 +345,9 @@ async function __uvHook(window, config = {}) {
};
event.respondWith(
worker ?
call(event.target, [ event.data.message, event.data.transfer ], event.that) :
call(event.target, [ event.data.message, event.data.origin, event.data.transfer ], event.that)
worker ?
call(event.target, [event.data.message, event.data.transfer], event.that) :
call(event.target, [event.data.message, event.data.origin, event.data.transfer], event.that)
);
});
@ -343,38 +395,43 @@ async function __uvHook(window, config = {}) {
if (__uv.attrs.isHtml(event.data.name)) {
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.rewriteHtml(event.data.value, { ...__uv.meta, document: true });
event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.cookieStr, window.location.href) });
};
if (__uv.attrs.isSrcset(event.data.name)) {
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.html.wrapSrcset(event.data.value);
};
if (__uv.attrs.isForbidden(event.data.name)) {
event.data.name = __uv.attributePrefix + '-attr-' + event.data.name;
};
});
});
client.element.on('audio', event => {
event.data.url = __uv.rewriteUrl(event.data.url);
});
// Element Property Attributes
client.element.hookProperty([ HTMLAnchorElement, HTMLAreaElement, HTMLLinkElement, HTMLBaseElement ], 'href', {
client.element.hookProperty([HTMLAnchorElement, HTMLAreaElement, HTMLLinkElement, HTMLBaseElement], 'href', {
get: (target, that) => {
return __uv.sourceUrl(
target.call(that)
);
},
set: (target, that, [ val ]) => {
set: (target, that, [val]) => {
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-href', val)
target.call(that, __uv.rewriteUrl(val));
},
});
client.element.hookProperty([ HTMLScriptElement, HTMLMediaElement, HTMLImageElement, HTMLInputElement, HTMLEmbedElement, HTMLIFrameElement, HTMLTrackElement, HTMLSourceElement ], 'src', {
client.element.hookProperty([HTMLScriptElement, HTMLMediaElement, HTMLImageElement, HTMLInputElement, HTMLEmbedElement, HTMLIFrameElement, HTMLTrackElement, HTMLSourceElement], 'src', {
get: (target, that) => {
return __uv.sourceUrl(
target.call(that)
);
},
set: (target, that, [ val ]) => {
set: (target, that, [val]) => {
if (new String(val).toString().trim().startsWith('blob:') && that instanceof HTMLMediaElement) {
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-src', val)
return target.call(that, __uv.blobUrls.get(val) || val);
@ -385,32 +442,42 @@ async function __uvHook(window, config = {}) {
},
});
client.element.hookProperty([ HTMLFormElement ], 'action', {
client.element.hookProperty([HTMLFormElement], 'action', {
get: (target, that) => {
return __uv.sourceUrl(
target.call(that)
);
},
set: (target, that, [ val ]) => {
set: (target, that, [val]) => {
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-action', val)
target.call(that, __uv.rewriteUrl(val));
},
});
client.element.hookProperty([HTMLImageElement], 'srcset', {
get: (target, that) => {
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcset') || target.call(that);
},
set: (target, that, [val]) => {
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-srcset', val)
target.call(that, __uv.html.wrapSrcset(val));
},
});
client.element.hookProperty(HTMLScriptElement, 'integrity', {
get: (target, that) => {
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-integrity');
},
set: (target, that, [ val ]) => {
set: (target, that, [val]) => {
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-integrity', val);
},
});
client.element.hookProperty(HTMLIFrameElement, 'sandbox', {
get: (target, that) => {
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-sandbox') || target.call(that);
},
set: (target, that, [ val ]) => {
set: (target, that, [val]) => {
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-sandbox', val);
},
});
@ -419,9 +486,9 @@ async function __uvHook(window, config = {}) {
get: (target, that) => {
const win = target.call(that);
try {
if (!win.__uv) __uvHook(win);
if (!win.__uv) __uvHook(win, config);
return win;
} catch(e) {
} catch (e) {
return win;
};
},
@ -432,14 +499,26 @@ async function __uvHook(window, config = {}) {
const doc = target.call(that);
try {
const win = doc.defaultView
if (!win.__uv) __uvHook(win);
if (!win.__uv) __uvHook(win, config);
return doc;
} catch(e) {
} catch (e) {
return win;
};
},
});
client.element.hookProperty(HTMLIFrameElement, 'srcdoc', {
get: (target, that) => {
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcdoc') || target.call(that);
},
set: (target, that, [val]) => {
target.call(that, __uv.rewriteHtml(val, {
document: true,
injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.cookieStr, window.location.href)
}))
},
});
client.node.on('getTextContent', event => {
if (event.that.tagName === 'SCRIPT') {
event.data.value = __uv.js.source(event.data.value);
@ -453,7 +532,7 @@ async function __uvHook(window, config = {}) {
});
// Document
client.document.on('getDomain', event => {
client.document.on('getDomain', event => {
event.data.value = __uv.domain;
});
client.document.on('setDomain', event => {
@ -475,7 +554,7 @@ async function __uvHook(window, config = {}) {
client.document.on('parseFromString', event => {
if (event.data.type !== 'text/html') return false;
event.data.string = __uv.rewriteHtml(event.data.string, { ...__uv.meta, document: true, });
event.data.string = __uv.rewriteHtml(event.data.string, {...__uv.meta, document: true, });
});
// Attribute (node.attributes)
@ -498,17 +577,14 @@ async function __uvHook(window, config = {}) {
if (__uv.attrs.isHtml(event.data.name)) {
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.rewriteHtml(event.data.value, { ...__uv.meta, document: true });
event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.cookieStr, window.location.href) });
};
});
client.override(window.JSON, 'stringify', (target, that, args) => {
try {
return target.apply(that, args);
} catch (e) {
console.log(e, 'Error', args);
if (__uv.attrs.isSrcset(event.data.name)) {
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
event.data.value = __uv.html.wrapSrcset(event.data.value);
};
});
// URL
@ -532,6 +608,70 @@ async function __uvHook(window, config = {}) {
};
});
client.storage.on('refresh', event => {
});
client.storage.on('get', event => {
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('set', event => {
if (event.that.__uv$storageObj) {
event.that.__uv$storageObj[event.data.name] = event.data.value;
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('delete', event => {
if (event.that.__uv$storageObj) {
delete event.that.__uv$storageObj[event.data.name];
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('getItem', event => {
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('setItem', event => {
if (event.that.__uv$storageObj) {
event.that.__uv$storageObj[event.data.name] = event.data.value;
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('removeItem', event => {
if (event.that.__uv$storageObj) {
delete event.that.__uv$storageObj[event.data.name];
};
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
});
client.storage.on('clear', event => {
if (event.that.__uv$storageObj) {
for (const key of client.nativeMethods.keys.call(null, event.that.__uv$storageObj)) {
delete event.that.__uv$storageObj[key];
client.storage.removeItem.call(event.that, methodPrefix + __uv.meta.url.origin + '@' + key);
event.respondWith();
};
};
});
client.storage.on('length', event => {
if (event.that.__uv$storageObj) {
event.respondWith(client.nativeMethods.keys.call(null, event.that.__uv$storageObj).length);
};
});
client.storage.on('key', event => {
if (event.that.__uv$storageObj) {
event.respondWith(
(client.nativeMethods.keys.call(null, event.that.__uv$storageObj)[event.data.index] || null)
);
};
});
client.websocket.on('websocket', event => {
const url = new URL(event.data.url);
@ -557,7 +697,7 @@ async function __uvHook(window, config = {}) {
path: url.pathname + url.search,
};
if (protocols.length) headers['Sec-WebSocket-Protocol'] = protocols.join(', ');
if (protocols.length) headers['Sec-WebSocket-Protocol'] = protocols.join(', ');
event.data.url = `wss://${window.location.host}/bare/v1/`;
event.data.protocols = [
@ -590,8 +730,6 @@ async function __uvHook(window, config = {}) {
});
client.object.on('getOwnPropertyDescriptors', event => {
console.log(event.data.descriptors);
for (const forbidden of __uv.filterKeys) {
delete event.data.descriptors[forbidden];
};
@ -607,7 +745,7 @@ async function __uvHook(window, config = {}) {
client.element.overrideAttribute();
client.element.overrideInsertAdjacentHTML();
client.element.overrideAudio();
// client.element.overrideQuerySelector();
// client.element.overrideQuerySelector();
client.node.overrideBaseURI();
client.node.overrideTextContent();
client.attribute.override();
@ -617,6 +755,8 @@ async function __uvHook(window, config = {}) {
client.document.overrideWrite();
client.document.overrideReferrer();
client.document.overrideParseFromString();
client.storage.overrideMethods();
client.storage.overrideLength();
//client.document.overrideQuerySelector();
client.object.overrideGetPropertyNames();
client.object.overrideGetOwnPropertyDescriptors();
@ -643,20 +783,34 @@ async function __uvHook(window, config = {}) {
(href) => {
return new URL(__uv.sourceUrl(href));
}
)
client.nativeMethods.defineProperty(__uv, '$wrap', {
get() {
return function(name) {
if (name === 'location') return __uv.methods.location;
if (name === 'eval') return __uv.methods.eval;
return name;
};
},
set: val => {
console.log('waht the fuck', val);
);
client.overrideDescriptor(window, 'localStorage', {
get: (target, that) => {
return (that || window).__uv.lsWrap;
},
});
client.overrideDescriptor(window, 'sessionStorage', {
get: (target, that) => {
return (that || window).__uv.ssWrap;
},
});
client.override(window, 'open', (target, that, args) => {
if (!args.length) return target.apply(that, args);
let [url] = args;
url = __uv.rewriteUrl(url);
return target.call(that, url);
});
__uv.$wrap = function(name) {
if (name === 'location') return __uv.methods.location;
if (name === 'eval') return __uv.methods.eval;
return name;
};
__uv.$get = function(that) {
@ -667,7 +821,7 @@ async function __uvHook(window, config = {}) {
__uv.eval = client.wrap(window, 'eval', (target, that, args) => {
if (!args.length || typeof args[0] !== 'string') return target.apply(that, args);
let [ script ] = args;
let [script] = args;
script = __uv.rewriteJS(script);
return target.call(that, script);
@ -687,12 +841,9 @@ async function __uvHook(window, config = {}) {
},
enumerable: false
});
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.setSource, {
value: function(source) {
if (!client.nativeMethods.isExtensible(this)) console.log('you suck');
if (!client.nativeMethods.isExtensible(this)) return this;
client.nativeMethods.defineProperty(this, __uv.methods.source, {
@ -715,7 +866,6 @@ async function __uvHook(window, config = {}) {
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.location, {
configurable: true,
get() {
return (this === window.document || this === window) ? __uv.location : this.location;
},
set(val) {
@ -727,6 +877,57 @@ async function __uvHook(window, config = {}) {
},
});
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.parent, {
configurable: true,
get() {
const val = this.parent;
if (this === window) {
try {
return '__uv' in val ? val : this;
} catch (e) {
return this;
};
};
return val;
},
set(val) {
this.parent = val;
},
});
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.top, {
configurable: true,
get() {
const val = this.top;
if (this === window) {
if (val === this.parent) return this[__uv.methods.parent];
try {
if (!('__uv' in val)) {
let current = this;
while (current.parent !== val) {
current = current.parent
};
return '__uv' in current ? current : this;
} else {
return val;
};
} catch (e) {
return this;
};
};
return val;
},
set(val) {
this.top = val;
},
});
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.eval, {
configurable: true,
get() {
@ -736,8 +937,4 @@ async function __uvHook(window, config = {}) {
this.eval = val;
},
});
};
if (!self.__uv) {
__uvHook(self, {});
};