diff --git a/app.js b/app.js index 3890ca9f..bcd19699 100644 --- a/app.js +++ b/app.js @@ -1,397 +1,399 @@ - const express = require('express'), - app = express(), - http = require('http'), - https = require('https'), - fs = require('fs'), - querystring = require('querystring'), - session = require('express-session'), - sanitizer = require('sanitizer'), - websocket = require('./ws-proxy.js'), - fetch = require('node-fetch'), - path = require("path"); +const { checkServerIdentity } = require('tls'); - const config = JSON.parse(fs.readFileSync('./config.json', { - encoding: 'utf8' - })); - if (!config.prefix.startsWith('/')) { - config.prefix = `/${config.prefix}`; - } +const express = require('express'), + app = express(), + http = require('http'), + https = require('https'), + fs = require('fs'), + querystring = require('querystring'), + session = require('express-session'), + sanitizer = require('sanitizer'), + websocket = require('./ws-proxy.js'), + fetch = require('node-fetch'), + path = require("path"); - if (!config.prefix.endsWith('/')) { - config.prefix = `${config.prefix}/`; - } +const config = JSON.parse(fs.readFileSync('./config.json', { + encoding: 'utf8' +})); +if (!config.prefix.startsWith('/')) { + config.prefix = `/${config.prefix}`; +} - let server; - let server_protocol; - const server_options = { - key: fs.readFileSync('./ssl/default.key'), - cert: fs.readFileSync('./ssl/default.crt') - } - if (config.ssl == true) { - server = https.createServer(server_options, app); - server_protocol = 'https://'; - } else { - server = http.createServer(app); - server_protocol = 'http://'; - }; +if (!config.prefix.endsWith('/')) { + config.prefix = `${config.prefix}/`; +} - // WebSocket Proxying - websocket(server); +let server; +let server_protocol; +const server_options = { + key: fs.readFileSync('./ssl/default.key'), + cert: fs.readFileSync('./ssl/default.crt') +} +if (config.ssl == true) { + server = https.createServer(server_options, app); + server_protocol = 'https://'; +} else { + server = http.createServer(app); + server_protocol = 'http://'; +}; - console.log(`Alloy Proxy now running on ${server_protocol}0.0.0.0:${config.port}! Proxy prefix is "${config.prefix}"!`); - server.listen(process.env.PORT || config.port); +// WebSocket Proxying +websocket(server); - btoa = (str) => { - str = new Buffer.from(str).toString('base64'); - return str; - }; +console.log(`Alloy Proxy now running on ${server_protocol}0.0.0.0:${config.port}! Proxy prefix is "${config.prefix}"!`); +server.listen(process.env.PORT || config.port); - atob = (str) => { - str = new Buffer.from(str, 'base64').toString('utf-8'); - return str; - }; +btoa = (str) => { + str = new Buffer.from(str).toString('base64'); + return str; +}; - rewrite_url = (dataURL, option) => { - var websiteURL; - var websitePath; - if (option == 'decode') { - websiteURL = atob(dataURL.split('/').splice(0, 1).join('/')); - websitePath = '/' + dataURL.split('/').splice(1).join('/'); - } else { - websiteURL = btoa(dataURL.split('/').splice(0, 3).join('/')); - websitePath = '/' + dataURL.split('/').splice(3).join('/'); - } - if (websitePath == '/') { - return `${websiteURL}`; - } else return `${websiteURL}${websitePath}`; - }; +atob = (str) => { + str = new Buffer.from(str, 'base64').toString('utf-8'); + return str; +}; - app.use(session({ - secret: 'alloy', - saveUninitialized: true, - resave: true, - cookieName: '__alloy_cookie_auth=yes', - duration: 30 * 60 * 1000, - activeDuration: 5 * 60 * 1000 - })); - - // We made our own version of body-parser instead, due to issues. - app.use((req, res, next) => { - if (req.method == 'POST') { - req.raw_body = ''; - req.on('data', chunk => { - req.raw_body += chunk.toString(); // convert buffer to string - }); - req.on('end', () => { - req.str_body = req.raw_body; - try { - req.body = JSON.parse(req.raw_body); - } catch (err) { - req.body = {} - } - next(); - }); - } else return next(); - }); - - app.use(`${config.prefix}utils/`, async (req, res, next) => { - if (req.url.startsWith('/assets/')) { - res.sendFile(__dirname + '/utils' + req.url); - } - if (req.query.url) { - let url = atob(req.query.url); - if (url.startsWith('https://') || url.startsWith('http://')) { - url = url; - } else if (url.startsWith('//')) { - url = 'http:' + url; - } else { - url = 'http://' + url; - } - return res.redirect(307, config.prefix + rewrite_url(url)); - } - }); - - /* - //Cookie Auth - - app.use(checkAuth); - - app.use(auth); - - function auth(req, res, next) { - - let user = new User({ - cookieName: '__alloy_cookie_auth=yes' - }); - - if (!req.signedCookies.user) { - var authHeader = req.headers.authorization; - if (!authHeader) { - var err = new Error('You are not authenticated!'); - err.status = 401; - next(err); - return; - } - var auth = new Buffer(authHeader.split(' ')[1], 'base64').toString().split(':'); - var pass = auth[1]; - if (user == '__alloy_cookie_auth=yes') { - res.cookie('user', 'admin', { - signed: true - }); - next(); // authorized - } else { - var err = new Error('You are not authenticated!'); - err.status = 401; - next(err); - } +rewrite_url = (dataURL, option) => { + var websiteURL; + var websitePath; + if (option == 'decode') { + websiteURL = atob(dataURL.split('/').splice(0, 1).join('/')); + websitePath = '/' + dataURL.split('/').splice(1).join('/'); } else { - if (req.signedCookies.user === 'admin') { - next(); - } else { - var err = new Error('You are not authenticated!'); - err.status = 401; - next(err); - } + websiteURL = btoa(dataURL.split('/').splice(0, 3).join('/')); + websitePath = '/' + dataURL.split('/').splice(3).join('/'); } - }; + if (websitePath == '/') { + return `${websiteURL}`; + } else return `${websiteURL}${websitePath}`; +}; - // Check the auth of the routes => middleware functions - function checkAuth(req, res, next) { - console.log('checkAuth ' + req.url); - // don 't serve /secure to those not logged in => /secure if for those who are logged in - // you should add to this list, for each and every secure url - if (req.url.indexOf(`${config.prefix}session/`) === 0 && (!req.session || !req.session.authenticated)) { - res.render(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 401: The website '${sanitizer.sanitize(proxy.url.hostname)}' is not permitted!`), { - status: 403 +app.use(session({ + secret: 'alloy', + saveUninitialized: true, + resave: true, + cookieName: '__alloy_cookie_auth=yes', + duration: 30 * 60 * 1000, + activeDuration: 5 * 60 * 1000 +})); + +// We made our own version of body-parser instead, due to issues. +app.use((req, res, next) => { + if (req.method == 'POST') { + req.raw_body = ''; + req.on('data', chunk => { + req.raw_body += chunk.toString(); // convert buffer to string }); + req.on('end', () => { + req.str_body = req.raw_body; + try { + req.body = JSON.parse(req.raw_body); + } catch (err) { + req.body = {} + } + next(); + }); + } else return next(); +}); + +app.use(`${config.prefix}utils/`, async(req, res, next) => { + if (req.url.startsWith('/assets/')) { + res.sendFile(__dirname + '/utils' + req.url); + } + if (req.query.url) { + let url = atob(req.query.url); + if (url.startsWith('https://') || url.startsWith('http://')) { + url = url; + } else if (url.startsWith('//')) { + url = 'http:' + url; + } else { + url = 'http://' + url; + } + return res.redirect(307, config.prefix + rewrite_url(url)); + } +}); + +/* +//Cookie Auth + + app.use(checkAuth); + + app.use(auth); + +function auth(req, res, next) { + +let user = new User({ + cookieName: '__alloy_cookie_auth=yes' + }); + + if (!req.signedCookies.user) { + var authHeader = req.headers.authorization; + if (!authHeader) { + var err = new Error('You are not authenticated!'); + err.status = 401; + next(err); return; - } - xt(); - } */ - - app.post(`${config.prefix}session/`, async (req, res, next) => { - let url = querystring.parse(req.raw_body).url; - if (url.startsWith('//')) { - url = 'http:' + url; - } else if (url.startsWith('https://') || url.startsWith('http://')) { - url = url + } + var auth = new Buffer(authHeader.split(' ')[1], 'base64').toString().split(':'); + var pass = auth[1]; + if (user == '__alloy_cookie_auth=yes') { + res.cookie('user', 'admin', { + signed: true + }); + next(); // authorized + } else { + var err = new Error('You are not authenticated!'); + err.status = 401; + next(err); + } + } else { + if (req.signedCookies.user === 'admin') { + next(); } else { - url = 'http://' + url - }; + var err = new Error('You are not authenticated!'); + err.status = 401; + next(err); + } + } + }; - /* let cookies = {}; - if (request.headers.cookie !== undefined) { - cookies = cookie.parse(request.headers.cookie); - } - - console.log(cookies); - response.writeHead(200, { - 'SET-Cookie': ['__alloy_cookie_auth=yes', - `Permanent=Cookies; Max-Age=${60*60*24*30}`, - 'Secure=Secure; Secure', - 'HttpOnly=HttpOnly; HttpOnly', - 'Path=Path; Path=/cookie' - ] - }) - response.end('Coookie!!'); */ - - req.session.authenticated = true; - }); - - app.use(config.prefix, async (req, res, next) => { - var proxy = {}; - proxy.url = rewrite_url(req.url.slice(1), 'decode'); - proxy.url = { - href: proxy.url, - hostname: proxy.url.split('/').splice(2).splice(0, 1).join('/'), - origin: proxy.url.split('/').splice(0, 3).join('/'), - encoded_origin: btoa(proxy.url.split('/').splice(0, 3).join('/')), - path: '/' + proxy.url.split('/').splice(3).join('/'), - protocol: proxy.url.split('\:').splice(0, 1).join(''), - } - - proxy.url.encoded_origin = btoa(proxy.url.origin); - - proxy.requestHeaders = req.headers; - proxy.requestHeaders['host'] = proxy.url.hostname; - if (proxy.requestHeaders['referer']) { - let referer = '/' + String(proxy.requestHeaders['referer']).split('/').splice(3).join('/'); - - referer = rewrite_url(referer.replace(config.prefix, ''), 'decode'); - - if (referer.startsWith('https://') || referer.startsWith('http://')) { - referer = referer; - - } else referer = proxy.url.href; - - proxy.requestHeaders['referer'] = referer; - } - - - if (proxy.requestHeaders['origin']) { - let origin = '/' + String(proxy.requestHeaders['origin']).split('/').splice(3).join('/'); - - origin = rewrite_url(origin.replace(config.prefix, ''), 'decode'); - - if (origin.startsWith('https://') || origin.startsWith('http://')) { - - origin = origin.split('/').splice(0, 3).join('/'); - - } else origin = proxy.url.origin; - - proxy.requestHeaders['origin'] = origin; - } - if (proxy.requestHeaders.cookie) { - delete proxy.requestHeaders.cookie; - } - const httpAgent = new http.Agent({ - keepAlive: true +// Check the auth of the routes => middleware functions +function checkAuth(req, res, next) { + console.log('checkAuth ' + req.url); +// don 't serve /secure to those not logged in => /secure if for those who are logged in +// you should add to this list, for each and every secure url + if (req.url.indexOf(`${config.prefix}session/`) === 0 && (!req.session || !req.session.authenticated)) { + res.render(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 401: The website '${sanitizer.sanitize(proxy.url.hostname)}' is not permitted!`), { + status: 403 }); - const httpsAgent = new https.Agent({ - rejectUnauthorized: false, - keepAlive: true - }); - proxy.options = { - method: req.method, - headers: proxy.requestHeaders, - redirect: 'manual', - agent: function(_parsedURL) { - if (_parsedURL.protocol == 'http:') { - return httpAgent; - } else { - return httpsAgent; - } - } - }; + return; + } + xt(); + } */ - if (req.method == 'POST') { - proxy.options.body = req.str_body; - } - if (proxy.url.hostname == 'discord.com' && proxy.url.path == '/') { - return res.redirect(307, config.prefix + rewrite_url('https://discord.com/login')); - }; +app.post(`${config.prefix}session/`, async(req, res, next) => { + let url = querystring.parse(req.raw_body).url; + if (url.startsWith('//')) { + url = 'http:' + url; + } else if (url.startsWith('https://') || url.startsWith('http://')) { + url = url + } else { + url = 'http://' + url + }; - if (proxy.url.hostname == 'www.reddit.com') { - return res.redirect(307, config.prefix + rewrite_url('https://old.reddit.com')); - }; + /* let cookies = {}; + if (request.headers.cookie !== undefined) { + cookies = cookie.parse(request.headers.cookie); + } - if (!req.url.slice(1).startsWith(`${proxy.url.encoded_origin}/`)) { - return res.redirect(307, config.prefix + proxy.url.encoded_origin + '/'); - }; + console.log(cookies); + response.writeHead(200, { + 'SET-Cookie': ['__alloy_cookie_auth=yes', + `Permanent=Cookies; Max-Age=${60*60*24*30}`, + 'Secure=Secure; Secure', + 'HttpOnly=HttpOnly; HttpOnly', + 'Path=Path; Path=/cookie' + ] + }) + response.end('Coookie!!'); */ - const blocklist = JSON.parse(fs.readFileSync('./blocklist.json', { - encoding: 'utf8' - })); + req.session.authenticated = true; +}); - let is_blocked = false; +app.use(config.prefix, async(req, res, next) => { + var proxy = {}; + proxy.url = rewrite_url(req.url.slice(1), 'decode'); + proxy.url = { + href: proxy.url, + hostname: proxy.url.split('/').splice(2).splice(0, 1).join('/'), + origin: proxy.url.split('/').splice(0, 3).join('/'), + encoded_origin: btoa(proxy.url.split('/').splice(0, 3).join('/')), + path: '/' + proxy.url.split('/').splice(3).join('/'), + protocol: proxy.url.split('\:').splice(0, 1).join(''), + } - Array.from(blocklist).forEach(blocked_hostname => { - if (proxy.url.hostname == blocked_hostname) { - is_blocked = true; - } - }); + proxy.url.encoded_origin = btoa(proxy.url.origin); - if (is_blocked == true) { - return res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 401: The website '${sanitizer.sanitize(proxy.url.hostname)}' is not permitted!`)) - } + proxy.requestHeaders = req.headers; + proxy.requestHeaders['host'] = proxy.url.hostname; + if (proxy.requestHeaders['referer']) { + let referer = '/' + String(proxy.requestHeaders['referer']).split('/').splice(3).join('/'); - proxy.response = await fetch(proxy.url.href, proxy.options).catch(err => res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 400: Could not make request to '${sanitizer.sanitize(proxy.url.href)}'!`))); + referer = rewrite_url(referer.replace(config.prefix, ''), 'decode'); - if (typeof proxy.response.buffer != 'function') return; + if (referer.startsWith('https://') || referer.startsWith('http://')) { + referer = referer; - proxy.buffer = await proxy.response.buffer(); + } else referer = proxy.url.href; - proxy.content_type = 'text/plain'; - - proxy.response.headers.forEach((e, i, a) => { - if (i == 'content-type') proxy.content_type = e; - }); - if (proxy.content_type == null || typeof proxy.content_type == 'undefined') proxy.content_type = 'text/html'; - - proxy.sendResponse = proxy.buffer; - - // Parsing the headers from the response to remove square brackets so we can set them as the response headers. - proxy.headers = Object.fromEntries( - Object.entries(JSON.parse(JSON.stringify(proxy.response.headers.raw()))) - .map(([key, val]) => [key, val[0]]) - ); - - // Parsing all the headers to remove all of the bad headers that could affect proxies performance. - Object.entries(proxy.headers).forEach(([header_name, header_value]) => { - if (header_name.startsWith('content-encoding') || header_name.startsWith('x-') || header_name.startsWith('cf-') || header_name.startsWith('strict-transport-security') || header_name.startsWith('content-security-policy')) { - delete proxy.headers[header_name]; - } - }); - - // If theres a location for a redirect in the response, then the proxy will get the response location then redirect you to the proxied version of the url. - if (proxy.response.headers.get('location')) { - return res.redirect(307, config.prefix + rewrite_url(String(proxy.response.headers.get('location')))); - } - - res.status(proxy.response.status); - res.set(proxy.headers); - res.contentType(proxy.content_type); - if (proxy.content_type.startsWith('text/html')) { - req.session.url = proxy.url.origin; - proxy.sendResponse = proxy.sendResponse.toString() - .replace(/integrity="(.*?)"/gi, '') - .replace(/nonce="(.*?)"/gi, '') - .replace(/(href|src|poster|data|action|srcset)="\/\/(.*?)"/gi, `$1` + `="http://` + `$2` + `"`) - .replace(/(href|src|poster|data|action|srcset)='\/\/(.*?)'/gi, `$1` + `='http://` + `$2` + `'`) - .replace(/(href|src|poster|data|action|srcset)="\/(.*?)"/gi, `$1` + `="${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `"`) - .replace(/(href|src|poster|data|action|srcset)='\/(.*?)'/gi, `$1` + `='${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `'`) - .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) { - str = str.split(`'`).slice(1).slice(0, -1).join(``); - return `'${config.prefix}${rewrite_url(str)}'` - }) - .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) { - str = str.split(`"`).slice(1).slice(0, -1).join(``); - return `"${config.prefix}${rewrite_url(str)}"` - }) - .replace(/(window|document).location.href/gi, `"${proxy.url.href}"`) - .replace(/(window|document).location.hostname/gi, `"${proxy.url.hostname}"`) - .replace(/(window|document).location.pathname/gi, `"${proxy.url.path}"`) - .replace(/location.href/gi, `"${proxy.url.href}"`) - .replace(/location.hostname/gi, `"${proxy.url.hostname}"`) - .replace(/location.pathname/gi, `"${proxy.url.path}"`) - .replace(//gi, ``); - - // Temp hotfix for Youtube search bar until my script injection can fix it. - - if (proxy.url.hostname == 'www.youtube.com') { - proxy.sendResponse = proxy.sendResponse.replace(/\/results/gi, `${config.prefix}${proxy.url.encoded_origin}/results`); - }; - } else if (proxy.content_type.startsWith('text/css')) { - proxy.sendResponse = proxy.sendResponse.toString() - .replace(/url\("\/\/(.*?)"\)/gi, `url("http://` + `$1` + `")`) - .replace(/url\('\/\/(.*?)'\)/gi, `url('http://` + `$1` + `')`) - .replace(/url\(\/\/(.*?)\)/gi, `url(http://` + `$1` + `)`) - .replace(/url\("\/(.*?)"\)/gi, `url("${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `")`) - .replace(/url\('\/(.*?)'\)/gi, `url('${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `')`) - .replace(/url\(\/(.*?)\)/gi, `url(${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `)`) - .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) { - str = str.split(`"`).slice(1).slice(0, -1).join(``); - return `"${config.prefix}${rewrite_url(str)}"` - }) - .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) { - str = str.split(`'`).slice(1).slice(0, -1).join(``); - return `'${config.prefix}${rewrite_url(str)}'` - }) - .replace(/\((https:\/\/|http:\/\/)(.*?)\)/gi, function(str) { - str = str.split(`(`).slice(1).join(``).split(')').slice(0, -1).join(''); - return `(${config.prefix}${rewrite_url(str)})` - }); - - }; - // We send the response from the server rewritten. - res.send(proxy.sendResponse); - }); - - //Querystrings - app.get('/', async (req, res) => { + proxy.requestHeaders['referer'] = referer; + } - /* + if (proxy.requestHeaders['origin']) { + let origin = '/' + String(proxy.requestHeaders['origin']).split('/').splice(3).join('/'); + + origin = rewrite_url(origin.replace(config.prefix, ''), 'decode'); + + if (origin.startsWith('https://') || origin.startsWith('http://')) { + + origin = origin.split('/').splice(0, 3).join('/'); + + } else origin = proxy.url.origin; + + proxy.requestHeaders['origin'] = origin; + } + if (proxy.requestHeaders.cookie) { + delete proxy.requestHeaders.cookie; + } + const httpAgent = new http.Agent({ + keepAlive: true + }); + const httpsAgent = new https.Agent({ + rejectUnauthorized: false, + keepAlive: true + }); + proxy.options = { + method: req.method, + headers: proxy.requestHeaders, + redirect: 'manual', + agent: function(_parsedURL) { + if (_parsedURL.protocol == 'http:') { + return httpAgent; + } else { + return httpsAgent; + } + } + }; + + if (req.method == 'POST') { + proxy.options.body = req.str_body; + } + if (proxy.url.hostname == 'discord.com' && proxy.url.path == '/') { + return res.redirect(307, config.prefix + rewrite_url('https://discord.com/login')); + }; + + if (proxy.url.hostname == 'www.reddit.com') { + return res.redirect(307, config.prefix + rewrite_url('https://old.reddit.com')); + }; + + if (!req.url.slice(1).startsWith(`${proxy.url.encoded_origin}/`)) { + return res.redirect(307, config.prefix + proxy.url.encoded_origin + '/'); + }; + + const blocklist = JSON.parse(fs.readFileSync('./blocklist.json', { + encoding: 'utf8' + })); + + let is_blocked = false; + + Array.from(blocklist).forEach(blocked_hostname => { + if (proxy.url.hostname == blocked_hostname) { + is_blocked = true; + } + }); + + if (is_blocked == true) { + return res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 401: The website '${sanitizer.sanitize(proxy.url.hostname)}' is not permitted!`)) + } + + proxy.response = await fetch(proxy.url.href, proxy.options).catch(err => res.send(fs.readFileSync('./utils/error/error.html', 'utf8').toString().replace('%ERROR%', `Error 400: Could not make request to '${sanitizer.sanitize(proxy.url.href)}'!`))); + + if (typeof proxy.response.buffer != 'function') return; + + proxy.buffer = await proxy.response.buffer(); + + proxy.content_type = 'text/plain'; + + proxy.response.headers.forEach((e, i, a) => { + if (i == 'content-type') proxy.content_type = e; + }); + if (proxy.content_type == null || typeof proxy.content_type == 'undefined') proxy.content_type = 'text/html'; + + proxy.sendResponse = proxy.buffer; + + // Parsing the headers from the response to remove square brackets so we can set them as the response headers. + proxy.headers = Object.fromEntries( + Object.entries(JSON.parse(JSON.stringify(proxy.response.headers.raw()))) + .map(([key, val]) => [key, val[0]]) + ); + + // Parsing all the headers to remove all of the bad headers that could affect proxies performance. + Object.entries(proxy.headers).forEach(([header_name, header_value]) => { + if (header_name.startsWith('content-encoding') || header_name.startsWith('x-') || header_name.startsWith('cf-') || header_name.startsWith('strict-transport-security') || header_name.startsWith('content-security-policy')) { + delete proxy.headers[header_name]; + } + }); + + // If theres a location for a redirect in the response, then the proxy will get the response location then redirect you to the proxied version of the url. + if (proxy.response.headers.get('location')) { + return res.redirect(307, config.prefix + rewrite_url(String(proxy.response.headers.get('location')))); + } + + res.status(proxy.response.status); + res.set(proxy.headers); + res.contentType(proxy.content_type); + if (proxy.content_type.startsWith('text/html')) { + req.session.url = proxy.url.origin; + proxy.sendResponse = proxy.sendResponse.toString() + .replace(/integrity="(.*?)"/gi, '') + .replace(/nonce="(.*?)"/gi, '') + .replace(/(href|src|poster|data|action|srcset)="\/\/(.*?)"/gi, `$1` + `="http://` + `$2` + `"`) + .replace(/(href|src|poster|data|action|srcset)='\/\/(.*?)'/gi, `$1` + `='http://` + `$2` + `'`) + .replace(/(href|src|poster|data|action|srcset)="\/(.*?)"/gi, `$1` + `="${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `"`) + .replace(/(href|src|poster|data|action|srcset)='\/(.*?)'/gi, `$1` + `='${config.prefix}${proxy.url.encoded_origin}/` + `$2` + `'`) + .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) { + str = str.split(`'`).slice(1).slice(0, -1).join(``); + return `'${config.prefix}${rewrite_url(str)}'` + }) + .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) { + str = str.split(`"`).slice(1).slice(0, -1).join(``); + return `"${config.prefix}${rewrite_url(str)}"` + }) + .replace(/(window|document).location.href/gi, `"${proxy.url.href}"`) + .replace(/(window|document).location.hostname/gi, `"${proxy.url.hostname}"`) + .replace(/(window|document).location.pathname/gi, `"${proxy.url.path}"`) + .replace(/location.href/gi, `"${proxy.url.href}"`) + .replace(/location.hostname/gi, `"${proxy.url.hostname}"`) + .replace(/location.pathname/gi, `"${proxy.url.path}"`) + .replace(//gi, ``); + + // Temp hotfix for Youtube search bar until my script injection can fix it. + + if (proxy.url.hostname == 'www.youtube.com') { + proxy.sendResponse = proxy.sendResponse.replace(/\/results/gi, `${config.prefix}${proxy.url.encoded_origin}/results`); + }; + } else if (proxy.content_type.startsWith('text/css')) { + proxy.sendResponse = proxy.sendResponse.toString() + .replace(/url\("\/\/(.*?)"\)/gi, `url("http://` + `$1` + `")`) + .replace(/url\('\/\/(.*?)'\)/gi, `url('http://` + `$1` + `')`) + .replace(/url\(\/\/(.*?)\)/gi, `url(http://` + `$1` + `)`) + .replace(/url\("\/(.*?)"\)/gi, `url("${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `")`) + .replace(/url\('\/(.*?)'\)/gi, `url('${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `')`) + .replace(/url\(\/(.*?)\)/gi, `url(${config.prefix}${proxy.url.encoded_origin}/` + `$1` + `)`) + .replace(/"(https:\/\/|http:\/\/)(.*?)"/gi, function(str) { + str = str.split(`"`).slice(1).slice(0, -1).join(``); + return `"${config.prefix}${rewrite_url(str)}"` + }) + .replace(/'(https:\/\/|http:\/\/)(.*?)'/gi, function(str) { + str = str.split(`'`).slice(1).slice(0, -1).join(``); + return `'${config.prefix}${rewrite_url(str)}'` + }) + .replace(/\((https:\/\/|http:\/\/)(.*?)\)/gi, function(str) { + str = str.split(`(`).slice(1).join(``).split(')').slice(0, -1).join(''); + return `(${config.prefix}${rewrite_url(str)})` + }); + + }; + // We send the response from the server rewritten. + res.send(proxy.sendResponse); +}); + +//Querystrings +app.get('/', async(req, res) => { + + + /* const path = require("path"); //Use this for path. fs.readFileSync( path, options ); @@ -405,162 +407,150 @@ } */ + /* var hbsites = {}; + && hostname == hbsites + */ - if (req.url == '/') { - return res.send(fs.readFileSync(path.resolve() + '/public/index.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'index.html'), 'utf8')); + } - if (req.url == '/?z') { - return res.send(fs.readFileSync(path.resolve() + '/public/z.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?z': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'surf.html'), 'utf8')); + } - if (req.url == '/?a') { - return res.send(fs.readFileSync(path.resolve() + '/public/a.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?a': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'proxnav', 'alloy.html'), 'utf8')); + } - if (req.url == '/?dd') { - return res.send(fs.readFileSync(path.resolve() + '/public/expr/d.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?dd': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'redirects', 'discordprox.html'), 'utf8')); + } - if (req.url == '/?b') { - return res.send(fs.readFileSync(path.resolve() + '/public/b.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?b': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'proxnav', 'node.html'), 'utf8')); + } - if (req.url == '/?y') { - return res.send(fs.readFileSync(path.resolve() + '/public/y.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?y': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'proxnav', 'youtube.html'), 'utf8')); + } - if (req.url == '/?e') { - return res.send(fs.readFileSync(path.resolve() + '/public/e.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?e': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'proxnav', 'pydodge.html'), 'utf8')); + } - if (req.url == '/?d') { - return res.send(fs.readFileSync(path.resolve() + '/public/d.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?d': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'proxnav', 'discordhub.html'), 'utf8')); + } - if (req.url == '/?c') { - return res.send(fs.readFileSync(path.resolve() + '/public/c.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?c': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'credits.html'), 'utf8')); + } - if (req.url == '/?f') { - return res.send(fs.readFileSync(path.resolve() + '/public/f.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?f': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'flash.html'), 'utf8')); + } - if (req.url == '/?g') { - return res.send(fs.readFileSync(path.resolve() + '/public/g.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?g': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'gtools.html'), 'utf8')); + } - if (req.url == '/?h') { - return res.send(fs.readFileSync(path.resolve() + '/public/h.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?h': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'games5.html'), 'utf8')); + } - if (req.url == '/?i') { - return res.send(fs.readFileSync(path.resolve() + '/public/i.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?i': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'icons.html'), 'utf8')); + } - if (req.url == '/?in') { - return res.send(fs.readFileSync(path.resolve() + '/public/info.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?in': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'info.html'), 'utf8')); + } - if (req.url == '/?k') { - return res.send(fs.readFileSync(path.resolve() + '/public/k.html', { - encoding: 'utf8' - })); - } + switch (req.url == '/?k') { + case '/?k': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'bppages', 'frames', 'krunker.html'), 'utf8')); + } - if (req.url == '/?m') { - return res.send(fs.readFileSync(path.resolve() + '/public/m.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?m': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'gba.html'), 'utf8')); + } - if (req.url == '/?n') { - return res.send(fs.readFileSync(path.resolve() + '/public/n.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?n': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'redirects', 'chatbox.html'), 'utf8')); + } - if (req.url == '/?p') { - return res.send(fs.readFileSync(path.resolve() + '/public/p.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?p': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'proxnav', 'pmprox.html'), 'utf8')); + } - if (req.url == '/?t') { - return res.send(fs.readFileSync(path.resolve() + '/public/t.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?t': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'terms.html'), 'utf8')); + } - if (req.url == '/?x') { - return res.send(fs.readFileSync(path.resolve() + '/public/x.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?x': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'nav', 'bookmarklets.html'), 'utf8')); + } - if (req.url == '/?yh') { - return res.send(fs.readFileSync(path.resolve() + '/public/yh.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?yh': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'redirects', 'ythub.html'), 'utf8')); + } - if (req.url == '/?ym') { - return res.send(fs.readFileSync(path.resolve() + '/public/ym.html', { - encoding: 'utf8' - })); - } + switch (req.url) { + case '/?ym': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'pages', 'redirects', 'ytmobile.html'), 'utf8')); + } - }); + // Frames Page - app.use('/', express.static('public')); + switch (req.url) { + case '/?j': + return res.send(fs.readFileSync(path.join(__dirname, 'public', 'hidden.html'), 'utf8')) + } - app.use(async (req, res, next) => { - if (req.headers['referer']) { +}); - let referer = '/' + String(req.headers['referer']).split('/').splice(3).join('/'); +app.use('/', express.static('public')); - referer = rewrite_url(referer.replace(config.prefix, ''), 'decode').split('/').splice(0, 3).join('/'); +app.use(async(req, res, next) => { + if (req.headers['referer']) { - if (referer.startsWith('https://') || referer.startsWith('http://')) { - res.redirect(307, config.prefix + btoa(referer) + req.url) - } else { - if (req.session.url) { + let referer = '/' + String(req.headers['referer']).split('/').splice(3).join('/'); - res.redirect(307, config.prefix + btoa(req.session.url) + req.url) + referer = rewrite_url(referer.replace(config.prefix, ''), 'decode').split('/').splice(0, 3).join('/'); - } else return next(); - } - } else if (req.session.url) { + if (referer.startsWith('https://') || referer.startsWith('http://')) { + res.redirect(307, config.prefix + btoa(referer) + req.url) + } else { + if (req.session.url) { - res.redirect(307, config.prefix + btoa(req.session.url) + req.url) + res.redirect(307, config.prefix + btoa(req.session.url) + req.url) - } else return next(); - }); \ No newline at end of file + } else return next(); + } + } else if (req.session.url) { + + res.redirect(307, config.prefix + btoa(req.session.url) + req.url) + + } else return next(); +}); \ No newline at end of file