Update cyclone.js

This commit is contained in:
Green! 2022-07-25 19:10:49 -04:00 committed by GitHub
parent 8a0099a6cf
commit 0d9d042a14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,240 +3,279 @@ const config = {
} }
class Cyclone { class Cyclone {
constructor() { constructor() {
this.tmp = location.pathname.split('/service')[1] this.tmp = location.pathname.split('/service')[1]
this.tmp = this.tmp.substring(1, this.tmp.length); this.tmp = this.tmp.substring(1, this.tmp.length);
this.tmp = this.tmp.replace("http://", '') this.tmp = this.tmp.replace("http://", '')
this.tmp = this.tmp.replace("https://", '') this.tmp = this.tmp.replace("https://", '')
this.tmp = this.tmp.replace("http:/", '') this.tmp = this.tmp.replace("http:/", '')
this.tmp = this.tmp.replace("https:/", '') this.tmp = this.tmp.replace("https:/", '')
this.tmp = location.protocol + "//" + this.tmp this.tmp = location.protocol + "//" + this.tmp
document._location = new URL(this.tmp); document._location = new URL(this.tmp);
this.url = new URL(document._location.href); this.url = new URL(document._location.href);
this.prefix = location.pathname.split('/')[1] this.prefix = location.pathname.split('/')[1]
this.bareEndpoint = location.host + "/" + this.prefix this.bareEndpoint = location.host + "/" + this.prefix
if (this.url.pathname == "/") { if (this.url.pathname == "/") {
this.paths = ['/'] this.paths = ['/']
} else { } else {
this.paths = this.url.pathname.split('/') this.paths = this.url.pathname.split('/')
} }
this.host = 'https://' + this.url.host this.host = 'https://' + this.url.host
this.targetAttrs = ['href', 'src', 'action', 'srcdoc', 'srcset']; this.targetAttrs = ['href', 'src', 'action', 'srcdoc', 'srcset'];
if (!document.cycloneInjected) { if (!document.cycloneInjected) {
console.log("Cyclone Injected with paths of:", this.paths, this.url.pathname) console.log("Cyclone Injected with paths of:", this.paths, this.url.pathname)
document.cycloneInjected = true document.cycloneInjected = true
} }
/*const LocationHandler = { /*const LocationHandler = {
get(target, prop, reciver) { get(target, prop, reciver) {
return loc[prop] return loc[prop]
}, },
set(target, prop, val) { set(target, prop, val) {
return 'hi' return 'hi'
} }
} }
document._location = new Proxy(LocationHandler, loc)*/ document._location = new Proxy(LocationHandler, loc)*/
} }
rewriteUrl(link) { rewriteUrl(link) {
if (!link) { if (!link) {
link = ""; link = "";
} }
var rewritten; var rewritten;
if (link.startsWith('https://') || link.startsWith('http://') || link.startsWith('//')) { if (link.startsWith('https://') || link.startsWith('http://') || link.startsWith('//')) {
if (link.startsWith('//')) { if (link.startsWith('//')) {
rewritten = 'https:' + link; rewritten = 'https:' + link;
} else { } else {
rewritten = link; rewritten = link;
}; };
} else { } else {
if (link.startsWith('.')) { if (link.startsWith('.')) {
let offset = 1; let offset = 1;
if (link.startsWith('..')) { if (link.startsWith('..')) {
offset = 2; offset = 2;
} }
let file = link.substr(link.indexOf('.') + 1 + offset, link.length) let file = link.substr(link.indexOf('.') + 1 + offset, link.length)
rewritten = this.url.hostname + file rewritten = this.url.hostname + file
} else { } else {
if (link.startsWith('/')) { if (link.startsWith('/')) {
rewritten = this.host + link rewritten = this.host + link
} else { } else {
rewritten = this.host + '/' + link; rewritten = this.host + '/' + link;
} }
} }
} }
var exceptions = ['about:', 'mailto:', 'javascript:', 'data:'] var exceptions = ['about:', 'mailto:', 'javascript:', 'data:']
let needstowrite = true; let needstowrite = true;
for (let i = 0; i < exceptions.length; i++) { for (let i = 0; i < exceptions.length; i++) {
if (link.startsWith(exceptions[i])) { if (link.startsWith(exceptions[i])) {
needstowrite = false needstowrite = false
} }
} }
if (needstowrite) { if (needstowrite) {
rewritten = location.protocol + '//' + this.bareEndpoint + '/' + rewritten rewritten = location.protocol + '//' + this.bareEndpoint + '/' + rewritten
return rewritten; return rewritten;
} else { } else {
return link; return link;
} }
} }
rewriteSrcset(sample) { rewriteSrcset(sample) {
return sample.split(',').map(e => { return sample.split(',').map(e => {
return (e.split(' ').map(a => { return (e.split(' ').map(a => {
if (a.startsWith('http') || (a.startsWith('/') && !a.startsWith(this.prefix))) { if (a.startsWith('http') || (a.startsWith('/') && !a.startsWith(this.prefix))) {
var url = this.rewriteUrl(url); var url = this.rewriteUrl(url);
} }
return a.replace(a, (url || a)) return a.replace(a, (url || a))
}).join(' ')) }).join(' '))
}).join(',') }).join(',')
} }
} }
// Rewriting of data types // Rewriting of data types
// CSS // CSS
class CSSRewriter extends Cyclone { class CSSRewriter extends Cyclone {
rewriteCSS(tag) { rewriteCSS(tag) {
var styles = window.getComputedStyle(tag) var styles = window.getComputedStyle(tag)
var _values = styles['_values'] var _values = styles['_values']
var prop = styles.getPropertyValue('background-image') var prop = styles.getPropertyValue('background-image')
var name = "background-image" var name = "background-image"
console.log(prop)
if (prop == "") {
if (!styles.getPropertyValue('background') == "") {
prop = styles.getPropertyValue('background')
name = "background"
} else {
name = "";
prop = "";
}
}
console.log(name); if (prop == "") {
if (!styles.getPropertyValue('background') == "") {
if (prop.includes("url(")) { prop = styles.getPropertyValue('background')
var start = prop.indexOf('url(') + 4 name = "background"
var end = prop.indexOf(')') - 4 } else {
name = "";
prop = "";
}
}
var url = prop.substring(start, end).toString('ascii'); if (prop.includes("url(")) {
var start = prop.indexOf('url(') + 4
if (url.startsWith(location.origin)) { var end = prop.indexOf(')') - 4
url = url.split(location.origin)
console.log("Relative URL", url); var url = prop.substring(start, end).toString('ascii');
} else {
url = url.slice(url.indexOf(location.origin)); if (url.startsWith(location.origin)) {
console.log("Absolute URL:",url) url = url.split(location.origin)
} } else {
url = url.slice(url.indexOf(location.origin));
url = this.rewriteUrl(url) }
tag.style[name] = url
} url = this.rewriteUrl(url)
} tag.style[name] = url
}
}
} }
// JS // JS
class JavaScriptRewriter extends Cyclone { class JavaScriptRewriter extends Cyclone {
rewriteJavascript(js) { constructor(proxy) {
var javascript = js.replace('window.location', 'document._dlocation') super();
javascript = javascript.replace('document.location', 'document._dlocation') //Proxied methods
javascript = javascript.replace('location.', 'document._location.') this.setAttrCy = HTMLElement.prototype.setAttribute;
return javascript this.getAttrCy = HTMLElement.prototype.getAttribute;
} this.proxy = proxy
}
rewriteJavascript(js) {
var javascript = js.replace('window.location', 'document._dlocation')
javascript = javascript.replace('document.location', 'document._dlocation')
javascript = javascript.replace('location.', 'document._location.')
return javascript
}
setAttribute(attr, value, mode) {
const setAttrCy = HTMLElement.prototype.setAttribute;
if (mode) {
this.setAttrCy.call(this, attr, value);
} else {
var url = attr
if (cyclone.targetAttrs.includes(attr)) {
url = cyclone.rewriteUrl(url);
}
setAttrCy.call(this, attr, value);
}
}
getAttribute(attrN, mode) {
const getAttrCy = HTMLElement.prototype.getAttribute;
if (mode) {
return getAttrCy.call(this, attrN);
} else {
var val = getAttrCy.call(this, attrN);
if (cyclone.targetAttrs.includes(attrN)) {
val = getAttrCy.call(this, 'data-origin-' + attrN);
}
return val;
}
}
} }
// HTML // HTML
class HTMLRewriter extends Cyclone { class HTMLRewriter extends Cyclone {
rewriteElement(element) { rewriteElement(element) {
var targetAttrs = this.targetAttrs; var targetAttrs = this.targetAttrs;
const attrs = [...element.attributes].reduce((attrs, attribute) => { var attrs;
attrs[attribute.name] = attribute.value; try {
return attrs; attrs = [...element.attributes || {}].reduce((attrs, attribute) => {
}, {}); attrs[attribute.name] = attribute.value;
return attrs;
}, {});
} catch {
attrs = {};
}
var elementAttributes = []; var elementAttributes = [];
for (var i = 0; i < targetAttrs.length; i++) { for (var i = 0; i < targetAttrs.length; i++) {
var attr = targetAttrs[i] var attr = targetAttrs[i]
var attrName = Object.keys(attrs)[i]; var attrName = Object.keys(attrs)[i];
var data = { var data = {
name: attr, name: attr,
value: element.getAttribute('data-origin-' + attr) || element.getAttribute(attr) value: element.getAttribute('data-origin-' + attr) || element.getAttribute(attr)
} }
if (data.value) { if (data.value) {
elementAttributes.push(data); elementAttributes.push(data);
} }
if (element.nonce) { if (element.nonce) {
element.setAttribute('nononce', element.nonce) element.setAttribute('nononce', element.nonce)
element.removeAttribute('nonce') element.removeAttribute('nonce')
} }
if (element.integrity) { if (element.integrity) {
element.setAttribute('nointegrity', element.integrity) element.setAttribute('nointegrity', element.integrity)
element.removeAttribute('integrity') element.removeAttribute('integrity')
} }
if (element.tagName == "script") { if (element.tagName == "script") {
if (!element.getAttribute('src')) { if (!element.getAttribute('src')) {
var jsRewrite = new JavaScriptRewriter(); var jsRewrite = new JavaScriptRewriter();
element.innerHTML = jsRewrite.rewriteJavascript(element.innerHTML) element.innerHTML = jsRewrite.rewriteJavascript(element.innerHTML)
} }
} }
// Css // Css
var cssRewrite = new CSSRewriter(); var cssRewrite = new CSSRewriter();
cssRewrite.rewriteCSS(element) cssRewrite.rewriteCSS(element)
} }
for (var i = 0; i < elementAttributes.length; i++) { for (var i = 0; i < elementAttributes.length; i++) {
var attr = elementAttributes[i] var attr = elementAttributes[i]
var attrName = attr.name; var attrName = attr.name;
var value = attr.value; var value = attr.value;
var bareValue = this.rewriteUrl(value); var bareValue = this.rewriteUrl(value);
if (attrName == "srcset") { if (attrName == "srcset") {
this.rewriteSrcset(value); this.rewriteSrcset(value);
} }
element.setAttribute(attrName, bareValue); element.setAttribute(attrName, bareValue);
element.setAttribute("data-origin-" + attrName, value); element.setAttribute("data-origin-" + attrName, value);
} }
} }
rewriteDocument() { rewriteDocument() {
var docElements = document.querySelectorAll('*'); var docElements = document.querySelectorAll('*');
for (var i = 0; i < docElements.length; i++) { for (var i = 0; i < docElements.length; i++) {
var element = docElements[i]; var element = docElements[i];
this.rewriteElement(element) this.rewriteElement(element)
} }
} }
rewriteiFrame(iframe) { rewriteiFrame(iframe) {
var frameDoc = (iframe.contentWindow || iframe.contentDocument || iframe.document); var frameDoc = (iframe.contentWindow || iframe.contentDocument || iframe.document);
let tags = frameDoc.querySelectorAll('*') let tags = frameDoc.querySelectorAll('*')
for (var i = 0; i < tags.length; i++) { for (var i = 0; i < tags.length; i++) {
var tag = tags[i] var tag = tags[i]
this.rewriteElement(tag) this.rewriteElement(tag)
} }
} }
} }
const cyclone = new Cyclone(); const cyclone = new Cyclone();
@ -245,52 +284,52 @@ const htmlRewriter = new HTMLRewriter();
const FetchIntercept = window.fetch; const FetchIntercept = window.fetch;
window.fetch = async (...args) => { window.fetch = async (...args) => {
let [resource, config] = args; let [resource, config] = args;
resource = cyclone.rewriteUrl(resource); resource = cyclone.rewriteUrl(resource);
const response = await FetchIntercept(resource, config); const response = await FetchIntercept(resource, config);
return response; return response;
} }
const MessageIntercept = window.postMessage; const MessageIntercept = window.postMessage;
window.postMessage = (...args) => { window.postMessage = (...args) => {
let [message, target, config] = args; let [message, target, config] = args;
target = cyclone.rewriteUrl(target); target = cyclone.rewriteUrl(target);
const response = MessageIntercept(message, target, config); const response = MessageIntercept(message, target, config);
return response; return response;
} }
var CWOriginal = Object.getOwnPropertyDescriptor(window.HTMLIFrameElement.prototype, 'contentWindow') var CWOriginal = Object.getOwnPropertyDescriptor(window.HTMLIFrameElement.prototype, 'contentWindow')
Object.defineProperty(window.HTMLIFrameElement.prototype, 'contentWindow', { Object.defineProperty(window.HTMLIFrameElement.prototype, 'contentWindow', {
get() { get() {
var iWindow = CWOriginal.get.call(this) var iWindow = CWOriginal.get.call(this);
cyclone.rewriteiFrame(iWindow) htmlRewriter.rewriteiFrame(iWindow);
return iWindow return iWindow
}, },
set() { set() {
return false; return false;
} }
}) })
const open = XMLHttpRequest.prototype.open; const open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, ...rest) { XMLHttpRequest.prototype.open = function(method, url, ...rest) {
url = cyclone.rewriteUrl(url) url = cyclone.rewriteUrl(url)
return open.call(this, method, url, ...rest); return open.call(this, method, url, ...rest);
}; };
var oPush = window.history.pushState; var oPush = window.history.pushState;
var oPlace = window.history.replaceState; var oPlace = window.history.replaceState;
function CycloneStates(dat, unused, url) { function CycloneStates(dat, unused, url) {
var cyUrl = cyclone.rewriteUrl(url); var cyUrl = cyclone.rewriteUrl(url);
oPush.call(this, dat, unused, cyUrl); oPush.call(this, dat, unused, cyUrl);
} }
window.history.pushState = CycloneStates window.history.pushState = CycloneStates
@ -300,33 +339,33 @@ history.replaceState = CycloneStates
const OriginalWebsocket = window.WebSocket const OriginalWebsocket = window.WebSocket
const ProxiedWebSocket = function() { const ProxiedWebSocket = function() {
const ws = new OriginalWebsocket(...arguments) const ws = new OriginalWebsocket(...arguments)
const originalAddEventListener = ws.addEventListener const originalAddEventListener = ws.addEventListener
const proxiedAddEventListener = function() { const proxiedAddEventListener = function() {
if (arguments[0] === "message") { if (arguments[0] === "message") {
const cb = arguments[1] const cb = arguments[1]
arguments[1] = function() { arguments[1] = function() {
var origin = arguments[0].origin var origin = arguments[0].origin
arguments[0].origin = cyclone.rewriteUrl(origin); arguments[0].origin = cyclone.rewriteUrl(origin);
return cb.apply(this, arguments) return cb.apply(this, arguments)
} }
} }
return originalAddEventListener.apply(this, arguments) return originalAddEventListener.apply(this, arguments)
} }
ws.addEventListener = proxiedAddEventListener ws.addEventListener = proxiedAddEventListener
Object.defineProperty(ws, "onmessage", { Object.defineProperty(ws, "onmessage", {
set(func) { set(func) {
return proxiedAddEventListener.apply(this, [ return proxiedAddEventListener.apply(this, [
"message", "message",
func, func,
false false
]); ]);
} }
}); });
return ws; return ws;
}; };
window.WebSocket = ProxiedWebSocket; window.WebSocket = ProxiedWebSocket;
@ -334,39 +373,45 @@ window.WebSocket = ProxiedWebSocket;
const nwtb = window.open const nwtb = window.open
function openNewTab(url, target, features) { function openNewTab(url, target, features) {
url = cyclone.rewriteUrl(url) url = cyclone.rewriteUrl(url)
nwtb(url, target, features) nwtb(url, target, features)
} }
window.open = openNewTab; window.open = openNewTab;
htmlRewriter.rewriteDocument(); window.onload = function() {
for (var i = 0; i < 12; i++) {
setTimeout(()=>{
htmlRewriter.rewriteDocument();
},500)
}
setInterval(function() {
htmlRewriter.rewriteDocument();
}, 3000);
}
let mutationE = new MutationObserver((mutationList, observer) => { let mutationE = new MutationObserver((mutationList, observer) => {
for (const mutation of mutationList) { for (const mutation of mutationList) {
mutation.addedNodes.forEach(node => { mutation.addedNodes.forEach(node => {
htmlRewriter.rewriteElement(node); htmlRewriter.rewriteElement(node);
}); });
} }
}).observe(document, { }).observe(document, {
childList: true, childList: true,
subtree: true subtree: true
}) })
setInterval(function() {
htmlRewriter.rewriteDocument();
}, 10000)
//For intercepting all requests //For intercepting all requests
if (!document.serviceWorkerRegistered) { if (!document.serviceWorkerRegistered) {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
window.addEventListener('load', function() { window.addEventListener('load', function() {
navigator.serviceWorker.register(location.origin + '/cySw.js').then(function(registration) { navigator.serviceWorker.register(location.origin + '/cySw.js').then(function(registration) {
console.log('Service worker registered with scope: ', registration.scope); console.log('Service worker registered with scope: ', registration.scope);
}, function(err) { }, function(err) {
console.log('ServiceWorker registration failed: ', err); console.log('ServiceWorker registration failed: ', err);
}); });
}); });
} }
document.serviceWorkerRegistered = true document.serviceWorkerRegistered = true
} }