diff --git a/README.md b/README.md index 5ac221f4..da4bd195 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,13 @@ This open source server is in alpha status. Use at your own risk. - Suports `.async.js` service files with asynchronous requests - Supports multiple simultaneous users - WebTV-compatible HTTP Proxy (via minisrv, or using an external proxy for enhanced features (such as [WebOne](https://github.com/atauenis/webone)) +- wtv-flashrom for LC2 and newer boxes (bf0app unsupported, need test unit) +- Can flash anything on [Ultra Willies](https://wtv.zefie.com/willie.php) with optional `use_zefie_server` flag set on `wtv-flashrom` service. ### Current issues: - May not run on non-development Windows machines (VS2019 with nodejs and python) - Power cycling box and re-connecting via ConnectSetup may invalidate encryption until server is restarted - wtv-update:/update does not yet function as intended -- wtv-flashrom features do not yet function as intended - HTTPS Proxying untested, likely needs SSL spoofing with self-signed solution ### Won't fix: @@ -26,7 +27,8 @@ This open source server is in alpha status. Use at your own risk. ### Feature Todo: - ~~(maybe) implement HTTP proxy (needs to be able to defluff most of the web, think retro WAP converter)~~ ***Done*** - ~~(maybe) enable "internet mode" (let user outside of minisrv)~~ ***Done*** -- Flashrom flashing functionality (at least for LC2 and higher) +- ~~Flashrom flashing functionality (at least for LC2 and higher)~~ ***Done*** +- Flashrom flashing for bf0app old classic (need donor unit) - SSID/IP black/whitelisting (including tying SSID to an IP or multiple IPs) - (maybe) Proper wtv-star (generic service outage page) support (maybe useful for allowing a unit to multiple sub-minisrvs). - (maybe) wtvchat stuff diff --git a/ServiceVault.md b/ServiceVault.md index d674a9cb..4b6d806f 100644 --- a/ServiceVault.md +++ b/ServiceVault.md @@ -16,14 +16,13 @@ Let us use the URL `wtv-1800:/preregister` as an example. This is what the serve - TXT file match (*Raw TXT Mode*) - Service parses and sends AS-IS. - You are expected to define headers -- `./ServiceVault/wtv-1800/preregister.async.js` \[ [Example](zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/willie.async.js) \] - - Asynchronous JS match (*Async JS Interpreter mode*) - - Executes the JavaScript in asynchronous mode. - - You are expected to call `sendToClient(socket,headers,data)` yourself, `socket` is already defined by the time your script runs, so you can just pass it through. - `./ServiceVault/wtv-1800/preregister.js` \[ [Example](zefie_wtvp_minisrv/ServiceVault/wtv-home/home.js) \] - Synchronous JS match (*JS Interpreter mode*) - Executes the JavaScript in synchronous mode. - You are expected to define `headers` and `data` before the end of your script. + - Access Asynchronous mode by setting `request_is_async = true;` + - Client request headers are available as an Array in variable `request_headers`, query arguments are also an Array, in `request_headers.query` + - In Asynchronous mode, you are expected to call `sendToClient(socket,headers,data)` yourself, `socket` is already defined by the time your script runs, so you can just pass it through. - `./ServiceVault/wtv-1800/preregister.html` \[ [Example](zefie_wtvp_minisrv/ServiceVault/wtv-home/zefie.html) \] - HTML match (*HTML mode*) - Like Direct File Mode, but you don't need to append `.html`. diff --git a/zefie_wtvp_minisrv/.gitignore b/zefie_wtvp_minisrv/.gitignore index 6d6f8150..0dade07a 100644 --- a/zefie_wtvp_minisrv/.gitignore +++ b/zefie_wtvp_minisrv/.gitignore @@ -9,6 +9,7 @@ ServiceLogPost/*_* # Large files not pertaining to the service code ServiceVault/wtv-flashrom/content/* ServiceVault/wtv-music/content/* +ServiceVault/wtv-music/midi/* # User-specific files *.rsuser diff --git a/zefie_wtvp_minisrv/ServiceDeps/LC2/artemis_18004653537.tok b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_HDD_artemis_18004653537.tok similarity index 100% rename from zefie_wtvp_minisrv/ServiceDeps/LC2/artemis_18004653537.tok rename to zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_HDD_artemis_18004653537.tok diff --git a/zefie_wtvp_minisrv/ServiceDeps/LC2/artemis_18006138199.tok b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_HDD_artemis_18006138199.tok similarity index 100% rename from zefie_wtvp_minisrv/ServiceDeps/LC2/artemis_18006138199.tok rename to zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_HDD_artemis_18006138199.tok diff --git a/zefie_wtvp_minisrv/ServiceDeps/LC2/LC2_OISP_5555732_56k.tok b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_OISP_5555732_56k.tok similarity index 100% rename from zefie_wtvp_minisrv/ServiceDeps/LC2/LC2_OISP_5555732_56k.tok rename to zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_OISP_5555732_56k.tok diff --git a/zefie_wtvp_minisrv/ServiceDeps/LC2/LC2_WTV_18006138199_56k.tok b/zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_WTV_18006138199_56k.tok similarity index 100% rename from zefie_wtvp_minisrv/ServiceDeps/LC2/LC2_WTV_18006138199_56k.tok rename to zefie_wtvp_minisrv/ServiceDeps/premade_tellyscripts/LC2/LC2_WTV_18006138199_56k.tok diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js index 67275dd8..6d0706f3 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/finish-prereg.js @@ -1,26 +1,40 @@ if (socket_session_data[socket.id].ssid != null && !getSessionData(socket_session_data[socket.id].ssid, 'wtvsec_login')) { var wtvsec_login = new WTVSec(); wtvsec_login.IssueChallenge(); - wtvsec_login.set_incarnation(request_headers['wtv-incarnation']); + wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); setSessionData(socket_session_data[socket.id].ssid, 'wtvsec_login', wtvsec_login) } else { var wtvsec_login = getSessionData(socket_session_data[socket.id].ssid, 'wtvsec_login') } -var contype = "text/tellyscript"; - -var skip_tellyscript = false; +var prereg_contype = "text/html"; // if relogin, skip tellyscript -if (query['relogin']) { - contype = "text/html"; // skip tellyscript +if (request_headers.query.relogin) { // skip tellyscript wtvsec_login.ticket_b64 = null; // clear old ticket } +// if relogin, skip tellyscript +var romtype, file_path = null; +if (!request_headers.query.relogin && services_configured.config.send_tellyscripts) { + var romtype = getSessionData(socket_session_data[socket.id].ssid, 'wtv-client-rom-type'); +} + +switch (romtype) { + case "US-LC2-disk-0MB-8MB": + prereg_contype = "text/tellyscript"; + var file_path = __dirname + "/ServiceDeps/premade_tellyscripts/LC2/LC2_OISP_5555732_56k.tok"; + break; + + default: + data = ''; + break; +} + headers = `200 OK Connection: Keep-Alive wtv-initial-key: ` + wtvsec_login.challenge_key.toString(CryptoJS.enc.Base64) + ` -Content-Type: `+ contype + ` +Content-Type: `+ prereg_contype + ` wtv-service: reset ` + getServiceString('wtv-1800') + ` ` + getServiceString('wtv-star') + ` @@ -30,20 +44,16 @@ wtv-boot-url: wtv-1800:/preregister?relogin=true wtv-visit: wtv-head-waiter:/login? wtv-client-time-zone: GMT -0000 wtv-client-time-dst-rule: GMT -wtv-client-date: `+strftime("%a, %d %b %Y %H:%M:%S", new Date(new Date().toUTCString()))+` GMT`; +wtv-client-date: `+ strftime("%a, %d %b %Y %H:%M:%S", new Date(new Date().toUTCString())) + ` GMT`; -// if relogin, skip tellyscript -var romtype = null; -if (!query['relogin'] && skip_tellyscript == false) { - var romtype = getSessionData(socket_session_data[socket.id].ssid, 'wtv-client-rom-type'); -} - -switch (romtype) { - case "US-LC2-disk-0MB-8MB": - data = getFile("LC2/LC2_OISP_5555732_56k.tok", true); - break; - - default: - data = ''; - break; +if (file_path) { + request_is_async = true; + fs.readFile(file_path, null, function (err, file_read_data) { + if (err) { + var errmsg = doErrorCode(400); + headers = errmsg[0]; + file_read_data = errmsg[1] + "\n" + err.toString(); + } + sendToClient(socket, headers, file_read_data); + }); } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js index bd9909f4..2885e20f 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js @@ -1,8 +1,8 @@ var gourl = "wtv-1800:/finish-prereg?"; -if (query['relogin']) gourl += "relogin=true"; +if (request_headers.query.relogin) gourl += "relogin=true"; -if (request_headers['wtv-ticket']) { +if (request_headers["wtv-ticket"]) { gourl = "wtv-head-waiter:/login-stage-two?"; } diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/ROMCache/HackTVLogoJewel.gif b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/ROMCache/HackTVLogoJewel.gif new file mode 100644 index 00000000..07a0f4b8 Binary files /dev/null and b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/ROMCache/HackTVLogoJewel.gif differ diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js new file mode 100644 index 00000000..e9297a37 --- /dev/null +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-by-path.js @@ -0,0 +1,74 @@ +request_is_async = true; + +var request_path = unescape(request_headers.query.path); +headers = "200 OK\n" + +if (request_headers.query.raw) { + if ((/\.brom$/).test(request_path)) headers += "Content-Type: binary/x-wtv-bootrom"; // maybe? + else headers += "Content-Type: binary/x-wtv-flashblock"; + if (services_configured.services[service_name].use_zefie_server) { + // get flashrom files from archive.midnightchannel.net + var options = { + host: "archive.midnightchannel.net", + path: "/zefie/files/wtv-flashrom/" + request_path, + timeout: 5000, + method: 'GET' + } + const req = https.request(options, function (res) { + var data_hex = ''; + res.setEncoding('hex'); + + res.on('data', d => { + data_hex += d; + }) + + res.on('end', function () { + if (!zquiet) console.log(` * Zefie's FlashROM Server HTTP Status: ${res.statusCode} ${res.statusMessage}`) + if (res.statusCode == 200) { + data = Buffer.from(data_hex, 'hex'); + } else if (res.statusCode == 404) { + var errpage = doErrorPage(404, "The service could not find the requested ROM on zefie's server.") + headers = errpage[0]; + data = errpage[1]; + } else { + var errpage = doErrorPage(400) + headers = errpage[0]; + data = errpage[1]; + } + sendToClient(socket, headers, data); + }); + }); + req.end(); + } else { + // use local flashrom files); + var flashrom_file_path = service_dir + '/' + request_path; + try { + fs.readFile(flashrom_file_path, null, function (err, data) { + if (err) { + errpage = doErrorPage(400) + headers = errpage[0]; + data = err.toString(); + } + sendToClient(socket, headers, data); + }); + } catch (e) { + var errpage = doErrorPage(404, "The service could not find the requested ROM.") + headers = errpage[0]; + data = errpage[1]; + sendToClient(socket, headers, data); + } + } +} else { + // no support for bf0app yet, but here we send the client to initiate-lc2-download + // to get the rom image + if (request_headers.query.path) { + headers += "Content-type: text/html\n" + headers += "wtv-visit: wtv-flashrom:/initiate-lc2-download?path=" + request_headers.query.path; + data = ''; + } else { + var errpage = doErrorPage(404) + headers = errpage[0]; + data = errpage[1]; + } + sendToClient(socket, headers, data); +} \ No newline at end of file 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 51d7b10f..76250b79 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/get-lc2-page.js @@ -2,11 +2,106 @@ // - ready query param to get flashrom path, check for its existance // - handle last part to redirect to lc2-download-complete // - handle failures +request_is_async = true; -headers = `200 OK +if (!request_headers.query.path) { + var errpage = doErrorPage(400); + headers = errpage[0]; + data = errpage[1]; +} else { + var request_path = unescape(request_headers.query.path); + if (services_configured.services[service_name].use_zefie_server) { + // read first 256 bytes of flashrom file from archive.midnightchannel.net + // to get `flashrom_message` and `numparts` if missing + var options = { + host: "archive.midnightchannel.net", + path: "/zefie/files/wtv-flashrom/" + request_path, + method: 'GET', + timeout: 5000, + headers: { + 'Range': 'bytes=0-256' + } + } + + var chunk; + + const req = https.request(options, function (res) { + var data = ''; + res.setEncoding('hex'); + + res.on('data', function (d) { + data += d; + }); + + res.on('error', function (e) { + console.log(" * Upstream FlashROM Error:", e); + var errpage = doErrorPage(400) + headers = errpage[0]; + data = errpage[1]; + sendToClient(socket, headers, data); + }); + + res.on('end', function () { + if (res.statusCode == 206) { + var flashrom_message = new Buffer.from(data.substring(36 * 2, 68 * 2), 'hex').toString('ascii').replace(/[^0-9a-z\ \.\-]/gi, ""); + processLC2DownloadPage(request_headers.query.path, flashrom_message, (request_headers.query.numparts || null)); + return; + } else if (res.statusCode == 404) { + var errpage = doErrorPage(404, "The service could not find the requested ROM on zefie's server.") + headers = errpage[0]; + data = errpage[1]; + } else { + var errpage = doErrorPage(400) + headers = errpage[0]; + data = errpage[1]; + } + sendToClient(socket, headers, data); + }); + }); + req.end(); + } else { + // use local flashrom files + var flashrom_file_path = service_dir + '/' + request_path; + fs.readFile(flashrom_file_path, null, function (err, data) { + try { + var data_128 = new Buffer.alloc(128); + data.copy(data_128, 0, 0, 128); + var flashrom_message = new Buffer.from(data_128.toString('hex').substring(36 * 2, 68 * 2), 'hex').toString('ascii').replace(/[^0-9a-z\ \.\-]/gi, ""); + processLC2DownloadPage(request_headers.query.path, flashrom_message, (request_headers.query.numparts || null)); + } catch (e) { + var errpage = doErrorPage(404, "The service could not find the requested ROM.") + headers = errpage[0]; + data = errpage[1]; + sendToClient(socket, headers, data); + } + }); + } +} + +async function processLC2DownloadPage(path, flashrom_message, numparts = null) { + if (numparts != null) var flashrom_numparts = parseInt(numparts); + if (!flashrom_numparts) flashrom_numparts = flashrom_message.substring(flashrom_message.length - 4).replace(/\D/g, ''); + var ind = new Array(); + ind[0] = (path.indexOf("part") + 4); + ind[1] = (path.indexOf(".", ind[0]) + 1); + var flashrom_part_num = path.substr(ind[0], (path.length - ind[1])); + var flashrom_lastpart = (flashrom_numparts == (parseInt(flashrom_part_num) + 1)) ? true : false; + var flashrom_rompath = 'wtv-flashrom:/get-by-path?path=' + path + '&raw=true'; + var flashrom_isboot = (/\.brom$/).test(path); + if (flashrom_lastpart) { + flashrom_next_rompath = "wtv-flashrom:/lc2-download-complete?"; + } else { + var flashrom_next_part_num = (parseInt(flashrom_part_num) + 1); + if (flashrom_next_part_num < 10) flashrom_next_part_num = "00" + flashrom_next_part_num; // 1s + else if (flashrom_next_part_num >= 10 && flashrom_next_part_num < 100) flashrom_next_part_num = "0" + flashrom_next_part_num; // 10s + var flashrom_next_rompath = flashrom_rompath.replace("part"+flashrom_part_num, "part"+flashrom_next_part_num).replace('get-by-path', 'get-lc2-page').replace("&raw=true", "&numparts=" + parseInt(flashrom_numparts)); + } + if (!flashrom_part_num || !flashrom_lastpart || !flashrom_rompath || !flashrom_next_rompath || !flashrom_isboot) { + + headers = `200 OK Content-type: text/html` -data = ` + data = `
+
|
+ |
-Updating now... +Updating now | |||||||||
|
+ | |||||||||||
| @@ -49,38 +148,37 @@ Updating now... |
-Your Internet Receiver is being updated automatically. +Your WebTV Unit is being updated automatically.
-This will take a while, and then
+ if (flashrom_isboot && parseInt(flashrom_part_num) == 16) {
+ data += `
The system will pause for about 30 seconds at the end of this
update. Please do not interrupt the system
during this time.
`
-}
-data += ` | ||||||||||
| Receiving part ${flashrom_part} of ${flashrom_total_parts} | -v${flashrom_version} (${flashrom_type}) | -
-
+
|
|
diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.html b/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.html
deleted file mode 100644
index 19abc99a..00000000
--- a/zefie_wtvp_minisrv/ServiceVault/wtv-flashrom/lc2-download-failed.html
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
| |||||||||||||||||||||||||||||||||||||||||||||