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
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 + `
|
||||
|
||||
@@ -22,8 +22,8 @@ function go() {
|
||||
}
|
||||
</script>
|
||||
<h2>Welcome to `+ z_title + `</h2>
|
||||
<h3>Encryption Status: `+cryptstatus+`</h3>`
|
||||
data += `<h4>Working stuff</h4>
|
||||
<h3>Encryption Status: `+cryptstatus+`</h3>
|
||||
Connection Speed: &rate;
|
||||
<form name=access onsubmit="go()">
|
||||
<ul>
|
||||
<li><a href="client:relog">client:relog (direct)</a></li>
|
||||
@@ -43,11 +43,6 @@ data += `width=250 height=10 bgcolor=#444444 text=#ffdd33 cursor=#cc9933 select
|
||||
</form></li>
|
||||
</ul>`
|
||||
|
||||
try {
|
||||
if (fs.lstatSync(service_dir + "/home.zefie.html")) {
|
||||
data += fs.readFileSync(service_dir + "/home.zefie.html", { 'encoding': 'utf8' });
|
||||
}
|
||||
} catch (e) {
|
||||
// silent
|
||||
}
|
||||
data += "</body>\n</html>";
|
||||
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' });
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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...");
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
428
zefie_wtvp_minisrv/package-lock.json
generated
428
zefie_wtvp_minisrv/package-lock.json
generated
@@ -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=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user