Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ludicrous
Path: blob/main/public/uv/uv.handler.js
1223 views
1
if (!self.__uv) {
2
__uvHook(self, self.__uv$config, self.__uv$config.bare);
3
};
4
5
async function __uvHook(window, config = {}, bare = '/bare/') {
6
if ('__uv' in window && window.__uv instanceof Ultraviolet) return false;
7
8
if (window.document && !!window.window) {
9
window.document.querySelectorAll("script[__uv-script]").forEach(node => node.remove())
10
};
11
12
const worker = !window.window;
13
const master = '__uv';
14
const methodPrefix = '__uv$';
15
const __uv = new Ultraviolet({
16
...config,
17
window,
18
});
19
20
if (typeof config.construct === 'function') {
21
config.construct(__uv, worker ? 'worker' : 'window');
22
};
23
24
const { client } = __uv;
25
const {
26
HTMLMediaElement,
27
HTMLScriptElement,
28
HTMLAudioElement,
29
HTMLVideoElement,
30
HTMLInputElement,
31
HTMLEmbedElement,
32
HTMLTrackElement,
33
HTMLAnchorElement,
34
HTMLIFrameElement,
35
HTMLAreaElement,
36
HTMLLinkElement,
37
HTMLBaseElement,
38
HTMLFormElement,
39
HTMLImageElement,
40
HTMLSourceElement,
41
} = window;
42
43
client.nativeMethods.defineProperty(window, '__uv', {
44
value: __uv,
45
enumerable: false,
46
});
47
48
49
__uv.meta.origin = location.origin;
50
__uv.location = client.location.emulate(
51
(href) => {
52
if (href === 'about:srcdoc') return new URL(href);
53
if (href.startsWith('blob:')) href = href.slice('blob:'.length);
54
return new URL(__uv.sourceUrl(href));
55
},
56
(href) => {
57
return __uv.rewriteUrl(href);
58
},
59
);
60
61
__uv.cookieStr = window.__uv$cookies || '';
62
__uv.meta.url = __uv.location;
63
__uv.domain = __uv.meta.url.host;
64
__uv.blobUrls = new window.Map();
65
__uv.referrer = '';
66
__uv.cookies = [];
67
__uv.localStorageObj = {};
68
__uv.sessionStorageObj = {};
69
70
try {
71
__uv.bare = new URL(bare, window.location.href);
72
} catch(e) {
73
__uv.bare = window.parent.__uv.bare;
74
};
75
76
if (__uv.location.href === 'about:srcdoc') {
77
__uv.meta = window.parent.__uv.meta;
78
};
79
80
if (window.EventTarget) {
81
__uv.addEventListener = window.EventTarget.prototype.addEventListener;
82
__uv.removeListener = window.EventTarget.prototype.removeListener;
83
__uv.dispatchEvent = window.EventTarget.prototype.dispatchEvent;
84
};
85
86
// Storage wrappers
87
client.nativeMethods.defineProperty(client.storage.storeProto, '__uv$storageObj', {
88
get() {
89
if (this === client.storage.sessionStorage) return __uv.sessionStorageObj;
90
if (this === client.storage.localStorage) return __uv.localStorageObj;
91
},
92
enumerable: false,
93
});
94
95
if (window.localStorage) {
96
for (const key in window.localStorage) {
97
if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {
98
__uv.localStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.localStorage.getItem(key);
99
};
100
};
101
102
__uv.lsWrap = client.storage.emulate(client.storage.localStorage, __uv.localStorageObj);
103
};
104
105
if (window.sessionStorage) {
106
for (const key in window.sessionStorage) {
107
if (key.startsWith(methodPrefix + __uv.location.origin + '@')) {
108
__uv.sessionStorageObj[key.slice((methodPrefix + __uv.location.origin + '@').length)] = window.sessionStorage.getItem(key);
109
};
110
};
111
112
__uv.ssWrap = client.storage.emulate(client.storage.sessionStorage, __uv.sessionStorageObj);
113
};
114
115
116
117
let rawBase = window.document ? client.node.baseURI.get.call(window.document) : window.location.href;
118
let base = __uv.sourceUrl(rawBase);
119
120
client.nativeMethods.defineProperty(__uv.meta, 'base', {
121
get() {
122
if (!window.document) return __uv.meta.url.href;
123
124
if (client.node.baseURI.get.call(window.document) !== rawBase) {
125
rawBase = client.node.baseURI.get.call(window.document);
126
base = __uv.sourceUrl(rawBase);
127
};
128
129
return base;
130
},
131
});
132
133
134
__uv.methods = {
135
setSource: methodPrefix + 'setSource',
136
source: methodPrefix + 'source',
137
location: methodPrefix + 'location',
138
function: methodPrefix + 'function',
139
string: methodPrefix + 'string',
140
eval: methodPrefix + 'eval',
141
parent: methodPrefix + 'parent',
142
top: methodPrefix + 'top',
143
};
144
145
__uv.filterKeys = [
146
master,
147
__uv.methods.setSource,
148
__uv.methods.source,
149
__uv.methods.location,
150
__uv.methods.function,
151
__uv.methods.string,
152
__uv.methods.eval,
153
__uv.methods.parent,
154
__uv.methods.top,
155
methodPrefix + 'protocol',
156
methodPrefix + 'storageObj',
157
methodPrefix + 'url',
158
methodPrefix + 'modifiedStyle',
159
methodPrefix + 'config',
160
methodPrefix + 'dispatched',
161
'Ultraviolet',
162
'__uvHook',
163
];
164
165
166
client.on('wrap', (target, wrapped) => {
167
client.nativeMethods.defineProperty(wrapped, 'name', client.nativeMethods.getOwnPropertyDescriptor(target, 'name'));
168
client.nativeMethods.defineProperty(wrapped, 'length', client.nativeMethods.getOwnPropertyDescriptor(target, 'length'));
169
170
client.nativeMethods.defineProperty(wrapped, __uv.methods.string, {
171
enumerable: false,
172
value: client.nativeMethods.fnToString.call(target),
173
});
174
175
client.nativeMethods.defineProperty(wrapped, __uv.methods.function, {
176
enumerable: false,
177
value: target,
178
});
179
});
180
181
client.fetch.on('request', event => {
182
event.data.input = __uv.rewriteUrl(event.data.input);
183
});
184
185
client.fetch.on('requestUrl', event => {
186
event.data.value = __uv.sourceUrl(event.data.value);
187
});
188
189
client.fetch.on('responseUrl', event => {
190
event.data.value = __uv.sourceUrl(event.data.value);
191
});
192
193
// XMLHttpRequest
194
client.xhr.on('open', event => {
195
event.data.input = __uv.rewriteUrl(event.data.input);
196
});
197
198
client.xhr.on('responseUrl', event => {
199
event.data.value = __uv.sourceUrl(event.data.value);
200
});
201
202
203
// Workers
204
client.workers.on('worker', event => {
205
event.data.url = __uv.rewriteUrl(event.data.url);
206
});
207
208
client.workers.on('addModule', event => {
209
event.data.url = __uv.rewriteUrl(event.data.url);
210
});
211
212
client.workers.on('importScripts', event => {
213
for (const i in event.data.scripts) {
214
event.data.scripts[i] = __uv.rewriteUrl(event.data.scripts[i]);
215
};
216
});
217
218
client.workers.on('postMessage', event => {
219
let to = event.data.origin;
220
221
event.data.origin = '*';
222
event.data.message = {
223
__data: event.data.message,
224
__origin: __uv.meta.url.origin,
225
__to: to,
226
};
227
});
228
229
// Navigator
230
client.navigator.on('sendBeacon', event => {
231
event.data.url = __uv.rewriteUrl(event.data.url);
232
});
233
234
// Cookies
235
client.document.on('getCookie', event => {
236
event.data.value = __uv.cookieStr;
237
});
238
239
client.document.on('setCookie', event => {
240
Promise.resolve(__uv.cookie.setCookies(event.data.value, __uv.db, __uv.meta)).then(() => {
241
__uv.cookie.db().then(db => {
242
__uv.cookie.getCookies(db).then(cookies => {
243
__uv.cookieStr = __uv.cookie.serialize(cookies, __uv.meta, true);
244
});
245
});
246
});
247
const cookie = __uv.cookie.setCookie(event.data.value)[0];
248
249
if (!cookie.path) cookie.path = '/';
250
if (!cookie.domain) cookie.domain = __uv.meta.url.hostname;
251
252
if (__uv.cookie.validateCookie(cookie, __uv.meta, true)) {
253
if (__uv.cookieStr.length) __uv.cookieStr += '; ';
254
__uv.cookieStr += `${cookie.name}=${cookie.value}`;
255
};
256
257
event.respondWith(event.data.value);
258
});
259
260
// HTML
261
client.element.on('setInnerHTML', event => {
262
switch (event.that.tagName) {
263
case 'SCRIPT':
264
event.data.value = __uv.js.rewrite(event.data.value);
265
break;
266
case 'STYLE':
267
event.data.value = __uv.rewriteCSS(event.data.value);
268
break;
269
default:
270
event.data.value = __uv.rewriteHtml(event.data.value);
271
};
272
});
273
274
client.element.on('getInnerHTML', event => {
275
switch (event.that.tagName) {
276
case 'SCRIPT':
277
event.data.value = __uv.js.source(event.data.value);
278
break;
279
default:
280
event.data.value = __uv.sourceHtml(event.data.value);
281
};
282
});
283
284
client.element.on('setOuterHTML', event => {
285
event.data.value = __uv.rewriteHtml(event.data.value, { document: event.that.tagName === 'HTML' });
286
});
287
288
client.element.on('getOuterHTML', event => {
289
switch (event.that.tagName) {
290
case 'HEAD':
291
event.data.value = __uv.sourceHtml(
292
event.data.value.replace(/<head(.*)>(.*)<\/head>/s, '<op-head$1>$2</op-head>')
293
).replace(/<op-head(.*)>(.*)<\/op-head>/s, '<head$1>$2</head>');
294
break;
295
case 'BODY':
296
event.data.value = __uv.sourceHtml(
297
event.data.value.replace(/<body(.*)>(.*)<\/body>/s, '<op-body$1>$2</op-body>')
298
).replace(/<op-body(.*)>(.*)<\/op-body>/s, '<body$1>$2</body>');
299
break;
300
default:
301
event.data.value = __uv.sourceHtml(event.data.value, { document: event.that.tagName === 'HTML' });
302
break;
303
};
304
305
//event.data.value = __uv.sourceHtml(event.data.value, { document: event.that.tagName === 'HTML' });
306
});
307
308
client.document.on('write', event => {
309
if (!event.data.html.length) return false;
310
event.data.html = [__uv.rewriteHtml(event.data.html.join(''))];
311
});
312
313
client.document.on('writeln', event => {
314
if (!event.data.html.length) return false;
315
event.data.html = [__uv.rewriteHtml(event.data.html.join(''))];
316
});
317
318
client.element.on('insertAdjacentHTML', event => {
319
event.data.html = __uv.rewriteHtml(event.data.html);
320
});
321
322
// EventSource
323
324
client.eventSource.on('construct', event => {
325
event.data.url = __uv.rewriteUrl(event.data.url);
326
});
327
328
329
client.eventSource.on('url', event => {
330
event.data.url = __uv.rewriteUrl(event.data.url);
331
});
332
333
// History
334
client.history.on('replaceState', event => {
335
if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta);
336
});
337
client.history.on('pushState', event => {
338
if (event.data.url) event.data.url = __uv.rewriteUrl(event.data.url, '__uv' in event.that ? event.that.__uv.meta : __uv.meta);
339
});
340
341
// Element get set attribute methods
342
client.element.on('getAttribute', event => {
343
if (client.element.hasAttribute.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name)) {
344
event.respondWith(
345
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name)
346
);
347
};
348
});
349
350
// Message
351
client.message.on('postMessage', event => {
352
let to = event.data.origin;
353
let call = __uv.call;
354
355
356
if (event.that) {
357
call = event.that.__uv$source.call;
358
};
359
360
event.data.origin = '*';
361
event.data.message = {
362
__data: event.data.message,
363
__origin: (event.that || event.target).__uv$source.location.origin,
364
__to: to,
365
};
366
367
event.respondWith(
368
worker ?
369
call(event.target, [event.data.message, event.data.transfer], event.that) :
370
call(event.target, [event.data.message, event.data.origin, event.data.transfer], event.that)
371
);
372
373
});
374
375
client.message.on('data', event => {
376
const { value: data } = event.data;
377
if (typeof data === 'object' && '__data' in data && '__origin' in data) {
378
event.respondWith(data.__data);
379
};
380
});
381
382
client.message.on('origin', event => {
383
const data = client.message.messageData.get.call(event.that);
384
if (typeof data === 'object' && data.__data && data.__origin) {
385
event.respondWith(data.__origin);
386
};
387
});
388
389
client.overrideDescriptor(window, 'origin', {
390
get: (target, that) => {
391
return __uv.location.origin;
392
},
393
});
394
395
client.node.on('baseURI', event => {
396
if (event.data.value.startsWith(window.location.origin)) event.data.value = __uv.sourceUrl(event.data.value);
397
});
398
399
client.element.on('setAttribute', event => {
400
if (event.that instanceof HTMLMediaElement && event.data.name === 'src' && event.data.value.startsWith('blob:')) {
401
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
402
event.data.value = __uv.blobUrls.get(event.data.value);
403
return;
404
};
405
406
if (__uv.attrs.isUrl(event.data.name)) {
407
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
408
event.data.value = __uv.rewriteUrl(event.data.value);
409
};
410
411
if (__uv.attrs.isStyle(event.data.name)) {
412
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
413
event.data.value = __uv.rewriteCSS(event.data.value, { context: 'declarationList' });
414
};
415
416
if (__uv.attrs.isHtml(event.data.name)) {
417
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
418
event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead:__uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.configScript, __uv.cookieStr, window.location.href) });
419
};
420
421
if (__uv.attrs.isSrcset(event.data.name)) {
422
event.target.call(event.that, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
423
event.data.value = __uv.html.wrapSrcset(event.data.value);
424
};
425
426
if (__uv.attrs.isForbidden(event.data.name)) {
427
event.data.name = __uv.attributePrefix + '-attr-' + event.data.name;
428
};
429
});
430
431
client.element.on('audio', event => {
432
event.data.url = __uv.rewriteUrl(event.data.url);
433
});
434
435
// Element Property Attributes
436
client.element.hookProperty([HTMLAnchorElement, HTMLAreaElement, HTMLLinkElement, HTMLBaseElement], 'href', {
437
get: (target, that) => {
438
return __uv.sourceUrl(
439
target.call(that)
440
);
441
},
442
set: (target, that, [val]) => {
443
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-href', val)
444
target.call(that, __uv.rewriteUrl(val));
445
},
446
});
447
448
client.element.hookProperty([HTMLScriptElement, HTMLAudioElement, HTMLVideoElement, HTMLMediaElement, HTMLImageElement, HTMLInputElement, HTMLEmbedElement, HTMLIFrameElement, HTMLTrackElement, HTMLSourceElement], 'src', {
449
get: (target, that) => {
450
return __uv.sourceUrl(
451
target.call(that)
452
);
453
},
454
set: (target, that, [val]) => {
455
if (new String(val).toString().trim().startsWith('blob:') && that instanceof HTMLMediaElement) {
456
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-src', val)
457
return target.call(that, __uv.blobUrls.get(val) || val);
458
};
459
460
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-src', val)
461
target.call(that, __uv.rewriteUrl(val));
462
},
463
});
464
465
client.element.hookProperty([HTMLFormElement], 'action', {
466
get: (target, that) => {
467
return __uv.sourceUrl(
468
target.call(that)
469
);
470
},
471
set: (target, that, [val]) => {
472
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-action', val)
473
target.call(that, __uv.rewriteUrl(val));
474
},
475
});
476
477
client.element.hookProperty([HTMLImageElement], 'srcset', {
478
get: (target, that) => {
479
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcset') || target.call(that);
480
},
481
set: (target, that, [val]) => {
482
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-srcset', val)
483
target.call(that, __uv.html.wrapSrcset(val));
484
},
485
});
486
487
client.element.hookProperty(HTMLScriptElement, 'integrity', {
488
get: (target, that) => {
489
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-integrity');
490
},
491
set: (target, that, [val]) => {
492
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-integrity', val);
493
},
494
});
495
496
client.element.hookProperty(HTMLIFrameElement, 'sandbox', {
497
get: (target, that) => {
498
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-sandbox') || target.call(that);
499
},
500
set: (target, that, [val]) => {
501
client.element.setAttribute.call(that, __uv.attributePrefix + '-attr-sandbox', val);
502
},
503
});
504
505
client.element.hookProperty(HTMLIFrameElement, 'contentWindow', {
506
get: (target, that) => {
507
const win = target.call(that);
508
try {
509
if (!win.__uv) __uvHook(win, config, bare);
510
return win;
511
} catch (e) {
512
return win;
513
};
514
},
515
});
516
517
client.element.hookProperty(HTMLIFrameElement, 'contentDocument', {
518
get: (target, that) => {
519
const doc = target.call(that);
520
try {
521
const win = doc.defaultView
522
if (!win.__uv) __uvHook(win, config, bare);
523
return doc;
524
} catch (e) {
525
return win;
526
};
527
},
528
});
529
530
client.element.hookProperty(HTMLIFrameElement, 'srcdoc', {
531
get: (target, that) => {
532
return client.element.getAttribute.call(that, __uv.attributePrefix + '-attr-srcdoc') || target.call(that);
533
},
534
set: (target, that, [val]) => {
535
target.call(that, __uv.rewriteHtml(val, {
536
document: true,
537
injectHead: __uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.configScript, __uv.cookieStr, window.location.href)
538
}))
539
},
540
});
541
542
client.node.on('getTextContent', event => {
543
if (event.that.tagName === 'SCRIPT') {
544
event.data.value = __uv.js.source(event.data.value);
545
};
546
});
547
548
client.node.on('setTextContent', event => {
549
if (event.that.tagName === 'SCRIPT') {
550
event.data.value = __uv.js.rewrite(event.data.value);
551
};
552
});
553
554
// Until proper rewriting is implemented for service workers.
555
// Not sure atm how to implement it with the already built in service worker
556
if ('serviceWorker' in window.navigator) {
557
delete window.Navigator.prototype.serviceWorker;
558
};
559
560
// Document
561
client.document.on('getDomain', event => {
562
event.data.value = __uv.domain;
563
});
564
client.document.on('setDomain', event => {
565
if (!event.data.value.toString().endsWith(__uv.meta.url.hostname.split('.').slice(-2).join('.'))) return event.respondWith('');
566
event.respondWith(__uv.domain = event.data.value);
567
})
568
569
client.document.on('url', event => {
570
event.data.value = __uv.location.href;
571
});
572
573
client.document.on('documentURI', event => {
574
event.data.value = __uv.location.href;
575
});
576
577
client.document.on('referrer', event => {
578
event.data.value = __uv.referrer || __uv.sourceUrl(event.data.value);
579
});
580
581
client.document.on('parseFromString', event => {
582
if (event.data.type !== 'text/html') return false;
583
event.data.string = __uv.rewriteHtml(event.data.string, {...__uv.meta, document: true, });
584
});
585
586
// Attribute (node.attributes)
587
client.attribute.on('getValue', event => {
588
if (client.element.hasAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name)) {
589
event.data.value = client.element.getAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name);
590
};
591
});
592
593
client.attribute.on('setValue', event => {
594
if (__uv.attrs.isUrl(event.data.name)) {
595
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
596
event.data.value = __uv.rewriteUrl(event.data.value);
597
};
598
599
if (__uv.attrs.isStyle(event.data.name)) {
600
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
601
event.data.value = __uv.rewriteCSS(event.data.value, { context: 'declarationList' });
602
};
603
604
if (__uv.attrs.isHtml(event.data.name)) {
605
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
606
event.data.value = __uv.rewriteHtml(event.data.value, {...__uv.meta, document: true, injectHead:__uv.createHtmlInject(__uv.handlerScript, __uv.bundleScript, __uv.configScript, __uv.cookieStr, window.location.href) });
607
};
608
609
if (__uv.attrs.isSrcset(event.data.name)) {
610
client.element.setAttribute.call(event.that.ownerElement, __uv.attributePrefix + '-attr-' + event.data.name, event.data.value);
611
event.data.value = __uv.html.wrapSrcset(event.data.value);
612
};
613
614
});
615
616
// URL
617
client.url.on('createObjectURL', event => {
618
let url = event.target.call(event.that, event.data.object);
619
if (url.startsWith('blob:' + location.origin)) {
620
let newUrl = 'blob:' + (__uv.meta.url.href !== 'about:blank' ? __uv.meta.url.origin : window.parent.__uv.meta.url.origin) + url.slice('blob:'.length + location.origin.length);
621
__uv.blobUrls.set(newUrl, url);
622
event.respondWith(newUrl);
623
} else {
624
event.respondWith(url);
625
};
626
});
627
628
client.url.on('revokeObjectURL', event => {
629
if (__uv.blobUrls.has(event.data.url)) {
630
const old = event.data.url;
631
event.data.url = __uv.blobUrls.get(event.data.url);
632
__uv.blobUrls.delete(old);
633
};
634
});
635
636
client.storage.on('get', event => {
637
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
638
});
639
640
client.storage.on('set', event => {
641
if (event.that.__uv$storageObj) {
642
event.that.__uv$storageObj[event.data.name] = event.data.value;
643
};
644
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
645
});
646
647
client.storage.on('delete', event => {
648
if (event.that.__uv$storageObj) {
649
delete event.that.__uv$storageObj[event.data.name];
650
};
651
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
652
});
653
654
client.storage.on('getItem', event => {
655
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
656
});
657
658
client.storage.on('setItem', event => {
659
if (event.that.__uv$storageObj) {
660
event.that.__uv$storageObj[event.data.name] = event.data.value;
661
};
662
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
663
});
664
665
client.storage.on('removeItem', event => {
666
if (event.that.__uv$storageObj) {
667
delete event.that.__uv$storageObj[event.data.name];
668
};
669
event.data.name = methodPrefix + __uv.meta.url.origin + '@' + event.data.name;
670
});
671
672
client.storage.on('clear', event => {
673
if (event.that.__uv$storageObj) {
674
for (const key of client.nativeMethods.keys.call(null, event.that.__uv$storageObj)) {
675
delete event.that.__uv$storageObj[key];
676
client.storage.removeItem.call(event.that, methodPrefix + __uv.meta.url.origin + '@' + key);
677
event.respondWith();
678
};
679
};
680
});
681
682
client.storage.on('length', event => {
683
if (event.that.__uv$storageObj) {
684
event.respondWith(client.nativeMethods.keys.call(null, event.that.__uv$storageObj).length);
685
};
686
});
687
688
client.storage.on('key', event => {
689
if (event.that.__uv$storageObj) {
690
event.respondWith(
691
(client.nativeMethods.keys.call(null, event.that.__uv$storageObj)[event.data.index] || null)
692
);
693
};
694
});
695
696
client.websocket.on('websocket', async event => {
697
let url;
698
try {
699
url = new URL(event.data.url);
700
} catch(e) {
701
return;
702
};
703
704
const headers = {
705
Host: url.host,
706
Origin: __uv.meta.url.origin,
707
Pragma: 'no-cache',
708
'Cache-Control': 'no-cache',
709
Upgrade: 'websocket',
710
'User-Agent': window.navigator.userAgent,
711
'Connection': 'Upgrade',
712
};
713
714
const cookies = __uv.cookie.serialize(__uv.cookies, { url }, false);
715
716
if (cookies) headers.Cookie = cookies;
717
const protocols = [...event.data.protocols];
718
719
const remote = {
720
protocol: url.protocol,
721
host: url.hostname,
722
port: url.port || (url.protocol === 'wss:' ? '443' : '80'),
723
path: url.pathname + url.search,
724
};
725
726
if (protocols.length) headers['Sec-WebSocket-Protocol'] = protocols.join(', ');
727
728
event.data.url = (__uv.bare.protocol === 'https:' ? 'wss://' : 'ws://') + __uv.bare.host + __uv.bare.pathname + 'v1/';
729
event.data.protocols = [
730
'bare',
731
__uv.encodeProtocol(JSON.stringify({
732
remote,
733
headers,
734
forward_headers: [
735
'accept',
736
'accept-encoding',
737
'accept-language',
738
'sec-websocket-extensions',
739
'sec-websocket-key',
740
'sec-websocket-version',
741
],
742
})),
743
];
744
745
const ws = new event.target(event.data.url, event.data.protocols);
746
747
client.nativeMethods.defineProperty(ws, methodPrefix + 'url', {
748
enumerable: false,
749
value: url.href,
750
});
751
752
event.respondWith(
753
ws
754
);
755
});
756
757
client.websocket.on('url', event => {
758
if ('__uv$url' in event.that) {
759
event.data.value = event.that.__uv$url;
760
};
761
});
762
763
client.websocket.on('protocol', event => {
764
if ('__uv$protocol' in event.that) {
765
event.data.value = event.that.__uv$protocol;
766
};
767
});
768
769
client.function.on('function', event => {
770
event.data.script = __uv.rewriteJS(event.data.script);
771
});
772
773
client.function.on('toString', event => {
774
if (__uv.methods.string in event.that) event.respondWith(event.that[__uv.methods.string]);
775
});
776
777
client.object.on('getOwnPropertyNames', event => {
778
event.data.names = event.data.names.filter(element => !(__uv.filterKeys.includes(element)));
779
});
780
781
client.object.on('getOwnPropertyDescriptors', event => {
782
for (const forbidden of __uv.filterKeys) {
783
delete event.data.descriptors[forbidden];
784
};
785
786
});
787
788
client.style.on('setProperty', event => {
789
if (client.style.dashedUrlProps.includes(event.data.property)) {
790
event.data.value = __uv.rewriteCSS(event.data.value, {
791
context: 'value',
792
...__uv.meta
793
})
794
};
795
});
796
797
client.style.on('getPropertyValue', event => {
798
if (client.style.dashedUrlProps.includes(event.data.property)) {
799
event.respondWith(
800
__uv.sourceCSS(
801
event.target.call(event.that, event.data.property),
802
{
803
context: 'value',
804
...__uv.meta
805
}
806
)
807
);
808
};
809
});
810
811
if ('CSS2Properties' in window) {
812
for (const key of client.style.urlProps) {
813
client.overrideDescriptor(window.CSS2Properties.prototype, key, {
814
get: (target, that) => {
815
return __uv.sourceCSS(
816
target.call(that),
817
{
818
context: 'value',
819
...__uv.meta
820
}
821
)
822
},
823
set: (target, that, val) => {
824
target.call(
825
that,
826
__uv.rewriteCSS(val, {
827
context: 'value',
828
...__uv.meta
829
})
830
);
831
}
832
});
833
};
834
} else if ('HTMLElement' in window) {
835
836
client.overrideDescriptor(
837
window.HTMLElement.prototype,
838
'style',
839
{
840
get: (target, that) => {
841
const value = target.call(that);
842
if (!value[methodPrefix + 'modifiedStyle']) {
843
844
for (const key of client.style.urlProps) {
845
client.nativeMethods.defineProperty(value, key, {
846
enumerable: true,
847
configurable: true,
848
get() {
849
const value = client.style.getPropertyValue.call(this, key) || '';
850
return __uv.sourceCSS(
851
value,
852
{
853
context: 'value',
854
...__uv.meta
855
}
856
)
857
},
858
set(val) {
859
client.style.setProperty.call(this,
860
(client.style.propToDashed[key] || key),
861
__uv.rewriteCSS(val, {
862
context: 'value',
863
...__uv.meta
864
})
865
)
866
}
867
});
868
client.nativeMethods.defineProperty(value, methodPrefix + 'modifiedStyle', {
869
enumerable: false,
870
value: true
871
});
872
};
873
};
874
return value;
875
}
876
}
877
);
878
};
879
880
client.style.on('setCssText', event => {
881
event.data.value = __uv.rewriteCSS(event.data.value, {
882
context: 'declarationList',
883
...__uv.meta
884
});
885
});
886
887
client.style.on('getCssText', event => {
888
event.data.value = __uv.sourceCSS(event.data.value, {
889
context: 'declarationList',
890
...__uv.meta
891
});
892
});
893
894
// Proper hash emulation.
895
if (!!window.window) {
896
__uv.addEventListener.call(window, 'hashchange', event => {
897
if (event.__uv$dispatched) return false;
898
event.stopImmediatePropagation();
899
const hash = window.location.hash;
900
client.history.replaceState.call(window.history, '', '', event.oldURL);
901
__uv.location.hash = hash;
902
});
903
};
904
905
client.location.on('hashchange', (oldUrl, newUrl, ctx) => {
906
if (ctx.HashChangeEvent && client.history.replaceState) {
907
client.history.replaceState.call(window.history, '', '', __uv.rewriteUrl(newUrl));
908
909
const event = new ctx.HashChangeEvent('hashchange', { newURL: newUrl, oldURL: oldUrl });
910
911
client.nativeMethods.defineProperty(event, methodPrefix + 'dispatched', {
912
value: true,
913
enumerable: false,
914
});
915
916
__uv.dispatchEvent.call(window, event);
917
};
918
});
919
920
// Hooking functions & descriptors
921
client.fetch.overrideRequest();
922
client.fetch.overrideUrl();
923
client.xhr.overrideOpen();
924
client.xhr.overrideResponseUrl();
925
client.element.overrideHtml();
926
client.element.overrideAttribute();
927
client.element.overrideInsertAdjacentHTML();
928
client.element.overrideAudio();
929
// client.element.overrideQuerySelector();
930
client.node.overrideBaseURI();
931
client.node.overrideTextContent();
932
client.attribute.overrideNameValue();
933
client.document.overrideDomain();
934
client.document.overrideURL();
935
client.document.overrideDocumentURI();
936
client.document.overrideWrite();
937
client.document.overrideReferrer();
938
client.document.overrideParseFromString();
939
client.storage.overrideMethods();
940
client.storage.overrideLength();
941
//client.document.overrideQuerySelector();
942
client.object.overrideGetPropertyNames();
943
client.object.overrideGetOwnPropertyDescriptors();
944
client.history.overridePushState();
945
client.history.overrideReplaceState();
946
client.eventSource.overrideConstruct();
947
client.eventSource.overrideUrl();
948
client.websocket.overrideWebSocket();
949
client.websocket.overrideProtocol();
950
client.websocket.overrideUrl();
951
client.url.overrideObjectURL();
952
client.document.overrideCookie();
953
client.message.overridePostMessage();
954
client.message.overrideMessageOrigin();
955
client.message.overrideMessageData();
956
client.workers.overrideWorker();
957
client.workers.overrideAddModule();
958
client.workers.overrideImportScripts();
959
client.workers.overridePostMessage();
960
client.style.overrideSetGetProperty();
961
client.style.overrideCssText();
962
client.navigator.overrideSendBeacon();
963
client.function.overrideFunction();
964
client.function.overrideToString();
965
client.location.overrideWorkerLocation(
966
(href) => {
967
return new URL(__uv.sourceUrl(href));
968
}
969
);
970
971
client.overrideDescriptor(window, 'localStorage', {
972
get: (target, that) => {
973
return (that || window).__uv.lsWrap;
974
},
975
});
976
client.overrideDescriptor(window, 'sessionStorage', {
977
get: (target, that) => {
978
return (that || window).__uv.ssWrap;
979
},
980
});
981
982
983
client.override(window, 'open', (target, that, args) => {
984
if (!args.length) return target.apply(that, args);
985
let [url] = args;
986
987
url = __uv.rewriteUrl(url);
988
989
return target.call(that, url);
990
});
991
992
__uv.$wrap = function(name) {
993
if (name === 'location') return __uv.methods.location;
994
if (name === 'eval') return __uv.methods.eval;
995
return name;
996
};
997
998
999
__uv.$get = function(that) {
1000
if (that === window.location) return __uv.location;
1001
if (that === window.eval) return __uv.eval;
1002
if (that === window.parent) {
1003
return window.__uv$parent;
1004
};
1005
if (that === window.top) {
1006
return window.__uv$top;
1007
};
1008
return that;
1009
};
1010
1011
__uv.eval = client.wrap(window, 'eval', (target, that, args) => {
1012
if (!args.length || typeof args[0] !== 'string') return target.apply(that, args);
1013
let [script] = args;
1014
1015
script = __uv.rewriteJS(script);
1016
return target.call(that, script);
1017
});
1018
1019
__uv.call = function(target, args, that) {
1020
return that ? target.apply(that, args) : target(...args);
1021
};
1022
1023
__uv.call$ = function(obj, prop, args = []) {
1024
return obj[prop].apply(obj, args);
1025
};
1026
1027
client.nativeMethods.defineProperty(window.Object.prototype, master, {
1028
get: () => {
1029
return __uv;
1030
},
1031
enumerable: false
1032
});
1033
1034
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.setSource, {
1035
value: function(source) {
1036
if (!client.nativeMethods.isExtensible(this)) return this;
1037
1038
client.nativeMethods.defineProperty(this, __uv.methods.source, {
1039
value: source,
1040
writable: true,
1041
enumerable: false
1042
});
1043
1044
return this;
1045
},
1046
enumerable: false,
1047
});
1048
1049
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.source, {
1050
value: __uv,
1051
writable: true,
1052
enumerable: false
1053
});
1054
1055
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.location, {
1056
configurable: true,
1057
get() {
1058
return (this === window.document || this === window) ? __uv.location : this.location;
1059
},
1060
set(val) {
1061
if (this === window.document || this === window) {
1062
__uv.location.href = val;
1063
} else {
1064
this.location = val;
1065
};
1066
},
1067
});
1068
1069
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.parent, {
1070
configurable: true,
1071
get() {
1072
const val = this.parent;
1073
1074
if (this === window) {
1075
try {
1076
return '__uv' in val ? val : this;
1077
} catch (e) {
1078
return this;
1079
};
1080
};
1081
return val;
1082
},
1083
set(val) {
1084
this.parent = val;
1085
},
1086
});
1087
1088
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.top, {
1089
configurable: true,
1090
get() {
1091
const val = this.top;
1092
1093
if (this === window) {
1094
if (val === this.parent) return this[__uv.methods.parent];
1095
try {
1096
if (!('__uv' in val)) {
1097
let current = this;
1098
1099
while (current.parent !== val) {
1100
current = current.parent
1101
};
1102
1103
return '__uv' in current ? current : this;
1104
1105
} else {
1106
return val;
1107
};
1108
} catch (e) {
1109
return this;
1110
};
1111
};
1112
return val;
1113
},
1114
set(val) {
1115
this.top = val;
1116
},
1117
});
1118
1119
1120
client.nativeMethods.defineProperty(window.Object.prototype, __uv.methods.eval, {
1121
configurable: true,
1122
get() {
1123
return this === window ? __uv.eval : this.eval;
1124
},
1125
set(val) {
1126
this.eval = val;
1127
},
1128
});
1129
};
1130