diff --git a/README.md b/README.md index ea305a88..f1746554 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # wtv minisrv node.js The ***wtv minisrv***, or "***zefie_wtvp_minisrv***" project is a node.js project that provides a mini WebTV Server, aiming for full WTVP (WebTV Protocol) support. -This open source server is in alpha status. Use at your own risk. +This open source server is in beta status. Use at your own risk. [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) @@ -14,22 +14,20 @@ This open source server is in alpha status. Use at your own risk. - WebTV cookie support (wtv-cookie) for HTTP(s) - Flashrom flashing support for all known units (including bf0app 'Old Classic') - 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 +- `wtv-disk:/sync` for Download-o-Rama style file downloading - Custom Tellyscripts *(not yet customizable though)* - Flat file client session store and registration system +- wtv-lzpf compression support by eMac (99.9%) ### Current issues: -- wtv-cookie implementation is still partial -- wtv-lzpf compression support is not yet reliable -- Mis-configuring wtv-update:/sync DiskMaps may cause units to delete contents of partitions (need more info) -- Satellite Receiver units reportedly cannot surf with http or https proxy. *(May be fixed by current partial wtv-cookie implementation)* +- Mis-configuring wtv-disk:/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)) - ~~No intentions to support user accounts, registration, or any form of database system~~ *(I guess this was a lie, but we still don't use a database!)* ### Feature Todo: -- wtv-lzpf support *(Milestone v1.0)* +- wtv-setup and bgm support - TellyScript generation and/or manipulation without external dependancies - ~~wtv-cookie full support~~ ***Done [v0.9.13](https://github.com/zefie/zefie_wtvp_minisrv/releases/tag/v0.9.13)*** - ~~Flashrom flashing for bf0app old classic~~ ***Done [v0.9.9](https://github.com/zefie/zefie_wtvp_minisrv/releases/tag/v0.9.9)*** diff --git a/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/UTV/utv_hsd.tok b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/UTV/utv_hsd.tok new file mode 100644 index 00000000..b0701c3e Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/UTV/utv_hsd.tok differ diff --git a/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/UTV/utv_normal.tok b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/UTV/utv_normal.tok new file mode 100644 index 00000000..4e888fab Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/UTV/utv_normal.tok differ diff --git a/zefie_wtvp_minisrv/ServiceVault/http_pc/get.js b/zefie_wtvp_minisrv/ServiceVault/http_pc/get.js index 658b975a..844beae0 100644 --- a/zefie_wtvp_minisrv/ServiceVault/http_pc/get.js +++ b/zefie_wtvp_minisrv/ServiceVault/http_pc/get.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (request_headers.query.url) { if (request_headers.query.url.indexOf(":/") > 0) { var service_request = request_headers.query.url.split(":/")[0]; @@ -31,7 +33,7 @@ if (request_headers.query.url) { } if (!headers) { - var errpage = doErrorPage(500) + var errpage = wtvshared.doErrorPage(500) headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/http_pc/index.js b/zefie_wtvp_minisrv/ServiceVault/http_pc/index.js index 802a1f4b..30c83bfe 100644 --- a/zefie_wtvp_minisrv/ServiceVault/http_pc/index.js +++ b/zefie_wtvp_minisrv/ServiceVault/http_pc/index.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Content-Type: text/html` diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/noflash.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/noflash.js index 1c68e5b8..87a0ede3 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/noflash.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/noflash.js @@ -1,7 +1,9 @@ +var minisrv_service_file = true; + if (socket.ssid != null && !ssid_sessions[socket.ssid].get("wtvsec_login")) { var wtvsec_login = new WTVSec(minisrv_config); wtvsec_login.IssueChallenge(); - wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); + if (request_headers["wtv-incarnation"]) 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"); diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/offer-open-isp-suggest.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/offer-open-isp-suggest.js index 2885e20f..6b76eb8d 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/offer-open-isp-suggest.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/offer-open-isp-suggest.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + var gourl = "wtv-1800:/finish-prereg?"; if (request_headers.query.relogin) gourl += "relogin=true"; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js index 56180d57..20430b9c 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js @@ -1,45 +1,47 @@ - var gourl = "wtv-head-waiter:/login?"; +var minisrv_service_file = true; - if (socket.ssid) { - if (ssid_sessions[socket.ssid].loadSessionData() == true) { - console.log(" * Loaded session data from disk for", wtvshared.filterSSID(socket.ssid)) - ssid_sessions[socket.ssid].setSessionData("registered", (ssid_sessions[socket.ssid].getSessionData("registered") == true) ? true : false); - } else { - ssid_sessions[socket.ssid].session_data = {}; - ssid_sessions[socket.ssid].setSessionData("registered", false); - } - if (ssid_sessions[socket.ssid].data_store) { - if (ssid_sessions[socket.ssid].data_store.sockets) { - var i = 0; - ssid_sessions[socket.ssid].data_store.sockets.forEach(function (k) { - if (typeof k != "undefined") { - if (k != socket) { - k.destroy(); - ssid_sessions[socket.ssid].data_store.sockets.delete(k); - i++; - } - } - }); - if (i > 0 && minisrv_config.config.debug_flags.debug) console.log(" # Closed", i, "previous sockets for", wtvshared.filterSSID(socket.ssid)); - } - } - if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { - if (minisrv_config.config.debug_flags.debug) console.log(" # Recreating primary WTVSec login instance for", wtvshared.filterSSID(socket.ssid)); - delete ssid_sessions[socket.ssid].data_store.wtvsec_login; - } +var gourl = "wtv-head-waiter:/login?"; - ssid_sessions[socket.ssid].data_store.wtvsec_login = new WTVSec(minisrv_config); - ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); - ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(request_headers["wtv-incarnation"] || 1); +if (socket.ssid) { + if (ssid_sessions[socket.ssid].loadSessionData() == true) { + console.log(" * Loaded session data from disk for", wtvshared.filterSSID(socket.ssid)) + ssid_sessions[socket.ssid].setSessionData("registered", (ssid_sessions[socket.ssid].getSessionData("registered") == true) ? true : false); } else { - console.log(" * Something bad happened (we don't know the client ssid???)"); - var errpage = doErrorPage(400) - headers = errpage[0]; - data = errpage[1]; + ssid_sessions[socket.ssid].session_data = {}; + ssid_sessions[socket.ssid].setSessionData("registered", false); + } + if (ssid_sessions[socket.ssid].data_store) { + if (ssid_sessions[socket.ssid].data_store.sockets) { + var i = 0; + ssid_sessions[socket.ssid].data_store.sockets.forEach(function (k) { + if (typeof k != "undefined") { + if (k != socket) { + k.destroy(); + ssid_sessions[socket.ssid].data_store.sockets.delete(k); + i++; + } + } + }); + if (i > 0 && minisrv_config.config.debug_flags.debug) console.log(" # Closed", i, "previous sockets for", wtvshared.filterSSID(socket.ssid)); + } + } + if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { + if (minisrv_config.config.debug_flags.debug) console.log(" # Recreating primary WTVSec login instance for", wtvshared.filterSSID(socket.ssid)); + delete ssid_sessions[socket.ssid].data_store.wtvsec_login; } - if (request_headers.query.relogin && ssid_sessions[socket.ssid].getSessionData("registered")) gourl += "relogin=true"; - if (request_headers.query.reconnect && ssid_sessions[socket.ssid].getSessionData("registered")) gourl += "reconnect=true"; + ssid_sessions[socket.ssid].data_store.wtvsec_login = new WTVSec(minisrv_config); + ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); + if (request_headers["wtv-incarnation"]) ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); +} else { + console.log(" * Something bad happened (we don't know the client ssid???)"); + var errpage = wtvshared.doErrorPage(400) + headers = errpage[0]; + data = errpage[1]; +} + +if (request_headers.query.relogin && ssid_sessions[socket.ssid].getSessionData("registered")) gourl += "relogin=true"; +if (request_headers.query.reconnect && ssid_sessions[socket.ssid].getSessionData("registered")) gourl += "reconnect=true"; if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { var prereg_contype = "text/html"; @@ -66,7 +68,7 @@ if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { } else { romtype = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); } - + var file_path = null; switch (romtype) { case "US-LC2-disk-0MB-8MB": case "US-LC2-disk-0MB-8MB-softmodem-CPU5230": @@ -75,15 +77,30 @@ if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { case "US-WEBSTAR-disk-0MB-16MB-softmodem-CPU5230": prereg_contype = "text/tellyscript"; // if wtv-open-access: true then client expects OpenISP - if (ssid_sessions[socket.ssid].get("wtv-open-access")) var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_OpenISP_56k.tok"; + if (ssid_sessions[socket.ssid].get("wtv-open-access")) file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_OpenISP_56k.tok"; else var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_WTV_18006138199.tok"; break; + case "US-DTV-disk-0MB-32MB-softmodem-CPU5230": + if (wtvshared.isMiniBrowser()) { + prereg_contype = "text/tellyscript"; + if (ssid_sessions[socket.ssid].get("wtv-open-access")) file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_OpenISP_56k.tok"; + else file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_WTV_18006138199.tok"; + } else { + prereg_contype = "text/dialscript"; + if (ssid_sessions[socket.ssid].get("wtv-lan") == "true") { + file_path = __dirname + "/ServiceDeps/premade_tellyscripts/UTV/utv_hsd.tok"; + } else { + // todo OpenISP telly + file_path = __dirname + "/ServiceDeps/premade_tellyscripts/UTV/utv_normal.tok"; + } + } + case "bf0app": prereg_contype = "text/tellyscript"; // if wtv-open-access: true then client expects OpenISP - if (ssid_sessions[socket.ssid].get("wtv-open-access")) var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/bf0app/bf0app_OISP.tok"; - else var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/bf0app/bf0app_WTV_18006138199.tok"; + if (ssid_sessions[socket.ssid].get("wtv-open-access")) file_path = __dirname + "/ServiceDeps/premade_tellyscripts/bf0app/bf0app_OISP.tok"; + else file_path = __dirname + "/ServiceDeps/premade_tellyscripts/bf0app/bf0app_WTV_18006138199.tok"; break; // the following are not yet zefie generated and may have an unknown username/password attached @@ -99,6 +116,11 @@ if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { data = ''; break; } + + if (socket.ssid.substr(0, 8) == "MSTVSIMU") { + prereg_contype = "text/dialscript"; + var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/UTV/utv_hsd.tok"; + } } @@ -157,7 +179,7 @@ if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { request_is_async = true; fs.readFile(file_path, null, function (err, file_read_data) { if (err) { - var errmsg = doErrorPage(400); + var errmsg = wtvshared.doErrorPage(400); headers = errmsg[0]; file_read_data = errmsg[1] + "\n" + err.toString(); } @@ -165,7 +187,7 @@ if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { }); } } else { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-chat/MakeChatPage.js b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/MakeChatPage.js index 22725453..bdecc0d2 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-chat/MakeChatPage.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/MakeChatPage.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = "200 OK"; if (request_headers.query.nick) headers += "\n" + ssid_sessions[socket.ssid].setIRCNick(request_headers.query.nick); headers += "\nContent-Type: text/html"; @@ -148,7 +150,7 @@ ${request_headers.query.channel} `; } else { - var errpage = doErrorPage("400 Chat requires host, port and channel arguments. Do not use the # on channels."); + var errpage = wtvshared.doErrorPage("400 Chat requires host, port and channel arguments. Do not use the # on channels."); headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-chat/home.js b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/home.js index 27008043..e3602a33 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-chat/home.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-chat/home.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + var irc_nick = ""; headers = "200 OK"; if (request_headers.query.nick) headers += "\n" + ssid_sessions[socket.ssid].setIRCNick(request_headers.query.nick); diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/add.js b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/add.js index 80975afb..2c9df7f8 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/add.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/add.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (socket.ssid) { if (request_headers.post_data) { if (ssid_sessions[socket.ssid]) { @@ -9,7 +11,7 @@ if (socket.ssid) { } if (!headers) { - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/get.js b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/get.js index 90f5ad98..9ab5d993 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/get.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/get.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (request_headers.post_data) { if (request_headers.query.domain && request_headers.query.path) { if (socket.ssid) { @@ -11,7 +13,7 @@ if (request_headers.post_data) { } if (!headers) { - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/list.js b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/list.js index e3f6a46b..7c2141bb 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/list.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/list.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (socket.ssid) { if (ssid_sessions[socket.ssid]) { @@ -8,7 +10,7 @@ if (socket.ssid) { } if (!headers) { - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/reset.js b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/reset.js index 6a1801dc..c0d6fd0d 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/reset.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-cookie/reset.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (socket.ssid) { if (ssid_sessions[socket.ssid]) { ssid_sessions[socket.ssid].resetCookies(); @@ -19,7 +21,7 @@ Redirecting shortly... Go Back } if (!headers) { - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-disk/delete-group.js b/zefie_wtvp_minisrv/ServiceVault/wtv-disk/delete-group.js index cc568a9c..1b3d42ae 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-disk/delete-group.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-disk/delete-group.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (request_headers.query.group) { const WTVDownloadList = require("./WTVDownloadList.js"); var wtvdl = new WTVDownloadList(minisrv_config, service_name); diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-disk/sync.js b/zefie_wtvp_minisrv/ServiceVault/wtv-disk/sync.js index 04be6bf5..c8ef1c13 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-disk/sync.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-disk/sync.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + const WTVDownloadList = require("./WTVDownloadList.js"); var wtvdl = new WTVDownloadList(minisrv_config, service_name); @@ -212,9 +214,7 @@ if (request_headers['wtv-request-type'] == 'download') { Object.keys(service_vaults).forEach(function (g) { if (diskmap_data_file != null) return; diskmap_data_file = service_vaults[g] + "/" + service_name + "/" + diskmap_group_data.files[k].location; - if (!fs.existsSync(diskmap_data_file)) { - console.error("Could not find a file for", diskmap_group_data.files[k].location, "(Last tried SV:", diskmap_data_file, ")"); - } + if (!fs.existsSync(diskmap_data_file)) diskmap_data_file = null; }); var diskmap_file_stat = fs.lstatSync(diskmap_data_file); @@ -298,20 +298,20 @@ if (request_headers['wtv-request-type'] == 'download') { headers = "200 OK\nContent-Type: wtv/download-list"; } catch (e) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; console.error(" # " + service_name+":/sync error", e); } } } else { - var errpage = doErrorPage(404, "The requested DiskMap does not exist."); + var errpage = wtvshared.doErrorPage(404, "The requested DiskMap does not exist."); headers = errpage[0]; data = errpage[1]; if (minisrv_config.config.debug_flags.debug) console.error(" # " + service_name +":/sync error", "could not find diskmap"); } } else { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; if (minisrv_config.config.debug_flags.debug) console.error(" # " + service_name + ":/sync error", "missing query arguments"); diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-disk/userstore.js b/zefie_wtvp_minisrv/ServiceVault/wtv-disk/userstore.js index f53bd496..be483345 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-disk/userstore.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-disk/userstore.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (request_headers.post_data) { if (request_headers.query.partialPath || request_headers.query.path) { if (socket.ssid) { @@ -15,7 +17,7 @@ if (request_headers.post_data) { } if (!headers) { - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/content/content-serve.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/content/content-serve.js index 95fdea50..51e8d521 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/content/content-serve.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/content/content-serve.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + const WTVFlashrom = require("./WTVFlashrom.js"); request_is_async = true; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/current-noflash.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/current-noflash.js index 25858295..dfef8bf7 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/current-noflash.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/current-noflash.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + const WTVFlashrom = require("./WTVFlashrom.js"); request_is_async = true; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js index 317c5fa4..5063b1c7 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + const WTVFlashrom = require("./WTVFlashrom.js"); request_is_async = true; @@ -28,7 +30,7 @@ if (request_headers.query.raw || bf0app_update) { headers += "Content-type: text/html" data = ''; } else { - var errpage = doErrorPage(404) + var errpage = wtvshared.doErrorPage(404) headers = errpage[0]; data = errpage[1]; } diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js index 4af7560b..fc5cb153 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js @@ -1,10 +1,11 @@ +var minisrv_service_file = true; const WTVFlashrom = require("./WTVFlashrom.js"); var wtvflashrom; request_is_async = true; if (!request_headers.query.path) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } else { @@ -21,7 +22,7 @@ async function processLC2DownloadPage(path, flashrom_info, numparts = null) { if (numparts != null) flashrom_info.part_count = parseInt(numparts); if (!flashrom_info.part_count) flashrom_info.part_count = parseInt(flashrom_info.message.substring(flashrom_info.message.length - 4).replace(/\D/g, '')); if (!flashrom_info.part_number || !flashrom_info.is_last_part || !flashrom_info.rompath || !flashrom_info.next_rompath || !flashrom_info.is_bootrom) { - if (!flashrom_info.is_last_part || request_headers.query.last_part) { + if (!flashrom_info.is_last_part) { flashrom_info.next_rompath = request_headers.request_url.replace(escape(request_headers.query.path), escape(flashrom_info.next_rompath.replace(service_name+":/",""))); } @@ -92,8 +93,7 @@ data += ` `; } else { - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; } diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/initiate-lc2-download.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/initiate-lc2-download.js index dc6ca784..8063dc7e 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/initiate-lc2-download.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/initiate-lc2-download.js @@ -1,9 +1,11 @@ +var minisrv_service_file = true; + if (request_headers.query.path) { var url = service_name + ":/get-lc2-page?path=" + request_headers.query.path; var romtype = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); if (romtype == "bf0app") { url = "client:updateflash?ipaddr=" + minisrv_config.services[service_name].host + "&port=" + minisrv_config.services[service_name].port + "&path=" + escape(service_name + ":/" +request_headers.query.path); - if (request_headers.query.numparts) url += escape("&numparts=" + request_headers.query.numparts); + if (request_headers.query.numparts) url += escape("?numparts=" + request_headers.query.numparts); } headers = "300 OK\n"; headers += "wtv-visit: " + url + "\n"; @@ -11,7 +13,7 @@ var romtype = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); headers += "Content-type: text/html"; data = ''; } else { - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js index b0e11ad6..c213f1a2 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-complete.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Connection: Close wtv-connection-close: true @@ -43,6 +45,7 @@ Updating complete + diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js index 3f6e1b91..5008076c 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + var error = ''; if (request_headers.query.error) { switch (request_headers.query.error) { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/noflash.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/noflash.js index 1ee36f57..489d9a21 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/noflash.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/noflash.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + const WTVFlashrom = require("./WTVFlashrom.js"); request_is_async = true; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/willie.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/willie.js index 2ac678cf..b3a2fcee 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/willie.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/willie.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + // willie is just a graphical frontend to a list of ROMs // the rest of the scripts should work if you manually link to a ROM, and actually have it. @@ -33,7 +35,7 @@ const req = https.request(options, function (res) { res.on('error', function (e) { if (!minisrv_config.config.debug_flags.quiet) console.log(" * Upstream Ultra Willies HTTP Error:", e); - var errpage = doErrorPage(400) + var errpage = wtvshared.doErrorPage(400) headers = errpage[0]; data = errpage[1]; sendToClient(socket, headers, data); diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/finalize-security.js b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/finalize-security.js index 086789bc..02c75246 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/finalize-security.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/finalize-security.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + var challenge_response, challenge_header = ''; var gourl; 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 4adea583..a0ff818f 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 @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + var challenge_response, challenge_header = ''; var gourl; @@ -61,7 +63,7 @@ else { if (request_headers.query.skip_splash) var home_url = "wtv-home:/home?"; else var home_url = "wtv-home:/splash?"; } else if (!ssid_sessions[socket.ssid].getSessionData("registered")) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } else { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js index 38e60ef4..77a2a638 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + var challenge_response, challenge_header = ""; var gourl = "wtv-head-waiter:/login-stage-two?"; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/relogin.js b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/relogin.js index 52cb2023..23bfa01d 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/relogin.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/relogin.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + var gourl = "wtv-1800:/preregister?"; if (request_headers.query.relogin) gourl += "relogin=true"; else if (request_headers.query.reconnect) gourl += "reconnect=true"; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js index 6b804319..c9dca1b5 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers =`200 OK Connection: Keep-Alive wtv-expire-all: wtv-home:/splash diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.js b/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.js index 52aa1306..93014d6d 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-home/splash.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Connection: Keep-Alive wtv-expire-all: wtv- diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js b/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js index b3e69ae5..a547fda7 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-log/log.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + // write posted log data to disk. should be decrypted by this point (if it was encrypted) if the crypto stream didn't break request_is_async = true; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js b/zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js index b4dbee53..909d4a53 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Content-Type: text/html`; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-register/BeMyGuest.js b/zefie_wtvp_minisrv/ServiceVault/wtv-register/BeMyGuest.js index dffe9ebf..75885f08 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-register/BeMyGuest.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-register/BeMyGuest.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (minisrv_config.config.allow_guests) { headers = `300 Moved Connection: Close @@ -20,7 +22,7 @@ wtv-reconnect-url: wtv-1800:/preregister?guest_login=true&reconnect=true wtv-boot-url: wtv-1800:/preregister?guest_login=true Location: client:relogin`; } else { - var errpage = doErrorPage(400, "Guest mode is not enabled on this service."); + var errpage = wtvshared.doErrorPage(400, "Guest mode is not enabled on this service."); headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-register/FinishRegistration.js b/zefie_wtvp_minisrv/ServiceVault/wtv-register/FinishRegistration.js index 1b4eb3b2..16db0283 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-register/FinishRegistration.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-register/FinishRegistration.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `300 Moved Connection: Close wtv-noback-all: wtv-register: diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAccountInfo.js b/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAccountInfo.js index 7c749a62..26dff84d 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAccountInfo.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAccountInfo.js @@ -1,22 +1,22 @@ - +var minisrv_service_file = true; if (!request_headers.query.registering) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } else { const WTVRegister = require("./WTVRegister.js") var wtvr = new WTVRegister(minisrv_config, SessionStore); var errpage = null; - if (!request_headers.query.registering) errpage = doErrorPage(400); - else if (!request_headers.query.subscriber_name) errpage = doErrorPage(400, "Please enter your name. This can be your real name, or your well-known online alias."); - else if (!request_headers.query.subscriber_username) errpage = doErrorPage(400, "Please enter a username."); - else if (request_headers.query.subscriber_username.length < 5) errpage = doErrorPage(400, "Please choose a username with 5 or more characters."); - else if (request_headers.query.subscriber_username.length > 16) errpage = doErrorPage(400, "Please choose a username with 16 or less characters."); - else if (!wtvr.checkUsernameSanity(request_headers.query.subscriber_username)) errpage = doErrorPage(400, "The username you have chosen contains invalid characters. Please choose a username with only letters, numbers, _ or -. Also, please be sure your username begins with a letter."); - else if (!wtvr.checkUsernameAvailable(request_headers.query.subscriber_username, ssid_sessions)) errpage = doErrorPage(400, "The username you have selected is already in use. Please select another username."); - else if (!request_headers.query.subscriber_contact) errpage = doErrorPage(400, "Please enter your contact information."); - else if (request_headers.query.subscriber_contact_method == "") errpage = doErrorPage(400, "Please select the type of contact information you provided."); + if (!request_headers.query.registering) errpage = wtvshared.doErrorPage(400); + else if (!request_headers.query.subscriber_name) errpage = wtvshared.doErrorPage(400, "Please enter your name. This can be your real name, or your well-known online alias."); + else if (!request_headers.query.subscriber_username) errpage = wtvshared.doErrorPage(400, "Please enter a username."); + else if (request_headers.query.subscriber_username.length < 5) errpage = wtvshared.doErrorPage(400, "Please choose a username with 5 or more characters."); + else if (request_headers.query.subscriber_username.length > 16) errpage = wtvshared.doErrorPage(400, "Please choose a username with 16 or less characters."); + else if (!wtvr.checkUsernameSanity(request_headers.query.subscriber_username)) errpage = wtvshared.doErrorPage(400, "The username you have chosen contains invalid characters. Please choose a username with only letters, numbers, _ or -. Also, please be sure your username begins with a letter."); + else if (!wtvr.checkUsernameAvailable(request_headers.query.subscriber_username, ssid_sessions)) errpage = wtvshared.doErrorPage(400, "The username you have selected is already in use. Please select another username."); + else if (!request_headers.query.subscriber_contact) errpage = wtvshared.doErrorPage(400, "Please enter your contact information."); + else if (request_headers.query.subscriber_contact_method == "") errpage = wtvshared.doErrorPage(400, "Please select the type of contact information you provided."); if (errpage) { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAgreement.js b/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAgreement.js index 29c5464c..f7498504 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAgreement.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateAgreement.js @@ -1,5 +1,7 @@ +var minisrv_service_file = true; + if (!request_headers.query.registering) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } else { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateReviewAccountInfo.js b/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateReviewAccountInfo.js index 9479296b..4e3f904b 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateReviewAccountInfo.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-register/ValidateReviewAccountInfo.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + if (!request_headers.query.registering || !request_headers.query.subscriber_name || !request_headers.query.subscriber_username || @@ -7,7 +9,7 @@ if (!request_headers.query.registering || !ssid_sessions[socket.ssid] || !socket.ssid ) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } else { @@ -18,7 +20,7 @@ if (!request_headers.query.registering || ssid_sessions[socket.ssid].setSessionData("subscriber_userid", '1' + Math.floor(Math.random() * 1000000000000000000)); ssid_sessions[socket.ssid].setSessionData("registered", true); if (!ssid_sessions[socket.ssid].storeSessionData(true)) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } else { diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-register/register.js b/zefie_wtvp_minisrv/ServiceVault/wtv-register/register.js index 4b68acc4..2de623ce 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-register/register.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-register/register.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Content-Type: text/html`; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-register/splash.js b/zefie_wtvp_minisrv/ServiceVault/wtv-register/splash.js index e2cca5fe..d2cb7e6a 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-register/splash.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-register/splash.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Connection: Keep-Alive wtv-expire-all: wtv- diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get-settings.js b/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get-settings.js index 87468535..ecba5e22 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get-settings.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get-settings.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK wtv-backgroundmusic-load-playlist: wtv-music:/get-playlist wtv-printer-model: -1,-1 diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/access.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/access.js index 28423f37..35281012 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/access.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/access.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + // Allow URL access outside our trusted minisrv if (request_headers.query.url) var url = request_headers.query.url; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastbacklist.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastbacklist.js index 6e352b5c..5489aaad 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastbacklist.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/blastbacklist.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK wtv-expire-all: wtv- wtv-expire-all: http diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/go-offline.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/go-offline.js index 4d108b25..07bc02ee 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/go-offline.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/go-offline.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK wtv-noback-all: wtv- wtv-expire-all: wtv- diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js index bc3d6111..3e72a105 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/info.js @@ -1,3 +1,4 @@ +var minisrv_service_file = true; var client_caps = null; @@ -167,7 +168,7 @@ ${wtv_system_sysconfig_str} `; } else { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/register.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/register.js index 6c7393f7..c9be28be 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/register.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/register.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Content-Type: text/html`; diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/tricks.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/tricks.js index acc79f73..b14b558e 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/tricks.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/tricks.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Content-Type: text/html` diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/unregister.js b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/unregister.js index 1f0af15a..7e7a2646 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/unregister.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-tricks/unregister.js @@ -1,3 +1,5 @@ +var minisrv_service_file = true; + headers = `200 OK Content-Type: text/html`; diff --git a/zefie_wtvp_minisrv/WTVFlashrom.js b/zefie_wtvp_minisrv/WTVFlashrom.js index cf8b6c9e..869d8fe4 100644 --- a/zefie_wtvp_minisrv/WTVFlashrom.js +++ b/zefie_wtvp_minisrv/WTVFlashrom.js @@ -8,51 +8,27 @@ class WTVFlashrom { no_debug = false; service_name = ""; minisrv_config = []; + wtvshared = null; constructor(minisrv_config, service_vaults, service_name, use_zefie_server = true, bf0app_update = false, no_debug = false) { + var { WTVShared } = require('./WTVShared.js'); this.service_vaults = service_vaults; this.service_name = service_name; this.use_zefie_server = use_zefie_server; this.bf0app_update = bf0app_update; this.no_debug = no_debug; this.minisrv_config = minisrv_config; + this.wtvshared = new WTVShared(minisrv_config); } - - doErrorPage(code, data = null) { - var headers = null; - switch (code) { - case 404: - if (data === null) data = "The service could not find the requested page."; - headers = "404 " + data + "\r\n"; - headers += "Content-Type: text/html\r\n"; - break; - case 400: - if (data === null) data = "HackTV ran into a technical problem."; - headers = "400 " + data + "\r\n"; - headers += "Content-Type: text/html\r\n"; - break; - default: - // what we send when we did not detect a wtv-url. - // e.g. when a pc browser connects - headers = "HTTP/1.1 200 OK\r\n"; - headers += "Content-Type: text/html\r\n"; - break; - } - console.error("doErrorPage Called:", code, data); - return new Array(headers, data); - } - - async doLocalFlashROM(flashrom_file_path, request_path, callback, info_only = false) { // use local flashrom files; - console.log(info_only); var self = this; try { this.fs.readFile(flashrom_file_path, null, function (err, data) { if (err) { - errpage = doErrorPage(400) + errpage = wtvshared.doErrorPage(400) var headers = errpage[0]; data = err.toString(); callback(data, headers); @@ -65,7 +41,7 @@ class WTVFlashrom { } }); } catch (e) { - var errpage = doErrorPage(404, "The service could not find the requested ROM.") + var errpage = wtvshared.doErrorPage(404, "The service could not find the requested ROM.") var headers = errpage[0]; var data = errpage[1]; callback(data, headers); @@ -107,24 +83,25 @@ class WTVFlashrom { flashrom_info.total_parts_size = data.readUInt32BE(32); flashrom_info.percent_complete = ((((flashrom_info.byte_progress + flashrom_info.part_total_size) / flashrom_info.total_parts_size)) * 100).toFixed(1); - if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Part Size :", flashrom_info.part_total_size); - if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Bytes Sent :", flashrom_info.byte_progress); - if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Bytes Sent+:", flashrom_info.byte_progress + flashrom_info.part_total_size, "(" + flashrom_info.percent_complete + "% complete)"); - if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Total Size :", flashrom_info.total_parts_size); + if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Part Size :", flashrom_info.part_total_size); + if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Bytes Sent :", flashrom_info.byte_progress); + if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Bytes Sent+:", flashrom_info.byte_progress + flashrom_info.part_total_size, "(" + flashrom_info.percent_complete + "% complete)"); + if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Total Size :", flashrom_info.total_parts_size); // read current part number bit from part header flashrom_info.part_number = data.readUInt16BE(28); - if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Curr Part Number :", flashrom_info.part_number); + if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Curr Part Number :", flashrom_info.part_number); flashrom_info.is_last_part = ((flashrom_info.byte_progress + flashrom_info.part_total_size) == flashrom_info.total_parts_size) ? true : false; if (flashrom_info.is_last_part) { - if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Curr Part is Last:", flashrom_info.is_last_part); + if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Curr Part is Last:", flashrom_info.is_last_part); } else { flashrom_info.next_part_number = flashrom_info.part_number + 1; - if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # Flashrom Next Part Number :", flashrom_info.next_part_number); + if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Next Part Number :", flashrom_info.next_part_number); } + if (this.minisrv_config.config.debug_flags.debug && this.minisrv_config.config.debug_flags.quiet) console.log(" # Sending", (flashrom_info.is_last_part) ? "Last Flashrom" : "Flashrom", "Part", flashrom_info.part_number, "- Bytes Sent:", flashrom_info.byte_progress + flashrom_info.part_total_size, "of", flashrom_info.total_parts_size, "(" + flashrom_info.percent_complete + " % complete)"); // read current part display message from part header flashrom_info.message = new Buffer.from(part_header.toString('hex').substring(36 * 2, 68 * 2), 'hex').toString('ascii').replace(/[^0-9a-z\ \.\-]/gi, ""); flashrom_info.rompath = `wtv-flashrom:/${path}`; @@ -142,7 +119,6 @@ class WTVFlashrom { async sendToClient(data, request_path, callback) { var headers = "200 OK\n"; - if (this.bf0app_update) headers += "minisrv-use-carriage-return: false\n"; var flashrom_info = this.getFlashromInfo(data, request_path) if (flashrom_info.is_bootrom) headers += "Content-Type: binary/x-wtv-bootrom"; // maybe? else headers += "Content-Type: binary/x-wtv-flashblock"; @@ -193,15 +169,16 @@ class WTVFlashrom { } else if (res.statusCode == 206) { var data = self.getFlashromInfo(Buffer.from(data_hex, 'hex'), request_path); } else if (res.statusCode == 404) { - var errpage = doErrorPage(404, "The service could not find the requested ROM on zefie's server.") + console.log(request_path); + var errpage = self.wtvshared.doErrorPage(404, "The service could not find the requested ROM on zefie's server.") headers = errpage[0]; var data = errpage[1]; } else { - var errpage = doErrorPage(400) + var errpage = self.wtvshared.doErrorPage(400) headers = errpage[0]; var data = errpage[1]; } - if (res.statusCode != 206) { + if (!headers && res.statusCode != 206) { self.sendToClient(data, request_path, callback); } else { callback(data, headers); diff --git a/zefie_wtvp_minisrv/WTVLzpf.js b/zefie_wtvp_minisrv/WTVLzpf.js index 09eb3cfd..3cdf16cc 100644 --- a/zefie_wtvp_minisrv/WTVLzpf.js +++ b/zefie_wtvp_minisrv/WTVLzpf.js @@ -1,268 +1,305 @@ /** -* Pure-JS implementation of WebTV's LZPF compression -* -* This is a port of my Lzpf compression code from my ROMFS Python tool -* Originally reverse engineered from the box -* -* By: Eric MacDonald (eMac) -* Modified By: zefie -*/ + * Pure-JS implementation of WebTV's LZPF compression + * + * This compression algorithm is based on LZP by Charles Bloom and was originally written for server to client communication by Andy McFadden + * This uses a (static) Huffman dictionary that was tuned for character occurances in a typical HTML page at the time (around 1996-1997). + * + * Andy McFadden: + * https://fadden.com/ + * LZP: + * https://cbloom.com/src/index_lz.html + * https://en.wikibooks.org/wiki/Data_Compression/Dictionary_compression#LZP + * + * I wouldn't recommend using LZPF on anything but HTML and other text-based data (unless the data has many repeating bytes) + * LZPF can be replaced with gzip for LC2 and newer boxes. Classic is stuck with LZPF. + * + * Reverse engineered and ported by: Eric MacDonald (eMac) + * Modified By: zefie +**/ class WTVLzpf { // Note: currentlty doesn't offer optimal streaming support but this is good enough to meet perf demands at the scale we're at. - current_length = 0; - current_literal = 0; - flag = 0xFFFF; + current_bit_length = 0; + current_bits = 0; + ring_bufer_index = 0xFFFF; working_data = 0; match_index = 0; - type_index = 0; + compression_mode = 0; checksum = 0; - flag_table = new Uint16Array(0x1000) + filler_byte = 0x20 + hash_table = new Uint16Array(0x1000) ring_buffer = new Uint8Array(0x2000) encoded_data = []; + /** + * This is used to encode (one-byte) literals with no previous tracked occurence. + * + * - Bytes with best compression: SPACE and LF and e"/<>Tainoprst + * - Bytes with good compression: TAB and ,-.1=ABCDEFGHILNOPRSbcdfghlmuw + * - Bytes that don't change the length of the bit stream: 024:MW_kvy + * - The rest will increase the length of bit stream + * + * I don't know what process they used to build this table. I assume they + * frequency-scanned a bunch of HTML files they had. + * + * Using Windows-1252 (based off of ISO-8859-1) chracter encoding to fill in this table. Didn't + * seem like they used a different table for Japan builds (ISO-2022-JP). + **/ nomatchEncode = [ - - [0x0000, 0x10], [0x0001, 0x10], [0x0002, 0x10], - [0x0003, 0x10], [0x0004, 0x10], [0x009A, 0x0F], - [0x0005, 0x10], [0x009C, 0x0F], [0x009E, 0x0F], - [0x3400, 0x06], [0x7000, 0x05], [0x00A0, 0x0F], - [0x0006, 0x10], [0x0380, 0x09], [0x0007, 0x10], - [0x0008, 0x10], [0x0009, 0x10], [0x000A, 0x10], - [0x000B, 0x10], [0x000C, 0x10], [0x000D, 0x10], - [0x000E, 0x10], [0x000F, 0x10], [0x00A2, 0x0F], - [0x0010, 0x10], [0x0011, 0x10], [0x0012, 0x10], - [0x0013, 0x10], [0x0014, 0x10], [0x0015, 0x10], - [0x0016, 0x10], [0x0017, 0x10], [0xE000, 0x04], - [0x0200, 0x0A], [0x7800, 0x05], [0x0400, 0x09], - [0x00B0, 0x0E], [0x0018, 0x10], [0x0120, 0x0B], - [0x0480, 0x09], [0x0140, 0x0B], [0x0160, 0x0B], - [0x0240, 0x0A], [0x00B8, 0x0D], [0x1400, 0x07], - [0x1600, 0x07], [0x3800, 0x06], [0x8000, 0x05], - [0x0A00, 0x08], [0x1800, 0x07], [0x0B00, 0x08], - [0x0500, 0x09], [0x0C00, 0x08], [0x0580, 0x09], - [0x0600, 0x09], [0x0680, 0x09], [0x0700, 0x09], - [0x0780, 0x09], [0x0D00, 0x08], [0x0180, 0x0B], - [0x8800, 0x05], [0x3C00, 0x06], [0x9000, 0x05], - [0x0280, 0x0A], [0x00B4, 0x0E], [0x4000, 0x06], - [0x1A00, 0x07], [0x1C00, 0x07], [0x1E00, 0x07], - [0x4400, 0x06], [0x2000, 0x07], [0x2200, 0x07], - [0x2400, 0x07], [0x4800, 0x06], [0x01A0, 0x0B], - [0x02C0, 0x0A], [0x2600, 0x07], [0x0E00, 0x08], - [0x4C00, 0x06], [0x5000, 0x06], [0x2800, 0x07], - [0x00C0, 0x0C], [0x5400, 0x06], [0x2A00, 0x07], - [0x9800, 0x05], [0x0800, 0x09], [0x0880, 0x09], - [0x0F00, 0x08], [0x00D0, 0x0C], [0x0300, 0x0A], - [0x0900, 0x09], [0x0019, 0x10], [0x001A, 0x10], - [0x001B, 0x10], [0x001C, 0x10], [0x1000, 0x08], - [0x001D, 0x10], [0xA000, 0x05], [0x2C00, 0x07], - [0x5800, 0x06], [0x5C00, 0x06], [0xF000, 0x04], - [0x2E00, 0x07], [0x3000, 0x07], [0x6000, 0x06], - [0xA800, 0x05], [0x01C0, 0x0B], [0x1100, 0x08], - [0x6400, 0x06], [0x6800, 0x06], [0xB000, 0x05], - [0xB800, 0x05], [0xC000, 0x05], [0x01E0, 0x0B], - [0xC800, 0x05], [0xD000, 0x05], [0xD800, 0x05], - [0x3200, 0x07], [0x1200, 0x08], [0x6C00, 0x06], - [0x0980, 0x09], [0x1300, 0x08], [0x0340, 0x0A], - [0x00E0, 0x0C], [0x00F0, 0x0C], [0x0100, 0x0C], - [0x0110, 0x0C], [0x001E, 0x10], [0x001F, 0x10], - [0x0020, 0x10], [0x0021, 0x10], [0x0022, 0x10], - [0x0023, 0x10], [0x0024, 0x10], [0x0025, 0x10], - [0x0026, 0x10], [0x0027, 0x10], [0x0028, 0x10], - [0x0029, 0x10], [0x002A, 0x10], [0x002B, 0x10], - [0x002C, 0x10], [0x002D, 0x10], [0x002E, 0x10], - [0x002F, 0x10], [0x00A4, 0x0F], [0x00A6, 0x0F], - [0x00A8, 0x0F], [0x0030, 0x10], [0x0031, 0x10], - [0x0032, 0x10], [0x0033, 0x10], [0x0034, 0x10], - [0x0035, 0x10], [0x0036, 0x10], [0x0037, 0x10], - [0x0038, 0x10], [0x0039, 0x10], [0x003A, 0x10], - [0x003B, 0x10], [0x003C, 0x10], [0x003D, 0x10], - [0x003E, 0x10], [0x003F, 0x10], [0x0040, 0x10], - [0x0041, 0x10], [0x0042, 0x10], [0x0043, 0x10], - [0x0044, 0x10], [0x0045, 0x10], [0x0046, 0x10], - [0x0047, 0x10], [0x0048, 0x10], [0x0049, 0x10], - [0x004A, 0x10], [0x004B, 0x10], [0x004C, 0x10], - [0x004D, 0x10], [0x004E, 0x10], [0x004F, 0x10], - [0x0050, 0x10], [0x0051, 0x10], [0x0052, 0x10], - [0x0053, 0x10], [0x0054, 0x10], [0x0055, 0x10], - [0x0056, 0x10], [0x0057, 0x10], [0x0058, 0x10], - [0x0059, 0x10], [0x005A, 0x10], [0x005B, 0x10], - [0x005C, 0x10], [0x005D, 0x10], [0x005E, 0x10], - [0x005F, 0x10], [0x0060, 0x10], [0x0061, 0x10], - [0x0062, 0x10], [0x00AA, 0x0F], [0x0063, 0x10], - [0x0064, 0x10], [0x0065, 0x10], [0x0066, 0x10], - [0x0067, 0x10], [0x0068, 0x10], [0x0069, 0x10], - [0x006A, 0x10], [0x006B, 0x10], [0x006C, 0x10], - [0x006D, 0x10], [0x006E, 0x10], [0x006F, 0x10], - [0x0070, 0x10], [0x0071, 0x10], [0x0072, 0x10], - [0x0073, 0x10], [0x0074, 0x10], [0x0075, 0x10], - [0x0076, 0x10], [0x0077, 0x10], [0x0078, 0x10], - [0x0079, 0x10], [0x007A, 0x10], [0x007B, 0x10], - [0x007C, 0x10], [0x007D, 0x10], [0x007E, 0x10], - [0x007F, 0x10], [0x0080, 0x10], [0x0081, 0x10], - [0x0082, 0x10], [0x0083, 0x10], [0x0084, 0x10], - [0x0085, 0x10], [0x0086, 0x10], [0x0087, 0x10], - [0x0088, 0x10], [0x0089, 0x10], [0x008A, 0x10], - [0x008B, 0x10], [0x008C, 0x10], [0x008D, 0x10], - [0x00AC, 0x0F], [0x008E, 0x10], [0x008F, 0x10], - [0x0090, 0x10], [0x0091, 0x10], [0x0092, 0x10], - [0x0093, 0x10], [0x00AE, 0x0F], [0x0094, 0x10], - [0x0095, 0x10], [0x0096, 0x10], [0x0097, 0x10], - [0x0098, 0x10], [0x0099, 0x10] + /* [FLATTENED HUFFMAN CODE, CODE BIT LENGTH] */ + [0x0000, 0x10] /* NUL */, [0x0001, 0x10] /* SOH */, [0x0002, 0x10] /* STX */, + [0x0003, 0x10] /* ETX */, [0x0004, 0x10] /* EOT */, [0x009A, 0x0F] /* ENQ */, + [0x0005, 0x10] /* ACK */, [0x009C, 0x0F] /* BEL */, [0x009E, 0x0F] /* BS */, + [0x3400, 0x06] /* TAB */, [0x7000, 0x05] /* LF */, [0x00A0, 0x0F] /* VT */, + [0x0006, 0x10] /* FF */, [0x0380, 0x09] /* CR */, [0x0007, 0x10] /* SO */, + [0x0008, 0x10] /* SI */, [0x0009, 0x10] /* DLE */, [0x000A, 0x10] /* DC1 */, + [0x000B, 0x10] /* DC2 */, [0x000C, 0x10] /* DC3 */, [0x000D, 0x10] /* DC4 */, + [0x000E, 0x10] /* NAK */, [0x000F, 0x10] /* SYN */, [0x00A2, 0x0F] /* BTB */, + [0x0010, 0x10] /* CAN */, [0x0011, 0x10] /* EM */, [0x0012, 0x10] /* SUB */, + [0x0013, 0x10] /* ESC */, [0x0014, 0x10] /* FS */, [0x0015, 0x10] /* GS */, + [0x0016, 0x10] /* RS */, [0x0017, 0x10] /* US */, [0xE000, 0x04] /* SPACE */, + [0x0200, 0x0A] /* ! */, [0x7800, 0x05] /* " */, [0x0400, 0x09] /* # */, + [0x00B0, 0x0E] /* $ */, [0x0018, 0x10] /* % */, [0x0120, 0x0B] /* & */, + [0x0480, 0x09] /* ' */, [0x0140, 0x0B] /* ( */, [0x0160, 0x0B] /* ) */, + [0x0240, 0x0A] /* * */, [0x00B8, 0x0D] /* + */, [0x1400, 0x07] /* , */, + [0x1600, 0x07] /* - */, [0x3800, 0x06] /* . */, [0x8000, 0x05] /* / */, + [0x0A00, 0x08] /* 0 */, [0x1800, 0x07] /* 1 */, [0x0B00, 0x08] /* 2 */, + [0x0500, 0x09] /* 3 */, [0x0C00, 0x08] /* 4 */, [0x0580, 0x09] /* 5 */, + [0x0600, 0x09] /* 6 */, [0x0680, 0x09] /* 7 */, [0x0700, 0x09] /* 8 */, + [0x0780, 0x09] /* 9 */, [0x0D00, 0x08] /* : */, [0x0180, 0x0B] /* ; */, + [0x8800, 0x05] /* < */, [0x3C00, 0x06] /* = */, [0x9000, 0x05] /* > */, + [0x0280, 0x0A] /* ? */, [0x00B4, 0x0E] /* @ */, [0x4000, 0x06] /* A */, + [0x1A00, 0x07] /* B */, [0x1C00, 0x07] /* C */, [0x1E00, 0x07] /* D */, + [0x4400, 0x06] /* E */, [0x2000, 0x07] /* F */, [0x2200, 0x07] /* G */, + [0x2400, 0x07] /* H */, [0x4800, 0x06] /* I */, [0x01A0, 0x0B] /* J */, + [0x02C0, 0x0A] /* K */, [0x2600, 0x07] /* L */, [0x0E00, 0x08] /* M */, + [0x4C00, 0x06] /* N */, [0x5000, 0x06] /* O */, [0x2800, 0x07] /* P */, + [0x00C0, 0x0C] /* Q */, [0x5400, 0x06] /* R */, [0x2A00, 0x07] /* S */, + [0x9800, 0x05] /* T */, [0x0800, 0x09] /* U */, [0x0880, 0x09] /* V */, + [0x0F00, 0x08] /* W */, [0x00D0, 0x0C] /* X */, [0x0300, 0x0A] /* Y */, + [0x0900, 0x09] /* Z */, [0x0019, 0x10] /* [ */, [0x001A, 0x10] /* \ */, + [0x001B, 0x10] /* ] */, [0x001C, 0x10] /* ^ */, [0x1000, 0x08] /* _ */, + [0x001D, 0x10] /* ` */, [0xA000, 0x05] /* a */, [0x2C00, 0x07] /* b */, + [0x5800, 0x06] /* c */, [0x5C00, 0x06] /* d */, [0xF000, 0x04] /* e */, + [0x2E00, 0x07] /* f */, [0x3000, 0x07] /* g */, [0x6000, 0x06] /* h */, + [0xA800, 0x05] /* i */, [0x01C0, 0x0B] /* j */, [0x1100, 0x08] /* k */, + [0x6400, 0x06] /* l */, [0x6800, 0x06] /* m */, [0xB000, 0x05] /* n */, + [0xB800, 0x05] /* o */, [0xC000, 0x05] /* p */, [0x01E0, 0x0B] /* q */, + [0xC800, 0x05] /* r */, [0xD000, 0x05] /* s */, [0xD800, 0x05] /* t */, + [0x3200, 0x07] /* u */, [0x1200, 0x08] /* v */, [0x6C00, 0x06] /* w */, + [0x0980, 0x09] /* x */, [0x1300, 0x08] /* y */, [0x0340, 0x0A] /* z */, + [0x00E0, 0x0C] /* { */, [0x00F0, 0x0C] /* | */, [0x0100, 0x0C] /* } */, + [0x0110, 0x0C] /* ~ */, [0x001E, 0x10] /* DEL */, [0x001F, 0x10] /* € */, + [0x0020, 0x10] /* */, [0x0021, 0x10] /* ‚ */, [0x0022, 0x10] /* ƒ */, + [0x0023, 0x10] /* „ */, [0x0024, 0x10] /* … */, [0x0025, 0x10] /* † */, + [0x0026, 0x10] /* ‡ */, [0x0027, 0x10] /* ˆ */, [0x0028, 0x10] /* ‰ */, + [0x0029, 0x10] /* Š */, [0x002A, 0x10] /* ‹ */, [0x002B, 0x10] /* Œ */, + [0x002C, 0x10] /* */, [0x002D, 0x10] /* Ž */, [0x002E, 0x10] /* */, + [0x002F, 0x10] /* */, [0x00A4, 0x0F] /* ‘ */, [0x00A6, 0x0F] /* ’ */, + [0x00A8, 0x0F] /* “ */, [0x0030, 0x10] /* ” */, [0x0031, 0x10] /* • */, + [0x0032, 0x10] /* – */, [0x0033, 0x10] /* — */, [0x0034, 0x10] /* ˜ */, + [0x0035, 0x10] /* ™ */, [0x0036, 0x10] /* š */, [0x0037, 0x10] /* › */, + [0x0038, 0x10] /* œ */, [0x0039, 0x10] /* */, [0x003A, 0x10] /* ž */, + [0x003B, 0x10] /* Ÿ */, [0x003C, 0x10] /* NBSP*/, [0x003D, 0x10] /* ¡ */, + [0x003E, 0x10] /* ¢ */, [0x003F, 0x10] /* £ */, [0x0040, 0x10] /* ¤ */, + [0x0041, 0x10] /* ¥ */, [0x0042, 0x10] /* ¦ */, [0x0043, 0x10] /* § */, + [0x0044, 0x10] /* ¨ */, [0x0045, 0x10] /* © */, [0x0046, 0x10] /* ª */, + [0x0047, 0x10] /* « */, [0x0048, 0x10] /* ¬ */, [0x0049, 0x10] /* SHY */, + [0x004A, 0x10] /* ® */, [0x004B, 0x10] /* ¯ */, [0x004C, 0x10] /* ° */, + [0x004D, 0x10] /* ± */, [0x004E, 0x10] /* ² */, [0x004F, 0x10] /* ³ */, + [0x0050, 0x10] /* ´ */, [0x0051, 0x10] /* µ */, [0x0052, 0x10] /* ¶ */, + [0x0053, 0x10] /* · */, [0x0054, 0x10] /* ¸ */, [0x0055, 0x10] /* ¹ */, + [0x0056, 0x10] /* º */, [0x0057, 0x10] /* » */, [0x0058, 0x10] /* ¼ */, + [0x0059, 0x10] /* ½ */, [0x005A, 0x10] /* ¾ */, [0x005B, 0x10] /* ¿ */, + [0x005C, 0x10] /* À */, [0x005D, 0x10] /* Á */, [0x005E, 0x10] /*  */, + [0x005F, 0x10] /* à */, [0x0060, 0x10] /* Ä */, [0x0061, 0x10] /* Å */, + [0x0062, 0x10] /* Æ */, [0x00AA, 0x0F] /* Ç */, [0x0063, 0x10] /* È */, + [0x0064, 0x10] /* É */, [0x0065, 0x10] /* Ê */, [0x0066, 0x10] /* Ë */, + [0x0067, 0x10] /* Ì */, [0x0068, 0x10] /* Í */, [0x0069, 0x10] /* Î */, + [0x006A, 0x10] /* Ï */, [0x006B, 0x10] /* Ð */, [0x006C, 0x10] /* Ñ */, + [0x006D, 0x10] /* Ò */, [0x006E, 0x10] /* Ó */, [0x006F, 0x10] /* Ô */, + [0x0070, 0x10] /* Õ */, [0x0071, 0x10] /* Ö */, [0x0072, 0x10] /* × */, + [0x0073, 0x10] /* Ø */, [0x0074, 0x10] /* Ù */, [0x0075, 0x10] /* Ú */, + [0x0076, 0x10] /* Û */, [0x0077, 0x10] /* Ü */, [0x0078, 0x10] /* Ý */, + [0x0079, 0x10] /* Þ */, [0x007A, 0x10] /* ß */, [0x007B, 0x10] /* à */, + [0x007C, 0x10] /* á */, [0x007D, 0x10] /* â */, [0x007E, 0x10] /* ã */, + [0x007F, 0x10] /* ä */, [0x0080, 0x10] /* å */, [0x0081, 0x10] /* æ */, + [0x0082, 0x10] /* ç */, [0x0083, 0x10] /* è */, [0x0084, 0x10] /* é */, + [0x0085, 0x10] /* ê */, [0x0086, 0x10] /* ë */, [0x0087, 0x10] /* ì */, + [0x0088, 0x10] /* í */, [0x0089, 0x10] /* î */, [0x008A, 0x10] /* ï */, + [0x008B, 0x10] /* ð */, [0x008C, 0x10] /* ñ */, [0x008D, 0x10] /* ò */, + [0x00AC, 0x0F] /* ó */, [0x008E, 0x10] /* ô */, [0x008F, 0x10] /* õ */, + [0x0090, 0x10] /* ö */, [0x0091, 0x10] /* ÷ */, [0x0092, 0x10] /* ø */, + [0x0093, 0x10] /* ù */, [0x00AE, 0x0F] /* ú */, [0x0094, 0x10] /* û */, + [0x0095, 0x10] /* ü */, [0x0096, 0x10] /* ý */, [0x0097, 0x10] /* þ */, + [0x0098, 0x10] /* ÿ */, [0x0099, 0x10] ]; + + /** + * This is the table that reduces the size based on repeated patterns in the file. + * + * When we find a byte match in the ring buffer we use this table to encode the length of the matched bytes. + * + * - These are intentionally 32-bit. The leftmost flag bit is 1 in each of these to tell the decoder to use match decoding. + * - LZP hash bits are used to encode the position where the matched bytes start. + * - We're allowed to match up to 298 bytes before we can't encode more (we need an entry in this table for each byte more). + * - We can reach for matches 65KB behind the current LZ cursor (65KB is the ring buffer size and highest a 16-bit hash can reach). + **/ matchEncode = [ - [0x80000000, 0x01], [0x80000000, 0x03], - [0xA0000000, 0x03], [0xC0000000, 0x03], - [0xE0000000, 0x06], [0xE4000000, 0x06], - [0xE8000000, 0x06], [0xEC000000, 0x06], - [0xF0000000, 0x06], [0xF4000000, 0x06], - [0xF8000000, 0x06], [0xFC000000, 0x0B], - [0xFC200000, 0x0B], [0xFC400000, 0x0B], - [0xFC600000, 0x0B], [0xFC800000, 0x0B], - [0xFCA00000, 0x0B], [0xFCC00000, 0x0B], - [0xFCE00000, 0x0B], [0xFD000000, 0x0B], - [0xFD200000, 0x0B], [0xFD400000, 0x0B], - [0xFD600000, 0x0B], [0xFD800000, 0x0B], - [0xFDA00000, 0x0B], [0xFDC00000, 0x0B], - [0xFDE00000, 0x0B], [0xFE000000, 0x0B], - [0xFE200000, 0x0B], [0xFE400000, 0x0B], - [0xFE600000, 0x0B], [0xFE800000, 0x0B], - [0xFEA00000, 0x0B], [0xFEC00000, 0x0B], - [0xFEE00000, 0x0B], [0xFF000000, 0x0B], - [0xFF200000, 0x0B], [0xFF400000, 0x0B], - [0xFF600000, 0x0B], [0xFF800000, 0x0B], - [0xFFA00000, 0x0B], [0xFFC00000, 0x0B], - [0xFFE00000, 0x13], [0xFFE02000, 0x13], - [0xFFE04000, 0x13], [0xFFE06000, 0x13], - [0xFFE08000, 0x13], [0xFFE0A000, 0x13], - [0xFFE0C000, 0x13], [0xFFE0E000, 0x13], - [0xFFE10000, 0x13], [0xFFE12000, 0x13], - [0xFFE14000, 0x13], [0xFFE16000, 0x13], - [0xFFE18000, 0x13], [0xFFE1A000, 0x13], - [0xFFE1C000, 0x13], [0xFFE1E000, 0x13], - [0xFFE20000, 0x13], [0xFFE22000, 0x13], - [0xFFE24000, 0x13], [0xFFE26000, 0x13], - [0xFFE28000, 0x13], [0xFFE2A000, 0x13], - [0xFFE2C000, 0x13], [0xFFE2E000, 0x13], - [0xFFE30000, 0x13], [0xFFE32000, 0x13], - [0xFFE34000, 0x13], [0xFFE36000, 0x13], - [0xFFE38000, 0x13], [0xFFE3A000, 0x13], - [0xFFE3C000, 0x13], [0xFFE3E000, 0x13], - [0xFFE40000, 0x13], [0xFFE42000, 0x13], - [0xFFE44000, 0x13], [0xFFE46000, 0x13], - [0xFFE48000, 0x13], [0xFFE4A000, 0x13], - [0xFFE4C000, 0x13], [0xFFE4E000, 0x13], - [0xFFE50000, 0x13], [0xFFE52000, 0x13], - [0xFFE54000, 0x13], [0xFFE56000, 0x13], - [0xFFE58000, 0x13], [0xFFE5A000, 0x13], - [0xFFE5C000, 0x13], [0xFFE5E000, 0x13], - [0xFFE60000, 0x13], [0xFFE62000, 0x13], - [0xFFE64000, 0x13], [0xFFE66000, 0x13], - [0xFFE68000, 0x13], [0xFFE6A000, 0x13], - [0xFFE6C000, 0x13], [0xFFE6E000, 0x13], - [0xFFE70000, 0x13], [0xFFE72000, 0x13], - [0xFFE74000, 0x13], [0xFFE76000, 0x13], - [0xFFE78000, 0x13], [0xFFE7A000, 0x13], - [0xFFE7C000, 0x13], [0xFFE7E000, 0x13], - [0xFFE80000, 0x13], [0xFFE82000, 0x13], - [0xFFE84000, 0x13], [0xFFE86000, 0x13], - [0xFFE88000, 0x13], [0xFFE8A000, 0x13], - [0xFFE8C000, 0x13], [0xFFE8E000, 0x13], - [0xFFE90000, 0x13], [0xFFE92000, 0x13], - [0xFFE94000, 0x13], [0xFFE96000, 0x13], - [0xFFE98000, 0x13], [0xFFE9A000, 0x13], - [0xFFE9C000, 0x13], [0xFFE9E000, 0x13], - [0xFFEA0000, 0x13], [0xFFEA2000, 0x13], - [0xFFEA4000, 0x13], [0xFFEA6000, 0x13], - [0xFFEA8000, 0x13], [0xFFEAA000, 0x13], - [0xFFEAC000, 0x13], [0xFFEAE000, 0x13], - [0xFFEB0000, 0x13], [0xFFEB2000, 0x13], - [0xFFEB4000, 0x13], [0xFFEB6000, 0x13], - [0xFFEB8000, 0x13], [0xFFEBA000, 0x13], - [0xFFEBC000, 0x13], [0xFFEBE000, 0x13], - [0xFFEC0000, 0x13], [0xFFEC2000, 0x13], - [0xFFEC4000, 0x13], [0xFFEC6000, 0x13], - [0xFFEC8000, 0x13], [0xFFECA000, 0x13], - [0xFFECC000, 0x13], [0xFFECE000, 0x13], - [0xFFED0000, 0x13], [0xFFED2000, 0x13], - [0xFFED4000, 0x13], [0xFFED6000, 0x13], - [0xFFED8000, 0x13], [0xFFEDA000, 0x13], - [0xFFEDC000, 0x13], [0xFFEDE000, 0x13], - [0xFFEE0000, 0x13], [0xFFEE2000, 0x13], - [0xFFEE4000, 0x13], [0xFFEE6000, 0x13], - [0xFFEE8000, 0x13], [0xFFEEA000, 0x13], - [0xFFEEC000, 0x13], [0xFFEEE000, 0x13], - [0xFFEF0000, 0x13], [0xFFEF2000, 0x13], - [0xFFEF4000, 0x13], [0xFFEF6000, 0x13], - [0xFFEF8000, 0x13], [0xFFEFA000, 0x13], - [0xFFEFC000, 0x13], [0xFFEFE000, 0x13], - [0xFFF00000, 0x13], [0xFFF02000, 0x13], - [0xFFF04000, 0x13], [0xFFF06000, 0x13], - [0xFFF08000, 0x13], [0xFFF0A000, 0x13], - [0xFFF0C000, 0x13], [0xFFF0E000, 0x13], - [0xFFF10000, 0x13], [0xFFF12000, 0x13], - [0xFFF14000, 0x13], [0xFFF16000, 0x13], - [0xFFF18000, 0x13], [0xFFF1A000, 0x13], - [0xFFF1C000, 0x13], [0xFFF1E000, 0x13], - [0xFFF20000, 0x13], [0xFFF22000, 0x13], - [0xFFF24000, 0x13], [0xFFF26000, 0x13], - [0xFFF28000, 0x13], [0xFFF2A000, 0x13], - [0xFFF2C000, 0x13], [0xFFF2E000, 0x13], - [0xFFF30000, 0x13], [0xFFF32000, 0x13], - [0xFFF34000, 0x13], [0xFFF36000, 0x13], - [0xFFF38000, 0x13], [0xFFF3A000, 0x13], - [0xFFF3C000, 0x13], [0xFFF3E000, 0x13], - [0xFFF40000, 0x13], [0xFFF42000, 0x13], - [0xFFF44000, 0x13], [0xFFF46000, 0x13], - [0xFFF48000, 0x13], [0xFFF4A000, 0x13], - [0xFFF4C000, 0x13], [0xFFF4E000, 0x13], - [0xFFF50000, 0x13], [0xFFF52000, 0x13], - [0xFFF54000, 0x13], [0xFFF56000, 0x13], - [0xFFF58000, 0x13], [0xFFF5A000, 0x13], - [0xFFF5C000, 0x13], [0xFFF5E000, 0x13], - [0xFFF60000, 0x13], [0xFFF62000, 0x13], - [0xFFF64000, 0x13], [0xFFF66000, 0x13], - [0xFFF68000, 0x13], [0xFFF6A000, 0x13], - [0xFFF6C000, 0x13], [0xFFF6E000, 0x13], - [0xFFF70000, 0x13], [0xFFF72000, 0x13], - [0xFFF74000, 0x13], [0xFFF76000, 0x13], - [0xFFF78000, 0x13], [0xFFF7A000, 0x13], - [0xFFF7C000, 0x13], [0xFFF7E000, 0x13], - [0xFFF80000, 0x13], [0xFFF82000, 0x13], - [0xFFF84000, 0x13], [0xFFF86000, 0x13], - [0xFFF88000, 0x13], [0xFFF8A000, 0x13], - [0xFFF8C000, 0x13], [0xFFF8E000, 0x13], - [0xFFF90000, 0x13], [0xFFF92000, 0x13], - [0xFFF94000, 0x13], [0xFFF96000, 0x13], - [0xFFF98000, 0x13], [0xFFF9A000, 0x13], - [0xFFF9C000, 0x13], [0xFFF9E000, 0x13], - [0xFFFA0000, 0x13], [0xFFFA2000, 0x13], - [0xFFFA4000, 0x13], [0xFFFA6000, 0x13], - [0xFFFA8000, 0x13], [0xFFFAA000, 0x13], - [0xFFFAC000, 0x13], [0xFFFAE000, 0x13], - [0xFFFB0000, 0x13], [0xFFFB2000, 0x13], - [0xFFFB4000, 0x13], [0xFFFB6000, 0x13], - [0xFFFB8000, 0x13], [0xFFFBA000, 0x13], - [0xFFFBC000, 0x13], [0xFFFBE000, 0x13], - [0xFFFC0000, 0x13], [0xFFFC2000, 0x13], - [0xFFFC4000, 0x13], [0xFFFC6000, 0x13], - [0xFFFC8000, 0x13], [0xFFFCA000, 0x13], - [0xFFFCC000, 0x13], [0xFFFCE000, 0x13], - [0xFFFD0000, 0x13], [0xFFFD2000, 0x13], - [0xFFFD4000, 0x13], [0xFFFD6000, 0x13], - [0xFFFD8000, 0x13], [0xFFFDA000, 0x13], - [0xFFFDC000, 0x13], [0xFFFDE000, 0x13], - [0xFFFE0000, 0x13], [0xFFFE2000, 0x13], - [0xFFFE4000, 0x13], [0xFFFE6000, 0x13], - [0xFFFE8000, 0x13], [0xFFFEA000, 0x13], - [0xFFFEC000, 0x13], [0xFFFEE000, 0x13], - [0xFFFF0000, 0x13], [0xFFFF2000, 0x13], - [0xFFFF4000, 0x13], [0xFFFF6000, 0x13], - [0xFFFF8000, 0x13], [0xFFFFA000, 0x13], - [0xFFFFC000, 0x13], [0xFFFFE000, 0x13], - [0x00000000, 0x00], [0x00000000, 0x00] + /* [MATCH CODE, MATCH CODE BIT LENGTH] */ + [0x80000000, 0x01], [0x80000000, 0x03], + [0xA0000000, 0x03], [0xC0000000, 0x03], + [0xE0000000, 0x06], [0xE4000000, 0x06], + [0xE8000000, 0x06], [0xEC000000, 0x06], + [0xF0000000, 0x06], [0xF4000000, 0x06], + [0xF8000000, 0x06], [0xFC000000, 0x0B], + [0xFC200000, 0x0B], [0xFC400000, 0x0B], + [0xFC600000, 0x0B], [0xFC800000, 0x0B], + [0xFCA00000, 0x0B], [0xFCC00000, 0x0B], + [0xFCE00000, 0x0B], [0xFD000000, 0x0B], + [0xFD200000, 0x0B], [0xFD400000, 0x0B], + [0xFD600000, 0x0B], [0xFD800000, 0x0B], + [0xFDA00000, 0x0B], [0xFDC00000, 0x0B], + [0xFDE00000, 0x0B], [0xFE000000, 0x0B], + [0xFE200000, 0x0B], [0xFE400000, 0x0B], + [0xFE600000, 0x0B], [0xFE800000, 0x0B], + [0xFEA00000, 0x0B], [0xFEC00000, 0x0B], + [0xFEE00000, 0x0B], [0xFF000000, 0x0B], + [0xFF200000, 0x0B], [0xFF400000, 0x0B], + [0xFF600000, 0x0B], [0xFF800000, 0x0B], + [0xFFA00000, 0x0B], [0xFFC00000, 0x0B], + [0xFFE00000, 0x13], [0xFFE02000, 0x13], + [0xFFE04000, 0x13], [0xFFE06000, 0x13], + [0xFFE08000, 0x13], [0xFFE0A000, 0x13], + [0xFFE0C000, 0x13], [0xFFE0E000, 0x13], + [0xFFE10000, 0x13], [0xFFE12000, 0x13], + [0xFFE14000, 0x13], [0xFFE16000, 0x13], + [0xFFE18000, 0x13], [0xFFE1A000, 0x13], + [0xFFE1C000, 0x13], [0xFFE1E000, 0x13], + [0xFFE20000, 0x13], [0xFFE22000, 0x13], + [0xFFE24000, 0x13], [0xFFE26000, 0x13], + [0xFFE28000, 0x13], [0xFFE2A000, 0x13], + [0xFFE2C000, 0x13], [0xFFE2E000, 0x13], + [0xFFE30000, 0x13], [0xFFE32000, 0x13], + [0xFFE34000, 0x13], [0xFFE36000, 0x13], + [0xFFE38000, 0x13], [0xFFE3A000, 0x13], + [0xFFE3C000, 0x13], [0xFFE3E000, 0x13], + [0xFFE40000, 0x13], [0xFFE42000, 0x13], + [0xFFE44000, 0x13], [0xFFE46000, 0x13], + [0xFFE48000, 0x13], [0xFFE4A000, 0x13], + [0xFFE4C000, 0x13], [0xFFE4E000, 0x13], + [0xFFE50000, 0x13], [0xFFE52000, 0x13], + [0xFFE54000, 0x13], [0xFFE56000, 0x13], + [0xFFE58000, 0x13], [0xFFE5A000, 0x13], + [0xFFE5C000, 0x13], [0xFFE5E000, 0x13], + [0xFFE60000, 0x13], [0xFFE62000, 0x13], + [0xFFE64000, 0x13], [0xFFE66000, 0x13], + [0xFFE68000, 0x13], [0xFFE6A000, 0x13], + [0xFFE6C000, 0x13], [0xFFE6E000, 0x13], + [0xFFE70000, 0x13], [0xFFE72000, 0x13], + [0xFFE74000, 0x13], [0xFFE76000, 0x13], + [0xFFE78000, 0x13], [0xFFE7A000, 0x13], + [0xFFE7C000, 0x13], [0xFFE7E000, 0x13], + [0xFFE80000, 0x13], [0xFFE82000, 0x13], + [0xFFE84000, 0x13], [0xFFE86000, 0x13], + [0xFFE88000, 0x13], [0xFFE8A000, 0x13], + [0xFFE8C000, 0x13], [0xFFE8E000, 0x13], + [0xFFE90000, 0x13], [0xFFE92000, 0x13], + [0xFFE94000, 0x13], [0xFFE96000, 0x13], + [0xFFE98000, 0x13], [0xFFE9A000, 0x13], + [0xFFE9C000, 0x13], [0xFFE9E000, 0x13], + [0xFFEA0000, 0x13], [0xFFEA2000, 0x13], + [0xFFEA4000, 0x13], [0xFFEA6000, 0x13], + [0xFFEA8000, 0x13], [0xFFEAA000, 0x13], + [0xFFEAC000, 0x13], [0xFFEAE000, 0x13], + [0xFFEB0000, 0x13], [0xFFEB2000, 0x13], + [0xFFEB4000, 0x13], [0xFFEB6000, 0x13], + [0xFFEB8000, 0x13], [0xFFEBA000, 0x13], + [0xFFEBC000, 0x13], [0xFFEBE000, 0x13], + [0xFFEC0000, 0x13], [0xFFEC2000, 0x13], + [0xFFEC4000, 0x13], [0xFFEC6000, 0x13], + [0xFFEC8000, 0x13], [0xFFECA000, 0x13], + [0xFFECC000, 0x13], [0xFFECE000, 0x13], + [0xFFED0000, 0x13], [0xFFED2000, 0x13], + [0xFFED4000, 0x13], [0xFFED6000, 0x13], + [0xFFED8000, 0x13], [0xFFEDA000, 0x13], + [0xFFEDC000, 0x13], [0xFFEDE000, 0x13], + [0xFFEE0000, 0x13], [0xFFEE2000, 0x13], + [0xFFEE4000, 0x13], [0xFFEE6000, 0x13], + [0xFFEE8000, 0x13], [0xFFEEA000, 0x13], + [0xFFEEC000, 0x13], [0xFFEEE000, 0x13], + [0xFFEF0000, 0x13], [0xFFEF2000, 0x13], + [0xFFEF4000, 0x13], [0xFFEF6000, 0x13], + [0xFFEF8000, 0x13], [0xFFEFA000, 0x13], + [0xFFEFC000, 0x13], [0xFFEFE000, 0x13], + [0xFFF00000, 0x13], [0xFFF02000, 0x13], + [0xFFF04000, 0x13], [0xFFF06000, 0x13], + [0xFFF08000, 0x13], [0xFFF0A000, 0x13], + [0xFFF0C000, 0x13], [0xFFF0E000, 0x13], + [0xFFF10000, 0x13], [0xFFF12000, 0x13], + [0xFFF14000, 0x13], [0xFFF16000, 0x13], + [0xFFF18000, 0x13], [0xFFF1A000, 0x13], + [0xFFF1C000, 0x13], [0xFFF1E000, 0x13], + [0xFFF20000, 0x13], [0xFFF22000, 0x13], + [0xFFF24000, 0x13], [0xFFF26000, 0x13], + [0xFFF28000, 0x13], [0xFFF2A000, 0x13], + [0xFFF2C000, 0x13], [0xFFF2E000, 0x13], + [0xFFF30000, 0x13], [0xFFF32000, 0x13], + [0xFFF34000, 0x13], [0xFFF36000, 0x13], + [0xFFF38000, 0x13], [0xFFF3A000, 0x13], + [0xFFF3C000, 0x13], [0xFFF3E000, 0x13], + [0xFFF40000, 0x13], [0xFFF42000, 0x13], + [0xFFF44000, 0x13], [0xFFF46000, 0x13], + [0xFFF48000, 0x13], [0xFFF4A000, 0x13], + [0xFFF4C000, 0x13], [0xFFF4E000, 0x13], + [0xFFF50000, 0x13], [0xFFF52000, 0x13], + [0xFFF54000, 0x13], [0xFFF56000, 0x13], + [0xFFF58000, 0x13], [0xFFF5A000, 0x13], + [0xFFF5C000, 0x13], [0xFFF5E000, 0x13], + [0xFFF60000, 0x13], [0xFFF62000, 0x13], + [0xFFF64000, 0x13], [0xFFF66000, 0x13], + [0xFFF68000, 0x13], [0xFFF6A000, 0x13], + [0xFFF6C000, 0x13], [0xFFF6E000, 0x13], + [0xFFF70000, 0x13], [0xFFF72000, 0x13], + [0xFFF74000, 0x13], [0xFFF76000, 0x13], + [0xFFF78000, 0x13], [0xFFF7A000, 0x13], + [0xFFF7C000, 0x13], [0xFFF7E000, 0x13], + [0xFFF80000, 0x13], [0xFFF82000, 0x13], + [0xFFF84000, 0x13], [0xFFF86000, 0x13], + [0xFFF88000, 0x13], [0xFFF8A000, 0x13], + [0xFFF8C000, 0x13], [0xFFF8E000, 0x13], + [0xFFF90000, 0x13], [0xFFF92000, 0x13], + [0xFFF94000, 0x13], [0xFFF96000, 0x13], + [0xFFF98000, 0x13], [0xFFF9A000, 0x13], + [0xFFF9C000, 0x13], [0xFFF9E000, 0x13], + [0xFFFA0000, 0x13], [0xFFFA2000, 0x13], + [0xFFFA4000, 0x13], [0xFFFA6000, 0x13], + [0xFFFA8000, 0x13], [0xFFFAA000, 0x13], + [0xFFFAC000, 0x13], [0xFFFAE000, 0x13], + [0xFFFB0000, 0x13], [0xFFFB2000, 0x13], + [0xFFFB4000, 0x13], [0xFFFB6000, 0x13], + [0xFFFB8000, 0x13], [0xFFFBA000, 0x13], + [0xFFFBC000, 0x13], [0xFFFBE000, 0x13], + [0xFFFC0000, 0x13], [0xFFFC2000, 0x13], + [0xFFFC4000, 0x13], [0xFFFC6000, 0x13], + [0xFFFC8000, 0x13], [0xFFFCA000, 0x13], + [0xFFFCC000, 0x13], [0xFFFCE000, 0x13], + [0xFFFD0000, 0x13], [0xFFFD2000, 0x13], + [0xFFFD4000, 0x13], [0xFFFD6000, 0x13], + [0xFFFD8000, 0x13], [0xFFFDA000, 0x13], + [0xFFFDC000, 0x13], [0xFFFDE000, 0x13], + [0xFFFE0000, 0x13], [0xFFFE2000, 0x13], + [0xFFFE4000, 0x13], [0xFFFE6000, 0x13], + [0xFFFE8000, 0x13], [0xFFFEA000, 0x13], + [0xFFFEC000, 0x13], [0xFFFEE000, 0x13], + [0xFFFF0000, 0x13], [0xFFFF2000, 0x13], + [0xFFFF4000, 0x13], [0xFFFF6000, 0x13], + [0xFFFF8000, 0x13], [0xFFFFA000, 0x13], + [0xFFFFC000, 0x13], [0xFFFFE000, 0x13], + // We never should select these. These were in the original executable so including them here. + [0x00000000, 0x00], [0x00000000, 0x00] ]; /** @@ -271,7 +308,7 @@ class WTVLzpf { * @returns {undefined} */ constructor() { - this.clear(); + this.reset(); } /** @@ -279,16 +316,16 @@ class WTVLzpf { * * @returns {undefined} */ - clear() { - this.current_length = 0; - this.current_literal = 0; - this.flag = 0xFFFF; + reset() { + this.current_bit_length = 0; + this.current_bits = 0; + this.ring_bufer_index = 0xFFFF; this.working_data = 0; this.match_index = 0; - this.type_index = 0; + this.compression_mode = 0; this.checksum = 0; - this.ring_buffer.fill(0x00, 0, 0x2000) - this.flag_table.fill(0xFFFF, 0, 0x1000); + this.ring_buffer.fill(this.filler_byte, 0, 0x2000) + this.hash_table.fill(0xFFFF, 0, 0x1000); this.encoded_data = []; } @@ -304,24 +341,24 @@ class WTVLzpf { } /** - * Encodes a literal onto the compressed byte array. + * Add bits onto the compressed bit stream. + * + * When we reach 8 bits we push a byte onto the compressed byte array. * - * @param code_length {Number} bit length of the code - * @param code {Number} code to be encoded + * @param bits {Number} bits to add + * @param bit_length {Number} bit length * * @returns {undefined} */ - EncodeLiteral(code_length, code) { - // Using >>> to stick with unsigned integers without making a mess with casting. + AddBits(bits, bit_length) { + this.current_bits |= bits >>> (this.current_bit_length & 0x1F); + this.current_bit_length += bit_length; - this.current_literal |= code >>> (this.current_length & 0x1F); - this.current_length += code_length; + while (this.current_bit_length > 7) { + this.AddByte((this.current_bits >>> 0x18) & 0xFF); - while (this.current_length > 7) { - this.AddByte((this.current_literal >>> 0x18) & 0xFF); - - this.current_length -= 8; - this.current_literal = (this.current_literal << 8) & 0xFFFFFFFF; + this.current_bit_length -= 8; + this.current_bits = (this.current_bits << 8) & 0xFFFFFFFF; } } @@ -331,7 +368,7 @@ class WTVLzpf { * @returns {undefined} Lzpf compression data */ Begin() { - this.clear(); + this.reset(); } /** @@ -347,7 +384,7 @@ class WTVLzpf { var uncompressed_len = unencoded_data.byteLength; var i = 0; - var flags_index = 0; + var hash_index = 0; while (i < uncompressed_len) { var code_length = -1; var code = -1; @@ -356,48 +393,58 @@ class WTVLzpf { this.ring_buffer[i & 0x1FFF] = byte; if (this.match_index > 0) { - if (byte != this.ring_buffer[this.flag] || this.match_index > 0x0127) { + // Cozy time + if (byte != this.ring_buffer[this.ring_bufer_index] || this.match_index > 0x0127) { + // End of matching. Either we no longer match or we reached out limit. code_length = this.matchEncode[this.match_index][1]; code = this.matchEncode[this.match_index][0]; this.match_index = 0; - this.type_index = 3; + this.compression_mode = 3; } else { + // Previous iteration found a match so we continue matching until we can't. this.match_index = (this.match_index + 1) & 0x1FFF; - this.flag = (this.flag + 1) & 0x1FFF; + this.ring_bufer_index = (this.ring_bufer_index + 1) & 0x1FFF; this.checksum = (this.checksum + byte) & 0xFFFF; this.working_data = ((this.working_data * 0x0100) + byte) & 0xFFFFFFFF; i++; } } else { - this.flag = 0xFFFF; + this.ring_bufer_index = 0xFFFF; if (i >= 3) { - flags_index = (this.working_data >>> 0x0B ^ this.working_data) & 0x0FFF; - this.flag = this.flag_table[flags_index]; - this.flag_table[flags_index] = i & 0x1FFF; + // Start recoding data so we can lookup matches. + hash_index = (this.working_data >>> 0x0B ^ this.working_data) & 0x0FFF; + this.ring_bufer_index = this.hash_table[hash_index]; + this.hash_table[hash_index] = i & 0x1FFF; } else { - this.type_index++; + // The first three uncompressed bytes aren't used for the matching algorithm. + this.compression_mode++; } - if (this.flag == 0xFFFF) { + if (this.ring_bufer_index == 0xFFFF) { + // We never seen this byte before so we encode it with our Huffman table. code_length = this.nomatchEncode[byte][1]; code = this.nomatchEncode[byte][0] << 0x10; - } else if (byte == this.ring_buffer[this.flag] && compress_data) { + } else if (byte == this.ring_buffer[this.ring_bufer_index] && compress_data) { + // Wow dude, a match has been found. Let's switch get our own room in the next iteration to see if we match further. this.match_index = 1; - this.flag = (this.flag + 1) & 0x1FFF; - this.type_index = 4; + this.ring_bufer_index = (this.ring_bufer_index + 1) & 0x1FFF; + this.compression_mode = 4; } else { + // We've seen these bytes before but the index in the ring buffer doesn't match so we revert to our neat Huffman table + // We add 1 flag bit of 0 to account for the fact we've had a hash table hit but no hit in the ring buffer. code_length = this.nomatchEncode[byte][1] + 1; code = this.nomatchEncode[byte][0] << 0x0F; } this.checksum = (this.checksum + byte) & 0xFFFF; + // We work on a 2-byte context so we store the last two bytes so we can do cool lookups with it this.working_data = ((this.working_data * 0x0100) + byte) & 0xFFFFFFFF; i++; } if (code_length > 0) { - this.EncodeLiteral(code_length, code); + this.AddBits(code, code_length); } } } @@ -405,7 +452,7 @@ class WTVLzpf { /** * Ends a compression stream. * - * @param type_index {Number} the end type used to finalize + * @param compression_mode {Number} the end type used to finalize * * @returns {Buffer} Lzpf compression data */ @@ -413,33 +460,34 @@ class WTVLzpf { var code_length = -1; var code = -1; - if (this.type_index == 2) { - this.EncodeLiteral(0x10, 0x00990000); - } else if (this.type_index >= 3) { - if (this.type_index == 4) { + if (this.compression_mode == 2) { + this.AddBits(0x00990000, 0x10); + } else if (this.compression_mode >= 3) { + if (this.compression_mode == 4) { code_length = this.matchEncode[this.match_index][1]; code = this.matchEncode[this.match_index][0]; - this.EncodeLiteral(code_length, code); + this.AddBits(code, code_length); } - var flags_index = (this.working_data >>> 0x0B ^ this.working_data) & 0x0FFF; - var flag = this.flag_table[flags_index]; - if (flag == 0xFFFF) { - this.EncodeLiteral(0x10, 0x00990000); + var hash_index = (this.working_data >>> 0x0B ^ this.working_data) & 0x0FFF; + var ring_bufer_index = this.hash_table[hash_index]; + if (ring_bufer_index == 0xFFFF) { + this.AddBits(0x00990000, 0x10); } else { - this.EncodeLiteral(0x11, 0x004c8000); + this.AddBits(0x004C8000, 0x11); } } - // Below is just metadata. The compressed block is complete. + // Add checksum bits + this.AddBits((this.checksum << 0x10) & 0xFFFFFFFF, 0x08); + this.AddBits((this.checksum << 0x18) & 0xFFFFFFFF, 0x08); - // Encode checksum - this.EncodeLiteral(0x08, (this.checksum << 0x10) & 0xFFFFFFFF); - this.EncodeLiteral(0x08, (this.checksum << 0x18) & 0xFFFFFFFF); + // If we have leftover bits then add it. + if (this.current_bit_length > 0) { + this.AddByte((this.current_bits >>> 0x18) & 0xFF); + } - // End - this.AddByte((this.current_literal >>> 0x18) & 0xFF); - this.AddByte(0x20); + this.AddByte(this.filler_byte); return Buffer.from(this.encoded_data); } diff --git a/zefie_wtvp_minisrv/WTVMime.js b/zefie_wtvp_minisrv/WTVMime.js index 8f316e5b..a404100f 100644 --- a/zefie_wtvp_minisrv/WTVMime.js +++ b/zefie_wtvp_minisrv/WTVMime.js @@ -75,9 +75,10 @@ class WTVMime { // gzip only if (content_type.match(/^audio\/(x-)?(s3m|mod|xm)$/)) compress_data = true; // s3m, mod, xm if (content_type.match(/^audio\/(x-)?(midi|wav|wave|aif(f)?)$/)) compress_data = true; // midi & wav + if (content_type.match(/^application\/karaoke$/)) compress_data = true; // midi karaoke if (content_type.match(/^binary\/x-wtv-approm$/)) compress_data = true; // approms if (content_type.match(/^binary\/doom-data$/)) compress_data = true; // DOOM WADs - if (content_type.match(/^wtv\/download-list$/)) compress_data = true; // WebTV Download List + if (content_type.match(/^wtv\/download-list$/)) compress_data = true; // WebTV Download List } } } @@ -179,6 +180,9 @@ class WTVMime { case "wad": wtv_mime_type = "binary/doom-data"; break; + case "kar": + wtv_mime_type = "application/karaoke"; + break; case "mp2": case "hsb": case "rmf": @@ -190,6 +194,7 @@ class WTVMime { } modern_mime_type = this.mime.lookup(path); + if (modern_mime_type === false) modern_mime_type = "application/octet-stream"; if (wtv_mime_type == "") wtv_mime_type = modern_mime_type; return new Array(wtv_mime_type, modern_mime_type); } diff --git a/zefie_wtvp_minisrv/WTVShared.js b/zefie_wtvp_minisrv/WTVShared.js index 44235cf8..d22de387 100644 --- a/zefie_wtvp_minisrv/WTVShared.js +++ b/zefie_wtvp_minisrv/WTVShared.js @@ -199,6 +199,68 @@ class WTVShared { return path.reverse().split(".")[0].reverse(); } + getLineFromFile(filename, line_no, callback) { + var stream = this.fs.createReadStream(filename, { + flags: 'r', + encoding: 'utf-8', + fd: null, + bufferSize: 64 * 1024 + }); + + + var fileData = ''; + stream.on('data', function (data) { + fileData += data; + + // The next lines should be improved + var lines = fileData.split("\n"); + + if (lines.length >= +line_no) { + stream.destroy(); + callback(null, lines[+line_no]); + } + }); + + stream.on('error', function () { + callback('Error', null); + }); + + stream.on('end', function () { + callback('File end reached without finding line', null); + }); + } + + doErrorPage(code, data = null, pc_mode = false) { + var headers = null; + switch (code) { + case 404: + if (data === null) data = "The service could not find the requested page."; + if (pc_mode) headers = "404 Not Found\n"; + else headers = code + " " + data + "\n"; + headers += "Content-Type: text/html\n"; + break; + case 400: + case 500: + if (data === null) data = "HackTV ran into a technical problem."; + if (pc_mode) headers = "500 Internal Server Error\n"; + else headers = code + " " + data + "\n"; + headers += "Content-Type: text/html\n"; + break; + case 401: + if (data === null) data = "Access Denied."; + if (pc_mode) headers = "401 Access Denied\n"; + else headers = code + " " + data + "\n"; + headers += "Content-Type: text/html\n"; + break; + default: + headers = code + " " + data + "\n"; + headers += "Content-Type: text/html\n"; + break; + } + console.error(" * doErrorPage Called:", code, data); + return new Array(headers, data); + } + /** * Strips bad things from paths * @param {string} base Base path diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index b97435b4..e2b3d7a6 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -71,47 +71,31 @@ function getServiceString(service, overrides = {}) { } } +// passthrough for old scripts function doErrorPage(code, data = null, pc_mode = false) { - var headers = null; - switch (code) { - case 404: - if (data === null) data = "The service could not find the requested page."; - if (pc_mode) headers = "404 Not Found\n"; - else headers = code + " "+ data + "\n"; - headers += "Content-Type: text/html\n"; - break; - case 400: - case 500: - if (data === null) data = "HackTV ran into a technical problem."; - if (pc_mode) headers = "500 Internal Server Error\n"; - else headers = code + " " + data + "\n"; - headers += "Content-Type: text/html\n"; - break; - case 401: - if (data === null) data = "Access Denied."; - if (pc_mode) headers = "401 Access Denied\n"; - else headers = code + " " + data + "\n"; - headers += "Content-Type: text/html\n"; - break; - default: - headers = code + " " + data + "\n"; - headers += "Content-Type: text/html\n"; - break; - } - console.error(" * doErrorPage Called:", code, data); - return new Array(headers, data); + return wtvshared.doErrorPage(code, data, pc_mode); +} + +async function sendRawFile(socket, path) { + if (!minisrv_config.config.debug_flags.quiet) console.log(" * Found " + path + " to handle request (Direct File Mode) [Socket " + socket.id + "]"); + var contypes = wtvmime.getContentType(path); + var headers = "200 OK\n" + headers += "Content-Type: " + contypes[0] + "\n"; + headers += "wtv-modern-content-type" + contypes[1]; + fs.readFile(path, null, function (err, data) { + sendToClient(socket, headers, data); + }); } async function processPath(socket, service_vault_file_path, request_headers = new Array(), service_name) { var headers, data = null; var request_is_async = false; var service_vault_found = false; - var service_path = service_vault_file_path; + var service_path = unescape(service_vault_file_path); try { service_vaults.forEach(function (service_vault_dir) { if (service_vault_found) return; service_vault_file_path = wtvshared.makeSafePath(service_vault_dir, service_path); - // deny access to catchall file name directly var service_path_split = service_path.split("/"); var service_path_request_file = service_path_split[service_path_split.length - 1]; @@ -121,28 +105,66 @@ async function processPath(socket, service_vault_file_path, request_headers = ne else minisrv_catchall = minisrv_config.config.catchall_file_name || null; if (minisrv_catchall) { if (service_path_request_file == minisrv_catchall) { - var errpage = doErrorPage(401, "Access Denied"); - headers = errpage[0]; - data = errpage[1]; + request_is_async = true; + var errpage = wtvshared.doErrorPage(401, "Access Denied"); + sendToClient(socket, errpage[0], errpage[1]); return; } } } + var is_dir = false; + var file_exists = false; minisrv_catchall, service_path_split, service_path_request_file = null; - if (fs.existsSync(service_vault_file_path)) { - // file exists, read it and return it + file_exists = true; + is_dir = fs.lstatSync(service_vault_file_path).isDirectory() + } + + if (file_exists && !is_dir) { + // file exists, read it and return it service_vault_found = true; request_is_async = true; - if (!minisrv_config.config.debug_flags.quiet) console.log(" * Found " + service_vault_file_path + " to handle request (Direct File Mode) [Socket " + socket.id + "]"); request_headers.service_file_path = service_vault_file_path; - var contypes = wtvmime.getContentType(service_vault_file_path); - headers = "200 OK\n" - headers += "Content-Type: " + contypes[0] + "\n"; - headers += "wtv-modern-content-type" + contypes[1]; - fs.readFile(service_vault_file_path, null, function (err, data) { - sendToClient(socket, headers, data); - }); + request_headers.raw_file = true; + + // service parsed files, we might not want to expose our service source files so we can protect them with a flag on the first line + if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "js" || wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "txt") { + if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "js") { + wtvshared.getLineFromFile(service_vault_file_path, 0, function (status, line) { + if (!status) { + if (line.match(/minisrv\_service\_file.*true/i)) { + var errpage = wtvshared.doErrorPage(403, "Access Denied"); + sendToClient(socket, errpage[0], errpage[1]); + } else { + sendRawFile(socket, service_vault_file_path); + } + } else { + var errpage = wtvshared.doErrorPage(400); + sendToClient(socket, errpage[0], errpage[1]); + } + }); + } + + if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "txt") { + wtvshared.getLineFromFile(service_vault_file_path, 0, function (status, line) { + if (!status) { + if (line.match(/^#!minisrv/i)) { + var errpage = wtvshared.doErrorPage(403, "Access Denied"); + sendToClient(socket, errpage[0], errpage[1]); + } else { + sendRawFile(socket, service_vault_file_path); + } + } else { + var errpage = wtvshared.doErrorPage(400); + sendToClient(socket, errpage[0], errpage[1]); + } + }); + } + } else { + // not a potential service file, so save to send + sendRawFile(socket, service_vault_file_path); + } + } else if (fs.existsSync(service_vault_file_path + ".txt")) { // raw text format, entire payload expected (headers and content) service_vault_found = true; @@ -211,6 +233,7 @@ async function processPath(socket, service_vault_file_path, request_headers = ne while (service_check_dir.join(path.sep) != service_vault_dir) { var catchall_file = service_check_dir.join(path.sep) + path.sep + minisrv_catchall_file_name; if (fs.existsSync(catchall_file)) { + service_vault_found = true; if (!minisrv_config.config.debug_flags.quiet) console.log(" * Found catchall at " + catchall_file + " to handle request (JS Interpreter Mode) [Socket " + socket.id + "]"); request_headers.service_file_path = catchall_file; var jscript_eval = fs.readFileSync(catchall_file).toString(); @@ -228,7 +251,7 @@ async function processPath(socket, service_vault_file_path, request_headers = ne // either `request_is_async`, or `headers` and `data` MUST be defined by this point! }); } catch (e) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1] + "

The interpreter said:
" + e.toString() + "
"; console.error(" * Scripting error:",e); @@ -236,12 +259,12 @@ async function processPath(socket, service_vault_file_path, request_headers = ne if (!request_is_async) { if (!service_vault_found) { console.error(" * Could not find a Service Vault for " + service_name + ":/" + service_path.replace(service_name + path.sep, "")); - var errpage = doErrorPage(404, null, socket.minisrv_pc_mode); + var errpage = wtvshared.doErrorPage(404, null, socket.minisrv_pc_mode); headers = errpage[0]; data = errpage[1]; } if (headers == null && !request_is_async) { - var errpage = doErrorPage(400, null, socket.minisrv_pc_mode); + var errpage = wtvshared.doErrorPage(400, null, socket.minisrv_pc_mode); headers = errpage[0]; data = errpage[1]; console.error(" * Scripting or Data error: Headers were not defined. (headers,data) as follows:") @@ -316,7 +339,7 @@ async function processURL(socket, request_headers) { shortURL_split.shift(); var shortURL_service_path = shortURL_split.join(":"); shortURL = shortURL_service_name + ":/" + shortURL_service_path; - } else if (shortURL.indexOf(":") == -1 && request_headers.request.indexOf("HTTP/1") > 0) { + } else if (shortURL.indexOf(":") == -1 && request_headers.request.indexOf("HTTP/1") > 0 && socket.ssid == null) { if (request_headers.Host) { if (minisrv_config.config.pc_server_hidden_service_enabled) { // browsers typically send a Host header @@ -329,7 +352,7 @@ async function processURL(socket, request_headers) { } else { // minimal pc mode to send error socket.minisrv_pc_mode = true; - var errpage = doErrorPage(401, "PC services are disabled on this server", socket.minisrv_pc_mode); + var errpage = wtvshared.doErrorPage(401, "PC services are disabled on this server", socket.minisrv_pc_mode); headers = errpage[0]; data = errpage[1] socket_sessions[socket.id].close_me = true; @@ -356,7 +379,7 @@ async function processURL(socket, request_headers) { } // assume webtv since there is a :/ in the GET var service_name = shortURL.split(':/')[0]; - var urlToPath = service_name + path.sep + shortURL.split(':/')[1]; + var urlToPath = wtvshared.fixPathSlashes(service_name + path.sep + shortURL.split(':/')[1]); if (minisrv_config.config.debug_flags.show_headers) console.log(" * Incoming headers on socket ID", socket.id, (await wtvshared.filterSSID(request_headers))); socket_sessions[socket.id].request_headers = request_headers; processPath(socket, urlToPath, request_headers, service_name); @@ -364,7 +387,7 @@ async function processURL(socket, request_headers) { doHTTPProxy(socket, request_headers); } else { // error reading headers (no request_url provided) - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1] socket_sessions[socket.id].close_me = true; @@ -465,11 +488,11 @@ async function doHTTPProxy(socket, request_headers) { }); }).on('error', function (err) { var errpage, headers, data = null; - if (err.code == "ENOTFOUND") errpage = doErrorPage(400, `The publisher ${request_data.host} is unknown.`); - else if (err.message.indexOf("HostUnreachable") > 0) errpage = doErrorPage(400, `The publisher ${request_data.host} could not be reached.`); + if (err.code == "ENOTFOUND") errpage = wtvshared.doErrorPage(400, `The publisher ${request_data.host} is unknown.`); + else if (err.message.indexOf("HostUnreachable") > 0) errpage = wtvshared.doErrorPage(400, `The publisher ${request_data.host} could not be reached.`); else { console.log(" * Unhandled Proxy Request Error:", err); - errpage = doErrorPage(400); + errpage = wtvshared.doErrorPage(400); } headers = errpage[0]; data = errpage[1]; @@ -521,7 +544,18 @@ function headerStringToObj(headers, response = false) { headers_obj.http_response = d.replace("\r", ""); } else if (/^(GET |PUT |POST)$/.test(d.substring(0, 4)) && !response) { headers_obj.request = d.replace("\r", ""); - headers_obj.request_url = decodeURI(d.split(' ')[1]).replace("\r", ""); + var request_url = d.split(' '); + if (request_url.length > 2) { + request_url.shift(); + request_url = request_url.join(" "); + if (request_url.indexOf("HTTP/") > 0) { + var index = request_url.indexOf(" HTTP/"); + request_url = request_url.substring(0, index); + } + } else { + request_url = request_url[1]; + } + headers_obj.request_url = decodeURI(request_url).replace("\r", ""); } else if (d.indexOf(":") > 0) { var d_split = d.split(':'); var header_name = d_split[0]; @@ -578,7 +612,7 @@ async function sendToClient(socket, headers_obj, data) { if (socket_sessions[socket.id]) { if (socket_sessions[socket.id].request_headers) { if (socket_sessions[socket.id].request_headers.service_file_path) { - if (wtvshared.getFileExt(socket_sessions[socket.id].request_headers.service_file_path).toLowerCase() !== "js") { + if (wtvshared.getFileExt(socket_sessions[socket.id].request_headers.service_file_path).toLowerCase() !== "js" || socket_sessions[socket.id].request_headers.raw_file === true) { var last_modified = wtvshared.getFileLastModifiedUTCString(socket_sessions[socket.id].request_headers.service_file_path); if (last_modified) headers_obj["Last-Modified"] = last_modified; } @@ -836,7 +870,7 @@ function checkSecurity(socket) { if (blacklist) console.log(" * Request from SSID", wtvshared.filterSSID(ssid), "(" + socket.remoteAddr + "), but that SSID is in the blacklist, rejecting."); else console.log(" * Request from SSID", wtvshared.filterSSID(socket.ssid), "(" + socket.remoteAddress + "), but that SSID is not in the whitelist, rejecting."); - var errpage = doErrorPage(401, "Access to this service is denied."); + var errpage = wtvshared.doErrorPage(401, "Access to this service is denied."); out = errpage; } @@ -942,7 +976,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq var enc_data = CryptoJS.enc.Hex.parse(data_hex.substring(header_length * 2)); if (enc_data.sigBytes > 0) { if (!socket_sessions[socket.id].wtvsec) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; headers += "wtv-visit: client:relog\n"; data = errpage[1]; @@ -1010,7 +1044,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (!ssid_sessions[socket.ssid].data_store.wtvsec_login) { ssid_sessions[socket.ssid].data_store.wtvsec_login = new WTVSec(minisrv_config); ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); - ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(headers["wtv-incarnation"]); + if (headers["wtv-incarnation"]) ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(headers["wtv-incarnation"]); ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = headers["wtv-ticket"]; ssid_sessions[socket.ssid].data_store.wtvsec_login.DecodeTicket(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64); } else { @@ -1018,7 +1052,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (minisrv_config.config.debug_flags.debug) console.log(" # New ticket from client"); ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = headers["wtv-ticket"]; ssid_sessions[socket.ssid].data_store.wtvsec_login.DecodeTicket(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64); - ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(headers["wtv-incarnation"]); + if (headers["wtv-incarnation"]) ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(headers["wtv-incarnation"]); } } } @@ -1077,7 +1111,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (minisrv_config.config.debug_flags.show_headers) console.log(secure_headers); if (!secure_headers.request) { socket_sessions[socket.id].secure = false; - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); headers = errpage[0]; data = errpage[1]; sendToClient(socket, headers, data); @@ -1138,7 +1172,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq processURL(socket, headers); } else if (socket_sessions[socket.id].post_data.length > (socket_sessions[socket.id].post_data_length * 2)) { // got too much data ? ... should not ever reach this code (section 2) - 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) + " (2)"; + var errpage = wtvshared.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) + " (2)"; headers = errpage[0]; data = errpage[1]; sendToClient(socket, headers, data); @@ -1220,7 +1254,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; socket.setTimeout(minisrv_config.config.socket_timeout * 1000); // 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); + var errpage = wtvshared.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]; data = errpage[1]; sendToClient(socket, headers, data); @@ -1238,7 +1272,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq var enc_data = CryptoJS.enc.Hex.parse(data_hex); if (enc_data.sigBytes > 0) { if (!socket_sessions[socket.id].wtvsec) { - var errpage = doErrorPage(400); + var errpage = wtvshared.doErrorPage(400); var headers = errpage[0]; headers += "wtv-visit: client:relog\n"; data = errpage[1]; @@ -1330,6 +1364,7 @@ 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.ssid = null; socket_sessions[socket.id] = []; socket.minisrv_pc_mode = false; socket.setEncoding('hex'); //set data encoding (Text: 'ascii', 'utf8' ~ Binary: 'hex', 'base64' (do not trust 'binary' encoding)) diff --git a/zefie_wtvp_minisrv/config.json b/zefie_wtvp_minisrv/config.json index db14be70..24fc2e72 100644 --- a/zefie_wtvp_minisrv/config.json +++ b/zefie_wtvp_minisrv/config.json @@ -1,6 +1,6 @@ { "config": { - "service_ip": "0.0.0.0", + "service_ip": "127.0.0.1", "ServiceVaults": [ "UserServiceVault", "ServiceVault" @@ -17,7 +17,7 @@ "post_data_socket_timeout": 30, "error_log_file": "errors.log", "catchall_file_name": "catchall.js", - "enable_lzpf_compression": false, + "enable_lzpf_compression": true, "enable_gzip_compression": true, "pc_server_hidden_service": "http_pc", "pc_server_hidden_service_enabled": false, @@ -59,7 +59,7 @@ "flags": "0x00000040", "debug": false, "use_zefie_server": true, - "bf0app_default_rom": "content/artemis-webtv-000/build7181/daily-nondebug/bf0app-part000.rom", + "bf0app_default_rom": "content/artemis-webtv-000/build7588/daily-nondebug/bf0app-part000.rom", "catchall_file_name": "content-serve.js" }, "wtv-setup": { diff --git a/zefie_wtvp_minisrv/package-lock.json b/zefie_wtvp_minisrv/package-lock.json index b87f18c9..4e98aa74 100644 --- a/zefie_wtvp_minisrv/package-lock.json +++ b/zefie_wtvp_minisrv/package-lock.json @@ -1,6 +1,6 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.9.18", + "version": "0.9.20", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -36,9 +36,9 @@ "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==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" }, "data-uri-to-buffer": { "version": "3.0.1", @@ -444,9 +444,9 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "vm2": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.3.tgz", - "integrity": "sha512-smLS+18RjXYMl9joyJxMNI9l4w7biW8ilSDaVRvFBDwOH8P0BK1ognFQTpg0wyQ6wIKLTblHJvROW692L/E53Q==" + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.5.tgz", + "integrity": "sha512-LuCAHZN75H9tdrAiLFf030oW7nJV5xwNMuk1ymOZwopmuK3d2H4L1Kv4+GFHgarKiLfXXLFU+7LDABHnwOkWng==" }, "word-wrap": { "version": "1.2.3", diff --git a/zefie_wtvp_minisrv/package.json b/zefie_wtvp_minisrv/package.json index 8a1ee8dd..0a7a1974 100644 --- a/zefie_wtvp_minisrv/package.json +++ b/zefie_wtvp_minisrv/package.json @@ -1,6 +1,6 @@ { "name": "zefie_wtvp_minisrv", - "version": "0.9.19", + "version": "0.9.21", "description": "WebTV Service (WTVP) Emulation Server", "main": "app.js", "homepage": "https://github.com/zefie/zefie_wtvp_minisrv", @@ -26,7 +26,7 @@ "url": "https://github.com/zefie/zefie_wtvp_minisrv.git" }, "dependencies": { - "crypto-js": "^4.0.0", + "crypto-js": "^4.1.1", "easy-crc": "0.0.2", "endianness": "^8.0.2", "mime-types": "^2.1.31",