v0.9.21
- numerous bug fixes - add UTV tellyscripts - BREAKING CHANGE: doErrorPage moved to wtvshared.doErrorPage - but I fixed flashrom error handling.. - added a passthrough for old scripts - added eMac's lzpf compression - Bump vm2 from 3.9.3 to 3.9.5 in /zefie_wtvp_minisrv
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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];
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Content-Type: text/html`
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
var gourl = "wtv-1800:/finish-prereg?";
|
||||
if (request_headers.query.relogin) gourl += "relogin=true";
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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}
|
||||
</body>
|
||||
</html>`;
|
||||
} 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];
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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... <a href="client:goback">Go Back</a>
|
||||
}
|
||||
|
||||
if (!headers) {
|
||||
var errpage = doErrorPage(400)
|
||||
var errpage = wtvshared.doErrorPage(400)
|
||||
headers = errpage[0];
|
||||
data = errpage[1];
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
const WTVFlashrom = require("./WTVFlashrom.js");
|
||||
request_is_async = true;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
const WTVFlashrom = require("./WTVFlashrom.js");
|
||||
request_is_async = true;
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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 += `
|
||||
<upgradeblock width=280 height=15
|
||||
nexturl="${flashrom_info.next_rompath}"
|
||||
errorurl="${service_name}:/lc2-download-failed?"
|
||||
`
|
||||
if (!flashrom_info.is_last_part) data += `blockurl = "${flashrom_info.rompath}"`;
|
||||
blockurl="${flashrom_info.rompath}"`;
|
||||
|
||||
data += `
|
||||
lastblock="${flashrom_info.is_last_part}"
|
||||
@@ -144,7 +144,7 @@ ${flashrom_info.message}
|
||||
</body>
|
||||
</html>`;
|
||||
} else {
|
||||
var errpage = doErrorPage(400)
|
||||
var errpage = wtvshared.doErrorPage(400)
|
||||
headers = errpage[0];
|
||||
data = errpage[1];
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Connection: Close
|
||||
wtv-connection-close: true
|
||||
@@ -43,6 +45,7 @@ Updating complete
|
||||
<img src="${service_name}:/ROMCache/S40H1.gif" width=560 height=6>
|
||||
<tr>
|
||||
<td width=104 height=10 valign=top align=left>
|
||||
|
||||
<td width=20 valign=top align=left>
|
||||
<td width=67 valign=top align=left>
|
||||
<td width=20 valign=top align=left>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
var error = '';
|
||||
if (request_headers.query.error) {
|
||||
switch (request_headers.query.error) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
const WTVFlashrom = require("./WTVFlashrom.js");
|
||||
request_is_async = true;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
var challenge_response, challenge_header = '';
|
||||
var gourl;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
var challenge_response, challenge_header = "";
|
||||
|
||||
var gourl = "wtv-head-waiter:/login-stage-two?";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers =`200 OK
|
||||
Connection: Keep-Alive
|
||||
wtv-expire-all: wtv-home:/splash
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Connection: Keep-Alive
|
||||
wtv-expire-all: wtv-
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Content-Type: text/html`;
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `300 Moved
|
||||
Connection: Close
|
||||
wtv-noback-all: wtv-register:
|
||||
|
||||
@@ -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 <b>letters</b>, <b>numbers</b>, <b>_</b> or <b>-</b>. 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 <b>letters</b>, <b>numbers</b>, <b>_</b> or <b>-</b>. 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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Content-Type: text/html`;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Connection: Keep-Alive
|
||||
wtv-expire-all: wtv-
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
wtv-expire-all: wtv-
|
||||
wtv-expire-all: http
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
wtv-noback-all: wtv-
|
||||
wtv-expire-all: wtv-
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
var client_caps = null;
|
||||
|
||||
@@ -167,7 +168,7 @@ ${wtv_system_sysconfig_str}
|
||||
|
||||
</body> </html>`;
|
||||
} else {
|
||||
var errpage = doErrorPage(400);
|
||||
var errpage = wtvshared.doErrorPage(400);
|
||||
headers = errpage[0];
|
||||
data = errpage[1];
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Content-Type: text/html`;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Content-Type: text/html`
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var minisrv_service_file = true;
|
||||
|
||||
headers = `200 OK
|
||||
Content-Type: text/html`;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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] /* <20> */,
|
||||
[0x0020, 0x10] /* */, [0x0021, 0x10] /* <20> */, [0x0022, 0x10] /* <20> */,
|
||||
[0x0023, 0x10] /* <20> */, [0x0024, 0x10] /* <20> */, [0x0025, 0x10] /* <20> */,
|
||||
[0x0026, 0x10] /* <20> */, [0x0027, 0x10] /* <20> */, [0x0028, 0x10] /* <20> */,
|
||||
[0x0029, 0x10] /* <20> */, [0x002A, 0x10] /* <20> */, [0x002B, 0x10] /* <20> */,
|
||||
[0x002C, 0x10] /* */, [0x002D, 0x10] /* <20> */, [0x002E, 0x10] /* */,
|
||||
[0x002F, 0x10] /* */, [0x00A4, 0x0F] /* <20> */, [0x00A6, 0x0F] /* <20> */,
|
||||
[0x00A8, 0x0F] /* <20> */, [0x0030, 0x10] /* <20> */, [0x0031, 0x10] /* <20> */,
|
||||
[0x0032, 0x10] /* <20> */, [0x0033, 0x10] /* <20> */, [0x0034, 0x10] /* <20> */,
|
||||
[0x0035, 0x10] /* <20> */, [0x0036, 0x10] /* <20> */, [0x0037, 0x10] /* <20> */,
|
||||
[0x0038, 0x10] /* <20> */, [0x0039, 0x10] /* */, [0x003A, 0x10] /* <20> */,
|
||||
[0x003B, 0x10] /* <20> */, [0x003C, 0x10] /* NBSP*/, [0x003D, 0x10] /* <20> */,
|
||||
[0x003E, 0x10] /* <20> */, [0x003F, 0x10] /* <20> */, [0x0040, 0x10] /* <20> */,
|
||||
[0x0041, 0x10] /* <20> */, [0x0042, 0x10] /* <20> */, [0x0043, 0x10] /* <20> */,
|
||||
[0x0044, 0x10] /* <20> */, [0x0045, 0x10] /* <20> */, [0x0046, 0x10] /* <20> */,
|
||||
[0x0047, 0x10] /* <20> */, [0x0048, 0x10] /* <20> */, [0x0049, 0x10] /* SHY */,
|
||||
[0x004A, 0x10] /* <20> */, [0x004B, 0x10] /* <20> */, [0x004C, 0x10] /* <20> */,
|
||||
[0x004D, 0x10] /* <20> */, [0x004E, 0x10] /* <20> */, [0x004F, 0x10] /* <20> */,
|
||||
[0x0050, 0x10] /* <20> */, [0x0051, 0x10] /* <20> */, [0x0052, 0x10] /* <20> */,
|
||||
[0x0053, 0x10] /* <20> */, [0x0054, 0x10] /* <20> */, [0x0055, 0x10] /* <20> */,
|
||||
[0x0056, 0x10] /* <20> */, [0x0057, 0x10] /* <20> */, [0x0058, 0x10] /* <20> */,
|
||||
[0x0059, 0x10] /* <20> */, [0x005A, 0x10] /* <20> */, [0x005B, 0x10] /* <20> */,
|
||||
[0x005C, 0x10] /* <20> */, [0x005D, 0x10] /* <20> */, [0x005E, 0x10] /* <20> */,
|
||||
[0x005F, 0x10] /* <20> */, [0x0060, 0x10] /* <20> */, [0x0061, 0x10] /* <20> */,
|
||||
[0x0062, 0x10] /* <20> */, [0x00AA, 0x0F] /* <20> */, [0x0063, 0x10] /* <20> */,
|
||||
[0x0064, 0x10] /* <20> */, [0x0065, 0x10] /* <20> */, [0x0066, 0x10] /* <20> */,
|
||||
[0x0067, 0x10] /* <20> */, [0x0068, 0x10] /* <20> */, [0x0069, 0x10] /* <20> */,
|
||||
[0x006A, 0x10] /* <20> */, [0x006B, 0x10] /* <20> */, [0x006C, 0x10] /* <20> */,
|
||||
[0x006D, 0x10] /* <20> */, [0x006E, 0x10] /* <20> */, [0x006F, 0x10] /* <20> */,
|
||||
[0x0070, 0x10] /* <20> */, [0x0071, 0x10] /* <20> */, [0x0072, 0x10] /* <20> */,
|
||||
[0x0073, 0x10] /* <20> */, [0x0074, 0x10] /* <20> */, [0x0075, 0x10] /* <20> */,
|
||||
[0x0076, 0x10] /* <20> */, [0x0077, 0x10] /* <20> */, [0x0078, 0x10] /* <20> */,
|
||||
[0x0079, 0x10] /* <20> */, [0x007A, 0x10] /* <20> */, [0x007B, 0x10] /* <20> */,
|
||||
[0x007C, 0x10] /* <20> */, [0x007D, 0x10] /* <20> */, [0x007E, 0x10] /* <20> */,
|
||||
[0x007F, 0x10] /* <20> */, [0x0080, 0x10] /* <20> */, [0x0081, 0x10] /* <20> */,
|
||||
[0x0082, 0x10] /* <20> */, [0x0083, 0x10] /* <20> */, [0x0084, 0x10] /* <20> */,
|
||||
[0x0085, 0x10] /* <20> */, [0x0086, 0x10] /* <20> */, [0x0087, 0x10] /* <20> */,
|
||||
[0x0088, 0x10] /* <20> */, [0x0089, 0x10] /* <20> */, [0x008A, 0x10] /* <20> */,
|
||||
[0x008B, 0x10] /* <20> */, [0x008C, 0x10] /* <20> */, [0x008D, 0x10] /* <20> */,
|
||||
[0x00AC, 0x0F] /* <20> */, [0x008E, 0x10] /* <20> */, [0x008F, 0x10] /* <20> */,
|
||||
[0x0090, 0x10] /* <20> */, [0x0091, 0x10] /* <20> */, [0x0092, 0x10] /* <20> */,
|
||||
[0x0093, 0x10] /* <20> */, [0x00AE, 0x0F] /* <20> */, [0x0094, 0x10] /* <20> */,
|
||||
[0x0095, 0x10] /* <20> */, [0x0096, 0x10] /* <20> */, [0x0097, 0x10] /* <20> */,
|
||||
[0x0098, 0x10] /* <20> */, [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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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] + "<br><br>The interpreter said:<br><pre>" + e.toString() + "</pre>";
|
||||
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<br>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<br>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<br>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<br>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))
|
||||
|
||||
@@ -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": {
|
||||
|
||||
14
zefie_wtvp_minisrv/package-lock.json
generated
14
zefie_wtvp_minisrv/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user