fix and optimize (except WTVIRC, it needs a lot of work)

This commit is contained in:
zefie
2025-08-12 17:44:26 -04:00
parent 733200c897
commit a85efc9968
22 changed files with 504 additions and 518 deletions

View File

@@ -0,0 +1,49 @@
{# Page list template for published pages #}
<HTML>
<HEAD>
<SCRIPT language="JavaScript">
var gIsWebTV = false;
var AppName = new String;
AppName = window.navigator.appName;
if (AppName.indexOf("WebTV") >= 0 )
gIsWebTV = true;
</SCRIPT>
<TITLE>{{ subscriber_name }}</TITLE>
</HEAD>
<body
background="/ROMCache/ExternalBackground.gif"
bgcolor=#1e4261
text=AEBFD1 link=B8BDC7
vlink=B8BDC7
hspace=0
vspace=0
>
<table cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=22 rowspan=100><td><td><td><td><td width=22 rowspan=100>
<tr>
<td height=12>
<tr>
<td height=25 valign=top colspan=4>
<font size=+1 color=D1D1D1>Pages of {{ subscriber_name }}</font>
<tr>
<td height=14>
<tr><td height=10>
{% for page in published_pages %}
<tr><td>
<td width=5>
<td>
<table>
<tr><td colspan=2><font color=AEBFD1><B>
<a href="{{ page.publishname }}/index.html">{{ page.title }}</a>
</B></font>
<tr>
<td width=12>
<td><font size=-1>{{ page.description }}</font>
</table>
<tr><td height=10>
<tr><td height=10>
{% endfor %}
</table>
</BODY>
</HTML>

View File

@@ -12,7 +12,7 @@ exports.createServer = (opts, handler) => {
socket.pause(); socket.pause();
// Determine if this is an HTTP(s) request // Determine if this is an HTTP(s) request
let byte = buffer[0]; const byte = buffer[0];
let protocol; let protocol;
if (byte === 22) { if (byte === 22) {
@@ -21,7 +21,7 @@ exports.createServer = (opts, handler) => {
protocol = 'http'; protocol = 'http';
} }
let proxy = server[protocol]; const proxy = server[protocol];
if (proxy) { if (proxy) {
// Push the buffer back onto the front of the data stream // Push the buffer back onto the front of the data stream
socket.unshift(buffer); socket.unshift(buffer);

View File

@@ -34,7 +34,7 @@ class LZSS {
} }
insertNode(i) { insertNode(i) {
let keyi = this.ring_buffer[i]; const keyi = this.ring_buffer[i];
let keyii = this.ring_buffer[i + 1] ^ this.ring_buffer[i + 2]; let keyii = this.ring_buffer[i + 1] ^ this.ring_buffer[i + 2];
keyii = ((keyii ^ (keyii >> 4)) & 0x0F) << 8; keyii = ((keyii ^ (keyii >> 4)) & 0x0F) << 8;
@@ -129,7 +129,7 @@ class LZSS {
this.parent[this.rchild[i]] = ii; this.parent[this.rchild[i]] = ii;
} }
this.parent[ii] = this.parent[i]; this.parent[ii] = this.parent[i];
let parent_link = this.parent[i]; const parent_link = this.parent[i];
if (this.rchild[parent_link] !== i) { if (this.rchild[parent_link] !== i) {
this.lchild[parent_link] = ii; this.lchild[parent_link] = ii;
} else { } else {

View File

@@ -4,8 +4,8 @@ const prototypes = {
return this.split("").reverse().join(""); return this.split("").reverse().join("");
}, },
toHexString: function () { toHexString: function () {
var result = ''; let result = '';
for (var i = 0; i < this.length; i++) { for (let i = 0; i < this.length; i++) {
result += this.charCodeAt(i).toString(16); result += this.charCodeAt(i).toString(16);
} }
return result; return result;
@@ -13,7 +13,7 @@ const prototypes = {
}, },
Array: { Array: {
replace: function(sub, newSub) { replace: function(sub, newSub) {
splits = this.split(sub, 2); const splits = this.split(sub, 2);
return Array.concat(splits[0], newSub, splits[1]) return Array.concat(splits[0], newSub, splits[1])
}, },
moveKey: function (from, to) { moveKey: function (from, to) {

View File

@@ -28,8 +28,8 @@ class WTVAdmin {
*/ */
constructor(minisrv_config, wtvclient, service_name) { constructor(minisrv_config, wtvclient, service_name) {
this.minisrv_config = minisrv_config; this.minisrv_config = minisrv_config;
var { WTVShared } = require("./WTVShared.js"); const { WTVShared } = require("./WTVShared.js");
var WTVRegister = require("./WTVRegister.js"); const WTVRegister = require("./WTVRegister.js");
this.wtvclient = wtvclient; this.wtvclient = wtvclient;
this.wtvshared = new WTVShared(minisrv_config); this.wtvshared = new WTVShared(minisrv_config);
this.wtvr = new WTVRegister(minisrv_config); this.wtvr = new WTVRegister(minisrv_config);
@@ -54,13 +54,14 @@ class WTVAdmin {
if (ssid == admin_ssid) { if (ssid == admin_ssid) {
return this.REASON_NOSELF; return this.REASON_NOSELF;
} else { } else {
var fake_config = this.wtvshared.getUserConfig(); const fake_config = this.wtvshared.getUserConfig();
if (!fake_config.config) fake_config.config = {}; if (!fake_config.config) fake_config.config = {};
if (!fake_config.config.ssid_block_list) fake_config.config.ssid_block_list = []; if (!fake_config.config.ssid_block_list) fake_config.config.ssid_block_list = [];
var entry_exists = false; let entry_exists = false;
var self = this; const self = this;
Object.keys(fake_config.config.ssid_block_list).forEach(function (k) { Object.keys(fake_config.config.ssid_block_list).forEach(function (k) {
if (fake_config.config.ssid_block_list[k] == ssid) { if (fake_config.config.ssid_block_list[k] == ssid) {
entry_exists = true;
return self.REASON_EXISTS; return self.REASON_EXISTS;
} }
}); });
@@ -78,8 +79,8 @@ class WTVAdmin {
* @returns {number} The result of the unban operation * @returns {number} The result of the unban operation
*/ */
unbanSSID(ssid) { unbanSSID(ssid) {
var config_changed = false; let config_changed = false;
var fake_config = this.wtvshared.getUserConfig(); const fake_config = this.wtvshared.getUserConfig();
if (!fake_config.config) fake_config.config = {}; if (!fake_config.config) fake_config.config = {};
if (!fake_config.config.ssid_block_list) fake_config.config.ssid_block_list = []; if (!fake_config.config.ssid_block_list) fake_config.config.ssid_block_list = [];
if (typeof ssid === 'string') { if (typeof ssid === 'string') {
@@ -100,8 +101,8 @@ class WTVAdmin {
}); });
} }
if (config_changed) { if (config_changed) {
wtvshared.writeToUserConfig(fake_config); this.wtvshared.writeToUserConfig(fake_config);
minisrv_config = reloadConfig(); //this.minisrv_config = reloadConfig();
return this.SUCCESS return this.SUCCESS
} else { } else {
return this.REASON_NONEXIST; return this.REASON_NONEXIST;
@@ -114,7 +115,7 @@ class WTVAdmin {
* @returns {string} The reason for rejecting the connection * @returns {string} The reason for rejecting the connection
*/ */
rejectConnection(reason_is_ssid) { rejectConnection(reason_is_ssid) {
var rejectReason; let rejectReason;
if (this.pcservices) { if (this.pcservices) {
rejectReason = this.clientAddress + " is not in the whitelist for PC Services Admin."; rejectReason = this.clientAddress + " is not in the whitelist for PC Services Admin.";
console.log(" * Request from IP (" + this.clientAddress + ") for PC Services Admin, but that IP is not authorized."); console.log(" * Request from IP (" + this.clientAddress + ") for PC Services Admin, but that IP is not authorized.");
@@ -158,12 +159,12 @@ class WTVAdmin {
* @returns {Array} An array of arrays, each containing the SSID and its associated account information * @returns {Array} An array of arrays, each containing the SSID and its associated account information
*/ */
listRegisteredSSIDs() { listRegisteredSSIDs() {
var search_dir = this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + this.path.sep + "accounts"); const search_dir = this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + this.path.sep + "accounts");
var self = this; const self = this;
var out = []; const out = [];
this.fs.readdirSync(search_dir).forEach(file => { this.fs.readdirSync(search_dir).forEach(file => {
if (self.fs.lstatSync(search_dir + self.path.sep + file).isDirectory()) { if (self.fs.lstatSync(search_dir + self.path.sep + file).isDirectory()) {
var user = self.getAccountInfoBySSID(file); const user = self.getAccountInfoBySSID(file);
out.push([file, user]); out.push([file, user]);
} }
}); });
@@ -176,19 +177,19 @@ class WTVAdmin {
* @return {boolean} True if authorized, false otherwise * @return {boolean} True if authorized, false otherwise
*/ */
isAuthorized(justchecking = false) { isAuthorized(justchecking = false) {
var allowed_ssid = false; let allowed_ssid = false;
var allowed_ip = false; let allowed_ip = false;
var use_ssid = (this.wtvclient.ssid && !this.pcservices) ? true : false const use_ssid = (this.wtvclient.ssid && !this.pcservices) ? true : false
if (use_ssid) { if (use_ssid) {
if (this.minisrv_config.services[this.service_name].authorized_ssids) { if (this.minisrv_config.services[this.service_name].authorized_ssids) {
var self = this; const self = this;
Object.keys(self.minisrv_config.services[this.service_name].authorized_ssids).forEach(function (k) { Object.keys(self.minisrv_config.services[this.service_name].authorized_ssids).forEach(function (k) {
if (typeof self.minisrv_config.services[self.service_name].authorized_ssids[k] == "string") { if (typeof self.minisrv_config.services[self.service_name].authorized_ssids[k] == "string") {
var ssid = self.minisrv_config.services[self.service_name].authorized_ssids[k] const ssid = self.minisrv_config.services[self.service_name].authorized_ssids[k]
if (ssid == self.wtvclient.ssid) allowed_ssid = true; if (ssid == self.wtvclient.ssid) allowed_ssid = true;
allowed_ip = true; // no ip block defined allowed_ip = true; // no ip block defined
} else { } else {
var ssid = k; const ssid = k;
if (ssid == self.wtvclient.ssid) { if (ssid == self.wtvclient.ssid) {
allowed_ssid = true; allowed_ssid = true;
Object.keys(self.minisrv_config.services[self.service_name].authorized_ssids[k]).forEach(function (j) { Object.keys(self.minisrv_config.services[self.service_name].authorized_ssids[k]).forEach(function (j) {
@@ -209,7 +210,7 @@ class WTVAdmin {
} }
if (this.minisrv_config.config.pc_admin.ip_whitelist) { if (this.minisrv_config.config.pc_admin.ip_whitelist) {
var self = this; const self = this;
Object.keys(this.minisrv_config.config.pc_admin.ip_whitelist).forEach(function (k) { Object.keys(this.minisrv_config.config.pc_admin.ip_whitelist).forEach(function (k) {
if (allowed_ip) return; if (allowed_ip) return;
allowed_ip = self.wtvshared.isInSubnet(self.clientAddress, self.minisrv_config.config.pc_admin.ip_whitelist[k]); allowed_ip = self.wtvshared.isInSubnet(self.clientAddress, self.minisrv_config.config.pc_admin.ip_whitelist[k]);
@@ -232,9 +233,9 @@ class WTVAdmin {
* @returns {Object|null} An object containing account information if the username is found, null otherwise * @returns {Object|null} An object containing account information if the username is found, null otherwise
*/ */
getAccountInfo(username, directory = null) { getAccountInfo(username, directory = null) {
var search_dir = this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + this.path.sep + "accounts"); let search_dir = this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + this.path.sep + "accounts");
var account_data = null; let account_data = null;
var self = this; const self = this;
if (directory) search_dir = directory; if (directory) search_dir = directory;
this.fs.readdirSync(search_dir).forEach(file => { this.fs.readdirSync(search_dir).forEach(file => {
if (self.fs.lstatSync(search_dir + self.path.sep + file).isDirectory() && account_data === null) { if (self.fs.lstatSync(search_dir + self.path.sep + file).isDirectory() && account_data === null) {
@@ -243,8 +244,8 @@ class WTVAdmin {
if (account_data !== null) return; if (account_data !== null) return;
if (!file.match(/.*\.json/ig)) return; if (!file.match(/.*\.json/ig)) return;
try { try {
var temp_session_data_file = self.fs.readFileSync(search_dir + self.path.sep + file, 'Utf8'); const temp_session_data_file = self.fs.readFileSync(search_dir + self.path.sep + file, 'Utf8');
var temp_session_data = JSON.parse(temp_session_data_file); const temp_session_data = JSON.parse(temp_session_data_file);
if (temp_session_data.subscriber_username.toLowerCase() == username.toLowerCase()) { if (temp_session_data.subscriber_username.toLowerCase() == username.toLowerCase()) {
account_data = [temp_session_data, (search_dir + self.path.sep + file).replace(this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + this.path.sep + "accounts"), "").split(this.path.sep)[1]]; account_data = [temp_session_data, (search_dir + self.path.sep + file).replace(this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + this.path.sep + "accounts"), "").split(this.path.sep)[1]];
@@ -255,11 +256,11 @@ class WTVAdmin {
}); });
if (account_data !== null) { if (account_data !== null) {
if (account_data.ssid) return account_data; if (account_data.ssid) return account_data;
var account_info = {}; const account_info = {};
account_info.ssid = account_data[1]; account_info.ssid = account_data[1];
account_info.username = account_data[0].subscriber_username; account_info.username = account_data[0].subscriber_username;
account_info.user_id = account_data[0].subscriber_userid; account_info.user_id = account_data[0].subscriber_userid;
var userSession = new this.WTVClientSessionData(this.minisrv_config, account_info.ssid); const userSession = new this.WTVClientSessionData(this.minisrv_config, account_info.ssid);
userSession.user_id = 0; userSession.user_id = 0;
account_info.account_users = userSession.listPrimaryAccountUsers(); account_info.account_users = userSession.listPrimaryAccountUsers();
return account_info; return account_info;
@@ -273,8 +274,8 @@ class WTVAdmin {
* @returns {Object|boolean} An object containing account information if the SSID is registered, false otherwise * @returns {Object|boolean} An object containing account information if the SSID is registered, false otherwise
*/ */
getAccountInfoBySSID(ssid) { getAccountInfoBySSID(ssid) {
var account_info = {}; const account_info = {};
var userSession = new this.WTVClientSessionData(this.minisrv_config, ssid); const userSession = new this.WTVClientSessionData(this.minisrv_config, ssid);
userSession.user_id = 0; userSession.user_id = 0;
if (userSession.isRegistered(false)) { if (userSession.isRegistered(false)) {
account_info.ssid = ssid; account_info.ssid = ssid;
@@ -301,7 +302,7 @@ class WTVAdmin {
* @returns {WTVClientSessionData} The session data object for the account * @returns {WTVClientSessionData} The session data object for the account
*/ */
getAccountBySSID(ssid) { getAccountBySSID(ssid) {
var userSession = new this.WTVClientSessionData(this.minisrv_config, ssid); const userSession = new this.WTVClientSessionData(this.minisrv_config, ssid);
userSession.user_id = 0; userSession.user_id = 0;
return userSession; return userSession;
} }
@@ -312,8 +313,8 @@ class WTVAdmin {
* @returns {boolean} True if the SSID is banned, false otherwise * @returns {boolean} True if the SSID is banned, false otherwise
*/ */
isBanned(ssid) { isBanned(ssid) {
var self = this; const self = this;
var isBanned = false; let isBanned = false;
if (this.minisrv_config.config.ssid_block_list) { if (this.minisrv_config.config.ssid_block_list) {
Object.keys(this.minisrv_config.config.ssid_block_list).forEach(function (k) { Object.keys(this.minisrv_config.config.ssid_block_list).forEach(function (k) {
if (self.minisrv_config.config.ssid_block_list[k] == ssid) { if (self.minisrv_config.config.ssid_block_list[k] == ssid) {

View File

@@ -60,9 +60,9 @@ class WTVAuthor {
pagestoreExists() { pagestoreExists() {
if (this.pagestore_dir === null) { if (this.pagestore_dir === null) {
// set pagestore directory local var so we don't call the function every time // set pagestore directory local var so we don't call the function every time
var userstore_dir = this.wtvclient.getUserStoreDirectory(); const userstore_dir = this.wtvclient.getUserStoreDirectory();
// PageStore // PageStore
var store_dir = "PageStore" + this.path.sep; const store_dir = "PageStore" + this.path.sep;
this.pagestore_dir = userstore_dir + store_dir; this.pagestore_dir = userstore_dir + store_dir;
} }
return this.fs.existsSync(this.pagestore_dir); return this.fs.existsSync(this.pagestore_dir);
@@ -79,66 +79,68 @@ class WTVAuthor {
} }
createPage(style) { createPage(style) {
this.pagestoreExists() this.pagestoreExists()
var pagestorepath = this.pagestore_dir; let pagenum = 0;
// All this shit is to work around the part where I don't use UUIDs to store pages, which is bad let pagefile = null;
var pages = this.fs.readdirSync(pagestorepath) const pagestorepath = this.pagestore_dir;
if (pages.length == 0) { // All this shit is to work around the part where I don't use UUIDs to store pages, which is bad
pagenum = 0; const pages = this.fs.readdirSync(pagestorepath)
} else { if (pages.length === 0) {
var pagelen = pages.length; pagenum = 0;
if (pagelen < 0) pagelen = 0; } else {
this.debug("createPage","pages",pages) let pagelen = pages.length;
var pagenums = []; if (pagelen < 0) pagelen = 0;
for(let i = 0; i < pagelen; i++) { this.debug("createPage","pages",pages)
var toarr = pages[i].slice(0, pages[i].indexOf('.')); let pagenums = [];
pagenums.push(parseInt(toarr)); for(let i = 0; i < pagelen; i++) {
} const toarr = pages[i].slice(0, pages[i].indexOf('.'));
pagenums = pagenums.sort() pagenums.push(parseInt(toarr));
this.debug("createPage", "pagenums", pagenums)
var pagenum = parseInt(pagenums[pagelen - 1]);
this.debug("createPage", "pagenum", pagenum)
this.debug("createPage", "pagelen", pagelen)
} }
if (pages.length == 0) { pagenums = pagenums.sort()
pagenum = 0 this.debug("createPage", "pagenums", pagenums)
var pagefile = pagenum + this.pageFileExt; const pagenum = parseInt(pagenums[pagelen - 1]);
} else { this.debug("createPage", "pagenum", pagenum)
var pagefile = (pagenum + 1) + this.pageFileExt; this.debug("createPage", "pagelen", pagelen)
} }
var pagefileout = this.pagestore_dir + pagefile; if (pages.length == 0) {
// JSON data structure pagenum = 0
var pagedata = { pagefile = pagenum + this.pageFileExt;
"style": style, } else {
"title": "(Untitled)", pagefile = (pagenum + 1) + this.pageFileExt;
"description": "(no description)", }
"pagebreaks": [], const pagefileout = this.pagestore_dir + pagefile;
"showtitle": true, // JSON data structure
"inlist": true, const pagedata = {
"published": false, "style": style,
"publishdate": null, "title": "(Untitled)",
"publishname": null, "description": "(no description)",
"blocks": [] "pagebreaks": [],
} "showtitle": true,
if (this.fs.existsSync(pagefileout)) { "inlist": true,
console.error(" * ERROR: Page already exists (should never happen). Page lost."); "published": false,
return false; "publishdate": null,
} "publishname": null,
"blocks": []
}
if (this.fs.existsSync(pagefileout)) {
console.error(" * ERROR: Page already exists (should never happen). Page lost.");
return false;
}
// Encode page data into JSON // Encode page data into JSON
var returnval = pages.length let returnval = pages.length
var result = this.fs.writeFileSync(pagefileout, JSON.stringify(pagedata)); this.fs.writeFileSync(pagefileout, JSON.stringify(pagedata));
if (returnval != 0) { if (returnval != 0) {
var npages = this.fs.readdirSync(pagestorepath) const npages = this.fs.readdirSync(pagestorepath)
var returnval = npages.length - 1; returnval = npages.length - 1;
} }
return returnval; return returnval;
} }
loadPage(pagenum) { loadPage(pagenum) {
this.pagestoreExists() this.pagestoreExists()
var page_file = this.listPages(); const page_file = this.listPages();
var page_data_raw = page_file[pagenum]; const page_data_raw = page_file[pagenum];
if (page_data_raw) { if (page_data_raw) {
return page_data_raw; return page_data_raw;
@@ -149,13 +151,13 @@ class WTVAuthor {
setStyle(style, title, desc, state, docName) { setStyle(style, title, desc, state, docName) {
// There's probably a better way to do this involving external files for each style, but no // There's probably a better way to do this involving external files for each style, but no
this.debug("setStyle", "this.wtvshared.makeSafeStringPath(style) (before load)", this.wtvshared.makeSafeStringPath(style)); this.debug("setStyle", "this.wtvshared.makeSafeStringPath(style) (before load)", this.wtvshared.makeSafeStringPath(style));
var template_data_file = this.wtvshared.getTemplate("wtv-author", "styles/" + this.wtvshared.makeSafeStringPath(style) + ".js", true); const template_data_file = this.wtvshared.getTemplate("wtv-author", "styles/" + this.wtvshared.makeSafeStringPath(style) + ".js", true);
if (template_data_file) { if (template_data_file) {
this.debug("setStyle", "template_data_file", template_data_file); this.debug("setStyle", "template_data_file", template_data_file);
const PBTemplate = require(template_data_file); const PBTemplate = require(template_data_file);
var pbtemplate = new PBTemplate(this, title, desc, state, docName); const pbtemplate = new PBTemplate(this, title, desc, state, docName);
var template_data = pbtemplate.get(); const template_data = pbtemplate.get();
var self = this; const self = this;
Object.keys(template_data).forEach((k) => { Object.keys(template_data).forEach((k) => {
self[k] = template_data[k]; self[k] = template_data[k];
}) })
@@ -291,8 +293,8 @@ class WTVAuthor {
} }
generatePage(state, pagenum, page) { generatePage(state, pagenum, page) {
var pagedata = this.loadPage(pagenum); const pagedata = this.loadPage(pagenum);
var title let title;
// Should probably have a better way to know if the page has no title // Should probably have a better way to know if the page has no title
if (pagedata.title == "(Untitled)" && state == "editing") if (pagedata.title == "(Untitled)" && state == "editing")
title = "<i>Choose this to add a title to your document</i>" title = "<i>Choose this to add a title to your document</i>"
@@ -300,7 +302,7 @@ class WTVAuthor {
title = pagedata.title title = pagedata.title
// Set the page style with too many paramaters // Set the page style with too many paramaters
this.setStyle(pagedata.style, title, pagedata.description, state, pagenum); this.setStyle(pagedata.style, title, pagedata.description, state, pagenum);
var html = this.header let html = this.header
if (page == 1) { if (page == 1) {
if (pagedata.showtitle == true){ if (pagedata.showtitle == true){
html += this.titheader html += this.titheader
@@ -310,12 +312,10 @@ class WTVAuthor {
// This generates blocks on separate pages in the most neat and optimized way possible (i think, i hate past jar) // This generates blocks on separate pages in the most neat and optimized way possible (i think, i hate past jar)
if (page != 1) { if (page != 1) {
for (let i = pagedata.pagebreaks[page - 2]; i < (pagedata.pagebreaks[page - 1] || pagedata.blocks.length); i++) { for (let i = pagedata.pagebreaks[page - 2]; i < (pagedata.pagebreaks[page - 1] || pagedata.blocks.length); i++) {
var type = pagedata.blocks[i].type
html += this.generateBlock(i, pagenum, state) html += this.generateBlock(i, pagenum, state)
} }
} else if (pagedata.pagebreaks.length != 0){ } else if (pagedata.pagebreaks.length != 0){
for (let i = 0; i < pagedata.pagebreaks[0]; i++) { for (let i = 0; i < pagedata.pagebreaks[0]; i++) {
var type = pagedata.blocks[i].type
html += this.generateBlock(i, pagenum, state) html += this.generateBlock(i, pagenum, state)
if (this.afterblock1 && i == 0) { if (this.afterblock1 && i == 0) {
html += this.afterblock1 html += this.afterblock1
@@ -323,7 +323,6 @@ class WTVAuthor {
} }
} else { } else {
for (let i = 0; i < pagedata.blocks.length; i++) { for (let i = 0; i < pagedata.blocks.length; i++) {
var type = pagedata.blocks[i].type
html += this.generateBlock(i, pagenum, state) html += this.generateBlock(i, pagenum, state)
if (this.afterblock1 && i == 0) { if (this.afterblock1 && i == 0) {
html += this.afterblock1 html += this.afterblock1
@@ -334,18 +333,18 @@ class WTVAuthor {
// Add the footer if we're not in edit mode // Add the footer if we're not in edit mode
html += this.getPaginationFooter(state, pagedata, page, pagenum) html += this.getPaginationFooter(state, pagedata, page, pagenum)
html += this.footerend html += this.footerend
return html; return html;
} }
editPage(pagedata, pagenum, callPublish = true) { editPage(pagedata, pagenum, callPublish = true) {
// just stolen from favorites lmao // just stolen from favorites lmao
var pageout = new Object(); const pageout = new Object();
var pagepath = this.pagestore_dir; const pagepath = this.pagestore_dir;
Object.assign(pageout, pagedata); Object.assign(pageout, pagedata);
var pagestorepath = this.pagestore_dir; const pagestorepath = this.pagestore_dir;
var pages = this.fs.readdirSync(pagestorepath) const pages = this.fs.readdirSync(pagestorepath)
var page = pages[pagenum] const page = pages[pagenum]
var result = this.fs.writeFileSync(pagepath + page, JSON.stringify(pageout)); const result = this.fs.writeFileSync(pagepath + page, JSON.stringify(pageout));
if (pagedata.published == true && callPublish) { if (pagedata.published == true && callPublish) {
this.publishPage(pagenum, pagedata.inlist, false) this.publishPage(pagenum, pagedata.inlist, false)
} }
@@ -353,44 +352,39 @@ class WTVAuthor {
} }
editMetadata(title, description, showtitle, pagenum) { editMetadata(title, description, showtitle, pagenum) {
var pagedata = this.loadPage(pagenum); const pagedata = this.loadPage(pagenum);
if (!pagedata) return false; if (!pagedata) return false;
if (showtitle == "true") pagedata.title = title;
var showtitle2 = false pagedata.description = description;
else pagedata.showtitle = !showtitle;
var showtitle2 = true
pagedata.title = title
pagedata.description = description
pagedata.showtitle = showtitle2
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
return true; return true;
} }
listPages() { listPages() {
// i don't remember why, but i'm pretty sure this function sucks // i don't remember why, but i'm pretty sure this function sucks
var pagestore = this.pagestoreExists(); const pagestore = this.pagestoreExists();
if (!pagestore) this.createPagestore(); if (!pagestore) this.createPagestore();
var userstore_dir = this.wtvclient.getUserStoreDirectory(); const userstore_dir = this.wtvclient.getUserStoreDirectory();
// PageStore // PageStore
var store_dir = "PageStore" + this.path.sep; const store_dir = "PageStore" + this.path.sep;
this.pagestore_dir = userstore_dir + store_dir; this.pagestore_dir = userstore_dir + store_dir;
var pagestorepath = this.pagestore_dir; const pagestorepath = this.pagestore_dir;
var self = this; const self = this;
self.pageArr = []; self.pageArr = [];
if (self.fs.existsSync(pagestorepath)) { if (self.fs.existsSync(pagestorepath)) {
var files = this.fs.readdirSync(pagestorepath) const files = this.fs.readdirSync(pagestorepath)
this.debug("listPages","files",files) this.debug("listPages","files",files)
files.map(function (v) { files.map(function (v) {
if (v.endsWith(self.pageFileExt)) { if (v.endsWith(self.pageFileExt)) {
// oh yeah it's because any non-JSON file in pagestore will throw an error and break everything // oh yeah it's because any non-JSON file in pagestore will throw an error and break everything
var page_data_raw = null; let page_data_raw = null;
var pagepath = pagestorepath + self.path.sep + v; const pagepath = pagestorepath + self.path.sep + v;
if (self.fs.existsSync(pagepath)) page_data_raw = self.fs.readFileSync(pagepath); if (self.fs.existsSync(pagepath)) page_data_raw = self.fs.readFileSync(pagepath);
if (page_data_raw) { if (page_data_raw) {
var page_data = JSON.parse(page_data_raw); const page_data = JSON.parse(page_data_raw);
self.pageArr.push(page_data); self.pageArr.push(page_data);
} }
} }
@@ -400,12 +394,12 @@ class WTVAuthor {
} }
deleteBlock(pagenum, position) { deleteBlock(pagenum, position) {
var pagedata = this.loadPage(pagenum); const pagedata = this.loadPage(pagenum);
if (!pagedata) return false; if (!pagedata) return false;
var block = pagedata.blocks[position] const block = pagedata.blocks[position];
var blocks = pagedata.blocks const blocks = pagedata.blocks;
blocks.splice(position, 1); blocks.splice(position, 1);
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
if (block.type == "break") if (block.type == "break")
@@ -418,7 +412,7 @@ class WTVAuthor {
return this.minisrv_config.services['wtv-author'].public_domain; return this.minisrv_config.services['wtv-author'].public_domain;
} else { } else {
if (this.minisrv_config.services['wtv-author'].publish_mode == "service") { if (this.minisrv_config.services['wtv-author'].publish_mode == "service") {
var target_service = this.minisrv_config.services[this.minisrv_config.services['wtv-author'].publish_dest]; const target_service = this.minisrv_config.services[this.minisrv_config.services['wtv-author'].publish_dest];
if (target_service) { if (target_service) {
return target_service.host + ":" + target_service.port; return target_service.host + ":" + target_service.port;
} }
@@ -437,9 +431,9 @@ class WTVAuthor {
} }
getPublishDir() { getPublishDir() {
var destDir = false; let destDir = false;
if (this.minisrv_config.services['wtv-author'].publish_mode == "service") { if (this.minisrv_config.services['wtv-author'].publish_mode == "service") {
var target_service = this.minisrv_config.services[this.minisrv_config.services['wtv-author'].publish_dest]; const target_service = this.minisrv_config.services[this.minisrv_config.services['wtv-author'].publish_dest];
if (target_service) { if (target_service) {
if (!target_service.pc_services) { if (!target_service.pc_services) {
console.error("Invalid service configuration: publish_dest is not a pc service."); console.error("Invalid service configuration: publish_dest is not a pc service.");
@@ -451,7 +445,7 @@ class WTVAuthor {
if (target_service.service_vaults) { if (target_service.service_vaults) {
destDir = target_service.service_vaults[0] + this.path.sep + target_service.servicevault_dir + this.path.sep; destDir = target_service.service_vaults[0] + this.path.sep + target_service.servicevault_dir + this.path.sep;
} else { } else {
destDir = minisrv_config.config.ServiceVaults[0] + this.path.sep + target_service.servicevault_dir + this.path.sep; destDir = this.minisrv_config.config.ServiceVaults[0] + this.path.sep + target_service.servicevault_dir + this.path.sep;
} }
} }
} else if (this.minisrv_config.services['wtv-author'].publish_mode == "directory") { } else if (this.minisrv_config.services['wtv-author'].publish_mode == "directory") {
@@ -465,12 +459,12 @@ class WTVAuthor {
unpublishPage(pagenum) { unpublishPage(pagenum) {
var pagedata = this.loadPage(pagenum) const pagedata = this.loadPage(pagenum)
var destDir = this.getPublishDir(); const destDir = this.getPublishDir();
if (pagedata.published != true) { if (pagedata.published != true) {
return "This page is not published." return "This page is not published."
} }
var publishname = pagedata.publishname; const publishname = pagedata.publishname;
if (this.fs.existsSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname)) { if (this.fs.existsSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname)) {
try { try {
this.fs.rmSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname, { recursive: true }) this.fs.rmSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname, { recursive: true })
@@ -491,9 +485,9 @@ class WTVAuthor {
publishPage(pagenum, listpublicly) { publishPage(pagenum, listpublicly) {
// this was done in a rush and probably also sucks // this was done in a rush and probably also sucks
// remember to increment the "hours wasted here" comment at the top of the file // remember to increment the "hours wasted here" comment at the top of the file
var pagedata = this.loadPage(pagenum) const pagedata = this.loadPage(pagenum)
var destDir = this.getPublishDir(); const destDir = this.getPublishDir();
var publishname = null; let publishname, fileout;
if (pagedata.published != true) { if (pagedata.published != true) {
publishname = pagedata.title.slice(0, 50).replaceAll(" ", "").replace(/[^A-Za-z0-9]/g, "-"); publishname = pagedata.title.slice(0, 50).replaceAll(" ", "").replace(/[^A-Za-z0-9]/g, "-");
@@ -510,11 +504,11 @@ class WTVAuthor {
this.fs.mkdirSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname + "/clipart/styleMedia/", { recursive: true }) this.fs.mkdirSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname + "/clipart/styleMedia/", { recursive: true })
this.fs.mkdirSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname + "/media/", { recursive: true }) this.fs.mkdirSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname + "/media/", { recursive: true })
for (let i = 1; i < pagedata.pagebreaks.length + 2; i++) { for (let i = 1; i < pagedata.pagebreaks.length + 2; i++) {
var pagehtml = this.generatePage("publishing", pagenum, i) const pagehtml = this.generatePage("publishing", pagenum, i)
if (i == 1) if (i == 1)
var fileout = "index.html" fileout = "index.html"
else else
var fileout = "page" + i + ".html" fileout = "page" + i + ".html"
this.fs.writeFile(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname + '/' + fileout, pagehtml, err => { this.fs.writeFile(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname + '/' + fileout, pagehtml, err => {
if (err) { if (err) {
console.error(err); console.error(err);
@@ -528,7 +522,7 @@ class WTVAuthor {
if (err) throw err; if (err) throw err;
}); });
} }
var strftime = require('strftime'); const strftime = require('strftime');
pagedata.publishdate = strftime("%a, %b %d, %Y, %I:%M%P", new Date(new Date().toUTCString())) pagedata.publishdate = strftime("%a, %b %d, %Y, %I:%M%P", new Date(new Date().toUTCString()))
pagedata.published = true; pagedata.published = true;
pagedata.inlist = listpublicly; pagedata.inlist = listpublicly;
@@ -540,66 +534,24 @@ class WTVAuthor {
generatePageList() { generatePageList() {
// this one's pretty ok i think, but it should have screenshots of each page // this one's pretty ok i think, but it should have screenshots of each page
const pagelist = this.listPages() const pagelist = this.listPages();
let html = `<HTML>
<HEAD> // Filter published pages that should be listed
<SCRIPT language="JavaScript"> const publishedPages = pagelist.filter(page => page.published === true && page.inlist === true);
var gIsWebTV = false;
var AppName = new String; const templatePath = this.wtvshared.getServiceDep('wtv-author/page_list.njk', true);
AppName = window.navigator.appName; this.nunjucks.configure({ autoescape: false });
if (AppName.indexOf("WebTV") >= 0 )
gIsWebTV = true; const html = this.nunjucks.render(templatePath, {
</SCRIPT> subscriber_name: this.wtvclient.session_store.subscriber_name,
<TITLE>${this.wtvclient.session_store.subscriber_name}</TITLE> published_pages: publishedPages
</HEAD> });
<body
background="/ROMCache/ExternalBackground.gif"
bgcolor=#1e4261
text=AEBFD1 link=B8BDC7
vlink=B8BDC7
hspace=0
vspace=0
>
<table cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=22 rowspan=100><td><td><td><td><td width=22 rowspan=100>
<tr>
<td height=12>
<tr>
<td height=25 valign=top colspan=4>
<font size=+1 color=D1D1D1>Pages of ${this.wtvclient.session_store.subscriber_name}</font>
<tr>
<td height=14>
<tr><td height=10>`;
loop:
for (let i = 0; i < pagelist.length; i++) {
if (pagelist[i].published == true && pagelist[i].inlist == true) {
html += `<tr><td>
<td width=5>
<td>
<table>
<tr><td colspan=2><font color=AEBFD1><B>
<a href=${pagelist[i].publishname}/index.html>${pagelist[i].title}</a>
</B></font>
<tr>
<td width=12>
<td><font size=-1>${pagelist[i].description}</font>
</table>
<tr><td height=10>
<tr><td height=10>`
} else {
continue loop;
}
}
html += `</table>
</BODY>
</HTML>`
this.fs.writeFile(this.getPublishDir() + this.wtvclient.session_store.subscriber_username + '/index.html', html, err => { this.fs.writeFile(this.getPublishDir() + this.wtvclient.session_store.subscriber_username + '/index.html', html, err => {
if (err) { if (err) {
console.error(err); console.error(err);
} }
// file written successfully // file written successfully
}); });
} }
@@ -628,7 +580,7 @@ vspace=0
for (let i = 0; i < pagelist.length; i++) { for (let i = 0; i < pagelist.length; i++) {
this.deletePage(i); this.deletePage(i);
} }
const userstore_dir = otherUser.getUserStoreDirectory(); const userstore_dir = this.wtvclient.getUserStoreDirectory();
const store_dir = "PageStore" + this.path.sep; const store_dir = "PageStore" + this.path.sep;
this.pagestore_dir = userstore_dir + store_dir; this.pagestore_dir = userstore_dir + store_dir;
this.wtvclient.switchUserID(0, false, false, false); this.wtvclient.switchUserID(0, false, false, false);
@@ -663,7 +615,7 @@ vspace=0
pagedata.blocks[oldposition].style = style pagedata.blocks[oldposition].style = style
if (oldposition != position) if (oldposition != position)
moveArrayKey(pagedata.blocks,oldposition,position); this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position);
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
return true; return true;
@@ -710,7 +662,7 @@ vspace=0
blocks[oldposition].caption = caption blocks[oldposition].caption = caption
if (oldposition != position) { if (oldposition != position) {
moveArrayKey(blocks, oldposition,position); this.wtvshared.moveObjectKey(blocks, oldposition,position);
} }
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
@@ -746,7 +698,7 @@ vspace=0
pagedata.blocks[oldposition].dividerAfter = dividerAfter pagedata.blocks[oldposition].dividerAfter = dividerAfter
if (oldposition != position) if (oldposition != position)
moveArrayKey(pagedata.blocks, oldposition,position); this.wtvshared.moveObjectKey(pagedata.blocks, oldposition,position);
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
return true; return true;
@@ -777,7 +729,7 @@ vspace=0
pagedata.blocks[oldposition].items = items pagedata.blocks[oldposition].items = items
if (oldposition != position) if (oldposition != position)
moveArrayKey(pagedata.blocks,oldposition,position); this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position);
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
return true; return true;
@@ -842,7 +794,7 @@ vspace=0
pagedata.blocks[oldposition].items = items pagedata.blocks[oldposition].items = items
if (oldposition != position) if (oldposition != position)
moveArrayKey(pagedata.blocks,oldposition,position); this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position);
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
return true; return true;
@@ -868,7 +820,7 @@ vspace=0
if (!pagedata) return false; if (!pagedata) return false;
if (oldposition != position) if (oldposition != position)
moveArrayKey(pagedata.blocks,oldposition,position); this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position);
this.editPage(pagedata, pagenum); this.editPage(pagedata, pagenum);
this.generateBreakList(pagenum); this.generateBreakList(pagenum);

View File

@@ -1246,18 +1246,18 @@ class WTVBGMusic {
constructor(minisrv_config, session_data) { constructor(minisrv_config, session_data) {
if (!minisrv_config) throw ("minisrv_config required"); if (!minisrv_config) throw ("minisrv_config required");
if (!session_data) throw ("WTVClientSessionData required"); if (!session_data) throw ("WTVClientSessionData required");
var WTVShared = require("./WTVShared.js")['WTVShared']; const WTVShared = require("./WTVShared.js")['WTVShared'];
this.minisrv_config = minisrv_config; this.minisrv_config = minisrv_config;
this.session_data = session_data; this.session_data = session_data;
this.wtvshared = new WTVShared(minisrv_config); this.wtvshared = new WTVShared(minisrv_config);
} }
getMusicObj(force_default = false) { getMusicObj(force_default = false) {
var music_obj = this.session_data.getSessionData("wtv-bgmusic"); let music_obj = this.session_data.getSessionData("wtv-bgmusic");
if (music_obj === null) music_obj = {}; if (music_obj === null) music_obj = {};
// check if we need to set defaults // check if we need to set defaults
var setDefaults = force_default; let setDefaults = force_default;
if (!music_obj.enableCategories) setDefaults = true; if (!music_obj.enableCategories) setDefaults = true;
else if (music_obj.enableCategories.length == 0) setDefaults = true; else if (music_obj.enableCategories.length == 0) setDefaults = true;
if (!music_obj.enableSongs) setDefaults = true; if (!music_obj.enableSongs) setDefaults = true;
@@ -1317,12 +1317,13 @@ class WTVBGMusic {
} }
getSong(songid) { getSong(songid) {
let musiclist;
if (this.session_data.hasCap("client-can-do-rmf")) { if (this.session_data.hasCap("client-can-do-rmf")) {
// use rmf list // use rmf list
var musiclist = this.musiclist_rmf; musiclist = this.musiclist_rmf;
} else { } else {
// use classic list // use classic list
var musiclist = this.musiclist_classic; musiclist = this.musiclist_classic;
} }
if (musiclist[songid]) return musiclist[songid]; if (musiclist[songid]) return musiclist[songid];
return null; return null;
@@ -1341,14 +1342,15 @@ class WTVBGMusic {
getCategorySongList(category) { getCategorySongList(category) {
let musiclist;
if (this.session_data.hasCap("client-can-do-rmf")) { if (this.session_data.hasCap("client-can-do-rmf")) {
// use rmf list // use rmf list
var musiclist = this.musiclist_rmf; musiclist = this.musiclist_rmf;
} else { } else {
// use classic list // use classic list
var musiclist = this.musiclist_classic; musiclist = this.musiclist_classic;
} }
var songList = []; const songList = [];
Object.keys(musiclist).forEach(function (k) { Object.keys(musiclist).forEach(function (k) {
musiclist[k].id = k; musiclist[k].id = k;
if (String(category).length === 1) { if (String(category).length === 1) {
@@ -1363,10 +1365,10 @@ class WTVBGMusic {
} }
getCategoryList() { getCategoryList() {
var enabledCategories = []; const enabledCategories = [];
var self = this; const self = this;
Object.keys(self.categories).forEach(function (k) { Object.keys(self.categories).forEach(function (k) {
var songList = self.getCategorySongList(parseInt(k) + 1); const songList = self.getCategorySongList(parseInt(k) + 1);
if (songList.length > 0) enabledCategories.push({ if (songList.length > 0) enabledCategories.push({
"id": parseInt(k) + 1, "name": self.categories[k] "id": parseInt(k) + 1, "name": self.categories[k]
}); });
@@ -1380,8 +1382,8 @@ class WTVBGMusic {
} }
isCategoryEnabled(category) { isCategoryEnabled(category) {
var music_obj = this.getMusicObj(); const music_obj = this.getMusicObj();
var enabled = false; let enabled = false;
music_obj.enableCategories.forEach(function (v) { music_obj.enableCategories.forEach(function (v) {
if (parseInt(v) == parseInt(category)) { if (parseInt(v) == parseInt(category)) {
enabled = true; enabled = true;
@@ -1391,13 +1393,13 @@ class WTVBGMusic {
} }
isSongEnabled(song, checkCat = false) { isSongEnabled(song, checkCat = false) {
var music_obj = this.getMusicObj(); const music_obj = this.getMusicObj();
var enabled = false; let enabled = false;
music_obj.enableSongs.forEach(function (v) { music_obj.enableSongs.forEach(function (v) {
if (parseInt(v) == parseInt(song)) { if (parseInt(v) == parseInt(song)) {
if (checkCat) { if (checkCat) {
songCategory = getSongCategory(song); const songCategory = this.getSongCategory(song);
if (isCategoryEnabled(songCategory)) { if (this.isCategoryEnabled(songCategory)) {
enabled = true; enabled = true;
} }
} else { } else {

View File

@@ -20,7 +20,7 @@ class WTVClientCapabilities {
// (this script does not do that, also note that LC2 MiniBrowser does not support client:relog) // (this script does not do that, also note that LC2 MiniBrowser does not support client:relog)
// None of this is 100% for certain yet (except the bitfield stuff), do not trust as verbatim, more testing needed // None of this is 100% for certain yet (except the bitfield stuff), do not trust as verbatim, more testing needed
var capabilities_table = [ const capabilities_table = [
["client-can-do-muzac", "Can Do Muzac"], ["client-can-do-muzac", "Can Do Muzac"],
["client-can-do-chat", "Can Chat"], ["client-can-do-chat", "Can Chat"],
["client-can-do-openISP", "Can do OpenISP"], ["client-can-do-openISP", "Can do OpenISP"],
@@ -97,7 +97,7 @@ class WTVClientCapabilities {
let remainingSize = hex.length; let remainingSize = hex.length;
for (let p = 0; p < hex.length / 8; p++) { for (let p = 0; p < hex.length / 8; p++) {
//In case remaining hex length (or initial) is not multiple of 8 //In case remaining hex length (or initial) is not multiple of 8
let blockSize = remainingSize < 8 ? remainingSize : 8; const blockSize = remainingSize < 8 ? remainingSize : 8;
binary += parseInt(hex.slice(p * 8, p * 8 + blockSize), 16).toString(2); binary += parseInt(hex.slice(p * 8, p * 8 + blockSize), 16).toString(2);

View File

@@ -158,7 +158,7 @@ class WTVClientSessionData {
findFreeUserSlot() { findFreeUserSlot() {
if (this.user_id != 0) return false; // subscriber only command if (this.user_id != 0) return false; // subscriber only command
let master_directory = this.getUserStoreDirectory(true); const master_directory = this.getUserStoreDirectory(true);
if (this.fs.existsSync(master_directory)) { if (this.fs.existsSync(master_directory)) {
for (let i = 0; i < this.minisrv_config.config.user_accounts.max_users_per_account; i++) { for (let i = 0; i < this.minisrv_config.config.user_accounts.max_users_per_account; i++) {
const test_dir = master_directory + this.path.sep + "user" + i; const test_dir = master_directory + this.path.sep + "user" + i;
@@ -184,7 +184,7 @@ class WTVClientSessionData {
if (this.user_id != 0) return false; // subscriber only command if (this.user_id != 0) return false; // subscriber only command
const master_directory = this.getUserStoreDirectory(true); const master_directory = this.getUserStoreDirectory(true);
let account_data = []; const account_data = [];
const self = this; const self = this;
this.fs.readdirSync(master_directory).forEach(f => { this.fs.readdirSync(master_directory).forEach(f => {
if (self.fs.lstatSync(master_directory + self.path.sep + f).isDirectory()) { if (self.fs.lstatSync(master_directory + self.path.sep + f).isDirectory()) {
@@ -339,7 +339,7 @@ class WTVClientSessionData {
if (!file_exists || (file_exists && overwrite)) result = this.fs.writeFileSync(store_full_path, data); if (!file_exists || (file_exists && overwrite)) result = this.fs.writeFileSync(store_full_path, data);
if (result !== false && last_modified) { if (result !== false && last_modified) {
const file_timestamp = new Date(last_modified * 1000); const file_timestamp = new Date(last_modified * 1000);
fs.utimesSync(store_full_path, Date.now(), file_timestamp) this.fs.utimesSync(store_full_path, Date.now(), file_timestamp)
} }
} catch (e) { } catch (e) {
console.error(" # User File Store failed", e); console.error(" # User File Store failed", e);
@@ -408,7 +408,7 @@ class WTVClientSessionData {
this.createScrapbook(); this.createScrapbook();
} }
let total_size = 0; let total_size = 0;
let files = this.fs.readdirSync(this.scrapbook_dir); const files = this.fs.readdirSync(this.scrapbook_dir);
files.forEach(file => { files.forEach(file => {
if (!file.endsWith('.meta')) { if (!file.endsWith('.meta')) {
const file_path = this.scrapbook_dir + file; const file_path = this.scrapbook_dir + file;
@@ -498,7 +498,7 @@ class WTVClientSessionData {
* @returns {Buffer|false} Buffer data, or false if could not open file * @returns {Buffer|false} Buffer data, or false if could not open file
*/ */
getUserStoreFileByURL(url) { getUserStoreFileByURL(url) {
let path_split = url.split('/'); const path_split = url.split('/');
path_split.shift(); path_split.shift();
path_split.shift(); path_split.shift();
const store_dir_path = path_split.join('/').replace('/', this.path.sep); const store_dir_path = path_split.join('/').replace('/', this.path.sep);
@@ -931,21 +931,7 @@ class WTVClientSessionData {
checkSecurity() { checkSecurity() {
const self = this; const self = this;
const rejectReason = null; let rejectReason = null;
const ip2long = function (ip) {
let components;
if (components = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) {
let iplong = 0;
let power = 1;
for (let i = 4; i >= 1; i -= 1) {
iplong += power * parseInt(components[i]);
power *= 256;
}
return iplong;
}
else return -1;
};
const rejectSSIDConnection = function (blacklist) { const rejectSSIDConnection = function (blacklist) {
if (blacklist) { if (blacklist) {
@@ -981,7 +967,7 @@ class WTVClientSessionData {
} else { } else {
rejectSSIDConnection(blacklist); rejectSSIDConnection(blacklist);
} }
if (ssid_access_list_ip_override && self.minisrv_config.config.debug_flags.debug) console.log(" * Request from disallowed SSID", wtvshared.filterSSID(ssid), "was allowed due to IP address whitelist"); if (ssid_access_list_ip_override && self.minisrv_config.config.debug_flags.debug) console.log(" * Request from disallowed SSID", this.wtvshared.filterSSID(ssid), "was allowed due to IP address whitelist");
} }
// process whitelist first // process whitelist first

View File

@@ -27,7 +27,7 @@ class WTVFTP {
let user = null; let user = null;
let pass = null; let pass = null;
let host = parsed.hostname; const host = parsed.hostname;
if (parsed.auth) { if (parsed.auth) {
const [username, password] = parsed.auth.split(':'); const [username, password] = parsed.auth.split(':');
@@ -56,7 +56,7 @@ class WTVFTP {
ftpClient.on('ready', () => { ftpClient.on('ready', () => {
if (filename) { if (filename) {
var totalsize = 0; let totalsize = 0;
ftpClient.cwd(dir, (err) => { ftpClient.cwd(dir, (err) => {
if (err) { if (err) {
this.sendToClient(socket, { 'Status': '500 Failed to change directory', 'Content-Type': 'text/plain' }, 'Failed to change directory'); this.sendToClient(socket, { 'Status': '500 Failed to change directory', 'Content-Type': 'text/plain' }, 'Failed to change directory');
@@ -134,7 +134,7 @@ class WTVFTP {
} }
formatDirectoryListing(list) { formatDirectoryListing(list) {
let html = `<html> const html = `<html>
<head> <head>
<title>FTP Directory Listing</title> <title>FTP Directory Listing</title>
<style> <style>

View File

@@ -169,7 +169,7 @@ class WTVFavorites {
if (!result) return false; if (!result) return false;
} catch (e) { } catch (e) {
console.error(" # FavErr: Favorite Store failed\n", e, "\n", favoritefileout, "\n", favorite, "\n"); console.error(" # FavErr: Favorite Store failed\n", e, "\n", favoritefileout, "\n", favoritedata, "\n");
} }
return false; return false;
} }
@@ -180,7 +180,7 @@ class WTVFavorites {
self.messageArr = []; self.messageArr = [];
this.fs.readdirSync(folderpath) this.fs.readdirSync(folderpath)
.map(function (v) { .map(function (v) {
const favorite_data_raw = null; let favorite_data_raw;
const favoritepath = folderpath + self.path.sep + v; const favoritepath = folderpath + self.path.sep + v;
if (self.fs.existsSync(favoritepath)) favorite_data_raw = self.fs.readFileSync(favoritepath); if (self.fs.existsSync(favoritepath)) favorite_data_raw = self.fs.readFileSync(favoritepath);
if (favorite_data_raw) { if (favorite_data_raw) {

View File

@@ -18,17 +18,16 @@ class WTVGuide {
generatePage(topic, subtopic, page = null) { generatePage(topic, subtopic, page = null) {
// sanitize a bit // sanitize a bit
var template = null; let template, template_args;
var template_args = null; let data = false;
var data = false;
switch (topic.toLowerCase()) { switch (topic.toLowerCase()) {
case "alerts": case "alerts":
// Handle error alert pages using Nunjucks templates // Handle error alert pages using Nunjucks templates
var template = this.wtvshared.getTemplate("wtv-guide", "templates/NunjucksTemplate.js", true); template = this.wtvshared.getTemplate("wtv-guide", "templates/NunjucksTemplate.js", true);
if (this.fs.existsSync(template)) { if (this.fs.existsSync(template)) {
// Map error names to template files // Map error names to template files
var errorTemplateMap = { const errorTemplateMap = {
"forbidden": topic + "/Forbidden.njk", "forbidden": topic + "/Forbidden.njk",
"hostmissing": topic + "/HostMissing.njk", "hostmissing": topic + "/HostMissing.njk",
"internalservererror": topic + "/InternalServerError.njk", "internalservererror": topic + "/InternalServerError.njk",
@@ -36,7 +35,7 @@ class WTVGuide {
"serviceunavailable": topic + "/ServiceUnavailable.njk" "serviceunavailable": topic + "/ServiceUnavailable.njk"
}; };
var templateName = errorTemplateMap[subtopic.toLowerCase()]; const templateName = errorTemplateMap[subtopic.toLowerCase()];
if (templateName) { if (templateName) {
template_args = { template_args = {
template_name: templateName, template_name: templateName,
@@ -48,27 +47,28 @@ class WTVGuide {
if (template) break; if (template) break;
case "glossary": case "glossary":
var template =this.wtvshared.getTemplate("wtv-guide", "templates/glossary.js", true); template =this.wtvshared.getTemplate("wtv-guide", "templates/glossary.js", true);
var glossary_datafile =this.wtvshared.getTemplate("wtv-guide", "glossary.json", true); const glossary_datafile =this.wtvshared.getTemplate("wtv-guide", "glossary.json", true);
if (!this.fs.existsSync(template)) break; if (!this.fs.existsSync(template)) break;
if (!this.fs.existsSync(glossary_datafile)) break; if (!this.fs.existsSync(glossary_datafile)) break;
var glossary = JSON.parse(this.fs.readFileSync(glossary_datafile)); const glossary = JSON.parse(this.fs.readFileSync(glossary_datafile));
if (glossary[subtopic.toUpperCase()]) { if (glossary[subtopic.toUpperCase()]) {
if (page) { if (page) {
// glossary word // glossary word
if (glossary[subtopic.toUpperCase()][page.toLowerCase()]) { if (glossary[subtopic.toUpperCase()][page.toLowerCase()]) {
var word = glossary[subtopic.toUpperCase()][page.toLowerCase()].word; const word = glossary[subtopic.toUpperCase()][page.toLowerCase()].word;
var definition = glossary[subtopic.toUpperCase()][page.toLowerCase()].definition; let definition = glossary[subtopic.toUpperCase()][page.toLowerCase()].definition;
// replace <word>the word</word> with a nice convienent link // replace <word>the word</word> with a nice convienent link
var search = "<word"; const search = "<word";
let start = 0;
while (start = definition.indexOf(search), start >= 0) { while (start = definition.indexOf(search), start >= 0) {
var link_word_for_link = null; let link_word_for_link = null;
var link_word_start_letter = null; let link_word_start_letter = null;
var link_word_override = null; let link_word_override = null;
var original_start, end = 0; let end = 0;
var start = start + search.length; start = start + search.length;
original_start = start; const original_start = start;
// handle <word="whatever"> // handle <word="whatever">
if (definition.charAt(start) != ">") { if (definition.charAt(start) != ">") {
start++; // +1 to skip = start++; // +1 to skip =
@@ -87,19 +87,19 @@ class WTVGuide {
} }
end = definition.indexOf("</word>", start); end = definition.indexOf("</word>", start);
if (end === -1) break; // malformed tag, exit loop if (end === -1) break; // malformed tag, exit loop
var link_word = definition.slice(start, end); const link_word = definition.slice(start, end);
if (!link_word_for_link) link_word_for_link = link_word.replace(/ /g, '').replace(/\'/g,'').replace(/\"/g,'').toLowerCase(); if (!link_word_for_link) link_word_for_link = link_word.replace(/ /g, '').replace(/\'/g,'').replace(/\"/g,'').toLowerCase();
if (!link_word_start_letter && link_word_for_link.length > 0) link_word_start_letter = link_word_for_link.charAt(0).toUpperCase(); if (!link_word_start_letter && link_word_for_link.length > 0) link_word_start_letter = link_word_for_link.charAt(0).toUpperCase();
if (!link_word_override) link_word_override = link_word; if (!link_word_override) link_word_override = link_word;
var link_url = `wtv-guide:/help?topic=Glossary&subtopic=${link_word_start_letter}&page=${link_word_for_link}&word=${encodeURIComponent(link_word_override)}` const link_url = `wtv-guide:/help?topic=Glossary&subtopic=${link_word_start_letter}&page=${link_word_for_link}&word=${encodeURIComponent(link_word_override)}`
var new_definition = definition.slice(0, original_start - search.length) + `<a href="${link_url}">${link_word}</a>` + definition.slice(end + 7); const new_definition = definition.slice(0, original_start - search.length) + `<a href="${link_url}">${link_word}</a>` + definition.slice(end + 7);
definition = new_definition; definition = new_definition;
} }
// replaces <boxname> with the friendly name of the type of unit the user has // replaces <boxname> with the friendly name of the type of unit the user has
while (definition.indexOf("<boxname>") >= 0) { while (definition.indexOf("<boxname>") >= 0) {
var romtype = this.session_data.get("wtv-client-rom-type"); const romtype = this.session_data.get("wtv-client-rom-type");
var boxname = ""; let boxname = "";
if (romtype == "US-WEBSTAR-disk-0MB-16MB-softmodem-CPU5230" || romtype == "US-DTV-disk-0MB-32MB-softmodem-CPU5230") boxname = "satellite receiver" if (romtype == "US-WEBSTAR-disk-0MB-16MB-softmodem-CPU5230" || romtype == "US-DTV-disk-0MB-32MB-softmodem-CPU5230") boxname = "satellite receiver"
else if (this.session_data.hasCap("client-has-tv-experience")) boxname = "WebTV Plus receiver"; else if (this.session_data.hasCap("client-has-tv-experience")) boxname = "WebTV Plus receiver";
else boxname = "WebTV Internet terminal"; else boxname = "WebTV Internet terminal";
@@ -107,13 +107,13 @@ class WTVGuide {
} }
// replaces <boxname_plus> with either "WebTV" or "WebTV Plus" depending on user box type // replaces <boxname_plus> with either "WebTV" or "WebTV Plus" depending on user box type
while (definition.indexOf("<boxname_plus>") >= 0) { while (definition.indexOf("<boxname_plus>") >= 0) {
var boxname = "WebTV"; let boxname = "WebTV";
if (this.session_data.hasCap("client-has-tv-experience")) boxname += " Plus"; if (this.session_data.hasCap("client-has-tv-experience")) boxname += " Plus";
definition = definition.replace(/\<boxname\_plus\>/g, boxname); definition = definition.replace(/\<boxname\_plus\>/g, boxname);
} }
// replaces <webhome> with either "Home" or "Web Home" depending on user box type // replaces <webhome> with either "Home" or "Web Home" depending on user box type
while (definition.indexOf("<webhome>") >= 0) { while (definition.indexOf("<webhome>") >= 0) {
var homename = "Home"; let homename = "Home";
if (this.session_data.hasCap("client-has-tv-experience")) homename = "Web " + homename; if (this.session_data.hasCap("client-has-tv-experience")) homename = "Web " + homename;
definition = definition.replace(/\<webhome\>/g, homename); definition = definition.replace(/\<webhome\>/g, homename);
} }
@@ -125,13 +125,13 @@ class WTVGuide {
} }
} else { } else {
// glossary letter word index // glossary letter word index
var template =this.wtvshared.getTemplate("wtv-guide", "templates/glossary_word_index.js", true); template =this.wtvshared.getTemplate("wtv-guide", "templates/glossary_word_index.js", true);
var isPlusBox = false; let isPlusBox = false;
if (this.session_data.hasCap("client-has-tv-experience")) isPlusBox = true; if (this.session_data.hasCap("client-has-tv-experience")) isPlusBox = true;
var worddb = []; const worddb = [];
Object.keys(glossary[subtopic.toUpperCase()]).forEach(function (k) { Object.keys(glossary[subtopic.toUpperCase()]).forEach(function (k) {
if (glossary[subtopic.toUpperCase()][k].plusonly && !isPlusBox) return; if (glossary[subtopic.toUpperCase()][k].plusonly && !isPlusBox) return;
var thisword = glossary[subtopic.toUpperCase()][k]; const thisword = glossary[subtopic.toUpperCase()][k];
thisword.link = k; thisword.link = k;
worddb.push(thisword); worddb.push(thisword);
}) })
@@ -148,13 +148,13 @@ class WTVGuide {
case "index": case "index":
switch (subtopic.toLowerCase()) { switch (subtopic.toLowerCase()) {
case "glossary": case "glossary":
var template =this.wtvshared.getTemplate("wtv-guide", "templates/glossary_index.js", true); template = this.wtvshared.getTemplate("wtv-guide", "templates/glossary_index.js", true);
var glossary_datafile =this.wtvshared.getTemplate("wtv-guide", "glossary.json", true); const glossary_datafile =this.wtvshared.getTemplate("wtv-guide", "glossary.json", true);
if (!this.fs.existsSync(template)) break; if (!this.fs.existsSync(template)) break;
if (!this.fs.existsSync(glossary_datafile)) break; if (!this.fs.existsSync(glossary_datafile)) break;
var glossary = JSON.parse(this.fs.readFileSync(glossary_datafile)); const glossary = JSON.parse(this.fs.readFileSync(glossary_datafile));
var letters = []; const letters = [];
Object.keys(glossary).forEach(function (k) { letters.push(k); }); Object.keys(glossary).forEach(function (k) { letters.push(k); });
template_args = { template_args = {
minisrv_config: this.minisrv_config, minisrv_config: this.minisrv_config,
@@ -167,20 +167,20 @@ class WTVGuide {
default: default:
// fallback to old js file method // fallback to old js file method
try { try {
var prerendered = null; let prerendered;
if (!page) prerendered = this.wtvshared.getTemplate("wtv-guide", "prerendered/" + topic + "/" + subtopic + ".js", true); if (!page) prerendered = this.wtvshared.getTemplate("wtv-guide", "prerendered/" + topic + "/" + subtopic + ".js", true);
else prerendered =this.wtvshared.getTemplate("wtv-guide", "prerendered/" + topic + "/" + subtopic + "/" + page + ".js", true); else prerendered =this.wtvshared.getTemplate("wtv-guide", "prerendered/" + topic + "/" + subtopic + "/" + page + ".js", true);
if (!this.fs.existsSync(prerendered)) break; if (!this.fs.existsSync(prerendered)) break;
var prerendered_jscode = this.fs.readFileSync(prerendered); let prerendered_jscode = this.fs.readFileSync(prerendered);
if (!prerendered_jscode) break; if (!prerendered_jscode) break;
prerendered_jscode = prerendered_jscode.toString('ascii'); prerendered_jscode = prerendered_jscode.toString('ascii');
var contextObj = { const contextObj = {
"session_data": this.session_data "session_data": this.session_data
} }
var vmResult = this.runScriptInVM(prerendered_jscode, contextObj); const vmResult = this.runScriptInVM(prerendered_jscode, contextObj);
if (vmResult.data) return vmResult.data; if (vmResult.data) return vmResult.data;
} catch (e) { } catch (e) {
console.log(e); console.log(e);
@@ -190,9 +190,9 @@ class WTVGuide {
} }
if (template && template_args) { if (template && template_args) {
if (!data) { if (!data) {
var WTVTemplate = require(template); // load template class const WTVTemplate = require(template); // load template class
try { try {
var wtvt = new WTVTemplate(template_args); // initialize template with our args const wtvt = new WTVTemplate(template_args); // initialize template with our args
data = wtvt.getTemplatePage(); // execute template function data = wtvt.getTemplatePage(); // execute template function
} catch (e) { } catch (e) {
console.log(" * wtv-template error:", e) console.log(" * wtv-template error:", e)

View File

@@ -959,6 +959,7 @@ class WTVIRC {
break; break;
} }
var srvCommand = parts[1]; var srvCommand = parts[1];
let whoisNick;
switch (srvCommand) { switch (srvCommand) {
case 'QUIT': case 'QUIT':
var user_name = this.usernames.get(nickname) || nickname; var user_name = this.usernames.get(nickname) || nickname;
@@ -1176,7 +1177,7 @@ class WTVIRC {
break; break;
} }
var targetUniqueId = parts[2]; var targetUniqueId = parts[2];
var whoisNick = this.findUserByUniqueId(targetUniqueId); whoisNick = this.findUserByUniqueId(targetUniqueId);
if (!whoisNick) { if (!whoisNick) {
whoisNick = parts[3].slice(1); // Remove leading ':' whoisNick = parts[3].slice(1); // Remove leading ':'
} }
@@ -3036,9 +3037,9 @@ class WTVIRC {
if (usermodes && usermodes.includes('B')) { if (usermodes && usermodes.includes('B')) {
output_lines.push(`:${this.servername} 335 ${socket.nickname} ${whoisNick} :is a bot\r\n`); output_lines.push(`:${this.servername} 335 ${socket.nickname} ${whoisNick} :is a bot\r\n`);
} }
var now = this.getDate(); const now = this.getDate();
var userTimestamp = whoisSocket.lastspoke || now; const userTimestamp = whoisSocket.lastspoke || now;
var idleTime = now - userTimestamp; const idleTime = now - userTimestamp;
output_lines.push(`:${this.servername} 317 ${socket.nickname} ${whoisNick} ${idleTime} ${this.usersignontimestamps.get(whoisNick) || 0} :seconds idle, signon time\r\n`); output_lines.push(`:${this.servername} 317 ${socket.nickname} ${whoisNick} ${idleTime} ${this.usersignontimestamps.get(whoisNick) || 0} :seconds idle, signon time\r\n`);
if (userChannels.length > 0) { if (userChannels.length > 0) {
output_lines.push(`:${this.servername} 319 ${socket.nickname} ${whoisNick} :${userChannels.join(' ')}\r\n`); output_lines.push(`:${this.servername} 319 ${socket.nickname} ${whoisNick} :${userChannels.join(' ')}\r\n`);
@@ -3090,7 +3091,7 @@ class WTVIRC {
if (cleanKillReason.startsWith(':')) { if (cleanKillReason.startsWith(':')) {
cleanKillReason = cleanKillReason.slice(1); cleanKillReason = cleanKillReason.slice(1);
} }
var targetSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === target_nick); targetSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === target_nick);
if (!targetSocket) { if (!targetSocket) {
await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${target_nick} :No such nick/channel\r\n`); await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${target_nick} :No such nick/channel\r\n`);
break; break;
@@ -3155,7 +3156,7 @@ class WTVIRC {
await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} WALLOPS :Not enough parameters\r\n`); await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} WALLOPS :Not enough parameters\r\n`);
break; break;
} }
var wallopsMessage = params.join(' '); let wallopsMessage = params.join(' ');
if (wallopsMessage.startsWith(':')) { if (wallopsMessage.startsWith(':')) {
wallopsMessage = wallopsMessage.slice(1); wallopsMessage = wallopsMessage.slice(1);
} }
@@ -3253,7 +3254,7 @@ class WTVIRC {
const nickname = this.nicknames.get(socket); const nickname = this.nicknames.get(socket);
if (nickname) { if (nickname) {
if (!socket.signedoff) { if (!socket.signedoff) {
var serverSocket = null; let serverSocket = null;
for (const [srvSocket, users] of this.serverusers.entries()) { for (const [srvSocket, users] of this.serverusers.entries()) {
if (users && typeof users.has === 'function' && users.has(nickname)) { if (users && typeof users.has === 'function' && users.has(nickname)) {
// Don't send QUIT to this server, as it owns the user // Don't send QUIT to this server, as it owns the user
@@ -3451,8 +3452,8 @@ class WTVIRC {
const sock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); const sock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user);
if (sock && sock !== exceptSocket) { if (sock && sock !== exceptSocket) {
if (sock.client_caps && sock.client_caps.includes('extended-join')) { if (sock.client_caps && sock.client_caps.includes('extended-join')) {
var account = this.accounts.get(sourceSocket.nickname) || '*'; const account = this.accounts.get(sourceSocket.nickname) || '*';
var userinfo = this.userinfo.get(sourceSocket.nickname) || ''; const userinfo = this.userinfo.get(sourceSocket.nickname) || '';
await this.safeWriteToSocket(sock, `:${sourceSocket.nickname}!${sourceSocket.username}@${sourceSocket.host} JOIN ${channel} ${account} :${userinfo}\r\n`); await this.safeWriteToSocket(sock, `:${sourceSocket.nickname}!${sourceSocket.username}@${sourceSocket.host} JOIN ${channel} ${account} :${userinfo}\r\n`);
} else { } else {
await this.safeWriteToSocket(sock,`:${sourceSocket.nickname}!${sourceSocket.username}@${sourceSocket.host} JOIN ${channel}\r\n`); await this.safeWriteToSocket(sock,`:${sourceSocket.nickname}!${sourceSocket.username}@${sourceSocket.host} JOIN ${channel}\r\n`);
@@ -3547,11 +3548,12 @@ class WTVIRC {
const realhost = socket.realhost; const realhost = socket.realhost;
const realaddress = socket.remoteAddress; const realaddress = socket.remoteAddress;
const nickname = this.nicknames.get(socket); const nickname = this.nicknames.get(socket);
var fullMask = `*!*@${host}`; let fullMask = `*!*@${host}`;
var fullMask2 = `*!*@${realhost}`; let fullMask2 = `*!*@${realhost}`;
var fullMask3 = `*!*@${realaddress}`; let fullMask3 = `*!*@${realaddress}`;
let userIdent;
if (nickname) { if (nickname) {
const userIdent = this.usernames.get(nickname) || nickname; userIdent = this.usernames.get(nickname) || nickname;
fullMask = `${nickname}!${userIdent}@${host}`; fullMask = `${nickname}!${userIdent}@${host}`;
fullMask2 = `${nickname}!${userIdent}@${realhost}`; fullMask2 = `${nickname}!${userIdent}@${realhost}`;
fullMask3 = `${nickname}!${userIdent}@${realaddress}`; fullMask3 = `${nickname}!${userIdent}@${realaddress}`;
@@ -3579,7 +3581,7 @@ class WTVIRC {
const nickRegex = new RegExp('^' + (maskNick || '*').replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i'); const nickRegex = new RegExp('^' + (maskNick || '*').replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i');
const userRegex = new RegExp('^' + (maskUser || '*').replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i'); const userRegex = new RegExp('^' + (maskUser || '*').replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i');
const hostRegex = new RegExp('^' + (maskHost || '*').replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i'); const hostRegex = new RegExp('^' + (maskHost || '*').replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i');
var matches = nickRegex.test(fullNick) && userRegex.test(fullUser) && hostRegex.test(fullHost); let matches = nickRegex.test(fullNick) && userRegex.test(fullUser) && hostRegex.test(fullHost);
if (!matches && fullMask2) { if (!matches && fullMask2) {
// Try matching against the real host if available // Try matching against the real host if available
const [fullNick2, fullRest2] = fullMask2.split('!', 2); const [fullNick2, fullRest2] = fullMask2.split('!', 2);
@@ -3598,7 +3600,7 @@ class WTVIRC {
filterHostname(socket, hostname) { filterHostname(socket, hostname) {
// Masks the user's hostname or IP for privacy // Masks the user's hostname or IP for privacy
const username = this.nicknames.get(socket); const username = this.nicknames.get(socket);
var modes = null; let modes = null;
if (username) { if (username) {
modes = this.getUserModes(username); modes = this.getUserModes(username);
} }
@@ -3679,7 +3681,7 @@ class WTVIRC {
findUserByUniqueId(uniqueId) { findUserByUniqueId(uniqueId) {
// Find a user by their unique ID // Find a user by their unique ID
var uniqueids = this.uniqueids || new Map(); let uniqueids = this.uniqueids || new Map();
if (!uniqueids || uniqueids === true) { if (!uniqueids || uniqueids === true) {
uniqueids = new Map(); uniqueids = new Map();
} }
@@ -3715,7 +3717,7 @@ class WTVIRC {
async doMOTD(nickname, socket = null) { async doMOTD(nickname, socket = null) {
// Sends the Message of the Day (MOTD) to the user // Sends the Message of the Day (MOTD) to the user
var output_lines = []; const output_lines = [];
output_lines.push(`:${this.servername} 375 ${nickname} :${this.servername} message of the day\r\n`); output_lines.push(`:${this.servername} 375 ${nickname} :${this.servername} message of the day\r\n`);
if (!this.irc_config.hide_version) { if (!this.irc_config.hide_version) {
output_lines.push(`:${this.servername} 372 ${nickname} :This is zefIRCd v${this.version}, running on minisrv v${this.minisrv_config.version}\r\n`); output_lines.push(`:${this.servername} 372 ${nickname} :This is zefIRCd v${this.version}, running on minisrv v${this.minisrv_config.version}\r\n`);
@@ -3723,7 +3725,7 @@ class WTVIRC {
if (typeof this.irc_motd === 'string' && this.irc_motd.length > 0) { if (typeof this.irc_motd === 'string' && this.irc_motd.length > 0) {
output_lines.push(`:${this.servername} 372 ${nickname} :${this.irc_motd}\r\n`); output_lines.push(`:${this.servername} 372 ${nickname} :${this.irc_motd}\r\n`);
} else if (Array.isArray(this.irc_motd) && this.irc_motd.length > 0) { } else if (Array.isArray(this.irc_motd) && this.irc_motd.length > 0) {
for (var line of this.irc_motd) { for (let line of this.irc_motd) {
if (line === '') { if (line === '') {
line = '-'; line = '-';
} }
@@ -3766,7 +3768,7 @@ class WTVIRC {
isRemoteServerUser(socket, username) { isRemoteServerUser(socket, username) {
// Check if the user is a remote server user // Check if the user is a remote server user
var serverUsers = this.serverusers.get(socket) || new Set(); let serverUsers = this.serverusers.get(socket) || new Set();
if (!serverUsers || serverUsers === true) { if (!serverUsers || serverUsers === true) {
serverUsers = new Set(); serverUsers = new Set();
} }
@@ -4006,7 +4008,7 @@ class WTVIRC {
if (!foundSocket) { if (!foundSocket) {
return null; return null;
} }
var modes = this.usermodes.get(nickname); const modes = this.usermodes.get(nickname);
if (!modes || modes === true) { if (!modes || modes === true) {
this.usermodes.set(nickname, [...this.default_user_modes]); this.usermodes.set(nickname, [...this.default_user_modes]);
} }
@@ -4030,9 +4032,10 @@ class WTVIRC {
async getHostname(socket) { async getHostname(socket) {
// Resolve the hostname for a socket, using reverse DNS lookup // Resolve the hostname for a socket, using reverse DNS lookup
let hostname;
if (socket && socket.remoteAddress) { if (socket && socket.remoteAddress) {
try { try {
var hostname = socket.remoteAddress hostname = socket.remoteAddress;
hostname = await new Promise((resolve) => { hostname = await new Promise((resolve) => {
dns.reverse(socket.remoteAddress, (err, hostnames) => { dns.reverse(socket.remoteAddress, (err, hostnames) => {
if (!err && hostnames && hostnames.length > 0) { if (!err && hostnames && hostnames.length > 0) {
@@ -4138,7 +4141,7 @@ class WTVIRC {
getGitRevision() { getGitRevision() {
try { try {
var gitPath = __dirname + path.sep + ".." + path.sep + ".." + path.sep + ".." + path.sep + ".git" + path.sep const gitPath = __dirname + path.sep + ".." + path.sep + ".." + path.sep + ".." + path.sep + ".git" + path.sep
const rev = fs.readFileSync(gitPath + "HEAD").toString().trim(); const rev = fs.readFileSync(gitPath + "HEAD").toString().trim();
if (rev.indexOf(':') === -1) { if (rev.indexOf(':') === -1) {
return rev.slice(0, 8); return rev.slice(0, 8);
@@ -4190,12 +4193,13 @@ class WTVIRC {
processChannelModeParams(channel, mode, target) { processChannelModeParams(channel, mode, target) {
let result = false;
if (!target) { if (!target) {
this.debugLog('warn', `No target specified for mode ${mode} on channel ${channel}`); this.debugLog('warn', `No target specified for mode ${mode} on channel ${channel}`);
return false; return false;
} }
if (mode === '+o' || mode === '-o') { if (mode === '+o' || mode === '-o') {
var channelOps = this.channelData.get(channel).ops; const channelOps = this.channelData.get(channel).ops;
if (mode === '+o') { if (mode === '+o') {
if (!channelOps.has(target)) { if (!channelOps.has(target)) {
channelOps.add(target); channelOps.add(target);
@@ -4208,7 +4212,7 @@ class WTVIRC {
} }
} }
} else if (mode === '+h' || mode === '-h') { } else if (mode === '+h' || mode === '-h') {
var channelHalfOps = this.channelData.get(channel).halfops; const channelHalfOps = this.channelData.get(channel).halfops;
if (mode === '+h') { if (mode === '+h') {
if (!channelHalfOps.has(target)) { if (!channelHalfOps.has(target)) {
channelHalfOps.add(target); channelHalfOps.add(target);
@@ -4221,7 +4225,7 @@ class WTVIRC {
} }
} }
} else if (mode === '+v' || mode === '-v') { } else if (mode === '+v' || mode === '-v') {
var channelVoices = this.channelData.get(channel).voices; const channelVoices = this.channelData.get(channel).voices;
if (mode === '+v') { if (mode === '+v') {
if (!channelVoices.has(target)) { if (!channelVoices.has(target)) {
channelVoices.add(target); channelVoices.add(target);
@@ -4234,7 +4238,7 @@ class WTVIRC {
} }
} }
} else if (mode === '+b' || mode === '-b') { } else if (mode === '+b' || mode === '-b') {
var channelBans = this.channelData.get(channel).bans; let channelBans = this.channelData.get(channel).bans;
if (mode === '+b') { if (mode === '+b') {
if (!channelBans.includes(target)) { if (!channelBans.includes(target)) {
channelBans.push(target); channelBans.push(target);
@@ -4247,7 +4251,7 @@ class WTVIRC {
} }
} }
} else if (mode === '+e' || mode === '-e') { } else if (mode === '+e' || mode === '-e') {
var channelExemptions = this.channelData.get(channel).exemptions; let channelExemptions = this.channelData.get(channel).exemptions;
if (mode === '+e') { if (mode === '+e') {
if (!channelExemptions.includes(target)) { if (!channelExemptions.includes(target)) {
channelExemptions.push(target); channelExemptions.push(target);
@@ -4260,7 +4264,7 @@ class WTVIRC {
} }
} }
} else if (mode === '+I' || mode === '-I') { } else if (mode === '+I' || mode === '-I') {
var channelInvites = this.channelData.get(channel).inviteexemptions; let channelInvites = this.channelData.get(channel).inviteexemptions;
if (mode === '+I') { if (mode === '+I') {
if (!channelInvites.includes(target)) { if (!channelInvites.includes(target)) {
channelInvites.push(target); channelInvites.push(target);
@@ -4274,14 +4278,14 @@ class WTVIRC {
} }
} else if (mode === '+l' || mode === '-l') { } else if (mode === '+l' || mode === '-l') {
if (mode === '+l') { if (mode === '+l') {
var result = this.setChannelMode(channel, 'l', true); result = this.setChannelMode(channel, 'l', true);
if (result === false && this.channelData.get(channel).limit === parseInt(target)) { if (result === false && this.channelData.get(channel).limit === parseInt(target)) {
return false; // Mode already set with the same limit return false; // Mode already set with the same limit
} }
this.channelData.get(channel).limit = parseInt(target); this.channelData.get(channel).limit = parseInt(target);
return true; return true;
} else { } else {
var result = this.setChannelMode(channel, 'l', false); result = this.setChannelMode(channel, 'l', false);
if (result === false && this.channelData.get(channel).limit === null) { if (result === false && this.channelData.get(channel).limit === null) {
return false; // Mode already unset return false; // Mode already unset
} }
@@ -4290,14 +4294,14 @@ class WTVIRC {
} }
} else if (mode === '+k' || mode === '-k') { } else if (mode === '+k' || mode === '-k') {
if (mode === '+k') { if (mode === '+k') {
var result = this.setChannelMode(channel, 'k', true); result = this.setChannelMode(channel, 'k', true);
if (result === false && this.channelData.get(channel).key === target) { if (result === false && this.channelData.get(channel).key === target) {
return false; // Mode already set with the same key return false; // Mode already set with the same key
} }
this.channelData.get(channel).key = target; this.channelData.get(channel).key = target;
return true; return true;
} else { } else {
var result = this.setChannelMode(channel, 'k', false); result = this.setChannelMode(channel, 'k', false);
if (result === false && !this.channelData.get(channel).key) { if (result === false && !this.channelData.get(channel).key) {
return false; // Mode already unset return false; // Mode already unset
} }
@@ -4309,13 +4313,13 @@ class WTVIRC {
async processChannelModes(nickname, channel, modes, params, socket) { async processChannelModes(nickname, channel, modes, params, socket) {
// Split modes into array and process each character // Split modes into array and process each character
let modeChars = modes.split(''); const modeChars = modes.split('');
let validModes = []; const validModes = [];
let supportedChannelModes = (this.supported_channel_modes.split(',').join('') + this.supported_prefixes[0]).split(''); const supportedChannelModes = (this.supported_channel_modes.split(',').join('') + this.supported_prefixes[0]).split('');
var serverModeMsg = ''; let serverModeMsg = '';
var target = null; let target = null;
if (socket.isserver) { if (socket.isserver) {
let sourceUniqueId = this.uniqueids.get(nickname); const sourceUniqueId = this.uniqueids.get(nickname);
serverModeMsg = `:${sourceUniqueId} MODE ${channel} `; serverModeMsg = `:${sourceUniqueId} MODE ${channel} `;
} else { } else {
if (!this.checkRegistered(socket)) { if (!this.checkRegistered(socket)) {
@@ -4323,13 +4327,14 @@ class WTVIRC {
} }
serverModeMsg = `:${socket.uniqueId} MODE ${channel} `; serverModeMsg = `:${socket.uniqueId} MODE ${channel} `;
} }
var username = this.usernames.get(nickname); const username = this.usernames.get(nickname);
var hostname = this.hostnames.get(nickname); const hostname = this.hostnames.get(nickname);
let modeMsg = `:${nickname}!${username}@${hostname} MODE ${channel} `; let modeMsg = `:${nickname}!${username}@${hostname} MODE ${channel} `;
let WTVMsg = `${nickname} has set channel mode `; let WTVMsg = `${nickname} has set channel mode `;
let addingFlag = false; let addingFlag = false;
let paramIndex = 0; let paramIndex = 0;
const output_lines = [];
if (!socket.isserver) { if (!socket.isserver) {
if (modeChars.includes('o')) { if (modeChars.includes('o')) {
if (!this.isIRCOp(nickname) && !this.isChannelOp(nickname, channel)) { if (!this.isIRCOp(nickname) && !this.isChannelOp(nickname, channel)) {
@@ -4344,8 +4349,7 @@ class WTVIRC {
return; return;
} }
} else if (modes === 'b') { } else if (modes === 'b') {
// Get the list of channel bans // Get the list of channel ban
output_lines = [];
if (this.channelData.has(channel).bans) { if (this.channelData.has(channel).bans) {
const bans = this.channelData.has(channel).bans; const bans = this.channelData.has(channel).bans;
for (const ban of bans) { for (const ban of bans) {
@@ -4357,7 +4361,6 @@ class WTVIRC {
return; return;
} else if (modes === 'e') { } else if (modes === 'e') {
// Get the list of channel exemptions // Get the list of channel exemptions
output_lines = [];
if (this.channelData.has(channel).exemptions) { if (this.channelData.has(channel).exemptions) {
const exemptions = this.channelData.has(channel).exemptions; const exemptions = this.channelData.has(channel).exemptions;
for (const exemption of exemptions) { for (const exemption of exemptions) {
@@ -4369,7 +4372,6 @@ class WTVIRC {
return; return;
} else if (modes === 'I') { } else if (modes === 'I') {
// Get the list of channel invites masks // Get the list of channel invites masks
output_lines = [];
if (this.channelData.has(channel).invites) { if (this.channelData.has(channel).invites) {
const invites = this.channelData.has(channel).invites; const invites = this.channelData.has(channel).invites;
for (const invite of invites) { for (const invite of invites) {
@@ -4389,7 +4391,8 @@ class WTVIRC {
for (let j = 0; j < modeChars.length; j++) { for (let j = 0; j < modeChars.length; j++) {
let param = null; let param = null;
let modeStr = ''; let modeStr = '';
let mc = modeChars[j]; const mc = modeChars[j];
let result = false;
if (mc === '+') { if (mc === '+') {
addingFlag = true; addingFlag = true;
modeMsg += '+'; modeMsg += '+';
@@ -4412,7 +4415,7 @@ class WTVIRC {
modeStr += mc; modeStr += mc;
// Modes that require a parameter // Modes that require a parameter
if ([...this.supported_prefixes[0], 'I', 'b', 'e', 'l', 'k'].includes(mc)) { if ([...this.supported_prefixes[0], 'I', 'b', 'e', 'l', 'k'].includes(mc)) {
var plusminus = (addingFlag) ? "+" : "-"; const plusminus = (addingFlag) ? "+" : "-";
param = params[paramIndex]; param = params[paramIndex];
if (socket.isserver) { if (socket.isserver) {
target = this.findUserByUniqueId(param); target = this.findUserByUniqueId(param);
@@ -4423,7 +4426,7 @@ class WTVIRC {
await this.safeWriteToSocket(socket, `:${this.servername} 401 ${nickname} ${param} :No such nick/channel\r\n`); await this.safeWriteToSocket(socket, `:${this.servername} 401 ${nickname} ${param} :No such nick/channel\r\n`);
return; return;
} }
var result = this.processChannelModeParams(channel, plusminus + mc, target, socket); result = this.processChannelModeParams(channel, plusminus + mc, target, socket);
paramIndex++; paramIndex++;
if (!result) { if (!result) {
if (params.length > 0) { if (params.length > 0) {
@@ -4431,7 +4434,7 @@ class WTVIRC {
} }
} }
} else { } else {
var result = this.setChannelMode(channel, mc, addingFlag); result = this.setChannelMode(channel, mc, addingFlag);
if (addingFlag) { if (addingFlag) {
if (mc === 'S' && this.kick_insecure_users_on_secure) { if (mc === 'S' && this.kick_insecure_users_on_secure) {
// Kick users who do not have user mode +z // Kick users who do not have user mode +z
@@ -4496,7 +4499,7 @@ class WTVIRC {
} }
async checkRegistered(socket, allowUnregistered = false, silent = false) { async checkRegistered(socket, allowUnregistered = false, silent = false) {
var retval = false let retval = false;
if (socket.isserver) { if (socket.isserver) {
if (!socket.is_srv_authorized && (!socket.registered && !allowUnregistered)) { if (!socket.is_srv_authorized && (!socket.registered && !allowUnregistered)) {
if (socket.writable && !silent) { if (socket.writable && !silent) {
@@ -4594,7 +4597,7 @@ class WTVIRC {
await new Promise(res => setTimeout(res, 100)); await new Promise(res => setTimeout(res, 100));
waited += 100; waited += 100;
} }
var output_lines = [] const output_lines = [];
output_lines.push(`:${this.servername} NOTICE AUTH :Welcome to \x02${this.network}\x0F\r\n`); output_lines.push(`:${this.servername} NOTICE AUTH :Welcome to \x02${this.network}\x0F\r\n`);
output_lines.push(`:${this.servername} 001 ${nickname} :Welcome to the IRC server, ${nickname}\r\n`); output_lines.push(`:${this.servername} 001 ${nickname} :Welcome to the IRC server, ${nickname}\r\n`);
output_lines.push(`:${this.servername} 002 ${nickname} :Your host is ${this.servername}, running version zefIRCd v${this.version}\r\n`); output_lines.push(`:${this.servername} 002 ${nickname} :Your host is ${this.servername}, running version zefIRCd v${this.version}\r\n`);
@@ -4625,17 +4628,18 @@ class WTVIRC {
}) })
.join(','); .join(',');
} }
let channelModesParts = this.supported_channel_modes.split(','); const channelModesParts = this.supported_channel_modes.split(',');
let sortedModesWithParams;
if (channelModesParts.length > 1) { if (channelModesParts.length > 1) {
let modesToSort = channelModesParts.slice(0, -1).join('').split(''); let modesToSort = channelModesParts.slice(0, -1).join('').split('');
modesToSort.push(...this.supported_prefixes[0].split('')); modesToSort.push(...this.supported_prefixes[0].split(''));
modesToSort = Array.from(new Set(modesToSort)); // remove duplicates modesToSort = Array.from(new Set(modesToSort)); // remove duplicates
modesToSort.sort(); modesToSort.sort();
var sortedModesWithParams = modesToSort.join(''); sortedModesWithParams = modesToSort.join('');
} }
var channelModes = this.supported_channel_modes.split(',').join('') + this.supported_prefixes[0]; const channelModes = this.supported_channel_modes.split(',').join('') + this.supported_prefixes[0];
var sortedChannelModes = sortModesAlphaCapsFirst(channelModes).replace(/,/g, ''); const sortedChannelModes = sortModesAlphaCapsFirst(channelModes).replace(/,/g, '');
var sortedUserModes = sortModesAlphaCapsFirst(this.supported_user_modes); const sortedUserModes = sortModesAlphaCapsFirst(this.supported_user_modes);
output_lines.push(`:${this.servername} 004 ${nickname} ${this.servername} zefIRCd-${this.version} ${sortedUserModes} ${sortedChannelModes} ${sortedModesWithParams}\r\n`); output_lines.push(`:${this.servername} 004 ${nickname} ${this.servername} zefIRCd-${this.version} ${sortedUserModes} ${sortedChannelModes} ${sortedModesWithParams}\r\n`);
for (const caps of this.caps) { for (const caps of this.caps) {
output_lines.push(`:${this.servername} 005 ${caps}\r\n`); output_lines.push(`:${this.servername} 005 ${caps}\r\n`);
@@ -4669,12 +4673,12 @@ class WTVIRC {
output_lines.push(`:${this.servername} 265 ${nickname} :Current Local Users: ${this.clients.length} Max: ${this.clientpeak}\r\n`); output_lines.push(`:${this.servername} 265 ${nickname} :Current Local Users: ${this.clients.length} Max: ${this.clientpeak}\r\n`);
const globalUsers = this.countGlobalUsers(); const globalUsers = this.countGlobalUsers();
this.globalpeak = Math.max(this.globalpeak, this.countGlobalUsers()); this.globalpeak = Math.max(this.globalpeak, this.countGlobalUsers());
var totalSockets = this.clients.length + this.servers.size; const totalSockets = this.clients.length + this.servers.size;
this.socketpeak = Math.max(this.socketpeak, totalSockets); this.socketpeak = Math.max(this.socketpeak, totalSockets);
output_lines.push(`:${this.servername} 266 ${nickname} :Current Global Users: ${globalUsers} Max: ${this.globalpeak}\r\n`); output_lines.push(`:${this.servername} 266 ${nickname} :Current Global Users: ${globalUsers} Max: ${this.globalpeak}\r\n`);
output_lines.push(`:${this.servername} 250 ${nickname} :Highest connection count: ${this.socketpeak} (${this.clientpeak} clients) (${this.totalConnections} connections received)\r\n`); output_lines.push(`:${this.servername} 250 ${nickname} :Highest connection count: ${this.socketpeak} (${this.clientpeak} clients) (${this.totalConnections} connections received)\r\n`);
var usermodes = this.usermodes.get(nickname); let usermodes = this.usermodes.get(nickname);
if (!usermodes || usermodes === true) { if (!usermodes || usermodes === true) {
usermodes = []; usermodes = [];
} }

View File

@@ -221,7 +221,7 @@ class WTVMail {
switch (header[0].toLowerCase()) { switch (header[0].toLowerCase()) {
case "from": case "from":
if (header[1].indexOf("<") >= 0) { if (header[1].indexOf("<") >= 0) {
let email = header[1].match(/(.+) \<(.+)\>/); const email = header[1].match(/(.+) \<(.+)\>/);
if (email) { if (email) {
from_name = email[1]; from_name = email[1];
from_addr = email[2]; from_addr = email[2];
@@ -289,8 +289,8 @@ class WTVMail {
// rely on filesystem times for sorting as it is quicker then reading every file // rely on filesystem times for sorting as it is quicker then reading every file
const file_timestamp = new Date(message_data.date * 1000); const file_timestamp = new Date(message_data.date * 1000);
fs.utimesSync(message_file, Date.now(), file_timestamp); this.fs.utimesSync(message_data.message_file, Date.now(), file_timestamp);
if (!result) console.error(" WARNING: Setting timestamp on " + message_file + " failed, mail dates will be inaccurate."); if (!result) console.error(" WARNING: Setting timestamp on " + message_data.message_file + " failed, mail dates will be inaccurate.");
} }
checkMessageIdSanity(messageid) { checkMessageIdSanity(messageid) {
@@ -482,8 +482,8 @@ class WTVMail {
this.fs.readdirSync(this.mailstore_dir).every(mailbox => { this.fs.readdirSync(this.mailstore_dir).every(mailbox => {
if (mailbox_name) return false; if (mailbox_name) return false;
self.fs.readdirSync(self.mailstore_dir + mailbox).every(file => { self.fs.readdirSync(self.mailstore_dir + mailbox).every(file => {
var regexSearch = messageid + self.msgFileExt; const regexSearch = messageid + self.msgFileExt;
var re = new RegExp(regexSearch, "ig"); const re = new RegExp(regexSearch, "ig");
if (!file.match(re)) return true; if (!file.match(re)) return true;
mailbox_name = mailbox; mailbox_name = mailbox;
return false; return false;

View File

@@ -1,32 +1,29 @@
/** /**
* Simple class for WebTV Mime Types and overrides * Class for WebTV Mime Types and overrides
*/ */
class WTVMime { class WTVMime {
mime = require('mime-types'); mime = require('mime-types');
wtvshared = null; wtvshared = null;
minisrv_config = []; minisrv_config = [];
constructor(minisrv_config) { constructor(minisrv_config) {
const { WTVShared } = require("./WTVShared.js"); const { WTVShared } = require("./WTVShared.js");
this.minisrv_config = minisrv_config; this.minisrv_config = minisrv_config;
this.wtvshared = new WTVShared(minisrv_config); this.wtvshared = new WTVShared(minisrv_config);
if (!String.prototype.reverse) { if (!String.prototype.reverse) {
String.prototype.reverse = function () { String.prototype.reverse = function () {
var splitString = this.split(""); const splitString = this.split("");
var reverseArray = splitString.reverse(); const reverseArray = splitString.reverse();
var joinArray = reverseArray.join(""); const joinArray = reverseArray.join("");
return joinArray; return joinArray;
} }
} }
} }
shouldWeCompress(ssid_session, headers_obj) { shouldWeCompress(ssid_session, headers_obj) {
var compress_data = false; let compress_data = false;
var compression_type = 0; // no compression let compression_type = 0; // no compression
if (ssid_session) { if (ssid_session) {
if (ssid_session.capabilities) { if (ssid_session.capabilities) {
if (ssid_session.capabilities['client-can-receive-compressed-data']) { if (ssid_session.capabilities['client-can-receive-compressed-data']) {
@@ -38,9 +35,9 @@ class WTVMime {
if (ssid_session) { if (ssid_session) {
// if gzip is enabled... // if gzip is enabled...
if (this.minisrv_config.config.enable_gzip_compression || this.minisrv_config.config.force_compression_type) { if (this.minisrv_config.config.enable_gzip_compression || this.minisrv_config.config.force_compression_type) {
var is_bf0app = ssid_session.get("wtv-client-rom-type") == "bf0app"; const is_bf0app = ssid_session.get("wtv-client-rom-type") == "bf0app";
var isOldBuild = this.wtvshared.isOldBuild(ssid_session); const isOldBuild = this.wtvshared.isOldBuild(ssid_session);
var is_softmodem = false; let is_softmodem = false;
if (ssid_session.get("wtv-client-rom-type")) is_softmodem = ssid_session.get("wtv-client-rom-type").match(/softmodem/); if (ssid_session.get("wtv-client-rom-type")) is_softmodem = ssid_session.get("wtv-client-rom-type").match(/softmodem/);
if (!is_bf0app && ((!is_softmodem && !isOldBuild) || (is_softmodem && !isOldBuild))) { if (!is_bf0app && ((!is_softmodem && !isOldBuild) || (is_softmodem && !isOldBuild))) {
// softmodem boxes do not appear to support gzip in the minibrowser // softmodem boxes do not appear to support gzip in the minibrowser
@@ -62,7 +59,7 @@ class WTVMime {
if (headers_obj["Content-Encoding"]) return 0; if (headers_obj["Content-Encoding"]) return 0;
// should we bother to compress? // should we bother to compress?
var content_type = ""; let content_type = "";
if (typeof (headers_obj) == 'string') content_type = headers_obj; if (typeof (headers_obj) == 'string') content_type = headers_obj;
else content_type = (typeof (headers_obj["wtv-modern-content-type"]) != 'undefined') ? headers_obj["wtv-modern-content-type"] : headers_obj["Content-type"]; else content_type = (typeof (headers_obj["wtv-modern-content-type"]) != 'undefined') ? headers_obj["wtv-modern-content-type"] : headers_obj["Content-type"];
@@ -102,9 +99,8 @@ class WTVMime {
* @returns {Array} (WebTV Content-Type, Modern Content-Type) * @returns {Array} (WebTV Content-Type, Modern Content-Type)
*/ */
getContentType(path) { getContentType(path) {
var file_ext = this.wtvshared.getFileExt(path).toLowerCase(); const file_ext = this.wtvshared.getFileExt(path).toLowerCase();
var wtv_mime_type = ""; let wtv_mime_type, modern_mime_type = "";
var modern_mime_type = "";
// process WebTV overrides, fall back to generic mime lookup // process WebTV overrides, fall back to generic mime lookup
switch (file_ext) { switch (file_ext) {
case "aif": case "aif":
@@ -296,50 +292,48 @@ class WTVMime {
generateMultipartMIME(tuples, options) { generateMultipartMIME(tuples, options) {
// modified for creating usenet compliant headers/content from an attachment // modified for creating usenet compliant headers/content from an attachment
var CRLF = '\n'; const CRLF = '\n';
if (tuples.length === 0) { if (tuples.length === 0) {
// according to rfc1341 there should be at least one encapsulation // according to rfc1341 there should be at least one encapsulation
throw new Error('Missing argument. At least one part to generate is required'); throw new Error('Missing argument. At least one part to generate is required');
} }
options = options || {}; options = options || {};
var preamble = options.preamble || "This is a multi-part message in MIME format."; const preamble = options.preamble || "This is a multi-part message in MIME format.";
var epilogue = options.epilogue; const epilogue = options.epilogue;
var boundary = options.boundary || "------------" + this.wtvshared.generateString(24); const boundary = options.boundary || "------------" + this.wtvshared.generateString(24);
if (boundary.length < 1 || boundary.length > 70) { if (boundary.length < 1 || boundary.length > 70) {
throw new Error('Boundary should be between 1 and 70 characters long'); throw new Error('Boundary should be between 1 and 70 characters long');
} }
var boundary_header = 'multipart/mixed; boundary="' + boundary + '"'; const boundary_header = 'multipart/mixed; boundary="' + boundary + '"';
var delimiter = CRLF + '--' + boundary; const delimiter = CRLF + '--' + boundary;
var closeDelimiter = delimiter + '--'; const closeDelimiter = delimiter + '--';
var wtvshared = this.wtvshared; const encapsulations = tuples.map(function (tuple, i) {
const mimetype = tuple.mime || 'text/plain';
const encoding = tuple.encoding || 'utf-8';
const use_base64 = tuple.use_base64 || !this.wtvshared.isASCII(tuple.content);
const is_base64 = tuple.is_base64 || this.wtvshared.isBase64(tuple.content);
const filename = (tuple.filename) ? tuple.filename : (use_base64) ? ('file' + i) : null;
var encapsulations = tuples.map(function (tuple, i) { const headers = [
var mimetype = tuple.mime || 'text/plain';
var encoding = tuple.encoding || 'utf-8';
var use_base64 = tuple.use_base64 || !wtvshared.isASCII(tuple.content);
var is_base64 = tuple.is_base64 || wtvshared.isBase64(tuple.content);
var filename = (tuple.filename) ? tuple.filename : (use_base64) ? ('file' + i) : null;
var headers = [
`Content-Type: ${mimetype}; ${(use_base64) ? `name="${filename}"` : `charset=${encoding.toUpperCase()}; format=flowed`}`, `Content-Type: ${mimetype}; ${(use_base64) ? `name="${filename}"` : `charset=${encoding.toUpperCase()}; format=flowed`}`,
]; ];
if (filename) headers.push(`Content-Disposition: attachment; filename="${filename}"`); if (filename) headers.push(`Content-Disposition: attachment; filename="${filename}"`);
headers.push(`Content-Transfer-Encoding: ${(use_base64) ? 'base64' : '7bit'}`); headers.push(`Content-Transfer-Encoding: ${(use_base64) ? 'base64' : '7bit'}`);
var bodyPart = headers.join(CRLF) + CRLF + CRLF; let bodyPart = headers.join(CRLF) + CRLF + CRLF;
if (use_base64 && !is_base64) bodyPart += wtvshared.lineWrap(Buffer.from(tuple.content).toString('base64'),72) + CRLF; if (use_base64 && !is_base64) bodyPart += this.wtvshared.lineWrap(Buffer.from(tuple.content).toString('base64'),72) + CRLF;
else bodyPart += wtvshared.lineWrap(tuple.content,72); else bodyPart += this.wtvshared.lineWrap(tuple.content,72);
return delimiter + CRLF + bodyPart; return delimiter + CRLF + bodyPart;
}); });
var multipartBody = [ const multipartBody = [
preamble ? preamble : undefined, preamble ? preamble : undefined,
encapsulations.join(''), encapsulations.join(''),
closeDelimiter, closeDelimiter,

View File

@@ -401,7 +401,7 @@ class WTVMinifyingProxy {
return cssDimension; return cssDimension;
} }
// Remove !important and other CSS-specific suffixes // Remove !important and other CSS-specific suffixes
let cleanDimension = cssDimension.replace(/\s*!important\s*/, '').trim(); const cleanDimension = cssDimension.replace(/\s*!important\s*/, '').trim();
// For other units or plain numbers, return as-is // For other units or plain numbers, return as-is
return cleanDimension; return cleanDimension;
@@ -487,7 +487,7 @@ class WTVMinifyingProxy {
// Extract button text to determine appropriate width // Extract button text to determine appropriate width
const valueMatch = attributes.match(/value="([^"]*)"/) || ['', '']; const valueMatch = attributes.match(/value="([^"]*)"/) || ['', ''];
const buttonText = valueMatch[1]; const buttonText = valueMatch[1];
let buttonWidth = Math.max(buttonText.length * 8, 80); // Minimum 80px const buttonWidth = Math.max(buttonText.length * 8, 80); // Minimum 80px
attributes = attributes.trim() + ` width="${buttonWidth}"`; attributes = attributes.trim() + ` width="${buttonWidth}"`;
} }
return `<input ${attributes}>`; return `<input ${attributes}>`;
@@ -751,7 +751,7 @@ ${bodyContent}
const title = titleMatch ? titleMatch[1].trim() : 'WebTV Page'; const title = titleMatch ? titleMatch[1].trim() : 'WebTV Page';
// Transform the HTML content // Transform the HTML content
let transformed = this.transformHtml(html, url); const transformed = this.transformHtml(html, url);
// Extract body content from either the transformed HTML or use all content // Extract body content from either the transformed HTML or use all content
let bodyContent = ''; let bodyContent = '';
@@ -837,7 +837,7 @@ ${bodyContent}
// Check if width exists and ensure it's reasonable for WebTV // Check if width exists and ensure it's reasonable for WebTV
const widthMatch = attributes.match(/width\s*=\s*["']?(\d+)["']?/); const widthMatch = attributes.match(/width\s*=\s*["']?(\d+)["']?/);
if (widthMatch) { if (widthMatch) {
let width = parseInt(widthMatch[1]); const width = parseInt(widthMatch[1]);
// Ensure minimum width of 200px for text inputs on WebTV // Ensure minimum width of 200px for text inputs on WebTV
if (width < 200) { if (width < 200) {
newAttributes = attributes.replace(/width\s*=\s*["']?\d+["']?/, `width="200"`); newAttributes = attributes.replace(/width\s*=\s*["']?\d+["']?/, `width="200"`);
@@ -894,7 +894,7 @@ ${bodyContent}
// Ensure minimum width for buttons // Ensure minimum width for buttons
const widthMatch = attributes.match(/width\s*=\s*["']?(\d+)["']?/); const widthMatch = attributes.match(/width\s*=\s*["']?(\d+)["']?/);
if (widthMatch) { if (widthMatch) {
let width = parseInt(widthMatch[1]); const width = parseInt(widthMatch[1]);
if (width < 80) { if (width < 80) {
newAttributes = attributes.replace(/width\s*=\s*["']?\d+["']?/, `width="80"`); newAttributes = attributes.replace(/width\s*=\s*["']?\d+["']?/, `width="80"`);
} }

View File

@@ -238,7 +238,7 @@ class WTVNews {
} }
getHeaderFromMessage(message, header) { getHeaderFromMessage(message, header) {
const response = null; let response;
if (message.article.headers) { if (message.article.headers) {
Object.keys(message.article.headers).forEach((k) => { Object.keys(message.article.headers).forEach((k) => {
if (k.toLowerCase() == header.toLowerCase()) { if (k.toLowerCase() == header.toLowerCase()) {
@@ -255,7 +255,7 @@ class WTVNews {
this.client.quit().then((response) => { this.client.quit().then((response) => {
if (response.code == 205) resolve(true); if (response.code == 205) resolve(true);
else { else {
console.error(" * WTVNews Error:", "Command: quit", e); console.error(" * WTVNews Error:", "Command: quit", response.code);
reject(`Unexpected response code ${response.code}`); reject(`Unexpected response code ${response.code}`);
} }
}).catch((e) => { }).catch((e) => {
@@ -291,7 +291,7 @@ class WTVNews {
this.client.post() this.client.post()
.then((response) => { .then((response) => {
if (response.code == 340) { if (response.code == 340) {
var articleData = {}; const articleData = {};
articleData.headers = { articleData.headers = {
'Relay-Version': "version zefie_wtvp_minisrv " + this.minisrv_config.version + "; site " + this.minisrv_config.config.domain_name, 'Relay-Version': "version zefie_wtvp_minisrv " + this.minisrv_config.version + "; site " + this.minisrv_config.config.domain_name,
'Posting-Version': "version zefie_wtvp_minisrv " + this.minisrv_config.version + "; site " + this.minisrv_config.config.domain_name, 'Posting-Version': "version zefie_wtvp_minisrv " + this.minisrv_config.version + "; site " + this.minisrv_config.config.domain_name,
@@ -328,7 +328,7 @@ class WTVNews {
}); });
} else { } else {
this.client.quit(); this.client.quit();
console.error('usenet upstream uncaught error', e); console.error('usenet upstream uncaught error');
reject("Could not send post. Server returned unknown error"); reject("Could not send post. Server returned unknown error");
}; };
}).catch((e) => { }).catch((e) => {
@@ -393,13 +393,13 @@ class WTVNews {
let message_type = 'text/plain'; let message_type = 'text/plain';
body.forEach((element) => { body.forEach((element) => {
let section_type = null; let section_type = null;
let section = element.split("\n"); const section = element.split("\n");
attachments[i] = {}; attachments[i] = {};
section.forEach((line) => { section.forEach((line) => {
this.debug('section_type', section_type, 'line', line); this.debug('section_type', section_type, 'line', line);
const section_header_match = line.match(/^Content\-/i) const section_header_match = line.match(/^Content\-/i)
if (section_header_match) { if (section_header_match) {
const section_match = line.match(/^Content\-Type\: (.+)\;/i) let section_match = line.match(/^Content\-Type\: (.+)\;/i)
if (section_match) { if (section_match) {
this.debug('section_match', section_match) this.debug('section_match', section_match)
section_type = section_match[1]; section_type = section_match[1];
@@ -474,10 +474,10 @@ class WTVNews {
Object.keys(message_relations[j]).forEach((h) => { Object.keys(message_relations[j]).forEach((h) => {
if (found) return; if (found) return;
if (message_relations[j][h].messageId == ref) { if (message_relations[j][h].messageId == ref) {
var searchref = messages[message_relations[j][h].index].headers.REFERENCES || null; let searchref = messages[message_relations[j][h].index].headers.REFERENCES || null;
var mainref = j; // j is already the main reference messageId let mainref = j; // j is already the main reference messageId
while (searchref !== null) { while (searchref !== null) {
var searchart = messages.find(e => e.messageId == searchref); const searchart = messages.find(e => e.messageId == searchref);
if (searchart) { if (searchart) {
mainref = searchart.messageId; mainref = searchart.messageId;
searchref = searchart.headers.REFERENCES || null; searchref = searchart.headers.REFERENCES || null;

View File

@@ -17,7 +17,7 @@ class WTVNewsServer {
this.wtvshared = new WTVShared(this.minisrv_config); this.wtvshared = new WTVShared(this.minisrv_config);
this.featuredGroups = minisrv_config.services['wtv-news'].featuredGroups; this.featuredGroups = minisrv_config.services['wtv-news'].featuredGroups;
const nntp_server = require('nntp-server-zefie'); const nntp_server = require('nntp-server-zefie');
var nntp_statuses = require('nntp-server-zefie/lib/status'); const nntp_statuses = require('nntp-server-zefie/lib/status');
this.username = username || null; this.username = username || null;
this.password = password || null; this.password = password || null;
@@ -34,7 +34,7 @@ class WTVNewsServer {
if (run_server) { if (run_server) {
// nntp-server module overrides // nntp-server module overrides
var self = this; const self = this;
nntp_server.prototype = { nntp_server.prototype = {
...nntp_server.prototype, ...nntp_server.prototype,
@@ -65,7 +65,7 @@ class WTVNewsServer {
if (!session.group.name) return nntp_statuses._412_GRP_NOT_SLCTD; if (!session.group.name) return nntp_statuses._412_GRP_NOT_SLCTD;
if (!session.group.current_article) return nntp_statuses._420_ARTICLE_NOT_SLCTD; if (!session.group.current_article) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
if (!self.articleExists(session.group.name, session.group.current_article)) return nntp_statuses._420_ARTICLE_NOT_SLCTD; if (!self.articleExists(session.group.name, session.group.current_article)) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
var res = self.getLastArticle(session.group.name, session.group.current_article); const res = self.getLastArticle(session.group.name, session.group.current_article);
if (!res) return nntp_statuses._422_NO_LAST_ARTICLE; if (!res) return nntp_statuses._422_NO_LAST_ARTICLE;
return res; return res;
}, },
@@ -74,14 +74,14 @@ class WTVNewsServer {
if (!session.group.name) return nntp_statuses._412_GRP_NOT_SLCTD; if (!session.group.name) return nntp_statuses._412_GRP_NOT_SLCTD;
if (!session.group.current_article) return nntp_statuses._420_ARTICLE_NOT_SLCTD; if (!session.group.current_article) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
if (!self.articleExists(session.group.name, session.group.current_article)) return nntp_statuses._420_ARTICLE_NOT_SLCTD; if (!self.articleExists(session.group.name, session.group.current_article)) return nntp_statuses._420_ARTICLE_NOT_SLCTD;
var res = self.getNextArticle(session.group.name, session.group.current_article); const res = self.getNextArticle(session.group.name, session.group.current_article);
if (!res) return nntp_statuses._421_NO_NEXT_ARTICLE; if (!res) return nntp_statuses._421_NO_NEXT_ARTICLE;
return res; return res;
}, },
_selectGroup: function (session, name) { _selectGroup: function (session, name) {
// selectGroup // selectGroup
var res = self.selectGroup(name); const res = self.selectGroup(name);
if (!res.failed) { if (!res.failed) {
session.group = res; session.group = res;
return true; return true;
@@ -90,7 +90,7 @@ class WTVNewsServer {
}, },
_buildHead: function (session, message) { _buildHead: function (session, message) {
var out = ""; let out = "";
Object.keys(message.headers).forEach((k) => { Object.keys(message.headers).forEach((k) => {
if (k.length > 0) out += `${k}: ${message.headers[k]}\r\n`; if (k.length > 0) out += `${k}: ${message.headers[k]}\r\n`;
}); });
@@ -100,13 +100,13 @@ class WTVNewsServer {
_buildHeaderField: function (session, message, field) { _buildHeaderField: function (session, message, field) {
if (field.indexOf(':') > 0) field = field.replace(/\:/g, ''); if (field.indexOf(':') > 0) field = field.replace(/\:/g, '');
var search = self.getHeader(message, field); const search = self.getHeader(message, field);
if (search) return search; if (search) return search;
else return null; else return null;
}, },
_getOverviewFmt: function (session) { _getOverviewFmt: function (session) {
var headers = [ const headers = [
"Subject:", "Subject:",
"From:", "From:",
"Date:", "Date:",
@@ -120,7 +120,7 @@ class WTVNewsServer {
_getArticle: function (session, message_id) { _getArticle: function (session, message_id) {
// getArticle // getArticle
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
var res = self.getArticle(session.group.name, message_id); const res = self.getArticle(session.group.name, message_id);
if (!res.messageId) reject(res); if (!res.messageId) reject(res);
else resolve(res) else resolve(res)
}); });
@@ -131,7 +131,7 @@ class WTVNewsServer {
}, },
_getRange: function (session, first, last) { _getRange: function (session, first, last) {
var res = self.listGroup(session.group.name, first, last) const res = self.listGroup(session.group.name, first, last)
if (res.failed) return false; if (res.failed) return false;
session.group = res.group_data; session.group = res.group_data;
return res.articles; return res.articles;
@@ -139,7 +139,7 @@ class WTVNewsServer {
} }
var tls_options = { const tls_options = {
ca: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_ca.pem'), ca: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_ca.pem'),
key: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_key.pem'), key: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_key.pem'),
cert: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_cert.pem'), cert: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_cert.pem'),
@@ -150,14 +150,14 @@ class WTVNewsServer {
} }
getMetaFilename(group) { getMetaFilename(group) {
var g = this.getGroupPath(group); const g = this.getGroupPath(group);
if (g) return g + this.path.sep + "meta.json"; if (g) return g + this.path.sep + "meta.json";
else return null; else return null;
} }
getHeader(message, header) { getHeader(message, header) {
if (message.headers) { if (message.headers) {
var search = Object.keys(message.headers).find(e => (e.toLowerCase() == header.toLowerCase())); const search = Object.keys(message.headers).find(e => (e.toLowerCase() == header.toLowerCase()));
if (search) return message.headers[search]; if (search) return message.headers[search];
} }
return null; return null;
@@ -172,7 +172,7 @@ class WTVNewsServer {
createMetaFile(group, description = null) { createMetaFile(group, description = null) {
const g = this.getMetaFilename(group); const g = this.getMetaFilename(group);
if (this.fs.existsSync(g)) return false; if (this.fs.existsSync(g)) return false;
var metadata = this.selectGroup(group, true, true); const metadata = this.selectGroup(group, true, true);
if (description) metadata.description = description; if (description) metadata.description = description;
this.saveMetadata(group, metadata, true); this.saveMetadata(group, metadata, true);
return (!metadata.failed) ? metadata : false return (!metadata.failed) ? metadata : false
@@ -196,7 +196,7 @@ class WTVNewsServer {
findHeaderCaseInsensitive(headers, header) { findHeaderCaseInsensitive(headers, header) {
// returns the key with the found case // returns the key with the found case
var response = null; let response;
if (headers) { if (headers) {
Object.keys(headers).forEach((k) => { Object.keys(headers).forEach((k) => {
if (k.toLowerCase() == header.toLowerCase()) { if (k.toLowerCase() == header.toLowerCase()) {
@@ -209,13 +209,13 @@ class WTVNewsServer {
} }
postArticle(group, post_data) { postArticle(group, post_data) {
var articleNumber = this.getMetadata(group).max_index + 1; const articleNumber = this.getMetadata(group).max_index + 1;
if (!articleNumber) return false; if (!articleNumber) return false;
try { try {
post_data.articleNumber = articleNumber; post_data.articleNumber = articleNumber;
post_data.messageId = this.getHeader(post_data, "message-id"); post_data.messageId = this.getHeader(post_data, "message-id");
if (!post_data.messageId) { if (!post_data.messageId) {
var messageId = "<" + this.wtvshared.generateString(16) + "@" + this.minisrv_config.config.domain_name + ">"; const messageId = "<" + this.wtvshared.generateString(16) + "@" + this.minisrv_config.config.domain_name + ">";
post_data.messageId = post_data.headers['Message-ID'] = messageId; post_data.messageId = post_data.headers['Message-ID'] = messageId;
} }
@@ -246,11 +246,11 @@ class WTVNewsServer {
} }
createArticle(group, articleNumber, article) { createArticle(group, articleNumber, article) {
var g = this.getGroupPath(group); const g = this.getGroupPath(group);
var file = g + this.path.sep + articleNumber + ".newz"; const file = g + this.path.sep + articleNumber + ".newz";
try { try {
this.fs.writeFileSync(file, JSON.stringify(article)); this.fs.writeFileSync(file, JSON.stringify(article));
var metadata = this.getMetadata(group); const metadata = this.getMetadata(group);
metadata.max_index = metadata.max_index + 1; metadata.max_index = metadata.max_index + 1;
metadata.total = metadata.total + 1; metadata.total = metadata.total + 1;
this.saveMetadata(group, metadata) this.saveMetadata(group, metadata)
@@ -276,7 +276,7 @@ class WTVNewsServer {
} }
createGroup(group, description = null) { createGroup(group, description = null) {
var g = this.getGroupPath(group); const g = this.getGroupPath(group);
if (!this.fs.existsSync(g)) { if (!this.fs.existsSync(g)) {
this.fs.mkdirSync(g); this.fs.mkdirSync(g);
return this.createMetaFile(group, description) return this.createMetaFile(group, description)
@@ -288,7 +288,7 @@ class WTVNewsServer {
const g = this.getArticlePath(group, article); const g = this.getArticlePath(group, article);
if (!this.fs.existsSync(g)) return false; if (!this.fs.existsSync(g)) return false;
try { try {
var data = JSON.parse(this.fs.readFileSync(g)); let data = JSON.parse(this.fs.readFileSync(g));
if (data.article) data = data.article; if (data.article) data = data.article;
data.index = data.articleNumber; data.index = data.articleNumber;
if (!data.body) data.body = ['']; if (!data.body) data.body = [''];
@@ -302,18 +302,18 @@ class WTVNewsServer {
selectGroup(group, force_update = false, initial_update = false) { selectGroup(group, force_update = false, initial_update = false) {
var g = this.getGroupPath(group); const g = this.getGroupPath(group);
var meta = this.getMetadata(group); let meta = this.getMetadata(group);
if (!meta) force_update, initial_update = true; if (!meta) force_update, initial_update = true;
let out;
if (initial_update) { if (initial_update) {
var out = { out = {
total: 0, total: 0,
min_index: 0, min_index: 0,
max_index: 0, max_index: 0,
name: group name: group
} }
} else var out = { ...meta } } else out = { ...meta }
if (meta.min_index == 0) force_update = true; if (meta.min_index == 0) force_update = true;
if (this.featuredGroups) { if (this.featuredGroups) {
@@ -330,7 +330,7 @@ class WTVNewsServer {
out.total = 0; out.total = 0;
this.fs.readdirSync(g).forEach(file => { this.fs.readdirSync(g).forEach(file => {
if (file == "meta.json") return; if (file == "meta.json") return;
var articleNumber = parseInt(file.split('.')[0]); const articleNumber = parseInt(file.split('.')[0]);
if (out.min_index == 0) out.min_index = articleNumber; if (out.min_index == 0) out.min_index = articleNumber;
else if (articleNumber < out.min_index) out.min_index = articleNumber; else if (articleNumber < out.min_index) out.min_index = articleNumber;
else if (articleNumber > out.max_index) out.max_index = articleNumber; else if (articleNumber > out.max_index) out.max_index = articleNumber;
@@ -354,7 +354,7 @@ class WTVNewsServer {
} }
getGroups(wildmat = null) { getGroups(wildmat = null) {
var groups = []; const groups = [];
this.fs.readdirSync(this.data_path).forEach(file => { this.fs.readdirSync(this.data_path).forEach(file => {
if (this.fs.lstatSync(this.data_path + this.path.sep + file).isDirectory()) { if (this.fs.lstatSync(this.data_path + this.path.sep + file).isDirectory()) {
if (wildmat) { if (wildmat) {
@@ -366,24 +366,24 @@ class WTVNewsServer {
} }
getLastArticle(group, current) { getLastArticle(group, current) {
var g = this.getGroupPath(group); const g = this.getGroupPath(group);
var res = null; let res;
try { try {
var articleNumbers = []; const articleNumbers = [];
this.fs.readdirSync(g).forEach(file => { this.fs.readdirSync(g).forEach(file => {
if (file == "meta.json") return; if (file == "meta.json") return;
var articleNumber = parseInt(file.split('.')[0]); const articleNumber = parseInt(file.split('.')[0]);
articleNumbers.push(articleNumber); articleNumbers.push(articleNumber);
}); });
articleNumbers.sort((a, b) => a - b) articleNumbers.sort((a, b) => a - b)
var index = articleNumbers.findIndex((e) => e == current) - 1; const index = articleNumbers.findIndex((e) => e == current) - 1;
if (index >= 0) res = articleNumbers[index]; if (index >= 0) res = articleNumbers[index];
} catch (e) { } catch (e) {
return e; return e;
} }
if (res) { if (res) {
if (res == current) return null; if (res == current) return null;
var message = this.getArticle(group, res); const message = this.getArticle(group, res);
if (message.messageId) { if (message.messageId) {
res = { "articleNumber": res, "message_id": message.messageId }; res = { "articleNumber": res, "message_id": message.messageId };
} }
@@ -392,23 +392,23 @@ class WTVNewsServer {
} }
getNextArticle(group, current) { getNextArticle(group, current) {
var g = this.getGroupPath(group); const g = this.getGroupPath(group);
var res = null; let res;
try { try {
var articleNumbers = []; const articleNumbers = [];
this.fs.readdirSync(g).forEach(file => { this.fs.readdirSync(g).forEach(file => {
if (file == "meta.json") return; if (file == "meta.json") return;
var articleNumber = parseInt(file.split('.')[0]); const articleNumber = parseInt(file.split('.')[0]);
articleNumbers.push(articleNumber); articleNumbers.push(articleNumber);
}); });
articleNumbers.sort((a, b) => a - b) articleNumbers.sort((a, b) => a - b)
var index = articleNumbers.findIndex((e) => e == current) + 1; const index = articleNumbers.findIndex((e) => e == current) + 1;
if (index < articleNumbers.length) res = articleNumbers[index]; if (index < articleNumbers.length) res = articleNumbers[index];
} catch (e) { } catch (e) {
return e; return e;
} }
if (res) { if (res) {
var message = this.getArticle(group, res); const message = this.getArticle(group, res);
if (message.messageId) { if (message.messageId) {
res = { "articleNumber": res, "message_id": message.messageId }; res = { "articleNumber": res, "message_id": message.messageId };
} }
@@ -432,28 +432,29 @@ class WTVNewsServer {
} }
listGroup(group, start, end, force_update = false) { listGroup(group, start, end, force_update = false) {
var g = this.getGroupPath(group); const g = this.getGroupPath(group);
var out = { const out = {
total: 0, total: 0,
min_index: 0, min_index: 0,
max_index: 0, max_index: 0,
name: group name: group
} }
var articles = []; let meta;
const articles = [];
try { try {
var meta = this.getMetadata(group); meta = this.getMetadata(group);
this.fs.readdirSync(g).forEach(file => { this.fs.readdirSync(g).forEach(file => {
if (file == "meta.json") return; if (file == "meta.json") return;
var articleNumber = parseInt(file.split('.')[0]); const articleNumber = parseInt(file.split('.')[0]);
if (articleNumber < start) return; if (articleNumber < start) return;
if (articleNumber > end) return false; if (articleNumber > end) return false;
if (out.min_index == null) out.min_index = articleNumber; if (out.min_index == null) out.min_index = articleNumber;
else if (articleNumber < out.min_index) out.min_index = articleNumber; else if (articleNumber < out.min_index) out.min_index = articleNumber;
if (articleNumber > out.max_index) out.max_index = articleNumber; if (articleNumber > out.max_index) out.max_index = articleNumber;
articles.push(this.getArticle(group, articleNumber)); articles.push(this.getArticle(group, articleNumber));
out.total++; out.total++;
}); });
if (force_update || this.doesMetaNeedRefreshing(meta)) { if (force_update || this.doesMetaNeedRefreshing(meta)) {
meta = { ...meta, ...out } meta = { ...meta, ...out }
meta.last_scan = Math.floor(Date.now() / 1000); meta.last_scan = Math.floor(Date.now() / 1000);

View File

@@ -30,8 +30,8 @@ class WTVRegister {
* @returns {boolean} True if the username is valid, false otherwise * @returns {boolean} True if the username is valid, false otherwise
*/ */
checkUsernameSanity(username) { checkUsernameSanity(username) {
var regex_str = "^([A-Za-z0-9-\_]{" + this.minisrv_config.config.user_accounts.min_username_length + "," + this.minisrv_config.config.user_accounts.max_username_length + "})$"; const regex_str = "^([A-Za-z0-9-\_]{" + this.minisrv_config.config.user_accounts.min_username_length + "," + this.minisrv_config.config.user_accounts.max_username_length + "})$";
var regex = new RegExp(regex_str); const regex = new RegExp(regex_str);
return regex.test(username); return regex.test(username);
} }
@@ -41,8 +41,8 @@ class WTVRegister {
* @returns {boolean} True if the SSID is available for registration, false if it already has an account registered. * @returns {boolean} True if the SSID is available for registration, false if it already has an account registered.
*/ */
checkSSIDAvailable(ssid) { checkSSIDAvailable(ssid) {
var directory = (directory) ? directory : this.session_store_dir + this.path.sep + "accounts"; const directory = this.session_store_dir + this.path.sep + "accounts";
var available = true; let available = true;
if (this.fs.existsSync(directory)) { if (this.fs.existsSync(directory)) {
this.fs.readdirSync(directory).forEach(file => { this.fs.readdirSync(directory).forEach(file => {
if (file.toLowerCase() == ssid.toLowerCase()) { if (file.toLowerCase() == ssid.toLowerCase()) {
@@ -61,23 +61,23 @@ class WTVRegister {
* @returns {boolean} True if the username is available, false if it is already taken * @returns {boolean} True if the username is available, false if it is already taken
*/ */
checkUsernameAvailable(username, directory = null) { checkUsernameAvailable(username, directory = null) {
var self = this; const self = this;
var return_val = false; let return_val = false;
// returns the user's ssid, and user_id and userid in an array if true, false if not // returns the user's ssid, and user_id and userid in an array if true, false if not
// check against reserved name list // check against reserved name list
if (this.minisrv_config.config.user_accounts.reserved_names_files) { if (this.minisrv_config.config.user_accounts.reserved_names_files) {
var reserved_names = [] const reserved_names = []
this.minisrv_config.config.user_accounts.reserved_names_files.forEach(function (v) { this.minisrv_config.config.user_accounts.reserved_names_files.forEach(function (v) {
var data = self.fs.readFileSync(v); const data = self.fs.readFileSync(v);
var json = JSON.parse(data); const json = JSON.parse(data);
json.forEach(function (v) { json.forEach(function (v) {
reserved_names.push(v); reserved_names.push(v);
}); });
}); });
Object.keys(reserved_names).forEach((k) => { Object.keys(reserved_names).forEach((k) => {
var regex = new RegExp("^"+reserved_names[k]+"$", 'i'); const regex = new RegExp("^"+reserved_names[k]+"$", 'i');
if (username.match(regex)) return_val = true; if (username.match(regex)) return_val = true;
}) })
} }
@@ -94,8 +94,8 @@ class WTVRegister {
} }
if (!file.match(/user.*\.json/ig)) return; if (!file.match(/user.*\.json/ig)) return;
try { try {
var temp_session_data_file = self.fs.readFileSync(directory + self.path.sep + file, 'Utf8'); const temp_session_data_file = self.fs.readFileSync(directory + self.path.sep + file, 'Utf8');
var temp_session_data = JSON.parse(temp_session_data_file); const temp_session_data = JSON.parse(temp_session_data_file);
if (temp_session_data.subscriber_username) { if (temp_session_data.subscriber_username) {
if (temp_session_data.subscriber_username.toLowerCase() == username.toLowerCase()) { if (temp_session_data.subscriber_username.toLowerCase() == username.toLowerCase()) {
return_val = true; return_val = true;
@@ -120,7 +120,7 @@ class WTVRegister {
*/ */
getHTMLTemplate(title, main_content, form_buttons, is_old_build) { getHTMLTemplate(title, main_content, form_buttons, is_old_build) {
try { try {
var template = this.wtvshared.getTemplate("wtv-register", "templates/NunjucksTemplate.js", true); const template = this.wtvshared.getTemplate("wtv-register", "templates/NunjucksTemplate.js", true);
if (this.fs.existsSync(template)) { if (this.fs.existsSync(template)) {
const WTVRegisterTemplate = require(template); const WTVRegisterTemplate = require(template);

View File

@@ -189,7 +189,7 @@ class WTVShared {
if (isNaN(inbyte)) return '00'; if (isNaN(inbyte)) return '00';
for (let ii = 0; ii < 8; ii++) { for (let ii = 0; ii < 8; ii++) {
let mix = (crc ^ inbyte) & 1; const mix = (crc ^ inbyte) & 1;
crc >>= 1; crc >>= 1;
if (mix) crc ^= 0x8C; if (mix) crc ^= 0x8C;
inbyte >>= 1; inbyte >>= 1;
@@ -448,7 +448,6 @@ class WTVShared {
* @return {object} Headers object * @return {object} Headers object
*/ */
headerStringToObj(headers, response = false) { headerStringToObj(headers, response = false) {
let inc_headers = 0;
const headers_obj = {}; const headers_obj = {};
headers_obj.raw_headers = headers; headers_obj.raw_headers = headers;
const headers_obj_pre = headers.split("\n"); const headers_obj_pre = headers.split("\n");
@@ -474,7 +473,7 @@ class WTVShared {
headers_obj.request_url = decodeURI(request_url).trim("\r"); headers_obj.request_url = decodeURI(request_url).trim("\r");
} else if (d.indexOf(":") > 0) { } else if (d.indexOf(":") > 0) {
const d_split = d.split(':'); const d_split = d.split(':');
let header_name = d_split[0]; const header_name = d_split[0];
if (typeof headers_obj[header_name] === 'string') { if (typeof headers_obj[header_name] === 'string') {
headers_obj[header_name] = [headers_obj[header_name]]; headers_obj[header_name] = [headers_obj[header_name]];
headers_obj[header_name].push((d_split.slice(1).join(':')).trim("\r")); headers_obj[header_name].push((d_split.slice(1).join(':')).trim("\r"));
@@ -590,9 +589,7 @@ class WTVShared {
* @returns {string} The decoded string * @returns {string} The decoded string
*/ */
decodeBufferText(buf) { decodeBufferText(buf) {
var out = ""; return this.utf8Decode(this.iconv.decode(Buffer.from(buf),'ISO-8859-1'));;
out = this.utf8Decode(this.iconv.decode(Buffer.from(buf),'ISO-8859-1'));
return out;
} }
/** /**
@@ -636,17 +633,16 @@ class WTVShared {
* @notice If the file exists but cannot be parsed, it will terminate the process with an error message * @notice If the file exists but cannot be parsed, it will terminate the process with an error message
*/ */
getUserConfig() { getUserConfig() {
let minisrv_user_config = {};
const user_config_filename = this.getAbsolutePath("user_config.json", this.appdir);
try { try {
var user_config_filename = this.getAbsolutePath("user_config.json", this.appdir);
if (this.fs.lstatSync(user_config_filename)) { if (this.fs.lstatSync(user_config_filename)) {
try { try {
var minisrv_user_config = this.parseJSON(this.fs.readFileSync(user_config_filename)); minisrv_user_config = this.parseJSON(this.fs.readFileSync(user_config_filename));
} catch (f) { } catch (f) {
console.error("ERROR: Could not read user_config.json", "\n\nReason:\n\n", f); console.error("ERROR: Could not read user_config.json", "\n\nReason:\n\n", f);
this.process.exit(1); this.process.exit(1);
} }
} else {
var minisrv_user_config = {}
} }
return minisrv_user_config; return minisrv_user_config;
} catch (e) { } catch (e) {
@@ -724,6 +720,7 @@ class WTVShared {
* @returns {object} The MiniSrv configuration object * @returns {object} The MiniSrv configuration object
*/ */
readMiniSrvConfig(user_config = true, notices = true, reload_notice = false) { readMiniSrvConfig(user_config = true, notices = true, reload_notice = false) {
let minisrv_config = {};
const log = (msg) => { const log = (msg) => {
if (notices || reload_notice) console.log(msg); if (notices || reload_notice) console.log(msg);
}; };
@@ -738,7 +735,7 @@ class WTVShared {
log(" *** Reading global configuration..."); log(" *** Reading global configuration...");
try { try {
var minisrv_config = this.parseJSON(this.fs.readFileSync(this.getAbsolutePath("includes" + this.path.sep + "config.json", this.appdir))); minisrv_config = this.parseJSON(this.fs.readFileSync(this.getAbsolutePath("includes" + this.path.sep + "config.json", this.appdir)));
} catch (e) { } catch (e) {
throw new Error("ERROR: Could not read config.json", e); throw new Error("ERROR: Could not read config.json", e);
} }
@@ -746,7 +743,7 @@ class WTVShared {
if (user_config) { if (user_config) {
log(" *** Reading user configuration..."); log(" *** Reading user configuration...");
try { try {
let minisrv_user_config = this.getUserConfig(); const minisrv_user_config = this.getUserConfig();
minisrv_config = this.integrateConfig(minisrv_config, minisrv_user_config); minisrv_config = this.integrateConfig(minisrv_config, minisrv_user_config);
} catch (e) { } catch (e) {
logError("ERROR: Could not integrate user_config.json", e); logError("ERROR: Could not integrate user_config.json", e);
@@ -804,11 +801,11 @@ class WTVShared {
writeToUserConfig(config) { writeToUserConfig(config) {
if (config) { if (config) {
try { try {
var minisrv_user_config = this.getUserConfig(); const minisrv_user_config = this.getUserConfig();
// write back // write back
try { try {
var new_user_config = {}; const new_user_config = {};
Object.assign(new_user_config, minisrv_user_config, config); Object.assign(new_user_config, minisrv_user_config, config);
if (this.minisrv_config.config.debug_flags.debug) console.log(" * Writing new user configuration..."); if (this.minisrv_config.config.debug_flags.debug) console.log(" * Writing new user configuration...");
this.fs.writeFileSync(this.getAbsolutePath("user_config.json", this.appdir), JSON.stringify(new_user_config, null, "\t")); this.fs.writeFileSync(this.getAbsolutePath("user_config.json", this.appdir), JSON.stringify(new_user_config, null, "\t"));
@@ -999,7 +996,7 @@ class WTVShared {
} }
// Allocate a buffer of the correct size // Allocate a buffer of the correct size
let decoded = Buffer.alloc(bufferLength); const decoded = Buffer.alloc(bufferLength);
let bufferIndex = 0; let bufferIndex = 0;
for (let i = 0; i < encoded.length; i++) { for (let i = 0; i < encoded.length; i++) {
@@ -1082,11 +1079,11 @@ class WTVShared {
const filterPasswords = this.minisrv_config.config.filter_passwords_in_logs === true; const filterPasswords = this.minisrv_config.config.filter_passwords_in_logs === true;
try { try {
// Assuming CryptoJS.enc.Utf8 exists and has a stringify method // Assuming CryptoJS.enc.Utf8 exists and has a stringify method
let post_text = CryptoJS.enc.Utf8.stringify(obj.post_data); const post_text = CryptoJS.enc.Utf8.stringify(obj.post_data);
let params = new URLSearchParams(post_text); const params = new URLSearchParams(post_text);
if (filterPasswords) { if (filterPasswords) {
for (let [key, value] of params) { for (const [key, value] of params) {
const lowerKey = key.toLowerCase(); const lowerKey = key.toLowerCase();
if (/passw(or)?d|^pass$/.test(lowerKey)) { if (/passw(or)?d|^pass$/.test(lowerKey)) {
params.set(key, '*'.repeat(value.length)); params.set(key, '*'.repeat(value.length));
@@ -1115,7 +1112,7 @@ class WTVShared {
// Prevent usage // Prevent usage
return; return;
// Search for the module in the require cache // Search for the module in the require cache
let resolvedPath = require.resolve(moduleName); const resolvedPath = require.resolve(moduleName);
// Remove the module from the cache // Remove the module from the cache
if (require.cache[resolvedPath]) { if (require.cache[resolvedPath]) {
@@ -1460,8 +1457,8 @@ class WTVShared {
* @returns {object} The modified object * @returns {object} The modified object
*/ */
moveObjectKey(currentKey, destKey, obj, case_insensitive = false) { moveObjectKey(currentKey, destKey, obj, case_insensitive = false) {
let keys = Object.keys(obj); const keys = Object.keys(obj);
let values = Object.values(obj); const values = Object.values(obj);
const currentIndex = typeof currentKey === 'string' ? this.findObjectKeyIndex(currentKey, obj, case_insensitive) : +currentKey; const currentIndex = typeof currentKey === 'string' ? this.findObjectKeyIndex(currentKey, obj, case_insensitive) : +currentKey;
if (currentIndex === -1) return obj; if (currentIndex === -1) return obj;

View File

@@ -31,13 +31,13 @@ class WTVShenanigans {
* @returns {boolean} True if the shenanigan is enabled, false otherwise. * @returns {boolean} True if the shenanigan is enabled, false otherwise.
*/ */
checkShenanigan(value) { checkShenanigan(value) {
var level = this.getShenanigansLevel(); const level = this.getShenanigansLevel();
// shenanigans are disabled, don't iterate // shenanigans are disabled, don't iterate
if (level === false) return false; if (level === false) return false;
var retval = false; let retval = false;
var shenanigans = this.shenanigans; const shenanigans = this.shenanigans;
// shenanigans are enabled, so check if the requested shenanigan is within the level enabled // shenanigans are enabled, so check if the requested shenanigan is within the level enabled
Object.keys(shenanigans).forEach((k) => { Object.keys(shenanigans).forEach((k) => {

View File

@@ -130,7 +130,7 @@ class WTVTellyScriptTokenizer {
if (regex.test(firstChar)) { if (regex.test(firstChar)) {
sequence += firstChar; sequence += firstChar;
while (this.index <= this.endIndex) { while (this.index <= this.endIndex) {
let nextChar = this.getNextCharacter(); const nextChar = this.getNextCharacter();
if (regex.test(nextChar)) { if (regex.test(nextChar)) {
sequence += nextChar; sequence += nextChar;
} else { } else {
@@ -246,13 +246,13 @@ class WTVTellyScriptTokenizer {
// The main tokenize method processes the raw script and produces an array of token bytes. // The main tokenize method processes the raw script and produces an array of token bytes.
tokenize() { tokenize() {
while (this.index <= this.endIndex) { while (this.index <= this.endIndex) {
let ch = this.getNextCharacter(); const ch = this.getNextCharacter();
// Handle comments starting with "/*" and ending with "*/". // Handle comments starting with "/*" and ending with "*/".
if (ch === "/" && this.peekCharacter() === "*") { if (ch === "/" && this.peekCharacter() === "*") {
this.getNextCharacter(); // consume '*' this.getNextCharacter(); // consume '*'
while (this.index <= this.endIndex) { while (this.index <= this.endIndex) {
let commentChar = this.getNextCharacter(); const commentChar = this.getNextCharacter();
if (commentChar === "*" && this.peekCharacter() === "/") { if (commentChar === "*" && this.peekCharacter() === "/") {
this.getNextCharacter(); // consume '/' this.getNextCharacter(); // consume '/'
break; break;
@@ -270,7 +270,7 @@ class WTVTellyScriptTokenizer {
this.tokenizeConstant(); this.tokenizeConstant();
} else { } else {
// Try to build an identifier/number sequence. // Try to build an identifier/number sequence.
let currentIdx = this.index; const currentIdx = this.index;
let checkSequence = this.buildCheckSequence(ch, "^[a-zA-Z0-9_]$"); let checkSequence = this.buildCheckSequence(ch, "^[a-zA-Z0-9_]$");
if (checkSequence !== "") { if (checkSequence !== "") {
if (this.replacements.has(checkSequence)) { if (this.replacements.has(checkSequence)) {
@@ -285,7 +285,7 @@ class WTVTellyScriptTokenizer {
if (this.replacements.has(checkSequence)) { if (this.replacements.has(checkSequence)) {
this.tokenizedData.push(this.replacements.get(checkSequence)); this.tokenizedData.push(this.replacements.get(checkSequence));
} else if (this.replacements.has(ch)) { } else if (this.replacements.has(ch)) {
let replacement = this.replacements.get(ch); const replacement = this.replacements.get(ch);
if (replacement === 0x7F) { if (replacement === 0x7F) {
this.lineNumber++; this.lineNumber++;
} }
@@ -777,14 +777,14 @@ class WTVTellyScriptDetokenizer {
let ii = 0; let ii = 0;
this.index++; // skip the token identifier (0x43) this.index++; // skip the token identifier (0x43)
while (this.index < this.tokenizedData.length) { while (this.index < this.tokenizedData.length) {
let byteVal = this.tokenizedData[this.index]; const byteVal = this.tokenizedData[this.index];
if (byteVal === 0x00) break; if (byteVal === 0x00) break;
let digit = byteVal - 0x30; const digit = byteVal - 0x30;
if (digit >= 0 && digit <= 0x0F) { if (digit >= 0 && digit <= 0x0F) {
constantValue = (constantValue << 4) + digit; constantValue = (constantValue << 4) + digit;
} }
if (ii >= 1 && (ii % 2) === 1 && alphanumericValue !== null) { if (ii >= 1 && (ii % 2) === 1 && alphanumericValue !== null) {
let charValue = constantValue & 0xFF; const charValue = constantValue & 0xFF;
if (charValue >= 0x30 && charValue <= 0x5A) { if (charValue >= 0x30 && charValue <= 0x5A) {
alphanumericValue += String.fromCharCode(charValue); alphanumericValue += String.fromCharCode(charValue);
} else { } else {
@@ -810,13 +810,13 @@ class WTVTellyScriptDetokenizer {
// Reads a string token until the null terminator and outputs it with proper escape replacements. // Reads a string token until the null terminator and outputs it with proper escape replacements.
detokenizeString() { detokenizeString() {
let count = 0; let count = 0;
let startIndex = ++this.index; const startIndex = ++this.index;
while (this.index <= this.endIndex) { while (this.index <= this.endIndex) {
if (this.tokenizedData[this.index] === 0x00) break; if (this.tokenizedData[this.index] === 0x00) break;
count++; count++;
this.index++; this.index++;
} }
let chars = []; const chars = [];
for (let i = startIndex; i < startIndex + count; i++) { for (let i = startIndex; i < startIndex + count; i++) {
chars.push(String.fromCharCode(this.tokenizedData[i])); chars.push(String.fromCharCode(this.tokenizedData[i]));
} }
@@ -835,7 +835,7 @@ class WTVTellyScriptDetokenizer {
detokenizeIdentifier() { detokenizeIdentifier() {
this.index++; // skip the identifier token indicator (0x49) this.index++; // skip the identifier token indicator (0x49)
while (this.index < this.tokenizedData.length) { while (this.index < this.tokenizedData.length) {
let byteVal = this.tokenizedData[this.index]; const byteVal = this.tokenizedData[this.index];
if (byteVal === 0x00) break; if (byteVal === 0x00) break;
this.rawData += String.fromCharCode(byteVal); this.rawData += String.fromCharCode(byteVal);
this.index++; this.index++;
@@ -861,9 +861,9 @@ class WTVTellyScriptDetokenizer {
this.rawData = ""; this.rawData = "";
this.index = 0; this.index = 0;
while (this.index <= this.endIndex) { while (this.index <= this.endIndex) {
let token = this.tokenizedData[this.index]; const token = this.tokenizedData[this.index];
if (this.instructions.hasOwnProperty(token)) { if (this.instructions.hasOwnProperty(token)) {
let instr = this.instructions[token]; const instr = this.instructions[token];
if (instr.terminate) break; if (instr.terminate) break;
if (instr.instruction) { if (instr.instruction) {
instr.instruction(); instr.instruction();
@@ -1150,7 +1150,7 @@ class WTVTellyScript {
* @returns {string} The minified TellyScript data. * @returns {string} The minified TellyScript data.
*/ */
minify() { minify() {
let minifier = new WTVTellyScriptMinifier(); const minifier = new WTVTellyScriptMinifier();
this.raw_data = minifier.minify(this); this.raw_data = minifier.minify(this);
this.raw_data = this.raw_data.replaceAll("\n\n\n", "\n"); this.raw_data = this.raw_data.replaceAll("\n\n\n", "\n");
this.tokenize(); this.tokenize();
@@ -1238,7 +1238,7 @@ class WTVTellyScript {
return TellyScriptState.PACKED; return TellyScriptState.PACKED;
} else { } else {
let hasNull = false, hasEOF = false; let hasNull = false, hasEOF = false;
for (let byte of data) { for (const byte of data) {
if (byte === 0x00) hasNull = true; if (byte === 0x00) hasNull = true;
if (byte === 0xff) hasEOF = true; if (byte === 0xff) hasEOF = true;
} }