From 6c479782e96622536aa8a2ac3df83d5c02e16ecf Mon Sep 17 00:00:00 2001 From: zefie Date: Mon, 19 Jul 2021 15:03:35 -0400 Subject: [PATCH] v0.9.1 - fix: throw proper error if wtv-update:/sync called without arguments - feature: Support to route all HTTP proxied requests over a SOCKS proxy (eg Tor or VPN) - feature: Psuedo-HTTPS (WebTV can now visit HTTPS URLs via proxy, but we do not use SSL encryption when sending back to the WebTV) - fix: header issue with login-stage-two.js - fix: encrypted request headers were shown despite verbosity level - update: wtv-update/sync: allow multiple groups in sync diskmap, fix md5 comparsion - update: wtv-home:/home: added connection speed - Renamed processSSID to filterSSID - Documented and rewrote some functions --- README.md | 8 +- ServiceVault.md | 11 +- .../ServiceVault/wtv-1800/finish-prereg.js | 5 +- .../wtv-head-waiter/login-stage-two.js | 11 +- .../ServiceVault/wtv-home/home.js | 15 +- .../ServiceVault/wtv-log/log.js | 4 +- .../ServiceVault/wtv-update/sync.js | 25 +- zefie_wtvp_minisrv/app.js | 136 +++--- zefie_wtvp_minisrv/config.json | 20 +- zefie_wtvp_minisrv/package-lock.json | 428 +++++++++++++++++- zefie_wtvp_minisrv/package.json | 3 +- 11 files changed, 567 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index 7ebb6d01..68d9c232 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,14 @@ This open source server is in alpha status. Use at your own risk. - Can handle client "relogin" and "reconnect" events - Suports `.js` service files with synchronous or asynchronous requests - Supports multiple simultaneous users -- WebTV-compatible HTTP Proxy (via minisrv, or using an external proxy for enhanced features (such as [WebOne](https://github.com/atauenis/webone)) +- WebTV-compatible HTTP(S) Proxy (via minisrv, or using an external proxy for enhanced features (such as [WebOne](https://github.com/atauenis/webone)) - wtv-flashrom for LC2 and newer boxes (bf0app unsupported, need test unit) - Can flash anything on [Ultra Willies](https://wtv.zefie.com/willie.php) with optional `use_zefie_server` flag set on `wtv-flashrom` service. +- wtv-update:/sync for Download-o-Rama style file downloading ### Current issues: -- wtv-update:/update does not yet function as intended -- HTTPS Proxying untested, likely needs SSL spoofing with self-signed solution +- Occasionally, in certain circumstances, a specific SSID may be unable to reconnect to the server until the server is restarted +- Mis-configuring wtv-update:/sync DiskMaps may cause units to delete contents of partitions (need more info) ### Won't fix: - wtv-encryption stream breaks when two different sessions have the same SSID (eg spoofing, won't fix (production did it too)) @@ -28,6 +29,7 @@ This open source server is in alpha status. Use at your own risk. - ~~Flashrom flashing functionality (at least for LC2 and higher)~~ ***Done*** - Flashrom flashing for bf0app old classic (need donor unit) - SSID/IP black/whitelisting (including tying SSID to an IP or multiple IPs) +- wtv-lzpf support - (maybe) Proper wtv-star (generic service outage page) support (maybe useful for allowing a unit to multiple sub-minisrvs). - (maybe) wtvchat stuff - (probably not) url tokenizer (eg wtv-token-blabla, was mostly to secure service URLs from unintended access, which this server does not aim to do) diff --git a/ServiceVault.md b/ServiceVault.md index 4b6d806f..3002959b 100644 --- a/ServiceVault.md +++ b/ServiceVault.md @@ -1,8 +1,15 @@ ## Brief ServiceVault Explanation -The server will look for a subdirectory under the running directory, called `ServiceVault` (might be user-configurable in the future). +The server will scan configured ServiceVaults in order of priority and look for files within them. -Within that directory, it looks for a subdirectory named after the wtv-service URL requested. +Currently only 2 Service Vaults are supported, the `User Server Vault` and the `Service Vault`. + +The paths to the Service Vaults are user configurable in `user_config.json` or `config.json` + +The `User Service Vault` has priority, and files found in that Service Vault will be loaded, even if the +file exists in the `Service Vault`. + +Within the Service Vaults, the server looks for a subdirectory named after the wtv-service URL requested. The server will then look for files in sequential order when requesting a URL, stopping at the first match. diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js index b51ac449..8278d416 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js @@ -1,10 +1,9 @@ -if (socket.ssid != null && !ssid_sessions[socket.ssid].get("wtvsec_login")) { +if (socket.ssid != null) { + if (ssid_sessions[socket.ssid].get("wtvsec_login")) ssid_sessions[socket.ssid].delete("wtvsec_login"); var wtvsec_login = new WTVSec(); wtvsec_login.IssueChallenge(); wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); ssid_sessions[socket.ssid].set("wtvsec_login", wtvsec_login); -} else if (socket.ssid != null) { - var wtvsec_login = ssid_sessions[socket.ssid].get("wtvsec_login"); } if (wtvsec_login) { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js index 52f33699..5ad309ac 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js @@ -24,11 +24,11 @@ if (socket.ssid !== null) { if (challenge_response && client_challenge_response) { //if (challenge_response.toString(CryptoJS.enc.Base64).substring(0,85) == client_challenge_response.substring(0,85)) { if (challenge_response.toString(CryptoJS.enc.Base64) == client_challenge_response) { - console.log(" * wtv-challenge-response success for " + processSSID(socket.ssid)); + console.log(" * wtv-challenge-response success for " + filterSSID(socket.ssid)); wtvsec_login.PrepareTicket(); //socket_sessions[socket.id].secure = true; } else { - console.log(" * wtv-challenge-response FAILED for " + processSSID(socket.ssid)); + console.log(" * wtv-challenge-response FAILED for " + filterSSID(socket.ssid)); if (zdebug) console.log("Response Expected:", challenge_response.toString(CryptoJS.enc.Base64)); if (zdebug) console.log("Response Received:", client_challenge_response) gourl = "wtv-head-waiter:/login?reissue_challenge=true"; @@ -63,7 +63,7 @@ wtv-country: US wtv-language-header: en-US,en wtv-visit: client:closeallpanels wtv-expire-all: client:closeallpanels -wtv-offline-user-list: `+offline_user_list+` +wtv-offline-user-list: `+ offline_user_list + ` wtv-bypass-proxy: true wtv-ticket: `+ wtvsec_login.ticket_b64 + ` wtv-messagewatch-checktimeoffset: off @@ -72,14 +72,15 @@ wtv-connection-timeout: 90 wtv-fader-timeout: 900 wtv-ssl-log-url: wtv-log:/log wtv-smartcard-inserted-message: Contacting service -user-id: `+userid+` +user-id: `+ userid + ` wtv-transition-override: off wtv-allow-dsc: true wtv-messenger-enable: 0 wtv-noback-all: wtv- wtv-service: reset `+ getServiceString('all') + ` -wtv-boot-url: wtv-1800:/preregister?relogin=true` +wtv-boot-url: wtv-1800:/preregister?relogin=true +`; //wtv-ssl-certs-download-url: wtv-head-waiter:/ssl-cert.der //wtv-ssl-certs-checksum: 473926DC1B11F635A6B920953FDCDE6A headers += `wtv-user-name: `+ nickname + ` diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js index 6d737a3d..e39da33d 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js @@ -22,8 +22,8 @@ function go() { }

Welcome to `+ z_title + `

-

Encryption Status: `+cryptstatus+`

` -data += `

Working stuff

+

Encryption Status: `+cryptstatus+`

+Connection Speed: &rate;
` -try { - if (fs.lstatSync(service_dir + "/home.zefie.html")) { - data += fs.readFileSync(service_dir + "/home.zefie.html", { 'encoding': 'utf8' }); - } -} catch (e) { - // silent -} -data += "\n"; \ No newline at end of file +if (fs.existsSync(service_vaults[0].path + "/" + service_name + "/home.zefie.html")) { + data += fs.readFileSync(service_vaults[0].path + "/" + service_name + "/home.zefie.html", { 'encoding': 'utf8' }); +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js b/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js index 05da295a..8df47106 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js @@ -23,7 +23,7 @@ Content-length: 0`; logdata_outstring_hex += request_headers.post_data.toString(CryptoJS.enc.Hex); if (minisrv_config.services[service_name].write_logs_to_disk) { fs.writeFile(fullpath, logdata_outstring_hex, "Hex", function () { - if (!zquiet) console.log(" * Wrote POST log data from", processSSID(socket.ssid), "for", socket.id); + if (!zquiet) console.log(" * Wrote POST log data from", filterSSID(socket.ssid), "for", socket.id); sendToClient(socket, headers, data); }); } else { @@ -43,7 +43,7 @@ Content-length: 0`; var logdata_outstring_hex = Buffer.from(logdata_outstring, 'utf8').toString('hex'); if (minisrv_config.services[service_name].write_logs_to_disk) { fs.writeFile(fullpath, logdata_outstring_hex, "Hex", function () { - if (!zquiet) console.log(" * Wrote GET log data from", processSSID(socket.ssid), "for", socket.id); + if (!zquiet) console.log(" * Wrote GET log data from", filterSSID(socket.ssid), "for", socket.id); sendToClient(socket, headers, data); }); } else { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js b/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js index 9328724b..bf987f34 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-update/sync.js @@ -75,10 +75,10 @@ function processGroup(diskmap_primary_group, diskmap_group_data, diskmap_subgrou post_data_current_file = post_data[k]; } if (post_data[k].indexOf(":") > 0) { - var post_data_line = post_data[k].split(":") + var post_data_line = post_data[k].split(": ") var post_data_line_name = post_data_line[0]; post_data_line.shift(); - var post_data_line_data = post_data_line.join(":"); + var post_data_line_data = post_data_line.join(": "); if (!post_data_fileinfo[post_data_filecount]) post_data_fileinfo[post_data_filecount] = new Array(); @@ -90,8 +90,6 @@ function processGroup(diskmap_primary_group, diskmap_group_data, diskmap_subgrou else { post_data_fileinfo[post_data_filecount][post_data_line_name] = post_data_line_data; } - - } else { post_data_filecount++; post_data_current_file = post_data_current_directory + post_data[k]; @@ -108,8 +106,10 @@ function processGroup(diskmap_primary_group, diskmap_group_data, diskmap_subgrou post_match_file = service_vaults[g].path + "/" + service_name + "/" + diskmap_group_data.files[k].location; if (!fs.existsSync(post_match_file)) post_match_file = null; }); + var post_match_file_lstat = fs.lstatSync(post_match_file); - var post_match_result = post_data_fileinfo.find(el => el["file"] === diskmap_group_data.files[k].file) || false; + var post_match_result = post_data_fileinfo.find(el => el.file === diskmap_group_data.files[k].file) || null; + var post_match_file_data = new Buffer.from(fs.readFileSync(post_match_file, { encoding: null, flags: 'r' @@ -121,7 +121,7 @@ function processGroup(diskmap_primary_group, diskmap_group_data, diskmap_subgrou if (post_match_result) { // md5s match, so client doesn't need file - if (diskmap_group_data.files[k]['wtv-checksum'] == post_match_result["wtv-checksum"]) return; + if (diskmap_group_data.files[k]['wtv-checksum'].toLowerCase() == post_match_result["wtv-checksum"]) return; else wtv_download_list.push(diskmap_group_data.files[k]); } else { wtv_download_list.push(diskmap_group_data.files[k]); @@ -150,13 +150,13 @@ if (request_headers.query.diskmap && request_headers.query.group && request_head } data = ''; diskmap_data = diskmap_data[request_headers.query.group]; - /*if (!diskmap_data.display) { + if (!diskmap_data.display) { Object.keys(diskmap_data).forEach(function (k) { if (diskmap_data[k]) data += processGroup(request_headers.query.group,diskmap_data[k],k); }); - } else { */ - data = processGroup(request_headers.query.group, diskmap_data); - //} + } else { + data = processGroup(request_headers.query.group, diskmap_data); + } headers = "200 OK\nContent-Type: wtv/download-list"; } catch (e) { @@ -172,5 +172,10 @@ if (request_headers.query.diskmap && request_headers.query.group && request_head data = errpage[1]; console.log("wtv-update:/sync error", "could not find diskmap"); } +} else { + var errpage = doErrorPage(400); + headers = errpage[0]; + data = errpage[1]; + if (zdebug) console.log("wtv-update:/sync error", "missing query arguments"); } diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index 18a9db91..16ffdc43 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -3,7 +3,7 @@ const fs = require('fs'); const http = require('http'); const https = require('https'); -const strftime = require('strftime'); +const strftime = require('strftime'); // used externally by service scripts const net = require('net'); const CryptoJS = require('crypto-js'); const mime = require('mime-types'); @@ -11,8 +11,14 @@ const { crc16 } = require('easy-crc'); var WTVSec = require('./wtvsec.js'); var ClientSessionData = require('./session_data.js'); +// Where we store our session information +var ssid_sessions = new Array(); +var socket_sessions = new Array(); + var ports = []; +// add .reverse() feature to all JavaScript Strings in this application +// works for service vault scripts too. String.prototype.reverse = function () { var splitString = this.split(""); var reverseArray = splitString.reverse(); @@ -20,9 +26,8 @@ String.prototype.reverse = function () { return joinArray; } - - function getServiceString(service) { + // used externally by service scripts if (service === "all") { var out = ""; Object.keys(minisrv_config.services).forEach(function (k) { @@ -38,12 +43,6 @@ function getServiceString(service) { } } -var ssid_sessions = new Array(); -var socket_buffer = new Array(); -var socket_sessions = new Array(); - -var script_processing_timeout = 10; // seconds - function getFileExt(path) { return path.reverse().split(".")[0].reverse(); } @@ -71,45 +70,45 @@ function doErrorPage(code, data = null) { return new Array(headers, data); } + function getConType(path) { // custom contype for flashrom if (path.indexOf("wtv-flashrom") && (getFileExt(path).toLowerCase() == "rom" || getFileExt(path).toLowerCase() == "brom")) { return "binary/x-wtv-flashblock"; } else if (getFileExt(path).toLowerCase() == "rmf") { return "audio/x-rmf"; - } + } return mime.lookup(path); } -async function processPath(socket, path, request_headers = new Array(), service_name) { +async function processPath(socket, service_vault_file_path, request_headers = new Array(), service_name) { var headers, data = null; - var request_is_direct_file = false; var request_is_async = false; var service_vault_found = false; - var service_path = path; + var service_path = service_vault_file_path; try { service_vaults.forEach(function (service_vault_dir) { if (service_vault_found) return; - path = service_vault_dir.path + "/" + service_path.replace(/\\/g, "/"); + service_vault_file_path = service_vault_dir.path + "/" + service_path.replace(/\\/g, "/"); - if (fs.existsSync(path)) { + if (fs.existsSync(service_vault_file_path)) { // file exists, read it and return it service_vault_found = true; request_is_async = true; - if (!zquiet) console.log(" * Found " + path + " in " + service_vault_dir.name +" to handle request (Direct File Mode) [Socket " + socket.id + "]"); - var contype = getConType(path); + if (!zquiet) console.log(" * Found " + service_vault_file_path + " in " + service_vault_dir.name +" to handle request (Direct File Mode) [Socket " + socket.id + "]"); + var contype = getConType(service_vault_file_path); headers = "200 OK\n" headers += "Content-Type: " + contype; - fs.readFile(path, null, function (err, data) { + fs.readFile(service_vault_file_path, null, function (err, data) { sendToClient(socket, headers, data); }); - } else if (fs.existsSync(path + ".txt")) { - service_vault_found = true; + } else if (fs.existsSync(service_vault_file_path + ".txt")) { // raw text format, entire payload expected (headers and content) - if (!zquiet) console.log(" * Found " + path + ".txt in " + service_vault_dir.name +" to handle request (Raw TXT Mode) [Socket " + socket.id + "]"); + service_vault_found = true; + if (!zquiet) console.log(" * Found " + service_vault_file_path + ".txt in " + service_vault_dir.name +" to handle request (Raw TXT Mode) [Socket " + socket.id + "]"); request_is_async = true; - fs.readFile(path + ".txt", 'Utf-8', function (err, file_raw) { + fs.readFile(service_vault_file_path + ".txt", 'Utf-8', function (err, file_raw) { if (file_raw.indexOf("\n\n") > 0) { // split headers and data by newline (unix format) var file_raw_split = file_raw.split("\n\n"); @@ -129,32 +128,35 @@ async function processPath(socket, path, request_headers = new Array(), service_ } sendToClient(socket, headers, data); }); - } else if (fs.existsSync(path + ".js")) { - service_vault_found = true; + } else if (fs.existsSync(service_vault_file_path + ".js")) { // synchronous js scripting, process with vars, must set 'headers' and 'data' appropriately. // loaded script will have r/w access to any JavaScript vars this function does. // request headers are in an array named `request_headers`. // Query arguments in `request_headers.query` - if (!zquiet) console.log(" * Found " + path + ".js in " + service_vault_dir.name + " to handle request (JS Interpreter mode) [Socket " + socket.id + "]"); + // Can upgrade to asynchronous by setting `request_is_async` to `true` + // In Asynchronous mode, you are expected to call sendToClient(socket,headers,data) by the end of your script + // `socket` is already defined and should be passed-through. + service_vault_found = true; + if (!zquiet) console.log(" * Found " + service_vault_file_path + ".js in " + service_vault_dir.name + " to handle request (JS Interpreter mode) [Socket " + socket.id + "]"); // expose var service_dir for script path to the root of the wtv-service var service_dir = service_vault_dir.path.replace(/\\/g, "/") + "/" + service_name; socket_sessions[socket.id].starttime = Math.floor(new Date().getTime() / 1000); - var jscript_eval = fs.readFileSync(path + ".js").toString(); + var jscript_eval = fs.readFileSync(service_vault_file_path + ".js").toString(); eval(jscript_eval); if (request_is_async && !zquiet) console.log(" * Script requested Asynchronous mode"); } - else if (fs.existsSync(path + ".html")) { - service_vault_found = true; + else if (fs.existsSync(service_vault_file_path + ".html")) { // Standard HTML with no headers, WTV Style - if (!zquiet) console.log(" * Found " + path + ".html in " + service_vault_dir.name +" to handle request (HTML Mode) [Socket " + socket.id + "]"); + service_vault_found = true; + if (!zquiet) console.log(" * Found " + service_vault_file_path + ".html in " + service_vault_dir.name +" to handle request (HTML Mode) [Socket " + socket.id + "]"); request_is_async = true; headers = "200 OK\n" headers += "Content-Type: text/html" - fs.readFile(path + ".html", null, function (err, data) { + fs.readFile(service_vault_file_path + ".html", null, function (err, data) { sendToClient(socket, headers, data); }); } - // 'headers' and 'data' should both be set with content by this point! + // either `request_is_async`, or `headers` and `data` MUST be defined by this point! }); } catch (e) { var errpage = doErrorPage(400); @@ -183,7 +185,7 @@ async function processPath(socket, path, request_headers = new Array(), service_ } } -function processSSID(obj) { +function filterSSID(obj) { if (minisrv_config.config.hide_ssid_in_logs) { if (typeof (obj) == "string") { if (obj.substr(0, 8) == "MSTVSIMU") { @@ -243,14 +245,14 @@ async function processURL(socket, request_headers) { reqverb = "Psuedo-encrypted " + reqverb; } if (ssid != null) { - console.log(" * " + reqverb + " for " + request_headers.request_url + " from WebTV SSID " + (await processSSID(ssid)), 'on', socket.id); + console.log(" * " + reqverb + " for " + request_headers.request_url + " from WebTV SSID " + (await filterSSID(ssid)), 'on', socket.id); } else { console.log(" * " + reqverb + " for " + request_headers.request_url, 'on', socket.id); } // assume webtv since there is a :/ in the GET var service_name = shortURL.split(':/')[0]; var urlToPath = service_name + "/" + shortURL.split(':/')[1]; - if (zshowheaders) console.log(" * Incoming headers on socket ID", socket.id, (await processSSID(request_headers))); + if (zshowheaders) console.log(" * Incoming headers on socket ID", socket.id, (await filterSSID(request_headers))); processPath(socket, urlToPath, request_headers, service_name); } else if (shortURL.indexOf('http://') >= 0 || shortURL.indexOf('https://') >= 0) { doHTTPProxy(socket, request_headers); @@ -266,8 +268,8 @@ async function processURL(socket, request_headers) { } async function doHTTPProxy(socket, request_headers) { - if (zshowheaders) console.log("HTTP Proxy: Client Request Headers on socket ID", socket.id, (await processSSID(request_headers))); - var request_type = request_headers.request.indexOf('https://') ? 'http' : 'https' + var request_type = (request_headers.request_url.substring(0,5) == 'https') ? 'https' : 'http' + if (zshowheaders) console.log(request_type.toUpperCase() +" Proxy: Client Request Headers on socket ID", socket.id, (await filterSSID(request_headers))); switch (request_type) { case "https": var proxy_agent = https; @@ -309,10 +311,15 @@ async function doHTTPProxy(socket, request_headers) { } if (minisrv_config.services[request_type].use_external_proxy && minisrv_config.services[request_type].external_proxy_port) { - options.host = minisrv_config.services[request_type].external_proxy_host; - options.port = minisrv_config.services[request_type].external_proxy_port; - options.path = request_headers.request.split(' ')[1]; - options.headers.Host = request_data.host; + if (minisrv_config.services[request_type].external_proxy_is_socks) { + var ProxyAgent = require('proxy-agent'); + options.agent = new ProxyAgent("socks://" + (minisrv_config.services[request_type].external_proxy_host || "127.0.0.1") + ":" + minisrv_config.services[request_type].external_proxy_port); + } else { + options.host = minisrv_config.services[request_type].external_proxy_host; + options.port = minisrv_config.services[request_type].external_proxy_port; + options.path = request_headers.request.split(' ')[1]; + options.headers.Host = request_data.host; + } } const req = proxy_agent.request(options, function (res) { var data = []; @@ -367,7 +374,7 @@ async function doHTTPProxy(socket, request_headers) { } } -async function headerStringToObj(headers, response = false) { +function headerStringToObj(headers, response = false) { var inc_headers = 0; var headers_obj = new Array(); var headers_obj_pre = headers.split("\n"); @@ -403,7 +410,7 @@ async function sendToClient(socket, headers_obj, data) { if (typeof (data) === 'undefined') data = ''; if (typeof (headers_obj) === 'string') { // string to header object - headers_obj = await headerStringToObj(headers_obj, true); + headers_obj = headerStringToObj(headers_obj, true); } // add Connection header if missing, default to Keep-Alive @@ -448,7 +455,7 @@ async function sendToClient(socket, headers_obj, data) { // header object to string - if (zshowheaders) console.log(" * Outgoing headers on socket ID", socket.id, (await processSSID(headers_obj))); + if (zshowheaders) console.log(" * Outgoing headers on socket ID", socket.id, (await filterSSID(headers_obj))); Object.keys(headers_obj).forEach(function (k) { if (k == "http_response") { headers += headers_obj[k] + "\r\n"; @@ -520,10 +527,11 @@ function moveObjectElement(currentKey, afterKey, obj) { } function headersAreStandard(string, verbose = false) { - // the test will see the binary compressed/enrypted data as ASCII, so a generic "isAscii" - // is not suffuicent. This checks for characters expected in unecrypted headers, and returns - // true only if every character in the string matches the regex. Once we know the string is binary - // we can better process it with the raw base64 data in processRequest() below. + // a generic "isAscii" check is not sufficient, as the test will see the binary + // compressed / encrypted data as ASCII. This function checks for characters expected + // in unencrypted headers, and returns true only if every character in the string matches + // the regex. Once we know the string is binary, we can better process it with the + // raw base64 or hex data in processRequest() below. return /^([A-Za-z0-9\+\/\=\-\.\,\ \"\;\:\?\&\r\n\(\)\%\<\>\_]{8,})$/.test(string); } @@ -540,7 +548,7 @@ async function processRequest(socket, data_hex, returnHeadersBeforeSecure = fals data = data.split("\n\n")[0]; } if (headersAreStandard(data)) { - headers = await headerStringToObj(data); + headers = headerStringToObj(data); } else if (!returnHeadersBeforeSecure) { // if its a POST request, assume its a binary blob and not encrypted (dangerous) if (!encryptedRequest) { @@ -615,7 +623,7 @@ async function processRequest(socket, data_hex, returnHeadersBeforeSecure = fals } if (socket_sessions[socket.id].secure != true) { // first time so reroll sessions - if (zdebug) console.log(" # [ SECURE ON BLOCK (" + socket.id + ")]"); + if (zdebug) console.log(" # [ SECURE ON BLOCK (" + socket.id + ") ]"); socket_sessions[socket.id].secure = true; } if (!headers.request_url) { @@ -642,7 +650,8 @@ async function processRequest(socket, data_hex, returnHeadersBeforeSecure = fals ssid_sessions[socket.ssid].set("box-does-psuedo-encryption", false); var dec_data = CryptoJS.lib.WordArray.create(socket_sessions[socket.id].wtvsec.Decrypt(0, enc_data)) var secure_headers = await processRequest(socket, dec_data.toString(CryptoJS.enc.Hex), true); - if (zdebug) console.log(" # Encrypted Request (SECURE ON)", "on", socket.id, secure_headers); + if (zdebug) console.log(" # Encrypted Request (SECURE ON)", "on", socket.id); + if (zshowheaders) console.log(secure_headers); if (!secure_headers.request) { socket_sessions[socket.id].secure = false; var errpage = doErrorPage(400); @@ -675,8 +684,9 @@ wtv-visit: client:relog Content-type: text/html`; data = ''; */ - delete socket_sessions[socket.id].wtvsec; + socket_sessions[socket.id].secure = false socket_sessions[socket.id].close_me = true; + delete socket_sessions[socket.id].wtvsec; sendToClient(socket, headers, data); } else { processURL(socket, headers); @@ -723,11 +733,10 @@ async function cleanupSocket(socket) { var fuckyou = ssid_sessions[socket.ssid].sockets; if (ssid_sessions[socket.ssid].sockets.length === 0 && ssid_sessions[socket.ssid].get("wtvsec_login")) { // if last socket for SSID disconnected, destroy login session - if (!zquiet) console.log(" * Last socket from WebTV SSID", processSSID(socket.ssid),"disconnected, destroying initial WTVSec instance"); + if (!zquiet) console.log(" * Last socket from WebTV SSID", filterSSID(socket.ssid),"disconnected, destroying initial WTVSec instance"); ssid_sessions[socket.ssid].delete("wtvsec_login"); } } -; socket.end(); } catch (e) { console.log(" # Could not clean up socket data for socket ID", socket.id, e); @@ -737,12 +746,22 @@ async function cleanupSocket(socket) { async function handleSocket(socket) { // create unique socket id with client address and port - socket.id = parseInt(crc16('CCITT-FALSE', Buffer.from(String(socket.remoteAddress) + String(socket.remotePort), "utf8")).toString(16), 16); socket_sessions[socket.id] = []; - socket.setEncoding('hex'); //set data encoding (either 'ascii', 'utf8', or 'base64') + socket.setEncoding('hex'); //set data encoding (Text: 'ascii', 'utf8' ~ Binary: 'hex', 'base64' (do not trust 'binary' encoding)) + + // NOTE: As it stands we use a 'timeout' to start processing data when we have not recieved any data + // from the client in X time (defined in config, in milliseconds). The problem with this is in the case of + // a modem retrain during a request. + + // TODO: Properly know when client is done sending data, by parsing headers. + // Caveat of this is that sometimes the Content-length header does not exist, or will be encrypted. + socket.on('data', function (data_hex) { - socket.setTimeout(minisrv_config.config.socket_timeout); + socket.setTimeout(minisrv_config.config.socket_timeout); // the timeout mentioned above + + // Store all received data into a buffer. Kind of misleading as its not a true JS Buffer + // but instead a CryptoJS WordArray if (socket_sessions[socket.id].buffer) { socket_sessions[socket.id].buffer.concat(CryptoJS.enc.Hex.parse(data_hex)); } else { @@ -753,6 +772,7 @@ async function handleSocket(socket) { socket.on('timeout', async function () { // start the async chain if (socket_sessions[socket.id].buffer) { + // process the request if the buffer exists processRequest(this, socket_sessions[socket.id].buffer.toString(CryptoJS.enc.Hex)); } }); @@ -762,6 +782,7 @@ async function handleSocket(socket) { }); socket.on('end', function () { + // Attempt to clean up all of our WTVSec instances cleanupSocket(socket); }); } @@ -793,6 +814,9 @@ function returnAbsolsutePath(path) { return path; } + +// SERVER START + var z_title = "zefie's wtv minisrv v" + require('./package.json').version; console.log("**** Welcome to " + z_title + " ****"); console.log(" *** Reading global configuration..."); diff --git a/zefie_wtvp_minisrv/config.json b/zefie_wtvp_minisrv/config.json index f1153a89..dad23fbd 100644 --- a/zefie_wtvp_minisrv/config.json +++ b/zefie_wtvp_minisrv/config.json @@ -32,7 +32,7 @@ "wtv-log": { "port": 1609, "connections": 1, - "write_logs_to_disk": false + "write_logs_to_disk": false }, "wtv-home": { "port": 1612, @@ -45,7 +45,7 @@ "wtv-flashrom": { "port": 1618, "flags": "0x00000040", - "use_zefie_server": true + "use_zefie_server": true }, "wtv-music": { "port": 1656, @@ -55,10 +55,18 @@ "http": { "port": 1650, "connections": 3, - "use_external_proxy": false, - "external_proxy_host": null, - "external_proxy_port": 8080 - + "use_external_proxy": true, + "external_proxy_is_socks": true, + "external_proxy_host": "127.0.0.1", + "external_proxy_port": 1080 + }, + "https": { + "port": 1650, + "connections": 3, + "use_external_proxy": true, + "external_proxy_is_socks": true, + "external_proxy_host": "127.0.0.1", + "external_proxy_port": 1080 } } } diff --git a/zefie_wtvp_minisrv/package-lock.json b/zefie_wtvp_minisrv/package-lock.json index 6bc8c08e..16578ae8 100644 --- a/zefie_wtvp_minisrv/package-lock.json +++ b/zefie_wtvp_minisrv/package-lock.json @@ -1,14 +1,79 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.7.2", + "version": "0.9.1", "lockfileVersion": 1, "requires": true, "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "requires": { + "tslib": "^2.0.1" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, "crypto-js": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" }, + "data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==" + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "degenerator": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.1.tgz", + "integrity": "sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ==", + "requires": { + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0", + "vm2": "^3.9.3" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, "easy-crc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/easy-crc/-/easy-crc-0.0.2.tgz", @@ -19,6 +84,159 @@ "resolved": "https://registry.npmjs.org/endianness/-/endianness-8.0.2.tgz", "integrity": "sha512-IU+77+jJ7lpw2qZ3NUuqBZFy3GuioNgXUdsL1L9tooDNTaw0TgOnwNuc+8Ns+haDaTifK97QLzmOANJtI/rGvw==" }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "file-uri-to-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + } + }, + "get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "requires": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, "mime-db": { "version": "1.48.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", @@ -32,10 +250,218 @@ "mime-db": "1.48.0" } }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "pac-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", + "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^5.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "5" + }, + "dependencies": { + "socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "requires": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + } + } + } + }, + "pac-resolver": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.0.tgz", + "integrity": "sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==", + "requires": { + "degenerator": "^3.0.1", + "ip": "^1.1.5", + "netmask": "^2.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", + "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", + "requires": { + "agent-base": "^6.0.0", + "debug": "4", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^5.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^5.0.0" + }, + "dependencies": { + "socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "requires": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + } + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + }, + "socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, "strftime": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.0.tgz", "integrity": "sha1-s/D6QZKVICpaKJ9ta+n0kJphcZM=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "vm2": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.3.tgz", + "integrity": "sha512-smLS+18RjXYMl9joyJxMNI9l4w7biW8ilSDaVRvFBDwOH8P0BK1ognFQTpg0wyQ6wIKLTblHJvROW692L/E53Q==" + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" } } } diff --git a/zefie_wtvp_minisrv/package.json b/zefie_wtvp_minisrv/package.json index 8f20cbef..60de7795 100644 --- a/zefie_wtvp_minisrv/package.json +++ b/zefie_wtvp_minisrv/package.json @@ -1,6 +1,6 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.9.0", + "version": "0.9.1", "description": "WebTV Service (WTVP) Emulation Server", "main": "app.js", "homepage": "https://github.com/zefie/zefie_wtvp_minisrv", @@ -26,6 +26,7 @@ "easy-crc": "0.0.2", "endianness": "^8.0.2", "mime-types": "^2.1.31", + "proxy-agent": "^5.0.0", "strftime": "^0.10.0" } }