diff --git a/README.md b/README.md index 5e88c245..c5e0ea95 100644 --- a/README.md +++ b/README.md @@ -44,3 +44,9 @@ This open source server is in alpha status. Use at your own risk. - Test with a WebTV Viewer or connect with a real box - To connect with a real box, you will need to open ports in your firewall and have a way to connect your WebTV (and preferably reroute 10.0.0.1 to the server) - See [ServiceVault.md](ServiceVault.md) for a brief introduction to how the service files work + +### How to Support the Project +- [Report Bugs](https://github.com/zefie/zefie_wtvp_minisrv/issues) +- [Add a Feature and send a Pull Request](https://github.com/zefie/zefie_wtvp_minisrv/pulls) +- Write and submit better documentation than I created (see Pull Request above) +- [Support financially on Patreon](https://www.patreon.com/zefie) \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-chat/home.html b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/home.html new file mode 100644 index 00000000..2f14e323 --- /dev/null +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/home.html @@ -0,0 +1,123 @@ + + + +Chat Home + + + + + + + +
+ + + +
+ +
+ + + + + +
+ + + + +
+
+ + + + + + + +
+
+
+
+ + + + + + + +
+ +
+ +
+ + + + +
+ +
+
+ + +
+ + +
   + + + + +
+ + +
+Chat Home +
+ + +
+
+
+ + + + + + + +
+
+ +yo yo yo yo + +enter your nick... + + +
+ + + + +
+
+ + +
+
+ + + +
+ + + + + + + +
+
+ + diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-chat/images/htv_chat.gif b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/images/htv_chat.gif new file mode 100644 index 00000000..7b19a7d9 Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/images/htv_chat.gif differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-chat/images/htv_chat.jpg b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/images/htv_chat.jpg new file mode 100644 index 00000000..3b66cc7c Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/images/htv_chat.jpg differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js index b5442803..0b59c112 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js @@ -28,11 +28,10 @@ function go() {

- +
@@ -35,7 +35,7 @@ WebTV Music Index
- +
@@ -48,7 +48,7 @@ WebTV Music Index
- +
@@ -74,7 +74,7 @@ WebTV Music Index
- +
@@ -87,7 +87,7 @@ WebTV Music Index
- +
diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/images/About_bg.jpg b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/images/About_bg.jpg new file mode 100644 index 00000000..dbfb1d9e Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/images/About_bg.jpg differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js index e69de29b..9afbc6b1 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js @@ -0,0 +1,148 @@ + +var client_caps = null; + +if (socket.ssid != null) { + if (ssid_sessions[socket.ssid].data_store.capabilities) { + client_caps = ssid_sessions[socket.ssid].data_store.capabilities; + } +} +if (client_caps) { + headers = `200 OK +Content-Type: text/html` + + + var client_label = "TODO"; + var boot_client_label = "TODO"; + var wtv_system_sysconfig_str = "TODO"; + + + var wtv_system_version = ssid_sessions[socket.ssid].get("wtv-system-version"); + var wtv_client_bootrom_version = ssid_sessions[socket.ssid].get("wtv-client-bootrom-version"); + var wtv_client_serial_number = filterSSID(ssid_sessions[socket.ssid].get("wtv-client-serial-number")); + var wtv_client_rom_type = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); + var wtv_system_chipversion_str = ssid_sessions[socket.ssid].get("wtv-system-chipversion"); + var wtv_system_sysconfig_hex = parseInt(ssid_sessions[socket.ssid].get("wtv-system-sysconfig")).toString(16); + + var capabilities_table = new WTVClientCapabilities().capabilities_table; + + + + data = ` + + +${minisrv_config.config.service_name} Info + + + + + + +
+
+
+ +

${minisrv_config.config.service_name} Info

+ +
+ + + + + + + + + + + + + + +
+
Connected to: + + Mini Service +
Service: + + ${z_title} +
Client: + + &vers; (Build ${wtv_system_version} [${client_label}]) +
Boot: + + &wtv-bootvers; (Build ${wtv_client_bootrom_version} [${boot_client_label}]) +
+ Silicon serial ID: + + ${wtv_client_serial_number} +
Connected at: + + &rate; +
Client IP number: + + ${socket.remoteAddress} +
+
ROM type: + + ${wtv_client_rom_type} +
Modem f/w (when available): + + &modem; +`; + if (ssid_sessions[socket.ssid].get("wtv-need-upgrade")) { + data += `
Mini-browser: + + Yes +`; + } + data += ` +
Chip version: + + ${wtv_system_chipversion_str} (TODO) +
SysConfig: + + 0x${wtv_system_sysconfig_hex.toUpperCase()} +
+ + + + +
+
Client capabilities: + + +
+ +`; + + + // start loop + + Object.keys(capabilities_table).forEach(function (k) { + data += ` +
${capabilities_table[k][1]} + + `; + if (client_caps[capabilities_table[k][0]]) data += "True\n"; + else data += "False\n"; + }); + +// end loop + +data += ` +
+ +
+
+
+${wtv_system_sysconfig_str}
+
+
+ + `; +} else { + var errpage = doErrorPage(400); + headers = errpage[0]; + data = errpage[1]; +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/WTVClientCapabilities.js b/zefie_wtvp_minisrv/WTVClientCapabilities.js new file mode 100644 index 00000000..587586cb --- /dev/null +++ b/zefie_wtvp_minisrv/WTVClientCapabilities.js @@ -0,0 +1,150 @@ +class WTVClientCapabilities { + + /***********************************\ + |* Special Thanks to: *| + |* Outatyme *| + |* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *| + |* For the binary information *| + |* about capability flags *| + \***********************************/ + + capabilities = null; + capabilities_table = null; + + + constructor(wtv_capability_flags = null) { + // [ flag_name, friendly_flag_name ] + // so far we assume the reversed bit order = the order on wtv-tricks:/info (production service) + // also speculation that `client-has-relogin-function` is forced true on the service side + // (this script does not do that, also note that LC2 MiniBrowser does not support client:relog) + // None of this is 100% for certain yet (except the bitfield stuff), do not trust as verbatim, more testing needed + + var capabilities_table = [ + ["client-can-do-muzac", "Can Do Muzac"], + ["client-can-do-chat", "Can Chat"], + ["client-can-do-openISP", "Can do OpenISP"], + ["client-can-receive-compressed-data", "Can receive compressed data"], + ["client-can-display-spotads1", "Can show Spotads1"], + ["client-can-print", "Can Print"], + ["client-can-do-macromedia-flash1", "Can do Macromedia Flash1"], + ["client-can-do-javascript", "Can do JavaScript"], + ["client-can-do-videoflash", "Can do VideoFlash"], + ["client-can-do-videoads", "Can do VideoAds"], + ["client-has-disk", "Has Disk"], + ["client-supports-classical-service", "Supports Classical"], + ["client-open-isp-settings-valid", "OISP settings valid"], + ["client-can-tell-valid-open-isp", "Can tell OISP settings valid"], + ["client-has-tuner", "Has Tuner"], + ["client-can-data-download", "Can data download"], + ["client-supports-approx-content-len", "Supports approximate content length"], + ["client-has-built-in-printer-port", "Has built-in printer port"], + ["client-has-tv-experience", "Has TV experience"], + ["client-can-handle-proxy-bypass", "Can handle proxy bypass"], + ["client-can-handle-download-v2", "Can handle Download protocol 2"], + ["client-has-relogin-function", "Has Relogin function"], + ["client-can-display-spotads2", "Can display spotads2"], + ["client-can-display-30-sec-video-ads", "Can display 30 second video ads"], + ["client-supports-etude-service", "Supports Etude"], + ["client-can-do-av-capture", "Can do AV capture"], + ["client-can-do-disconnected-email", "Can do disconnected email"], + ["client-can-do-macromedia-flash2", "Can do Macromedia Flash2"], + ["client-has-memory-size-bit1-set", "Memory size bit1 set"], + ["client-has-memory-size-bit2-set", "Memory size bit2 set"], + ["client-has-memory-size-bit3-set", "Memory size bit3 set"], + ["client-can-do-rmf", "Can do RMF"], + ["client-can-do-png", "Can do PNG"], + ["client-does-broadband-data-dowload", "Supports broadband download"], + ["client-has-softmodem", "Has Softmodem"], + ["client-can-do-preparsed-epg", "Can do pre-parsed EPG"], + ["client-supports-funk-e-service", "Supports Funk-e"], + ["client-wants-dial-script", "Wants dial script"], + ["client-upgrade-visits-not-needed", "Upgrade visits not needed"], + ["client-uses-flexible-videoad-paths", "Uses flexible videoad paths"], + ["client-non-production-build", "Non-production build"], + ["client-can-download-printer-drivers", "Can download printer drivers"], + ["client-supports-hiphop-service", "Supports HipHop"], + ["client-can-use-messenger", "Can use MSN Messenger"], + ["client-uses-third-party-billing", "Uses 3rd-party billing"], + ["client-can-do-offlineads", "Can do offline ads"], + ["client-has-no-dialin-support", "Has no dialin support"], + ["client-has-ssl-support-for-wtvp", "Has SSL support for WTVP"], + ["client-can-do-audio-capture", "Can do audio capture"], + ["client-can-do-metered-pricing", "Can do Metered Pricing"], + ["client-negotiates-user-agent", "Can Negotiate User-Agent"], + ["client-can-do-element-logging", "Can do Unsupported Element Logging"], + ["client-supports-jazz-security", "Supports Jazz security"], + ["client-supports-MSN-service", "Supports MSN service"], + ["client-supports-notify-port-header", "Supports notify port header"], + ["client-supports-messenger-update-light", "Supports MSN Messenger update light"], + ["client-supports-MSN-chat", "Supports MSN Chat"], + ["client-supports-MSN-chat-findu", "Supports MSN Chat FindU"], + ["client-supports-MSN-messenger-CVR", "Supports MSN Messenger CVR"], + ["client-supports-MSN-messenger-MSNP8", "Supports MSN Messenger MSNP8"], + ["client-supports-MSN-chat-R9C", "Supports MSN Chat R9C"] + ]; + + this.capabilities_table = capabilities_table; + + var capabilities = new Array(); + + // might want to pass without a flag to get the table + if (wtv_capability_flags != null) { + + // define function to convert hex string to binary string (0s & 1s) + var hex2bin = function (hex) { + var binary = ""; + var remainingSize = hex.length; + for (var p = 0; p < hex.length / 8; p++) { + //In case remaining hex length (or initial) is not multiple of 8 + var blockSize = remainingSize < 8 ? remainingSize : 8; + + binary += parseInt(hex.substr(p * 8, blockSize), 16).toString(2); + + remainingSize -= blockSize; + } + return binary; + } + + // Add .reverse() to strings for ease of processing + if (!String.prototype.reverse) { + String.prototype.reverse = function () { + var splitString = this.split(""); + var reverseArray = splitString.reverse(); + var joinArray = reverseArray.join(""); + return joinArray; + } + } + + // convert wtv_capability_flags to binary string, reverse the string, and split into array containing each character; + var bitfield = hex2bin(wtv_capability_flags).reverse().split(""); + + // only add to the capabilities array if the result is true + var add = function (flag_name, flag) { + if (flag) capabilities[flag_name] = flag; + } + + // process bitfield and set capabilities + Object.keys(bitfield).forEach(function (k) { + // Convert binary to boolean, 0 to false, 1 to true + var bitfield_result = (bitfield[k] == "1") + + // set flags based on position of bit + add(capabilities_table[k][0], bitfield_result); + }); + + this.capabilities = capabilities; + return capabilities; + } + } + + get(key = null) { + if (typeof (this.capabilities) === 'undefined') return null; + else if (key === null) return this.capabilities; + else if (this.capabilities[key]) return this.capabilities[key]; + else return null; + } + +} + + +module.exports = WTVClientCapabilities; \ No newline at end of file diff --git a/zefie_wtvp_minisrv/session_data.js b/zefie_wtvp_minisrv/WTVClientSessionData.js similarity index 66% rename from zefie_wtvp_minisrv/session_data.js rename to zefie_wtvp_minisrv/WTVClientSessionData.js index f6e14679..7bec66c7 100644 --- a/zefie_wtvp_minisrv/session_data.js +++ b/zefie_wtvp_minisrv/WTVClientSessionData.js @@ -1,4 +1,13 @@ -class ClientSessionData { +class WTVClientSessionData { + + /***********************************\ + |* Special Thanks to: *| + |* No one *| + |* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *| + |* There is literally nothing *| + |* special about this class *| + \***********************************/ + data_store = null; constructor() { @@ -25,4 +34,4 @@ class ClientSessionData { } -module.exports = ClientSessionData; \ No newline at end of file +module.exports = WTVClientSessionData; \ No newline at end of file diff --git a/zefie_wtvp_minisrv/wtvsec.js b/zefie_wtvp_minisrv/WTVSec.js similarity index 95% rename from zefie_wtvp_minisrv/wtvsec.js rename to zefie_wtvp_minisrv/WTVSec.js index 147bc03d..99206228 100644 --- a/zefie_wtvp_minisrv/wtvsec.js +++ b/zefie_wtvp_minisrv/WTVSec.js @@ -2,9 +2,21 @@ const CryptoJS = require('crypto-js'); const endianness = require('endianness'); var crypto = require('crypto'); +/***********************************\ +|* Special Thanks to: *| +|* eMac (Eric MacDonald) *| +|* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *| +|* For the encryption/decryption *| +|* information and process *| +\***********************************/ + class WTVSec { - //initial_shared_key = CryptoJS.lib.WordArray.random(8); - initial_shared_key_b64 = "CC5rWmRUE0o="; // You can change this but it doesn't mean much for security. Just make sure its static. 8 bytes base64 encoded. + // Initial Shared Key, in Base64 Format + // You can change this but it doesn't mean much for security. Just make sure its static. 8 bytes base64 encoded. + // If you intend to link multiple minisrv's together, they must all share the same Initial Shared Key. + + initial_shared_key_b64 = "CC5rWmRUE0o="; + initial_shared_key = null; current_shared_key = null; challenge_key = null; diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index fddcc4e1..f0e09753 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -9,8 +9,9 @@ const net = require('net'); const CryptoJS = require('crypto-js'); const mime = require('mime-types'); const { crc16 } = require('easy-crc'); -var WTVSec = require('./wtvsec.js'); -var ClientSessionData = require('./session_data.js'); +var WTVSec = require('./WTVSec.js'); +var WTVClientCapabilities = require('./WTVClientCapabilities.js'); +var WTVClientSessionData = require('./WTVClientSessionData.js'); // Where we store our session information var ssid_sessions = new Array(); @@ -20,11 +21,13 @@ 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(); - var joinArray = reverseArray.join(""); - return joinArray; +if (!String.prototype.reverse) { + String.prototype.reverse = function () { + var splitString = this.split(""); + var reverseArray = splitString.reverse(); + var joinArray = reverseArray.join(""); + return joinArray; + } } function getServiceString(service) { @@ -509,7 +512,16 @@ async function sendToClient(socket, headers_obj, data) { } if (zquiet) console.log(" * Sent" + verbosity_mod + " " + headers_obj.http_response + " to client (Content-Type:", headers_obj['Content-Type'], "~", headers_obj['Content-Length'], "bytes)"); } - socket_sessions[socket.id].buffer = null; + + if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; + if (socket_sessions[socket.id].header_buffer) delete socket_sessions[socket.id].header_buffer; + if (socket_sessions[socket.id].secure_buffer) delete socket_sessions[socket.id].secure_buffer; + if (socket_sessions[socket.id].buffer) delete socket_sessions[socket.id].buffer; + if (socket_sessions[socket.id].headers) delete socket_sessions[socket.id].headers; + if (socket_sessions[socket.id].post_data) delete socket_sessions[socket.id].post_data; + if (socket_sessions[socket.id].post_data_length) delete socket_sessions[socket.id].post_data_length; + if (socket_sessions[socket.id].post_data_percents_shown) delete socket_sessions[socket.id].post_data_percents_shown; + if (socket_sessions[socket.id].close_me) socket.end(); if (headers_obj["Connection"]) { if (headers_obj["Connection"].toLowerCase() == "close" && wtv_connection_close == "true") { @@ -561,7 +573,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq // This function sucks and needs to be rewritten - var headers = null; + var headers = new Array(); if (socket_sessions[socket.id]) { if (socket_sessions[socket.id].headers) { headers = socket_sessions[socket.id].headers; @@ -577,7 +589,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq data = data.split("\n\n")[0]; } if (headersAreStandard(data)) { - if (headers != null) { + if (headers.length != 0) { var new_header_obj = headerStringToObj(data); Object.keys(new_header_obj).forEach(function (k, v) { headers[k] = new_header_obj[k]; @@ -621,10 +633,12 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } } + if (!headers) return; + if (headers["wtv-client-serial-number"] != null) { socket.ssid = headers["wtv-client-serial-number"]; if (!ssid_sessions[socket.ssid]) { - ssid_sessions[socket.ssid] = new ClientSessionData(); + ssid_sessions[socket.ssid] = new WTVClientSessionData(); } if (!ssid_sessions[socket.ssid].data_store.sockets) ssid_sessions[socket.ssid].data_store.sockets = new Set(); ssid_sessions[socket.ssid].data_store.sockets.add(socket); @@ -709,6 +723,15 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } } + // Passed Security + + if (headers["wtv-capability-flags"] != null) { + if (!ssid_sessions[socket.ssid]) { + ssid_sessions[socket.ssid] = new WTVClientSessionData(); + } + if (!ssid_sessions[socket.ssid].data_store.capabilities) ssid_sessions[socket.ssid].data_store.capabilities = new WTVClientCapabilities(headers["wtv-capability-flags"]); + } + // log all client wtv- headers to the SessionData for that SSID // this way we can pull up client info such as wtv-client-rom-type or wtv-system-sysconfig @@ -782,8 +805,23 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq // SECURE ON and detected encrypted data 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, true); + if (!socket_sessions[socket.id].secure_buffer) socket_sessions[socket.id].secure_buffer = ""; + socket_sessions[socket.id].secure_buffer += dec_data.toString(CryptoJS.enc.Hex); + var secure_headers = null; + if (headers['request']) { + if (headers['request'] == "GET") { + if (socket_sessions[socket.id].secure_buffer.indexOf("0d0a0d0a") || socket_sessions[socket.id].secure_buffer.indexOf("0a0a")) { + secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); + } + } else { + secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); + } + } else { + secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); + } if (!secure_headers) return; + + delete socket_sessions[socket.id].secure_buffer; if (zdebug) console.log(" # Encrypted Request (SECURE ON)", "on", socket.id); if (zshowheaders) console.log(secure_headers); if (!secure_headers.request) { @@ -839,11 +877,14 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } if (socket_sessions[socket.id].post_data.length == (socket_sessions[socket.id].post_data_length * 2)) { // got all expected data + if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; console.log(" * Incoming", post_string, "request on", socket.id, "from", filterSSID(socket.ssid), "to", headers['request_url'], "(got all expected", socket_sessions[socket.id].post_data_length, "bytes of data from client already)"); headers.post_data = CryptoJS.enc.Hex.parse(socket_sessions[socket.id].post_data); + if (socket_sessions[socket.id].headers) delete socket_sessions[socket.id].headers; processURL(socket, headers); } else { // expecting more data (see below) + socket_sessions[socket.id].expecting_post_data = true; console.log(" * Incoming", post_string, "request on", socket.id, "from", filterSSID(socket.ssid), "to", headers['request_url'], "(expecting", socket_sessions[socket.id].post_data_length, "bytes of data from client...)"); } if (socket_sessions[socket.id].post_data.length > (socket_sessions[socket.id].post_data_length * 2)) { @@ -909,6 +950,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } if (socket_sessions[socket.id].post_data.length == (socket_sessions[socket.id].post_data_length * 2)) { // got all expected data + if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; headers.post_data = CryptoJS.enc.Hex.parse(socket_sessions[socket.id].post_data); if (socket_sessions[socket.id].secure == true) { if (zdebug) console.log(" # Encrypted POST Content (SECURE ON)", "on", socket.id, "[", headers.post_data.sigBytes, "bytes ]"); @@ -922,6 +964,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq return; } if (socket_sessions[socket.id].post_data.length > (socket_sessions[socket.id].post_data_length * 2)) { + if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; // got too much data ? ... should not ever reach this code var errpage = doErrorPage(400, "Received too much data in POST request
Got " + (socket_sessions[socket.id].post_data.length / 2) + ", expected " + socket_sessions[socket.id].post_data_length); headers = errpage[0]; @@ -956,7 +999,18 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } if (!socket_sessions[socket.id].secure_buffer) socket_sessions[socket.id].secure_buffer = ""; socket_sessions[socket.id].secure_buffer += dec_data.toString(CryptoJS.enc.Hex); - var secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); + var secure_headers = null; + if (headers['request']) { + if (headers['request'] == "GET") { + if (socket_sessions[socket.id].secure_buffer.indexOf("0d0a0d0a") || socket_sessions[socket.id].secure_buffer.indexOf("0a0a")) { + secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); + } + } else { + var secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); + } + } else { + var secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); + } if (secure_headers) { delete socket_sessions[socket.id].secure_buffer; if (!headers) headers = new Array(); @@ -1016,18 +1070,18 @@ async function handleSocket(socket) { socket.setEncoding('hex'); //set data encoding (Text: 'ascii', 'utf8' ~ Binary: 'hex', 'base64' (do not trust 'binary' encoding)) socket.setTimeout(600000); socket.on('data', function (data_hex) { - if (!socket_sessions[socket.id].secure) { + if (!socket_sessions[socket.id].secure && !socket_sessions[socket.id].expecting_post_data) { // buffer unencrypted data until we see the classic double-newline, or get blank if (!socket_sessions[socket.id].header_buffer) socket_sessions[socket.id].header_buffer = ""; socket_sessions[socket.id].header_buffer += data_hex; - var header_buffer_text = CryptoJS.enc.Hex.parse(socket_sessions[socket.id].header_buffer).toString(CryptoJS.enc.Latin1); - if (header_buffer_text.indexOf("\r\n\r\n") != -1 || header_buffer_text.indexOf("\n\n") != -1 || header_buffer_text == "") { + if (socket_sessions[socket.id].header_buffer.indexOf("0d0a0d0a") != -1 || socket_sessions[socket.id].header_buffer.indexOf("0a0a") != -1) { data_hex = socket_sessions[socket.id].header_buffer; delete socket_sessions[socket.id].header_buffer; processRequest(this, data_hex); } } else { // stream encrypted requests through the processor + if (socket_sessions[socket.id].header_buffer) delete socket_sessions[socket.id].header_buffer; processRequest(this, data_hex); } }); @@ -1238,4 +1292,3 @@ initstring = initstring.substring(0, initstring.length - 2); console.log(" * Started server on ports " + initstring + "...") var listening_ip_string = (minisrv_config.config.bind_ip != "0.0.0.0") ? "IP: " + minisrv_config.config.bind_ip : "all interfaces"; console.log(" * Listening on", listening_ip_string,"~","Service IP:", service_ip); - diff --git a/zefie_wtvp_minisrv/package.json b/zefie_wtvp_minisrv/package.json index 14ecdc61..5286c4aa 100644 --- a/zefie_wtvp_minisrv/package.json +++ b/zefie_wtvp_minisrv/package.json @@ -1,10 +1,13 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.9.5", + "version": "0.9.6", "description": "WebTV Service (WTVP) Emulation Server", "main": "app.js", "homepage": "https://github.com/zefie/zefie_wtvp_minisrv", "license": "GPL3", + "scripts": { + "test": "node test.js" + }, "author": { "name": "zefie", "email": "zefie@zefie.net", diff --git a/zefie_wtvp_minisrv/test.js b/zefie_wtvp_minisrv/test.js new file mode 100644 index 00000000..49c0d926 --- /dev/null +++ b/zefie_wtvp_minisrv/test.js @@ -0,0 +1,33 @@ +const { promisify } = require('util'); +const { resolve } = require('path'); +const fs = require('fs'); +const readdir = promisify(fs.readdir); +const stat = promisify(fs.stat); +const { exec } = require("child_process"); +var path = require('path'); + +async function getFiles(dir) { + const subdirs = await readdir(dir); + const files = await Promise.all(subdirs.map(async (subdir) => { + const res = resolve(dir, subdir); + return (await stat(res)).isDirectory() ? getFiles(res) : res; + })); + return files.reduce((a, f) => a.concat(f), []); +} + +getFiles(__dirname) + .then(files => { + files.forEach(function (file) { + if (path.extname(file) == ".js" && file.indexOf("node_modules") == -1) { + console.log(" * Checking syntax of", file.replace(__dirname + path.sep, "." + path.sep)); + exec("node --check \"" + file + "\"", (error, stdout, stderr) => { + if (stderr.length > 0) { + console.log(`${stderr}`); + return; + } + }); + } + }); + }) + .catch(e => console.error(e)); + diff --git a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj index 02be7160..2c248647 100644 --- a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj +++ b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj @@ -202,12 +202,16 @@ - + + Code - + + Code + + Code