From 22c7229e38b4f5faa9079b703194e31b5d8c88a5 Mon Sep 17 00:00:00 2001 From: zefie Date: Wed, 13 Aug 2025 21:42:22 -0400 Subject: [PATCH] more optimizations, remove WTVIRC for now, upgrade test.js --- zefie_wtvp_minisrv/.eslintignore | 6 + zefie_wtvp_minisrv/.temp-eslint-config.json | 235 + zefie_wtvp_minisrv/app.js | 168 +- zefie_wtvp_minisrv/diskmap_gen.js | 2 +- .../templates/wtv-author/styles/American.js | 6 +- .../templates/wtv-author/styles/Baseball.js | 6 +- .../templates/wtv-author/styles/Blue.js | 6 +- .../templates/wtv-author/styles/Blue_Sands.js | 6 +- .../templates/wtv-author/styles/Cats.js | 6 +- .../templates/wtv-author/styles/Channukah.js | 4 +- .../templates/wtv-author/styles/Christmas.js | 4 +- .../templates/wtv-author/styles/Democratic.js | 6 +- .../templates/wtv-author/styles/Easter.js | 4 +- .../templates/wtv-author/styles/Eyeballs.js | 6 +- .../templates/wtv-author/styles/Finance.js | 6 +- .../templates/wtv-author/styles/Flowers.js | 6 +- .../templates/wtv-author/styles/Football.js | 6 +- .../templates/wtv-author/styles/Green.js | 6 +- .../wtv-author/styles/Green_Paper.js | 6 +- .../templates/wtv-author/styles/Grey.js | 6 +- .../templates/wtv-author/styles/Halloween.js | 4 +- .../templates/wtv-author/styles/Its_a_Boy.js | 6 +- .../templates/wtv-author/styles/Its_a_Girl.js | 6 +- .../templates/wtv-author/styles/Marble.js | 6 +- .../templates/wtv-author/styles/New_Wave.js | 6 +- .../templates/wtv-author/styles/Ocean.js | 8 +- .../templates/wtv-author/styles/Paisley.js | 6 +- .../templates/wtv-author/styles/Red.js | 6 +- .../templates/wtv-author/styles/Republican.js | 6 +- .../templates/wtv-author/styles/Ringbinder.js | 6 +- .../templates/wtv-author/styles/Rivets.js | 6 +- .../wtv-author/styles/South_Beach.js | 6 +- .../templates/wtv-author/styles/Space.js | 6 +- .../templates/wtv-author/styles/Stone.js | 6 +- .../templates/wtv-author/styles/Tan.js | 6 +- .../templates/wtv-author/styles/Water.js | 6 +- .../templates/wtv-author/styles/Wedding.js | 6 +- .../prerendered/Tips/Options/Send.js | 2 +- .../prerendered/Users/Addresses/Addresses2.js | 2 +- .../wtv-guide/templates/glossary_index.js | 2 +- .../templates/glossary_word_index.js | 6 +- .../includes/ServiceVault/http_pb/index.js | 2 +- .../ServiceVault/http_pc/admin/index.js | 2 +- .../ServiceVault/http_pc/admin/ssid.js | 18 +- .../ServiceVault/http_pc/viewergen/index.js | 26 +- .../includes/ServiceVault/wtv-1800/noflash.js | 4 +- .../ServiceVault/wtv-1800/preregister.js | 18 +- .../includes/ServiceVault/wtv-admin/admin.js | 2 +- .../includes/ServiceVault/wtv-admin/ban.js | 6 +- .../ServiceVault/wtv-admin/deleteaccount.js | 6 +- .../ServiceVault/wtv-admin/deleteuser.js | 4 +- .../ServiceVault/wtv-admin/findaccount.js | 4 +- .../ServiceVault/wtv-admin/operatortweaks.js | 10 +- .../ServiceVault/wtv-admin/polyzoot.js | 4 +- .../ServiceVault/wtv-admin/regenfavs.js | 2 +- .../ServiceVault/wtv-admin/reloadconfig.js | 2 +- .../wtv-admin/removeuserpasswd.js | 4 +- .../includes/ServiceVault/wtv-admin/unban.js | 10 +- .../wtv-admin/validate-operator-tweaks.js | 2 +- .../wtv-author/add-media-to-block.js | 8 +- .../ServiceVault/wtv-author/doc-info.js | 6 +- .../ServiceVault/wtv-author/documents.js | 6 +- .../ServiceVault/wtv-author/edit-block.js | 30 +- .../ServiceVault/wtv-author/edit-title.js | 6 +- .../ServiceVault/wtv-author/publish.js | 14 +- .../ServiceVault/wtv-author/save-block.js | 30 +- .../ServiceVault/wtv-author/save-title.js | 2 +- .../ServiceVault/wtv-author/scrapbook-add.js | 2 +- .../includes/ServiceVault/wtv-chat/home.js | 4 +- .../wtv-disk/content/DownloadScreen.tmpl.js | 2 +- .../includes/ServiceVault/wtv-disk/sync.js | 38 +- .../includes/ServiceVault/wtv-favorite/add.js | 6 +- .../wtv-favorite/commit-discard-favorites.js | 10 +- .../wtv-favorite/commit-discard-folders.js | 2 +- .../wtv-favorite/commit-move-favorites.js | 8 +- .../wtv-favorite/commit-samples-page.js | 13 +- .../wtv-favorite/favorite-index.js | 4 +- .../ServiceVault/wtv-favorite/favorite.js | 19 +- .../wtv-favorite/serve-arrange-favorites.js | 2 +- .../wtv-favorite/serve-browser.js | 4 +- .../serve-choose-shortcut-favorites.js | 4 +- .../wtv-favorite/serve-discard-favorites.js | 6 +- .../wtv-favorite/serve-discard-folders.js | 4 +- .../wtv-favorite/serve-move-favorites.js | 8 +- .../wtv-favorite/serve-rename-favorites.js | 4 +- .../wtv-favorite/serve-samples-page.js | 12 +- .../wtv-favorite/serve-shortcut-list.js | 2 +- .../wtv-favorite/serve-shortcuts-favorites.js | 4 +- .../wtv-flashrom/content/content-serve.js | 2 +- .../wtv-flashrom/current-noflash.js | 2 +- .../ServiceVault/wtv-flashrom/get-by-path.js | 2 +- .../ServiceVault/wtv-flashrom/get-lc2-page.js | 6 +- .../wtv-flashrom/initiate-lc2-download.js | 2 +- .../ServiceVault/wtv-flashrom/noflash.js | 2 +- .../wtv-head-waiter/ValidateLogin.js | 12 +- .../wtv-head-waiter/choose-user.js | 4 +- .../wtv-head-waiter/finalize-security.js | 2 +- .../wtv-head-waiter/login-stage-two.js | 4 +- .../ServiceVault/wtv-head-waiter/login.js | 6 +- .../ServiceVault/wtv-mail/addressbook.js | 12 +- .../ServiceVault/wtv-mail/addresslist.js | 2 +- .../ServiceVault/wtv-mail/get-attachment.js | 4 +- .../ServiceVault/wtv-mail/listmail.js | 14 +- .../ServiceVault/wtv-mail/readmail.js | 4 +- .../ServiceVault/wtv-mail/sendmail.js | 24 +- .../ServiceVault/wtv-mail/verify-address.js | 2 +- .../ServiceVault/wtv-news/get-attachment.js | 6 +- .../includes/ServiceVault/wtv-news/lobby.js | 4 +- .../includes/ServiceVault/wtv-news/news.js | 28 +- .../wtv-passport/messengerlogin.js | 2 +- .../wtv-register/ValidateAccountInfo.js | 2 +- .../wtv-register/ValidateAgreement.js | 10 +- .../ServiceVault/wtv-setup/accounts.js | 2 +- .../ServiceVault/wtv-setup/add-user-name.js | 2 +- .../wtv-setup/add-user-password.js | 2 +- .../ServiceVault/wtv-setup/add-user.js | 2 +- .../ServiceVault/wtv-setup/choose-bg-songs.js | 2 +- .../ServiceVault/wtv-setup/edit-password.js | 15 +- .../ServiceVault/wtv-setup/edit-user-begin.js | 15 +- .../ServiceVault/wtv-setup/edit-user-name.js | 11 +- .../ServiceVault/wtv-setup/keyboard.js | 2 +- .../ServiceVault/wtv-setup/mail-signature.js | 2 +- .../wtv-setup/messenger-enable.js | 2 +- .../ServiceVault/wtv-setup/messenger.js | 6 +- .../ServiceVault/wtv-setup/remove-users.js | 4 +- .../includes/ServiceVault/wtv-setup/screen.js | 17 +- .../includes/ServiceVault/wtv-setup/set-bg.js | 2 +- .../includes/ServiceVault/wtv-setup/setup.js | 4 +- .../wtv-setup/transfer-account.js | 2 +- .../wtv-setup/validate-add-user-done.js | 6 +- .../wtv-setup/validate-add-user.js | 4 +- .../wtv-setup/validate-bg-song-category.js | 12 +- .../wtv-setup/validate-change-name.js | 11 +- .../wtv-setup/validate-change-password.js | 12 +- .../wtv-setup/validate-mail-signature.js | 2 +- .../wtv-setup/validate-remove-users.js | 8 +- .../wtv-setup/validate-transfer-account.js | 2 +- .../includes/ServiceVault/wtv-tricks/info.js | 46 +- .../ServiceVault/wtv-tricks/tricks.js | 4 +- .../includes/ServiceVault/wtvchat/catchall.js | 2 +- .../includes/classes/WTVAdmin.js | 22 +- .../includes/classes/WTVAuthor.js | 92 +- .../includes/classes/WTVBGMusic.js | 12 +- .../includes/classes/WTVClientCapabilities.js | 4 +- .../includes/classes/WTVClientSessionData.js | 72 +- .../includes/classes/WTVDisk.js | 10 +- .../includes/classes/WTVFavorites.js | 14 +- .../includes/classes/WTVFlashrom.js | 18 +- .../includes/classes/WTVGuide.js | 7 +- zefie_wtvp_minisrv/includes/classes/WTVIRC.js | 4719 ----------------- .../includes/classes/WTVMail.js | 14 +- .../includes/classes/WTVMime.js | 14 +- .../includes/classes/WTVNews.js | 30 +- .../includes/classes/WTVNewsServer.js | 28 +- .../includes/classes/WTVRegister.js | 6 +- .../includes/classes/WTVShared.js | 14 +- .../includes/classes/WTVShenanigans.js | 2 +- zefie_wtvp_minisrv/includes/config.json | 50 - zefie_wtvp_minisrv/irconly.js | 12 - zefie_wtvp_minisrv/packer.js | 2 +- zefie_wtvp_minisrv/sync_nntp.js | 4 +- zefie_wtvp_minisrv/test.js | 35 +- 162 files changed, 1002 insertions(+), 5539 deletions(-) create mode 100644 zefie_wtvp_minisrv/.eslintignore create mode 100644 zefie_wtvp_minisrv/.temp-eslint-config.json delete mode 100644 zefie_wtvp_minisrv/includes/classes/WTVIRC.js delete mode 100644 zefie_wtvp_minisrv/irconly.js diff --git a/zefie_wtvp_minisrv/.eslintignore b/zefie_wtvp_minisrv/.eslintignore new file mode 100644 index 00000000..3adf7b2e --- /dev/null +++ b/zefie_wtvp_minisrv/.eslintignore @@ -0,0 +1,6 @@ +node_modules/ +SessionStore/ +ServiceLogPost/ +PageBuilderVault/ +*.min.js +*.log diff --git a/zefie_wtvp_minisrv/.temp-eslint-config.json b/zefie_wtvp_minisrv/.temp-eslint-config.json new file mode 100644 index 00000000..5446dd55 --- /dev/null +++ b/zefie_wtvp_minisrv/.temp-eslint-config.json @@ -0,0 +1,235 @@ +{ + "parserOptions": { + "ecmaVersion": 2022, + "sourceType": "script" + }, + "env": { + "node": true, + "es2022": true + }, + "rules": { + "eqeqeq": [ + "warn", + "always" + ], + "no-eq-null": "warn", + "no-redeclare": 2, + "no-undef": 2, + "no-use-before-define": [ + "error", + { + "variables": false, + "functions": false, + "classes": false + } + ], + "block-scoped-var": 2, + "no-const-assign": 2, + "prefer-const": 1, + "no-var": 1, + "no-restricted-globals": [ + "warn", + { + "name": "escape", + "message": "escape() is deprecated. Use encodeURIComponent() instead." + }, + { + "name": "unescape", + "message": "unescape() is deprecated. Use decodeURIComponent() instead." + } + ], + "no-restricted-syntax": [ + "warn", + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.property.name='substr']", + "message": "String.prototype.substr() is deprecated. Use String.prototype.slice() instead." + }, + { + "selector": "CallExpression[callee.name='substr']", + "message": "substr() is deprecated. Use slice() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.property.name='substring']", + "message": "substring() found, for continuity, please use String.prototype.slice() instead." + }, + { + "selector": "CallExpression[callee.name='substring']", + "message": "substring() found, for continuity, please use slice() instead." + }, + { + "selector": "CallExpression[callee.type='Buffer'][callee.property.name='slice']", + "message": "Found .slice() call. If this is on a Buffer, use Buffer.subarray() instead for better performance." + }, + { + "selector": "NewExpression[callee.name='Buffer']", + "message": "new Buffer() is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='fs'][callee.property.name='exists']", + "message": "fs.exists() is deprecated. Use fs.existsSync() or fs.access() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isArray']", + "message": "util.isArray() is deprecated. Use Array.isArray() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isBoolean']", + "message": "util.isBoolean() is deprecated. Use typeof x === 'boolean' instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isBuffer']", + "message": "util.isBuffer() is deprecated. Use Buffer.isBuffer() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isDate']", + "message": "util.isDate() is deprecated. Use x instanceof Date instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isError']", + "message": "util.isError() is deprecated. Use x instanceof Error instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isFunction']", + "message": "util.isFunction() is deprecated. Use typeof x === 'function' instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isNull']", + "message": "util.isNull() is deprecated. Use x === null instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isNullOrUndefined']", + "message": "util.isNullOrUndefined() is deprecated. Use x == null instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isNumber']", + "message": "util.isNumber() is deprecated. Use typeof x === 'number' instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isObject']", + "message": "util.isObject() is deprecated. Use typeof x === 'object' && x !== null instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isPrimitive']", + "message": "util.isPrimitive() is deprecated. Use manual type checking instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isRegExp']", + "message": "util.isRegExp() is deprecated. Use x instanceof RegExp instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isString']", + "message": "util.isString() is deprecated. Use typeof x === 'string' instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isSymbol']", + "message": "util.isSymbol() is deprecated. Use typeof x === 'symbol' instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='isUndefined']", + "message": "util.isUndefined() is deprecated. Use x === undefined instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='debug']", + "message": "util.debug() is deprecated. Use console.error() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='error']", + "message": "util.error() is deprecated. Use console.error() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='print']", + "message": "util.print() is deprecated. Use console.log() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='puts']", + "message": "util.puts() is deprecated. Use console.log() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='util'][callee.property.name='pump']", + "message": "util.pump() is deprecated. Use stream.pipeline() instead." + }, + { + "selector": "CallExpression[callee.name='require'][arguments.0.value='domain']", + "message": "The 'domain' module is deprecated. Use AsyncLocalStorage or async_hooks instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='crypto'][callee.property.name='createCredentials']", + "message": "crypto.createCredentials() is deprecated. Use tls.createSecureContext() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='crypto'][callee.property.name='Credentials']", + "message": "crypto.Credentials is deprecated. Use tls.SecureContext instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.name='session_data'][callee.property.name='hasCap']", + "message": "session_data.hasCap() is deprecated. Use session_data.capabilities.get() instead." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.object.type='MemberExpression'][callee.object.property.name='session_data'][callee.property.name='hasCap']", + "message": "session_data.hasCap() is deprecated. Use session_data.capabilities.get() instead." + }, + { + "selector": "BinaryExpression[operator='==='][left.type='Literal'][left.value=/^\\d+$/][left.typeof='number'][right.type='Identifier']", + "message": "Comparing string literal that looks like a number with a variable using strict equality. Consider parseInt() or ensure both operands are the same type." + }, + { + "selector": "BinaryExpression[operator='==='][left.type='Identifier'][right.type='Literal'][right.value=/^\\d+$/][right.typeof='number']", + "message": "Comparing variable with string literal that looks like a number using strict equality. Consider parseInt() or ensure both operands are the same type." + }, + { + "selector": "BinaryExpression[operator='==='][left.type='Literal'][left.typeof='string'][right.type='Literal'][right.typeof='number']", + "message": "Comparing string literal with number literal using strict equality. This will always be false." + }, + { + "selector": "BinaryExpression[operator='==='][left.type='Literal'][left.typeof='number'][right.type='Literal'][right.typeof='string']", + "message": "Comparing number literal with string literal using strict equality. This will always be false." + }, + { + "selector": "BinaryExpression[operator='!=='][left.type='Literal'][left.typeof='string'][right.type='Literal'][right.typeof='number']", + "message": "Comparing string literal with number literal using strict inequality. This will always be true." + }, + { + "selector": "BinaryExpression[operator='!=='][left.type='Literal'][left.typeof='number'][right.type='Literal'][right.typeof='string']", + "message": "Comparing number literal with string literal using strict inequality. This will always be true." + } + ] + }, + "globals": { + "wtvmime": "readonly", + "http": "readonly", + "https": "readonly", + "sharp": "readonly", + "util": "readonly", + "nunjucks": "readonly", + "URL": "readonly", + "URLSearchParams": "readonly", + "wtvshared": "readonly", + "zlib": "readonly", + "clientShowAlert": "readonly", + "WTVClientSessionData": "readonly", + "WTVClientCapabilities": "readonly", + "strftime": "readonly", + "CryptoJS": "readonly", + "crypto": "readonly", + "fs": "readonly", + "path": "readonly", + "debug": "readonly", + "minisrv_config": "readonly", + "socket": "readonly", + "headers": "readonly", + "data": "readonly", + "request_is_async": "readonly", + "minisrv_version_string": "readonly", + "getServiceString": "readonly", + "sendToClient": "readonly", + "service_vaults": "readonly", + "service_deps": "readonly", + "ssid_sessions": "readonly", + "moveArrayKey": "readonly", + "cwd": "readonly", + "request_headers": "readonly", + "session_data": "readonly", + "service_name": "readonly", + "WTVAuthor": "readonly" + } +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index 0f7f29e1..6412441a 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -27,13 +27,11 @@ const WTVClientCapabilities = require(classPath + "/WTVClientCapabilities.js"); const WTVClientSessionData = require(classPath + "/WTVClientSessionData.js"); const WTVMime = require(classPath + "/WTVMime.js"); const WTVFlashrom = require(classPath + "/WTVFlashrom.js"); -const WTVIRC = require(classPath + "/WTVIRC.js"); const WTVFTP = require(classPath + "/WTVFTP.js"); const vm = require('vm'); const debug = require('debug')('app'); const express = require('express'); -let wtvirc = null; let wtvnewsserver = null; const minisrv_config = wtvshared.getMiniSrvConfig(); // snatches minisrv_config @@ -66,7 +64,7 @@ function getServiceByPort(port) { Object.keys(minisrv_config.services).forEach((k) => { if (service_name) return; if (minisrv_config.services[k].port) { - if (port == parseInt(minisrv_config.services[k].port) && getServiceEnabled(k)) + if (port === parseInt(minisrv_config.services[k].port) && getServiceEnabled(k)) service_name = k; } }) @@ -78,7 +76,7 @@ function getServiceByVHost(vhost) { Object.keys(minisrv_config.services).forEach((k) => { if (service_name) return; if (minisrv_config.services[k].vhost) { - if (vhost.toLowerCase() == minisrv_config.services[k].vhost.toLowerCase()) + if (vhost.toLowerCase() === minisrv_config.services[k].vhost.toLowerCase()) service_name = k; } }) @@ -130,8 +128,8 @@ function verifyServicePort(service_name, socket) { function getServiceByVaultDir(vault_dir) { let res = vault_dir; Object.keys(minisrv_config.services).forEach((k) => { - if (res != vault_dir) return; - if (minisrv_config.services[k].servicevault_dir) { + if (res !== vault_dir) return; + if (minisrv_config.services[k].servicevault_dir) { if (minisrv_config.services[k].servicevault_dir === vault_dir) { res = k; return false; @@ -161,20 +159,20 @@ function configureService(service_name, service_obj, initial = false) { // minisrv_config service toString service_obj.toString = function (overrides) { const self = Object.assign({}, this); - if (overrides != null) { - if (typeof (overrides) == 'object') { + if (overrides !== null) { + if (typeof (overrides) === 'object') { Object.keys(overrides).forEach(function (k) { - if (k != "exceptions") self[k] = overrides[k]; + if (k !== "exceptions") self[k] = overrides[k]; }); } } let outstr = ''; - if ((service_name == "wtv-star" && self.no_star_word != true) || service_name != "wtv-star") { + if ((service_name === "wtv-star" && self.no_star_word !== true) || service_name !== "wtv-star") { outstr = `wtv-service: name=${self.service_name} host=${self.host} port=${self.port}`; if (self.flags) outstr += ` flags=${self.flags}`; if (self.connections) outstr += ` connections=${self.connections}`; } - if (service_name == "wtv-star") { + if (service_name === "wtv-star") { outstr += `\nwtv-service: name=wtv-* host=${self.host} port=${self.port}`; if (self.flags) outstr += ` flags=${self.flags}`; if (self.connections) outstr += ` connections=${self.connections}`; @@ -357,7 +355,6 @@ const runScriptInVM = function (script_data, user_contextObj = {}, privileged = console.error(" *!* Could not load module", module_file, "requested by service", contextObj.service_name, e) } if (vm_modules[k] === "WTVNews") contextObj['wtvnewsserver'] = wtvnewsserver; - if (vm_modules[k] === "WTVIRC") contextObj['wtvirc'] = wtvirc; }) } } @@ -420,7 +417,7 @@ async function handleCGI(executable, cgi_file, socket, request_headers, vault, s const split_req = request_headers.request.split(' '); request_data.method = split_req[0]; let request_type = (request_headers.request_url.indexOf(":/")) ? request_headers.request_url.split(":/")[0] : 'http'; - if (request_type != "http" && request_type != "https") { + if (request_type !== "http" && request_type !== "https") { request_type = "wtvp"; request_data.host = minisrv_config.config.service_ip; request_data.port = minisrv_config.services[service_name].port; @@ -467,14 +464,14 @@ async function handleCGI(executable, cgi_file, socket, request_headers, vault, s raw_header_split.forEach(function (header) { if (header) { header = header.split(": "); - if (header[0] == "Request") return; + if (header[0] === "Request") return; if (header[1]) { env["HTTP_"+header[0].toUpperCase().replaceAll("-","_")] = header[1]; } } }); env.SCRIPT_URI = request_type + "://" + request_data.host; - if (request_data.port != 80 && request_data.port != 443 ) env.SCRIPT_URI += ":" + request_data.port; + if (request_data.port !== 80 && request_data.port !== 443) env.SCRIPT_URI += ":" + request_data.port; env.SCRIPT_URI += env.SCRIPT_NAME; env.SCRIPT_URL = env.SCRIPT_NAME; env.PHP_SELF = env.SCRIPT_NAME; @@ -506,8 +503,8 @@ async function handleCGI(executable, cgi_file, socket, request_headers, vault, s options.gid = process.getgid(); } - if (!minisrv_config.config.debug_flags.quiet) (executable == cgi_file) ? console.debug(" * Executing CGI:", executable) : console.debug(" * Executing CGI:", executable, cgi_file); - const cgi = (executable == cgi_file) ? spawn(cgi_file, options=options) : spawn(executable, [cgi_file], options) + if (!minisrv_config.config.debug_flags.quiet) (executable === cgi_file) ? console.debug(" * Executing CGI:", executable) : console.debug(" * Executing CGI:", executable, cgi_file); + const cgi = (executable === cgi_file) ? spawn(cgi_file, options=options) : spawn(executable, [cgi_file], options) let data = ""; let error = ""; @@ -523,7 +520,7 @@ async function handleCGI(executable, cgi_file, socket, request_headers, vault, s error += dat; }); cgi.on('close', function (code) { - if (code == 0) { + if (code === 0) { const stdout = data.split("\r\n\r\n", 2); let headers = stdout[0]; data = stdout[1]; @@ -622,7 +619,7 @@ async function processPath(socket, service_vault_file_path, request_headers = [] if (minisrv_config.services[service_name]) minisrv_catchall = minisrv_config.services[service_name].catchall_file_name || minisrv_config.config.catchall_file_name || null; else minisrv_catchall = minisrv_config.config.catchall_file_name || null; if (minisrv_catchall) { - if (service_path_request_file == minisrv_catchall) { + if (service_path_request_file === minisrv_catchall) { request_is_async = true; const errpage = wtvshared.doErrorPage(401, null, null, pc_services); sendToClient(socket, errpage[0], errpage[1]); @@ -726,7 +723,7 @@ async function processPath(socket, service_vault_file_path, request_headers = [] service_vault_found = true; handlePHP(socket, request_headers, service_vault_file_path, service_vault_dir + path.sep + service_name, (pc_services) ? pc_service_name : service_name, (pc_services) ? null : ssid_sessions[socket.ssid], extra_path) return; - } else if (service_vault_dir == vaults_to_scan[vaults_to_scan.length - 1]) { + } else if (service_vault_dir === vaults_to_scan[vaults_to_scan.length - 1]) { const errpage = wtvshared.doErrorPage(404, null, null, pc_services); sendToClient(socket, errpage[0], errpage[1]); return; @@ -754,7 +751,7 @@ async function processPath(socket, service_vault_file_path, request_headers = [] service_vault_found = true; handleCGI(service_vault_file_path, service_vault_file_path, socket, request_headers, service_vault_dir + path.sep + service_name, (pc_services) ? pc_service_name : service_name, (pc_services) ? null : ssid_sessions[socket.ssid], extra_path) return; - } else if (service_vault_dir == vaults_to_scan[vaults_to_scan.length - 1]) { + } else if (service_vault_dir === vaults_to_scan[vaults_to_scan.length - 1]) { const errpage = wtvshared.doErrorPage(404, null, null, pc_services); sendToClient(socket, errpage[0], errpage[1]); return; @@ -785,13 +782,13 @@ async function processPath(socket, service_vault_file_path, request_headers = [] request_headers.service_file_path = service_vault_file_path; request_headers.raw_file = true; // process flashroms - if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "rom" || wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "brom") { + if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() === "rom" || wtvshared.getFileExt(service_vault_file_path).toLowerCase() === "brom") { let bf0app_update = false; const request_path = request_headers.request_url.replace(service_name + ":/", ""); const romtype = ssid_sessions[socket.ssid].get("wtv-client-rom-type"); const bootver = ssid_sessions[socket.ssid].get("wtv-client-bootrom-version") - if ((romtype == "bf0app" || !romtype) && (bootver == "105" || !bootver)) { + if ((romtype === "bf0app" || !romtype) && (bootver === "105" || !bootver)) { // assume old classic in flash mode, override user setting and send tellyscript // because it is required to proceed in flash mode bf0app_update = true; @@ -807,8 +804,8 @@ async function processPath(socket, service_vault_file_path, request_headers = [] }); // service parsed files, we might not want to expose our service source files so we can protect them with a flag on the first line - } else if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "js" || wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "txt") { - if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "js") { + } else if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() === "js" || wtvshared.getFileExt(service_vault_file_path).toLowerCase() === "txt") { + if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() === "js") { wtvshared.getLineFromFile(service_vault_file_path, 0, function (status, line) { if (!status) { if (line.match(/minisrv\_service\_file.*true/i)) { @@ -828,7 +825,7 @@ async function processPath(socket, service_vault_file_path, request_headers = [] }); } - if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() == "txt") { + if (wtvshared.getFileExt(service_vault_file_path).toLowerCase() === "txt") { wtvshared.getLineFromFile(service_vault_file_path, 0, function (status, line) { if (!status) { if (line.match(/^#!minisrv/i)) { @@ -860,7 +857,7 @@ async function processPath(socket, service_vault_file_path, request_headers = [] const service_check_dir = service_vault_file_path.split(path.sep); service_check_dir.pop(); // pop filename - while (service_check_dir.join(path.sep) != service_vault_dir && service_check_dir.length > 0) { + while (service_check_dir.join(path.sep) !== service_vault_dir && service_check_dir.length > 0) { const catchall_file = service_check_dir.join(path.sep) + path.sep + minisrv_catchall_file_name; if (fs.existsSync(catchall_file)) { @@ -948,7 +945,7 @@ async function processPath(socket, service_vault_file_path, request_headers = [] headers = errpage[0]; data = errpage[1]; } - if (headers == null && !request_is_async) { + if (headers === null && !request_is_async) { const errpage = wtvshared.doErrorPage(400, null, null, pc_services); headers = errpage[0]; data = errpage[1]; @@ -1048,7 +1045,7 @@ async function processURL(socket, request_headers, pc_services = false) { } } else { const qraw_split = post_data_string.split("="); - if (qraw_split.length == 2) { + if (qraw_split.length === 2) { const k = qraw_split[0]; data = decodeURIComponent(qraw_split[1].replace(/\+/g, "%20")); if (request_headers.query[k]) { @@ -1131,21 +1128,21 @@ minisrv-no-mail-count: true`; if (pc_services) { const ssl = (socket.ssl) ? true : false; - if (original_service_name == service_name) console.log(" * " + ((ssl) ? "SSL " : "") + "PC request on service " + service_name + " for " + request_headers.request_url, 'on', socket.id); + if (original_service_name === service_name) console.log(" * " + ((ssl) ? "SSL " : "") + "PC request on service " + service_name + " for " + request_headers.request_url, 'on', socket.id); else console.log(" * " + ((ssl) ? "SSL " : "") + "PC request on service " + original_service_name + " (Service Vault " + service_name + ") for " + request_headers.request_url, 'on', socket.id); } if ((shortURL.includes(':/')) && (!shortURL.includes('://') || (shortURL.includes('://') && allow_double_slash))) { let ssid = socket.ssid; - if (ssid == null) { + if (ssid === null) { // prevent possible injection attacks via malformed SSID and filesystem SessionStore ssid = wtvshared.makeSafeSSID(request_headers["wtv-client-serial-number"]); - if (ssid == "") ssid = null; + if (ssid === "") ssid = null; } if (!pc_services) { let reqverb = "Request"; if (request_headers.encrypted || request_headers.secure) reqverb = "Encrypted " + reqverb; - if (ssid != null) { + if (ssid !== null) { console.log(" * " + reqverb + " for " + request_headers.request_url + " from WebTV SSID " + (await wtvshared.filterSSID(ssid)), 'on', socket.id); } else { console.log(" * " + reqverb + " for " + request_headers.request_url, 'on', socket.id); @@ -1153,7 +1150,7 @@ minisrv-no-mail-count: true`; if (!service_name) { // detect if client is trying to load wtv-star due to client-perceived error - if (getSocketDestinationPort(socket) == getPortByService("wtv-star")) { + if (getSocketDestinationPort(socket) === getPortByService("wtv-star")) { // is wtv-star if (minisrv_config.config.debug_flags.debug) console.debug(" * client requested", shortURL, "on wtv-star port", getSocketDestinationPort(socket)) shortURL = "wtv-star:/star"; @@ -1190,7 +1187,7 @@ minisrv-no-mail-count: true`; processPath(socket, urlToPath, request_headers, service_name, shared_romcache, pc_services); } else if (pc_services) { // if a directory, request index - if (shortURL.indexOf("/ROMCache/") == 0 && minisrv_config.config.enable_shared_romcache) { + if (shortURL.indexOf("/ROMCache/") === 0 && minisrv_config.config.enable_shared_romcache) { shared_romcache = wtvshared.fixPathSlashes(minisrv_config.config.SharedROMCache + path.sep + shortURL.split('/')[1] + '/' + shortURL.split('/')[2]); } if (shortURL.endsWith("/")) shortURL += "index"; @@ -1380,7 +1377,7 @@ async function doHTTPProxy(socket, request_headers) { } // RFC7239 - if (socket.remoteAddress != "127.0.0.1") { + if (socket.remoteAddress !== "127.0.0.1") { options.headers["X-Forwarded-For"] = socket.remoteAddress; } @@ -1446,7 +1443,7 @@ async function doHTTPProxy(socket, request_headers) { }); }).on('error', function (err) { // severe errors, such as unable to connect. - if (err.code == "ENOTFOUND" || err.message.indexOf("HostUnreachable") > 0) { + if (err.code === "ENOTFOUND" || err.message.indexOf("HostUnreachable") > 0) { const errpage = wtvshared.doErrorPage(400, `The publisher ${request_data.host} is unknown.`); sendToClient(socket, errpage[0], errpage[1]); } else { @@ -1484,7 +1481,7 @@ async function sendToClient(socket, headers_obj, data = null) { } if (!socket.res) { wtv_connection_close = (headers_obj["wtv-connection-close"]) ? true : false; - if (typeof (headers_obj["wtv-connection-close"]) != 'undefined') delete headers_obj["wtv-connection-close"]; + if (typeof (headers_obj["wtv-connection-close"]) !== 'undefined') delete headers_obj["wtv-connection-close"]; if (!headers_obj['minisrv-no-mail-count']) { if (ssid_sessions[socket.ssid]) { @@ -1527,7 +1524,7 @@ async function sendToClient(socket, headers_obj, data = null) { // WebTV client headers_obj[contype_key] = headers_obj[contype_key].split(";")[0]; } - if (contype_key != "Content-type") { + if (contype_key !== "Content-type") { headers_obj["Content-type"] = headers_obj[contype_key]; delete headers_obj[contype_key]; } @@ -1576,7 +1573,7 @@ async function sendToClient(socket, headers_obj, data = null) { if (content_length >= 256) compression_type = wtvmime.shouldWeCompress(ssid_sessions[socket.ssid], headers_obj); if (socket_sessions[socket.id].request_headers) { if (socket_sessions[socket.id].request_headers.query) { - if (socket_sessions[socket.id].wtv_request_type == "download") { + if (socket_sessions[socket.id].wtv_request_type === "download") { if (socket_sessions[socket.id].request_headers.query.dont_compress) { compression_type = 0; } @@ -1595,7 +1592,7 @@ async function sendToClient(socket, headers_obj, data = null) { } if (socket.res) { // pc mode with response object available - if (compression_type == 1) compression_type = 2; // wtv-lzpf not supported in pc mode + if (compression_type === 1) compression_type = 2; // wtv-lzpf not supported in pc mode } // compress if needed @@ -1619,7 +1616,7 @@ async function sendToClient(socket, headers_obj, data = null) { } let compressed_content_length = 0; - if (content_length == 0 || compression_type != 1) { + if (content_length === 0 || compression_type !== 1) { // ultimately send compressed content length compressed_content_length = data.byteLength; content_length = compressed_content_length; @@ -1629,12 +1626,12 @@ async function sendToClient(socket, headers_obj, data = null) { } const compression_ratio = (uncompressed_content_length / compressed_content_length).toFixed(2); const compression_percentage = ((1 - (compressed_content_length / uncompressed_content_length)) * 100).toFixed(1); - if (uncompressed_content_length != compressed_content_length) if (minisrv_config.config.debug_flags.debug) console.debug(" # Compression stats: Orig Size:", uncompressed_content_length, "~ Comp Size:", compressed_content_length, "~ Ratio:", compression_ratio, "~ Saved:", compression_percentage.toString() + "%"); + if (uncompressed_content_length !== compressed_content_length) if (minisrv_config.config.debug_flags.debug) console.debug(" # Compression stats: Orig Size:", uncompressed_content_length, "~ Comp Size:", compressed_content_length, "~ Ratio:", compression_ratio, "~ Saved:", compression_percentage.toString() + "%"); } if (!socket.res) { // encrypt if needed - if (socket_sessions[socket.id].secure == true && !socket_sessions[socket.id].do_not_encrypt) { + if (socket_sessions[socket.id].secure === true && !socket_sessions[socket.id].do_not_encrypt) { headers_obj["wtv-encrypted"] = 'true'; headers_obj = wtvshared.moveObjectKey('wtv-encrypted', 'Connection', headers_obj); if (content_length > 0 && socket_sessions[socket.id].wtvsec) { @@ -1719,7 +1716,7 @@ async function sendToClient(socket, headers_obj, data = null) { else debug(" * ["+socket.remoteAddress+"] Outgoing Status "+headers_obj.Status+" headers on socket ID", socket.id, headers_obj); Object.keys(headers_obj).forEach(function (k) { - if (k == "Status") { + if (k === "Status") { headers += headers_obj[k] + eol; } else { if (typeof headers_obj[k] === 'object') { @@ -1733,7 +1730,7 @@ async function sendToClient(socket, headers_obj, data = null) { }); if (headers_obj["Connection"]) { - if (headers_obj["Connection"].toLowerCase() == "close" && wtv_connection_close) { + if (headers_obj["Connection"].toLowerCase() === "close" && wtv_connection_close) { socket_sessions[socket.id].destroy_me = true; } } @@ -1757,12 +1754,12 @@ async function sendToClient(socket, headers_obj, data = null) { if (minisrv_config.config.debug_flags.quiet) console.debug(" * Sent response " + headers_obj.Status + " to PC client (Content-Type:", headers_obj['Content-type'], "~", headers_obj['Content-length'], "bytes)"); } else { let toClient = null; - if (typeof data == 'string') { + if (typeof data === 'string') { toClient = headers + eol + data; sendToSocket(socket, Buffer.from(toClient)); } else if (typeof data === 'object') { - let verbosity_mod = (headers_obj["wtv-encrypted"] == 'true') ? " encrypted response" : ""; - if (socket_sessions[socket.id].secure_headers == true) { + let verbosity_mod = (headers_obj["wtv-encrypted"] === 'true') ? " encrypted response" : ""; + if (socket_sessions[socket.id].secure_headers === true) { // encrypt headers if (minisrv_config.config.debug_flags.quiet) verbosity_mod += " with encrypted headers"; const enc_headers = socket_sessions[socket.id].wtvsec.Encrypt(1, headers + eol); @@ -1780,9 +1777,9 @@ async function sendToSocket(socket, data) { let can_write = true; let close_socket = false; let expected_data_out = 0; - while ((socket.bytesWritten == 0 || socket.bytesWritten != expected_data_out) && can_write) { + while ((socket.bytesWritten === 0 || socket.bytesWritten !== expected_data_out) && can_write) { if (expected_data_out === 0) expected_data_out = data.byteLength + (socket_sessions[socket.id].socket_total_written || 0); - if (socket.bytesWritten == expected_data_out) break; + if (socket.bytesWritten === expected_data_out) break; const data_left = (expected_data_out - socket.bytesWritten); // buffer size = lesser of chunk_size or size remaining @@ -1803,7 +1800,7 @@ async function sendToSocket(socket, data) { break; } } - if (socket.bytesWritten == expected_data_out || close_socket) { + if (socket.bytesWritten === expected_data_out || close_socket) { socket_sessions[socket.id].socket_total_written = socket.bytesWritten; if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; if (socket_sessions[socket.id].header_buffer) delete socket_sessions[socket.id].header_buffer; @@ -1851,7 +1848,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } let data = Buffer.from(data_hex, 'hex').toString('ascii'); if (typeof data === "string") { - if ((data.includes("\r\n\r\n") || data.includes("\n\n") || data.includes("\n\r\n")) && typeof socket_sessions[socket.id].post_data == "undefined") { + if ((data.includes("\r\n\r\n") || data.includes("\n\n") || data.includes("\n\r\n")) && typeof socket_sessions[socket.id].post_data === "undefined") { if (data.includes("\r\n\r\n")) { data = data.split("\r\n\r\n")[0]; } else if (data.includes("\n\r\n")) { @@ -1861,7 +1858,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq data = data.split("\n\n")[0]; } if (isUnencryptedString(data)) { - if (headers.length != 0) { + if (headers.length !== 0) { const new_header_obj = wtvshared.headerStringToObj(data); Object.keys(new_header_obj).forEach(function (k, v) { headers[k] = new_header_obj[k]; @@ -1873,7 +1870,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq // if its a POST request, assume its a binary blob and not encrypted (dangerous) if (!encryptedRequest) { // its not a POST and it failed the isUnencryptedString test, so we think this is an encrypted blob - if (socket_sessions[socket.id].secure != true) { + if (socket_sessions[socket.id].secure !== true) { // first time so reroll sessions socket_sessions[socket.id].wtvsec = new WTVSec(minisrv_config); socket_sessions[socket.id].wtvsec.IssueChallenge(); @@ -1902,7 +1899,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (!headers) return; - if (headers["wtv-client-serial-number"] != null && socket.ssid == null) { + if (headers["wtv-client-serial-number"] !== null && socket.ssid === null) { socket.ssid = wtvshared.makeSafeSSID(headers["wtv-client-serial-number"]); if (minisrv_config.config.require_valid_ssid) { if (!wtvshared.checkSSID(socket.ssid)) { @@ -1915,7 +1912,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } } } - if (socket.ssid != null) { + if (socket.ssid !== null) { if (!ssid_sessions[socket.ssid]) { ssid_sessions[socket.ssid] = new WTVClientSessionData(minisrv_config, socket.ssid); ssid_sessions[socket.ssid].SaveIfRegistered(); @@ -1930,7 +1927,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (!ssid_sessions[socket.ssid].getClientAddress()) ssid_sessions[socket.ssid].setClientAddress(socket.remoteAddress); if (ssid_sessions[socket.ssid]) ssid_sessions[socket.ssid].checkSecurity(); - if (headers["wtv-capability-flags"] != null) { + if (headers["wtv-capability-flags"] !== null) { if (!ssid_sessions[socket.ssid]) { ssid_sessions[socket.ssid] = new WTVClientSessionData(minisrv_config, socket.ssid); ssid_sessions[socket.ssid].SaveIfRegistered(); @@ -1957,21 +1954,21 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (headers["wtv-incarnation"]) ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(headers["wtv-incarnation"]); ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = headers["wtv-ticket"]; ssid_sessions[socket.ssid].data_store.wtvsec_login.DecodeTicket(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64); - if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id != null) { + if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id !== null) { if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id >= 0) { ssid_sessions[socket.ssid].switchUserID(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id, true, false); ssid_sessions[socket.ssid].setUserLoggedIn(true); } } } else { - if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 != headers["wtv-ticket"]) { + if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 !== headers["wtv-ticket"]) { if (!ssid_sessions[socket.ssid].data_store.wtvsec_login.update_ticket) { if (minisrv_config.config.debug_flags.debug) console.debug(" # New ticket from client"); ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = headers["wtv-ticket"]; ssid_sessions[socket.ssid].data_store.wtvsec_login.DecodeTicket(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64); if (headers["wtv-incarnation"]) ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(headers["wtv-incarnation"]); if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id >= 0) { - if (ssid_sessions[socket.ssid].user_id != ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id) { + if (ssid_sessions[socket.ssid].user_id !== ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id) { ssid_sessions[socket.ssid].switchUserID(ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_store.user_id, true, false); ssid_sessions[socket.ssid].setUserLoggedIn(true); } @@ -1995,7 +1992,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq socket_sessions[socket.id].wtvsec.ticket_b64 = headers["wtv-ticket"]; socket_sessions[socket.id].wtvsec.SecureOn(); } - if (socket_sessions[socket.id].secure != true) { + if (socket_sessions[socket.id].secure !== true) { // first time so reroll sessions socket_sessions[socket.id].secure = true; } @@ -2016,7 +2013,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq socket_sessions[socket.id].secure_buffer += dec_data.toString(CryptoJS.enc.Hex); let secure_headers = null; if (headers['request']) { - if (headers['request'] == "GET") { + if (headers['request'] === "GET") { if (socket_sessions[socket.id].secure_buffer.indexOf("0d0a0d0a") || socket_sessions[socket.id].secure_buffer.indexOf("0a0d0a") ||socket_sessions[socket.id].secure_buffer.indexOf("0a0a")) { secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); } @@ -2049,7 +2046,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } else if (skipSecure) { if (headers) { if (headers['request']) { - if (headers['request'].slice(0, 4) == "POST") { + if (headers['request'].slice(0, 4) === "POST") { if (socket_sessions[socket.id].secure_buffer) delete socket_sessions[socket.id].secure_buffer; } else { return headers; @@ -2063,10 +2060,10 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } // handle POST if (headers['request'] && !socket_sessions[socket.id].expecting_post_data) { - if (headers['request'].slice(0, 4) == "POST") { + if (headers['request'].slice(0, 4) === "POST") { let post_string = "POST"; socket.setTimeout(minisrv_config.config.post_data_socket_timeout * 1000); - if (typeof socket_sessions[socket.id].post_data == "undefined") { + if (typeof socket_sessions[socket.id].post_data === "undefined") { if (socket_sessions[socket.id].post_data_percents_shown) delete socket_sessions[socket.id].post_data_percents_shown; socket_sessions[socket.id].post_data_length = parseInt(headers['Content-length'] || headers['Content-Length'] || 0); socket_sessions[socket.id].post_data = ""; @@ -2084,7 +2081,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } } - if (socket_sessions[socket.id].post_data.length == (socket_sessions[socket.id].post_data_length * 2)) { + if (socket_sessions[socket.id].post_data.length === (socket_sessions[socket.id].post_data_length * 2)) { // got all expected data if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; console.log(" * Incoming", post_string, "request on", socket.id, "from", wtvshared.filterSSID(socket.ssid), "to", headers['request_url'], "(got all expected", socket_sessions[socket.id].post_data_length, "bytes of data from client already)"); @@ -2123,7 +2120,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq if (socket_sessions[socket.id].post_data_length > (minisrv_config.config.max_post_length * 1024 * 1024)) { cleanupSocket(socket); } else { - if (headers.length == 0) { + if (headers.length === 0) { headers = socket_sessions[socket.id].headers; } else { socket_sessions[socket.id].headers = headers; @@ -2142,7 +2139,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq socket_sessions[socket.id].post_data += dec_data.toString(CryptoJS.enc.Hex); let post_string = "POST"; - if (socket_sessions[socket.id].secure == true) post_string = "Encrypted " + post_string; + if (socket_sessions[socket.id].secure === true) post_string = "Encrypted " + post_string; if (minisrv_config.config.post_debug) { // `post_debug` logging of every chunk @@ -2157,23 +2154,23 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq console.debug(" * Received", postPercent, "% of", socket_sessions[socket.id].post_data_length, "bytes on", socket.id, "from", wtvshared.filterSSID(socket.ssid)); socket_sessions[socket.id].post_data_percents_shown[postPercent] = true; } - if (postPercent == 100) delete socket_sessions[socket.id].post_data_percents_shown; + if (postPercent === 100) delete socket_sessions[socket.id].post_data_percents_shown; } } } - } - - if (socket_sessions[socket.id].post_data.length == (socket_sessions[socket.id].post_data_length * 2)) { + } + + if (socket_sessions[socket.id].post_data.length === (socket_sessions[socket.id].post_data_length * 2)) { // got all expected data if (socket_sessions[socket.id].expecting_post_data) delete socket_sessions[socket.id].expecting_post_data; socket.setTimeout(minisrv_config.config.socket_timeout * 1000); - if (headers.length == 0) { + if (headers.length === 0) { const errpage = wtvshared.doErrorPage(400); sendToClient(socket, errpage[0], errpage[1]); return; } headers.post_data = CryptoJS.enc.Hex.parse(socket_sessions[socket.id].post_data); - if (socket_sessions[socket.id].secure == true) { + if (socket_sessions[socket.id].secure === true) { if (minisrv_config.config.debug_flags.debug) console.debug(" # Encrypted POST Content (SECURE ON)", "on", socket.id, "[", headers.post_data.sigBytes, "bytes ]"); } else { if (minisrv_config.config.debug_flags.debug) console.debug(" # Unencrypted POST Content", "on", socket.id); @@ -2196,7 +2193,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq } } else if (!skipSecure) { if (!encryptedRequest) { - if (socket_sessions[socket.id].secure != true) { + if (socket_sessions[socket.id].secure !== true) { socket_sessions[socket.id].wtvsec = new WTVSec(minisrv_config); socket_sessions[socket.id].wtvsec.IssueChallenge(); socket_sessions[socket.id].wtvsec.SecureOn(); @@ -2220,7 +2217,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq socket_sessions[socket.id].secure_buffer += dec_data.toString(CryptoJS.enc.Hex); let secure_headers = null; if (headers['request']) { - if (headers['request'] == "GET") { + if (headers['request'] === "GET") { if (socket_sessions[socket.id].secure_buffer.indexOf("0d0a0d0a") || socket_sessions[socket.id].secure_buffer.indexOf("0a0d0a") || socket_sessions[socket.id].secure_buffer.indexOf("0a0a")) { secure_headers = await processRequest(socket, socket_sessions[socket.id].secure_buffer, true, true); } @@ -2238,7 +2235,7 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq headers[k] = secure_headers[k]; }); if (headers['request']) { - if (headers['request'].slice(0, 4) == "POST") { + if (headers['request'].slice(0, 4) === "POST") { if (!socket_sessions[socket.id].post_data) { socket_sessions[socket.id].post_data_length = headers['Content-length'] || headers['Content-Length'] || 0; socket_sessions[socket.id].post_data = ""; @@ -2486,15 +2483,6 @@ Object.keys(minisrv_config.services).forEach(function (k) { }) -if (minisrv_config.config.irc) { - if (minisrv_config.config.irc.enabled && minisrv_config.config.irc.port > 0) { - if (!wtvirc) { - wtvirc = new WTVIRC(minisrv_config, minisrv_config.config.bind_ip, minisrv_config.config.irc.port, minisrv_config.config.irc.debug || false); - wtvirc.start(); - console.log(" * Configured Service: IRC Server on", minisrv_config.config.bind_ip + ":" + minisrv_config.config.irc.port); - } - } -} if (minisrv_config.config.hide_ssid_in_logs) console.log(" * Masking SSIDs in console logs for security"); else console.log(" * Full SSIDs will be shown in console logs"); @@ -2703,8 +2691,8 @@ Content-type: text/html`; return false; }); -if (bind_ports.length > 0) console.log(` * Started WTVP Server on port${bind_ports.length != 1 ? "s" : ""} ` + bind_ports.join(", ") + "..."); -if (pc_bind_ports.length > 0) console.log(` * Started HTTP Server on port${pc_bind_ports.length != 1 ? "s" : ""} ` + pc_bind_ports.join(", ") + "..."); +if (bind_ports.length > 0) console.log(` * Started WTVP Server on port${bind_ports.length !== 1 ? "s" : ""} ` + bind_ports.join(", ") + "..."); +if (pc_bind_ports.length > 0) console.log(` * Started HTTP Server on port${pc_bind_ports.length !== 1 ? "s" : ""} ` + pc_bind_ports.join(", ") + "..."); -const listening_ip_string = (minisrv_config.config.bind_ip != "0.0.0.0") ? "IP: " + minisrv_config.config.bind_ip : "all interfaces"; +const listening_ip_string = (minisrv_config.config.bind_ip !== "0.0.0.0") ? "IP: " + minisrv_config.config.bind_ip : "all interfaces"; console.log(" * Listening on", listening_ip_string, "~", "Service IP:", service_ip); \ No newline at end of file diff --git a/zefie_wtvp_minisrv/diskmap_gen.js b/zefie_wtvp_minisrv/diskmap_gen.js index db144086..0967b463 100644 --- a/zefie_wtvp_minisrv/diskmap_gen.js +++ b/zefie_wtvp_minisrv/diskmap_gen.js @@ -73,7 +73,7 @@ const fileList = recursiveDirList(service_vault_dir); if (fileList.length > 0) { const diskmap = {}; diskmap[group_name] = {}; - if (client_dest.slice(client_dest.length - 1, 1) != '/') client_dest += '/'; + if (client_dest.slice(client_dest.length - 1, 1) !== '/') client_dest += '/'; diskmap[group_name].base = client_dest; diskmap[group_name].location = service_vault_subdir; diskmap[group_name].files = []; diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/American.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/American.js index 1edc4921..6eb1de2f 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/American.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/American.js @@ -25,7 +25,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -34,7 +34,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -44,7 +44,7 @@ to return to editing it. this.styledata.text + `>${title} `; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Baseball.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Baseball.js index 3548ba63..cc37f0e2 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Baseball.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Baseball.js @@ -26,7 +26,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -38,7 +38,7 @@ to return to editing it.  

`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -47,7 +47,7 @@ to return to editing it. this.styledata.text + `>${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue.js index 12738555..85a578a0 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue.js @@ -22,7 +22,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -37,7 +37,7 @@ to return to editing it.
`; this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -47,7 +47,7 @@ to return to editing it. `>${title} `; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue_Sands.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue_Sands.js index a5d4ea57..883bb55a 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue_Sands.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Blue_Sands.js @@ -23,7 +23,7 @@ class PBTemplate { `; // Do some templating here for some fucking reason - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
@@ -33,7 +33,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -43,7 +43,7 @@ to return to editing it. this.styledata.titheader += ` ${title} `; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Cats.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Cats.js index 362a606c..e155c1d5 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Cats.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Cats.js @@ -21,7 +21,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += ``; this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `
${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += `
`; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Channukah.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Channukah.js index 578ecc45..17efb83c 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Channukah.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Channukah.js @@ -50,13 +50,13 @@ to return to editing it.
You are previewing your page. Press Back @@ -34,13 +34,13 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Christmas.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Christmas.js index f0c13317..9856864b 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Christmas.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Christmas.js @@ -46,7 +46,7 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -55,7 +55,7 @@ to return to editing it. this.styledata.text + `>${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Democratic.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Democratic.js index f87c22d5..d8b231a6 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Democratic.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Democratic.js @@ -26,7 +26,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -35,7 +35,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -44,7 +44,7 @@ to return to editing it. this.styledata.text + `>${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Easter.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Easter.js index e2f987fe..f5ab441a 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Easter.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Easter.js @@ -61,13 +61,13 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Eyeballs.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Eyeballs.js index d2ca874d..691a57be 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Eyeballs.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Eyeballs.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Finance.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Finance.js index 8e2ba614..cb87e504 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Finance.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Finance.js @@ -26,7 +26,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -42,7 +42,7 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -51,7 +51,7 @@ to return to editing it. ${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Flowers.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Flowers.js index 3c445739..eed4883b 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Flowers.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Flowers.js @@ -22,7 +22,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -34,13 +34,13 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Football.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Football.js index 5f76b111..08462aab 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Football.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Football.js @@ -26,7 +26,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -35,7 +35,7 @@ to return to editing it.
`; } this.styledata.titheader = `

`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -44,7 +44,7 @@ to return to editing it. this.styledata.text + `>${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green.js index b274203a..862c7698 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green.js @@ -22,7 +22,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -38,7 +38,7 @@ to return to editing it. `; this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -48,7 +48,7 @@ to return to editing it. `>${title} `; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green_Paper.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green_Paper.js index 542ee9e5..6611dfc7 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green_Paper.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Green_Paper.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Grey.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Grey.js index d16642c7..4862e52b 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Grey.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Grey.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Halloween.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Halloween.js index 3d2eec5d..cb39f8d8 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Halloween.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Halloween.js @@ -47,7 +47,7 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -56,7 +56,7 @@ to return to editing it. this.styledata.text + `>${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Boy.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Boy.js index 507a79d5..61e2c27f 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Boy.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Boy.js @@ -22,7 +22,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -34,13 +34,13 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Girl.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Girl.js index 8135af18..d908b010 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Girl.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Its_a_Girl.js @@ -22,7 +22,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += ` @@ -461,11 +461,11 @@ if (showIt) { document.viewOptionEmbed.document.write(' ` -if (blockType == "snapshot" || blockType == "scrapbook") { +if (blockType === "snapshot" || blockType === "scrapbook") { data += `View this picture` -} else if (blockType == "clipart") +} else if (blockType === "clipart") data += `View this picture` @@ -551,9 +551,9 @@ vspace=0
You are previewing your page. Press Back @@ -34,13 +34,13 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Marble.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Marble.js index 7de43254..3f3e00a4 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Marble.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Marble.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/New_Wave.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/New_Wave.js index 5a3fd066..561f10cb 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/New_Wave.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/New_Wave.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -42,7 +42,7 @@ to return to editing it. this.styledata.text + `>${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ocean.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ocean.js index cdd301ac..ec75c730 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ocean.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ocean.js @@ -26,7 +26,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -35,7 +35,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -47,7 +47,7 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } this.styledata.titheader += @@ -56,7 +56,7 @@ to return to editing it. this.styledata.text + `>${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } this.styledata.titheader += ` diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Paisley.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Paisley.js index c5a8ce16..deafcdfa 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Paisley.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Paisley.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Red.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Red.js index 3192b602..846a9d28 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Red.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Red.js @@ -22,7 +22,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `` @@ -91,7 +91,7 @@ function validateSelection(cmd, ssid, friendlymsg) { data += "The SSID does not exist in the SessionStore." } } - } else if (request_headers.query.cmd == "delete") { + } else if (request_headers.query.cmd === "delete") { redirectmsg = ""; const ssid = request_headers.query.ssid; if (ssid) { @@ -102,7 +102,7 @@ function validateSelection(cmd, ssid, friendlymsg) { redirectmsg = `An SSID is required for the ${request_headers.query.cmd} command.`; } headers = "302 OK\nLocation: /admin/?cmd=list&msg=" + encodeURI(redirectmsg); - } else if (request_headers.query.cmd == "ban") { + } else if (request_headers.query.cmd === "ban") { redirectmsg = ""; const ssid = request_headers.query.ssid; if (ssid) { @@ -110,7 +110,7 @@ function validateSelection(cmd, ssid, friendlymsg) { if (result === wtva.SUCCESS) { reloadConfig(); redirectmsg = "The SSID is now banned."; - } else if (result == wtva.REASON_EXISTS) { + } else if (result === wtva.REASON_EXISTS) { redirectmsg = "The SSID was already banned."; } else { redirectmsg = "Unknown response " + result.toString(); @@ -119,7 +119,7 @@ function validateSelection(cmd, ssid, friendlymsg) { redirectmsg = `An SSID is required for the ${request_headers.query.cmd} command.`; } headers = "302 OK\nLocation: /admin/?cmd=ssid&ssid=" + encodeURI(ssid) + "&msg=" + encodeURI(redirectmsg); - } else if (request_headers.query.cmd == "unban") { + } else if (request_headers.query.cmd === "unban") { redirectmsg = "The SSID was not banned, so it could not be unbanned."; const ssid = request_headers.query.ssid; if (ssid) { @@ -127,7 +127,7 @@ function validateSelection(cmd, ssid, friendlymsg) { if (result === wtva.SUCCESS) { reloadConfig(); redirectmsg = "The SSID is now unbanned."; - } else if (result == wtva.REASON_EXISTS) { + } else if (result === wtva.REASON_EXISTS) { redirectmsg = "The SSID was not banned."; } else { redirectmsg = "Unknown response " + result.toString(); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/viewergen/index.js b/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/viewergen/index.js index 1ff5c9ed..c47bae16 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/viewergen/index.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/viewergen/index.js @@ -74,7 +74,7 @@ const patch_limits = { function getPatchDataType(type, invert = false) { let patch_data = false; - if ((type == "wtv-incarnation" && !invert) || (type == "wtv-encryption" && invert)) { + if ((type === "wtv-incarnation" && !invert) || (type === "wtv-encryption" && invert)) { patch_data = "wtv-client-serial-number: %s\r\n" patch_data += "wtv-user-requested-upgrade: %s\r\n"; patch_data += "wtv-system-cpuprid: %s\r\n"; @@ -87,7 +87,7 @@ function getPatchDataType(type, invert = false) { patch_data += "wtv-system-chipversion: %s\r\n"; patch_data += "User-Agent: %s\r\n"; } - else if ((type == "wtv-encryption" && !invert) || (type == "wtv-incarnation" && invert) ) { + else if ((type === "wtv-encryption" && !invert) || (type === "wtv-incarnation" && invert) ) { patch_data = "wtv-tourist-enabled: %s\r\n"; patch_data += "wtv-demo-enabled: %s\r\n"; patch_data += "wtv-default-client-scriptprops: %s\r\n"; @@ -106,7 +106,7 @@ function getPatchDataType(type, invert = false) { function getResData(file) { let res_data = null; - if (file.slice(-2, 2).toLowerCase() == "gz") { + if (file.slice(-2, 2).toLowerCase() === "gz") { const res_gz_data = wtvshared.getServiceDep("/viewergen/" + file); res_data = zlib.gunzipSync(res_gz_data); } else { @@ -227,14 +227,14 @@ function getPatchData(fname, client_data_obj, start_url = "client:GoToConn", def const val = customized_patch_data[idx]; if (typeof val === 'string') { // start url override - if (start_url != patch_defaults.start_url && start_url.length <= patch_limits.start_url) { - if (val.slice(0, patch_defaults.start_url.length) == patch_defaults.start_url) + if (start_url !== patch_defaults.start_url && start_url.length <= patch_limits.start_url) { + if (val.slice(0, patch_defaults.start_url.length) === patch_defaults.start_url) customized_patch_data[idx] = start_url + "\x00"; } // default service ip override - if (default_ip != patch_defaults.default_ip && default_ip.length <= patch_limits.default_ip) { - if (val.slice(0, patch_defaults.default_ip.length) == patch_defaults.default_ip) + if (default_ip !== patch_defaults.default_ip && default_ip.length <= patch_limits.default_ip) { + if (val.slice(0, patch_defaults.default_ip.length) === patch_defaults.default_ip) customized_patch_data[idx] = default_ip + "\x00"; } } else { @@ -242,7 +242,7 @@ function getPatchData(fname, client_data_obj, start_url = "client:GoToConn", def // not a buffer object let patch_data_string = ""; const block_length = val['length']; - const patch_data = getPatchDataType(val['type'], (fname.slice(12, 3) != "1.1")); + const patch_data = getPatchDataType(val['type'], (fname.slice(12, 3) !== "1.1")); if (patch_data) { const patch_data_array = patch_data.split("\r\n"); @@ -256,7 +256,7 @@ function getPatchData(fname, client_data_obj, start_url = "client:GoToConn", def } }); } - if (fname.slice(12, 3) != "2.5") { + if (fname.slice(12, 3) !== "2.5") { const length_difference = block_length - patch_data_string.length; if (length_difference > 0) patch_data_string += "\x00".repeat(length_difference - (val['type'].length + 1)); @@ -292,7 +292,7 @@ function patchBinary(patchDataObject) { function generateSSID() { const ssid_template = "91xxxxxxaeb002"; let ssid = ssid_template; - while (ssid.indexOf("x") != -1) { + while (ssid.indexOf("x") !== -1) { // random hex char from 0-F ssid = ssid.replace("x", Math.floor(Math.random() * 16).toString(16)) } @@ -458,7 +458,7 @@ if (request_headers.query.viewer && const viewer_gz_data = wtvshared.getServiceDep("/viewergen/" + viewer_file + ".gz"); const viewer_data = zlib.gunzipSync(viewer_gz_data); const viewer_md5 = crypto.createHash('md5').update(viewer_data).digest("hex"); - if (viewer_md5 != viewer_stock_md5s[viewer_file]) { + if (viewer_md5 !== viewer_stock_md5s[viewer_file]) { console.error(viewer_file, "md5sum error. expected:", viewer_stock_md5s[viewer_file], ", got:", viewer_md5) const errpage = wtvshared.doErrorPage("500", null, socket.minisrv_pc_mode) headers = errpage[0]; @@ -514,7 +514,7 @@ Content-Disposition: attachment; filename="${viewer_file.replace(".exe", ".zip") console.log(request_headers) let update_str = "http://" + request_headers.host + request_headers.request_url.split('?')[0] + "?ssid=" + client_ssid; Object.keys(request_headers.query).forEach((k) => { - if (k != "random_ssid") { + if (k !== "random_ssid") { update_str += "&" + encodeURIComponent(k) + "=" + encodeURIComponent(request_headers.query[k]); } }); @@ -525,7 +525,7 @@ Content-Disposition: attachment; filename="${viewer_file.replace(".exe", ".zip") const romset_zip = new AdmZip(wtvshared.getServiceDep("/viewergen/" + viewer_file.replace(".exe", "").replace("WebTVIntel", "AppData") + ".zip", true)); const zipEntries = romset_zip.getEntries(); zipEntries.forEach(function (zipEntry) { - if (zipEntry.entryName == "Setup.bmp" && request_headers.query.logo) { + if (zipEntry.entryName === "Setup.bmp" && request_headers.query.logo) { const logo_file = logos[parseInt(request_headers.query.logo) || 0]; if (logo_file) { const logo_gz_data = wtvshared.getServiceDep("/viewergen/" + logo_file + ".gz"); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/noflash.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/noflash.js index 97aff745..cc88f3a8 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/noflash.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/noflash.js @@ -1,12 +1,12 @@ const minisrv_service_file = true; let wtvsec_login; -if (socket.ssid != null && !session_data.get("wtvsec_login")) { +if (socket.ssid !== null && !session_data.get("wtvsec_login")) { wtvsec_login = session_data.createWTVSecSession(); wtvsec_login.IssueChallenge(); if (request_headers["wtv-incarnation"]) wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); session_data.set("wtvsec_login", wtvsec_login); -} else if (socket.ssid != null) { +} else if (socket.ssid !== null) { wtvsec_login = session_data.get("wtvsec_login"); } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js index a92e91e7..78bb1db1 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js @@ -3,9 +3,9 @@ let gourl = "wtv-head-waiter:/login?"; let file_path = null; if (session_data) { - if (session_data.loadSessionData() == true) { + if (session_data.loadSessionData() === true) { console.log(" * Loaded session data from disk for", wtvshared.filterSSID(socket.ssid)) - session_data.setSessionData("registered", (session_data.getSessionData("registered") == true) ? true : false); + session_data.setSessionData("registered", (session_data.getSessionData("registered") === true) ? true : false); } else { session_data.session_data = {}; session_data.setSessionData("registered", false); @@ -14,8 +14,8 @@ if (session_data) { if (session_data.data_store.sockets) { let i = 0; session_data.data_store.sockets.forEach(function (k) { - if (typeof k != "undefined") { - if (k != socket) { + if (typeof k !== "undefined") { + if (k !== socket) { k.destroy(); session_data.data_store.sockets.delete(k); i++; @@ -59,7 +59,7 @@ if (session_data.data_store.wtvsec_login) { let send_tellyscript = (minisrv_config.services[service_name].send_tellyscripts && !request_headers.query.relogin && !bootrom !== 0); const wtv_script_id = parseInt(session_data.get("wtv-script-id")); const wtv_script_mod = parseInt(session_data.get("wtv-script-mod")); - if ((request_headers.query.reconnect || request_headers.query.relogin) && wtv_script_id != 0) send_tellyscript = false; + if ((request_headers.query.reconnect || request_headers.query.relogin) && wtv_script_id !== 0) send_tellyscript = false; if (wtv_script_id !== 0 && wtv_script_mod !== 0) send_tellyscript = false; if (!minisrv_config.services[service_name].send_tellyscript_to_mame) { if (wtvshared.parseSSID(socket.ssid).boxType === "MAME") { @@ -68,7 +68,7 @@ if (session_data.data_store.wtvsec_login) { } if (minisrv_config.services[service_name].tellyscript_ssid_blacklist) { - send_tellyscript = (minisrv_config.services[service_name].tellyscript_ssid_blacklist.findIndex(element => element == socket.ssid) == -1) + send_tellyscript = (minisrv_config.services[service_name].tellyscript_ssid_blacklist.findIndex(element => element === socket.ssid) === -1) } if (send_tellyscript) { @@ -157,8 +157,8 @@ if (session_data.data_store.wtvsec_login) { if (request_headers.query.reconnect) gourl = null; - if (file_path != null && send_tellyscript && !minisrv_config.config.debug_flags.quiet) console.log(" * Sending TellyScript", file_path, "on socket", socket.id); - if (template != null && send_tellyscript && !minisrv_config.config.debug_flags.quiet) console.log(" * Generating TellyScript on socket", socket.id); + if (file_path !== null && send_tellyscript && !minisrv_config.config.debug_flags.quiet) console.log(" * Sending TellyScript", file_path, "on socket", socket.id); + if (template !== null && send_tellyscript && !minisrv_config.config.debug_flags.quiet) console.log(" * Generating TellyScript on socket", socket.id); headers = "200 OK\n" @@ -181,7 +181,7 @@ if (session_data.data_store.wtvsec_login) { headers += "wtv-boot-url: wtv-head-waiter:/login?relogin=true"; headers += "\n"; } - if (gourl != null) headers += "wtv-visit: " + gourl + "\n"; + if (gourl !== null) headers += "wtv-visit: " + gourl + "\n"; if (!bf0app_update && session_data.get("wtv-open-access")) headers += "wtv-open-isp-disabled: false\n"; headers += "wtv-client-time-zone: GMT -0000\n"; headers += "wtv-client-time-dst-rule: GMT\n" diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/admin.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/admin.js index 9af9e026..73304625 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/admin.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/admin.js @@ -7,7 +7,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/ban.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/ban.js index 0b07005a..6837ec29 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/ban.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/ban.js @@ -7,7 +7,7 @@ if (auth === true) { let result, ssid, password; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } @@ -44,10 +44,10 @@ wtv-expire-all: wtv-admin:/ban`;

` if (request_headers.query.ssid) { - if (result == wtva.REASON_SELF) { + if (result === wtva.REASON_SELF) { data += "Cannot ban yourself." } else { - if (result == wtva.REASON_EXISTS) { + if (result === wtva.REASON_EXISTS) { data += "SSID " + request_headers.query.ssid + " is already in the ban list.

"; } else if (result === wtva.SUCCESS) { reloadConfig(); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteaccount.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteaccount.js index 9bc64a6c..ad4b258e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteaccount.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteaccount.js @@ -8,7 +8,7 @@ if (auth === true) { let ssid_match = false; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } @@ -19,7 +19,7 @@ if (auth === true) { user_info = wtva.getAccountInfoBySSID(ssid); if (request_headers.query.confirm_delete) { user_info = null; - if (ssid == socket.ssid) { + if (ssid === socket.ssid) { ssid_match = true; } else { // delete @@ -63,7 +63,7 @@ wtv-noback-all: wtv-admin:/deleteaccount`; if (Object.keys(user_info.account_users).length > 1) { data += `` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteuser.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteuser.js index 16ac6692..cc957cb8 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteuser.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/deleteuser.js @@ -12,7 +12,7 @@ if (auth === true) { const show_box_was_unregistered = false; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } @@ -22,7 +22,7 @@ if (auth === true) { user_info = wtva.getAccountInfo(request_headers.query.username.toLowerCase()); // username search if (user_info) { - if (user_info.ssid == socket.ssid) { + if (user_info.ssid === socket.ssid) { show_cannot_modify_self = true; } if (request_headers.query.confirm_delete) { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/findaccount.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/findaccount.js index 482a1003..a8d54d50 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/findaccount.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/findaccount.js @@ -8,7 +8,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } @@ -53,7 +53,7 @@ wtv-noback-all: wtv-admin:/findaccount`; if (Object.keys(user_info.account_users).length > 1) { data += `` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/operatortweaks.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/operatortweaks.js index 7d83e7ae..cf38d846 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/operatortweaks.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/operatortweaks.js @@ -20,15 +20,15 @@ function generateFormField(type, confvar, options = null) { confvar_value = user_config.config[confvar] || minisrv_config.config[confvar]; } - if (type == "input") + if (type === "input") return `` - if (type == "checkbox") + if (type === "checkbox") return `\n` - if (type == "select") { + if (type === "select") { let out = `"; @@ -39,7 +39,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/polyzoot.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/polyzoot.js index 56786389..5c25b144 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/polyzoot.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/polyzoot.js @@ -8,7 +8,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } @@ -79,7 +79,7 @@ data += `

` if (request_headers.query.username) { if (user_info && !request_headers.query.confirm && !request_headers.query.reset) { - if (user_info.username == session_data.getSessionData("subscriber_username")) { + if (user_info.username === session_data.getSessionData("subscriber_username")) { data += `Are you sure you want to Polyzoot yourself?
Are you a masochist?`; } else { data += `Are you sure you want to Polyzoot ${user_info.username}?
Are you a sadist?`; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/regenfavs.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/regenfavs.js index 68c16409..e50c8ed1 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/regenfavs.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/regenfavs.js @@ -8,7 +8,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/reloadconfig.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/reloadconfig.js index 481bb24a..f2f1bc0d 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/reloadconfig.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/reloadconfig.js @@ -7,7 +7,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/removeuserpasswd.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/removeuserpasswd.js index b9b9d87c..7de85c2e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/removeuserpasswd.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/removeuserpasswd.js @@ -10,7 +10,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } @@ -19,7 +19,7 @@ if (auth === true) { if (request_headers.query.username) { user_info = wtva.getAccountInfo(request_headers.query.username.toLowerCase()); // username search if (user_info) { - if (user_info.ssid == socket.ssid) { + if (user_info.ssid === socket.ssid) { show_cannot_modify_self = true; } const userAccount = wtva.getAccountBySSID(user_info.ssid); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/unban.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/unban.js index 79e461fe..b2cbdee1 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/unban.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/unban.js @@ -10,7 +10,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } @@ -22,7 +22,7 @@ if (auth === true) { if (!fake_config.config.ssid_block_list) fake_config.config.ssid_block_list = []; if (typeof request_headers.query.unban_ssid === 'string') { Object.keys(fake_config.config.ssid_block_list).forEach(function (k) { - if (fake_config.config.ssid_block_list[k] == request_headers.query.unban_ssid) { + if (fake_config.config.ssid_block_list[k] === request_headers.query.unban_ssid) { fake_config.config.ssid_block_list.splice(k, 1); ssids_removed.push(request_headers.query.unban_ssid) config_changed = true; @@ -30,9 +30,9 @@ if (auth === true) { }); } else { Object.keys(fake_config.config.ssid_block_list).forEach(function (k) { - Object.keys(request_headers.query.unban_ssid).forEach(function (j) { - if (fake_config.config.ssid_block_list[k] == request_headers.query.unban_ssid[j]) { - fake_config.config.ssid_block_list.splice(k,1); + Object.keys(request_headers.query.unban_ssid).forEach(function (j) { + if (fake_config.config.ssid_block_list[k] === request_headers.query.unban_ssid[j]) { + fake_config.config.ssid_block_list.splice(k, 1); ssids_removed.push(request_headers.query.unban_ssid[j]) config_changed = true; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/validate-operator-tweaks.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/validate-operator-tweaks.js index f140f617..e482ab86 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/validate-operator-tweaks.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-admin/validate-operator-tweaks.js @@ -8,7 +8,7 @@ if (auth === true) { let password = null; if (request_headers.Authorization) { const authheader = request_headers.Authorization.split(' '); - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); if (password) password = password.split(':')[1]; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/add-media-to-block.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/add-media-to-block.js index c2b72ac0..ce6d23d0 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/add-media-to-block.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/add-media-to-block.js @@ -10,7 +10,7 @@ const oldPosition = request_headers.query.oldBlockNum; const editing = request_headers.query.editing; let page; -if (editing == "true"){ +if (editing === "true"){ session_data.pagestore.editPhotoBlock(docName, request_headers.query.blockNum, request_headers.query.newBlockNum, null, null, request_headers.query.blockTitle, request_headers.query.photoBlockCaption); headers = `300 OK wtv-expire-all: wtv-author:/block-preview @@ -22,14 +22,14 @@ Location: wtv-author:/show-blocks?docName=${docName}` } else { const page = session_data.pagestore.loadPage(docName); const blockNum = request_headers.query.blockNum; - if (request_headers.query.scrapbookID != undefined) { + if (request_headers.query.scrapbookID !== undefined) { const image = session_data.pagestore.getScrapbookImage(parseInt(request_headers.query.scrapbookID)); - if (page.blocks[blockNum] != undefined) + if (page.blocks[blockNum] !== undefined) session_data.pagestore.editPhotoBlock(docName, request_headers.query.blockNum, request_headers.query.blockNum, image, "scrapbook", null, null); else session_data.pagestore.createPhotoBlock(docName, image, "scrapbook"); } else { - if (page.blocks[blockNum] != undefined) + if (page.blocks[blockNum] !== undefined) session_data.pagestore.editPhotoBlock(docName, request_headers.query.blockNum, request_headers.query.blockNum, request_headers.query.mediaPath, "clipart", null, null); else session_data.pagestore.createPhotoBlock(docName, request_headers.query.mediaPath, "clipart"); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/doc-info.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/doc-info.js index bcb17f9d..57f752e7 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/doc-info.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/doc-info.js @@ -3,7 +3,7 @@ const minisrv_service_file = true; const pagestore_exists = session_data.pagestore.pagestoreExists(); const docName = request_headers.query.docName; -if (pagestore_exists != true) +if (pagestore_exists !== true) { session_data.pagestore.createPagestore(); headers = `300 OK @@ -129,7 +129,7 @@ ${page.title}

` -if (page.published == true) +if (page.published === true) data += `published ${page.publishdate}` else data += "not published" @@ -163,7 +163,7 @@ Change how your page is listed

@@ -211,7 +211,7 @@ if (textsize == "-1") Medium ` -} else if (textsize == "+1") +} else if (textsize === "+1") { data += ` @@ -233,7 +233,7 @@ data += `
You are previewing your page. Press Back @@ -38,7 +38,7 @@ to return to editing it. `; this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -48,7 +48,7 @@ to return to editing it. `>${title} `; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Republican.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Republican.js index 99e8febc..f167cc7f 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Republican.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Republican.js @@ -26,7 +26,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -35,7 +35,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -44,7 +44,7 @@ to return to editing it. this.styledata.text + `>${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ringbinder.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ringbinder.js index 5bb016be..eeffb511 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ringbinder.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Ringbinder.js @@ -22,7 +22,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -37,13 +37,13 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Rivets.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Rivets.js index a3095a4f..fea664c8 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Rivets.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Rivets.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/South_Beach.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/South_Beach.js index 2c283b89..70f9d439 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/South_Beach.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/South_Beach.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Space.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Space.js index 01a1d9c3..e49313eb 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Space.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Space.js @@ -21,7 +21,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -30,7 +30,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -49,7 +49,7 @@ ${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Stone.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Stone.js index 4b6a2908..bcd721b8 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Stone.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Stone.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -42,7 +42,7 @@ to return to editing it. this.styledata.text + `>${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Tan.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Tan.js index fb67724f..8467b9fd 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Tan.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Tan.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -42,7 +42,7 @@ to return to editing it. this.styledata.text + `>${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Water.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Water.js index d41b53c3..557ba079 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Water.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Water.js @@ -23,7 +23,7 @@ class PBTemplate {
`; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += `
You are previewing your page. Press Back @@ -32,7 +32,7 @@ to return to editing it.
`; } this.styledata.titheader = ``; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } @@ -41,7 +41,7 @@ to return to editing it. ${title}`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Wedding.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Wedding.js index 12290bef..6c5981e5 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Wedding.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-author/styles/Wedding.js @@ -26,7 +26,7 @@ class PBTemplate { ${title} `; - if (state == "previewing") { + if (state === "previewing") { this.styledata.header += ` every 8 entries, but only if its not the last entry i = 0; data += `
You are previewing your page. Press Back @@ -40,13 +40,13 @@ to return to editing it.
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ` `; } this.styledata.titheader += `${title}
`; - if (state == "editing") { + if (state === "editing") { this.styledata.titheader += ``; } diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/prerendered/Tips/Options/Send.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/prerendered/Tips/Options/Send.js index 4dee1294..ea6cb07e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/prerendered/Tips/Options/Send.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/prerendered/Tips/Options/Send.js @@ -64,7 +64,7 @@ the page's address.
\n${self.page_args.letters[k]}\n` i++; j++; - if (i == 8 && self.page_args.letters.length != (j + 1)) { + if (i === 8 && self.page_args.letters.length !== (j + 1)) { // add new
\n`; diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/templates/glossary_word_index.js b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/templates/glossary_word_index.js index 959c7c61..5a2fa8a7 100644 --- a/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/templates/glossary_word_index.js +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/templates/wtv-guide/templates/glossary_word_index.js @@ -63,11 +63,11 @@ Choose a word to see what it means. // test data += `${self.page_args.words[k].word}
\n` words_rendered++; - if (self.page_args.words.length % 2 != 0) { + if (self.page_args.words.length % 2 !== 0) { // odd so split later to put extra on first row - if (words_rendered - 1 == table_split) data += `
`; + if (words_rendered - 1 === table_split) data += ``; } else { - if (words_rendered == table_split) data += ``; + if (words_rendered === table_split) data += ``; } }); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/http_pb/index.js b/zefie_wtvp_minisrv/includes/ServiceVault/http_pb/index.js index a5ff3626..57a4b3d1 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/http_pb/index.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/http_pb/index.js @@ -5,7 +5,7 @@ let site = ""; if (minisrv_config.services['wtv-author'].public_domain) { site = minisrv_config.services['wtv-author'].public_domain; } else { - if (minisrv_config.services['wtv-author'].publish_mode == "service") { + if (minisrv_config.services['wtv-author'].publish_mode === "service") { const target_service = minisrv_config.services[minisrv_config.services['wtv-author'].publish_dest]; if (target_service) { site = target_service.host + ":" + target_service.port; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/index.js b/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/index.js index b26c332b..0475b834 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/index.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/index.js @@ -9,7 +9,7 @@ if (auth === true) { const authheader = request_headers.authorization.split(' '); console.log(request_headers) - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { password = Buffer.from(authheader[1], 'base64').toString(); password = password.split(':')[1]; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/ssid.js b/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/ssid.js index 1fb1a48c..aca2f5b6 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/ssid.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/http_pc/admin/ssid.js @@ -9,7 +9,7 @@ if (auth === true) { const authheader = request_headers.authorization.split(' '); console.log(request_headers) - if (authheader[0] == "Basic") { + if (authheader[0] === "Basic") { let password = Buffer.from(authheader[1], 'base64').toString(); password = password.split(':')[1]; } @@ -29,7 +29,7 @@ Content-Type: text/html` Welcome to the zefie minisrv v${minisrv_config.version} Account Administration

`; - if (request_headers.query.cmd == "list") { + if (request_headers.query.cmd === "list") { data += `
`; if (request_headers.query.msg) { data += decodeURI(request_headers.query.msg) + "
"; @@ -41,7 +41,7 @@ Welcome to the zefie minisrv v${minisrv_config.version} Account Administration }); data += `
`; - } else if (request_headers.query.cmd == "ssid") { + } else if (request_headers.query.cmd === "ssid") { const ssid = request_headers.query.ssid; if (!ssid) { redirectmsg = `An SSID is required for the ${request_headers.query.cmd} command.`; @@ -78,7 +78,7 @@ function validateSelection(cmd, ssid, friendlymsg) { if (Object.keys(user_info.account_users).length > 1) { data += `
Additional Users:`; Object.keys(user_info.account_users).forEach(function (k) { - if (k == "subscriber") return; + if (k === "subscriber") return; data += user_info.account_users[k].subscriber_username + "
"; }) data += `
Additional Users:`; Object.keys(user_info.account_users).forEach(function (k) { - if (k == "subscriber") return; + if (k === "subscriber") return; data += user_info.account_users[k].subscriber_username + "
"; }) data += `
Additional Users:`; Object.keys(user_info.account_users).forEach(function (k) { - if (k == "subscriber") return; + if (k === "subscriber") return; data += user_info.account_users[k].subscriber_username + "
"; }) data += `
` - if (page.published != true) + if (page.published !== true) data += `Publish page
diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/documents.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/documents.js index e855cec0..f18fc4f6 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/documents.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/documents.js @@ -4,7 +4,7 @@ const pagestore_exists = session_data.pagestore.pagestoreExists(); const site = session_data.pagestore.getPublishDomain(); -if (pagestore_exists != true) +if (pagestore_exists !== true) session_data.pagestore.createPagestore(); const pagearray = session_data.pagestore.listPages(); @@ -163,7 +163,7 @@ data = ` ` for (let i = 0; i < numofpages; i++) { data += `
` - if (i == 0) + if (i === 0) data += ` ` @@ -181,7 +181,7 @@ ${pagearray[i].description}

` -if (pagearray[i].published == true) +if (pagearray[i].published === true) data += `published ${pagearray[i].publishdate}` else data += "not published" diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-block.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-block.js index dce72075..3b490f24 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-block.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-block.js @@ -203,7 +203,7 @@ Add text to your document

Text size:` const textsize = pagedata.blocks[oldBlockNum].size -if (textsize == "-1") +if (textsize === "-1") { data += ` Small Large SmallText style:` const textstyle = pagedata.blocks[oldBlockNum].style -if (textstyle == "B") +if (textstyle === "B") { data += ` @@ -243,7 +243,7 @@ Plain Italic
` -} else if (textstyle == "I") { +} else if (textstyle === "I") { data += `
Plain
@@ -597,7 +597,7 @@ autohiragana growable width=100% value="` -if (pagedata.blocks[oldBlockNum].caption != null) +if (pagedata.blocks[oldBlockNum].caption !== null) data += `${pagedata.blocks[oldBlockNum].caption}` data += `" cols=45 rows=3> @@ -837,14 +837,14 @@ Add a heading to your document
` -if (blockType == "snapshot") { +if (blockType === "snapshot") { data += `` -} else if (blockType == "clipart") { +} else if (blockType === "clipart") { data += `` } data += ` @@ -579,7 +579,7 @@ DisplayViewOption(true);
` - else if (pagedata.blocks[oldBlockNum].size == "H1") + else if (pagedata.blocks[oldBlockNum].size === "H1") data += ` @@ -870,7 +870,7 @@ Before the heading @@ -1204,7 +1204,7 @@ function SetListItems() for (let i = 0; i < pagedata.blocks[oldBlockNum].items.length; i++) { data += `ListElements[${i}] = new Object;` - if (pagedata.blocks[oldBlockNum].items[i].name == undefined) + if (typeof pagedata.blocks[oldBlockNum].items[i].name === 'undefined') data += `ListElements[${i}].desc = "";` else data += `ListElements[${i}].desc = "${pagedata.blocks[oldBlockNum].items[i].name}";` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-title.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-title.js index c2ea3d16..4adf301b 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-title.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/edit-title.js @@ -7,7 +7,7 @@ headers = `200 OK Connection: Keep-Alive Content-Type: text/html` -if (request_headers.query.publishing == "true") { +if (request_headers.query.publishing === "true") { data = ` @@ -110,7 +110,7 @@ cols=45 rows=4 MAXLENGTH=128> ` -} else if (request_headers.query.titleOnly == "true") { +} else if (request_headers.query.titleOnly === "true") { data = ` @@ -194,7 +194,7 @@ as well as in the list of your pages.
Text size:` - if (pagedata.blocks[oldBlockNum].size == "H3") + if (pagedata.blocks[oldBlockNum].size === "H3") data += ` Small Medium Large Small @@ -862,7 +862,7 @@ data += `
Add a divider line: Before the heading
After the heading
diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/publish.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/publish.js index 528606e5..3f1b5f98 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/publish.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/publish.js @@ -4,7 +4,7 @@ const docName = request_headers.query.docName; const page = session_data.pagestore.loadPage(docName); const site = session_data.pagestore.getPublishDomain(); -if (request_headers.query.publishStage == "1") { +if (request_headers.query.publishStage === "1") { headers = `200 OK Content-Type: text/html` @@ -77,7 +77,7 @@ Your public list of pages will be at:
Include in public list @@ -116,24 +116,24 @@ Include in public list ` -} else if (request_headers.query.publishStage == "2") { +} else if (request_headers.query.publishStage === "2") { let inlist; - if (request_headers.query.includeInPublicList != undefined) { + if (typeof request_headers.query.includeInPublicList !== 'undefined') { inlist = true; } else { inlist = false; } const result = session_data.pagestore.publishPage(docName, inlist); - if (result == true) { + if (result === true) { headers = `300 OK wtv-expire-all: wtv-author:/documents Location: wtv-author:/congrats?docName=${docName}` } else { headers = `400 ${result}` } -} else if (request_headers.query.unpublish == "1") { +} else if (request_headers.query.unpublish === "1") { const result = session_data.pagestore.unpublishPage(docName); - if (result == true) { + if (result === true) { headers = `300 OK wtv-expire-all: wtv-author:/documents wtv-expire-all: wtv-author:/doc-info diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-block.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-block.js index 940f3128..9865772e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-block.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-block.js @@ -11,9 +11,9 @@ const editing = request_headers.query.editing; const blockClass = request_headers.query.blockClass; switch(blockClass) { case "23": - if (editing == "true") { + if (editing === "true") { const photo = request_headers.query.photoBlockPhoto; - if (request_headers.query.toSnapshot == "true") + if (request_headers.query.toSnapshot === "true") session_data.pagestore.editPhotoBlock(docName, request_headers.query.blockNum, request_headers.query.newBlockNum, photo, "snapshot", request_headers.query.blockTitle, request_headers.query.photoBlockCaption); else session_data.pagestore.editPhotoBlock(docName, request_headers.query.blockNum, request_headers.query.newBlockNum, null, null, request_headers.query.blockTitle, request_headers.query.photoBlockCaption); @@ -36,14 +36,14 @@ Location: ${request_headers.query.returnPageURL + "&numOfBlocks=" + page.blocks. } break; case "21": - if (caption.length == 0) { + if (caption.length === 0) { headers = "400 You must enter a caption. Please enter a caption and try again." } else { - if (editing == "true") { - if (size.length == 0) + if (editing === "true") { + if (size.length === 0) size = null; - - if (style.length == 0) + + if (style.length === 0) style = null; session_data.pagestore.editTextBlock(docName, title, caption, size, style, position, oldPosition); headers = `300 OK @@ -53,10 +53,10 @@ Location: ${request_headers.query.returnPageURL + "&numOfBlocks=" + page.blocks. wtv-expire-all: wtv-author:/edit-block Location: wtv-author:/show-blocks?docName=${docName}` } else { - if (size.length == 0) + if (size.length === 0) size = null; - - if (style.length == 0) + + if (style.length === 0) style = null; session_data.pagestore.createTextBlock(docName, title, caption, size, style, position); headers = `300 OK @@ -72,10 +72,10 @@ Location: ${request_headers.query.returnPageURL + "&numOfBlocks=" + page.blocks. size = request_headers.query.headingBlockSize const dividerBefore = request_headers.query.headingBlockDividerBefore const dividerAfter = request_headers.query.headingBlockDividerAfter - if (header.length == 0) { + if (header.length === 0) { headers = "400 You must enter a header. Please enter a header and try again." } else { - if (editing == "true") { + if (editing === "true") { session_data.pagestore.editHeaderBlock(docName, header, size, dividerBefore, dividerAfter, position, request_headers.query.blockNum); headers = `300 OK wtv-expire-all: wtv-author:/block-preview @@ -94,7 +94,7 @@ Location: wtv-author:/show-blocks?docName=${docName}` } break; case "24": - if (editing == "true") { + if (editing === "true") { const listItems = request_headers.query.listItemText.filter(function(e){ return e.replace(/(\r\n|\n|\r)/gm,"")}); session_data.pagestore.editListBlock(docName, title, listItems, position, request_headers.query.blockNum); headers = `300 OK @@ -114,7 +114,7 @@ Location: wtv-author:/show-blocks?docName=${docName}` } break; case "25": - if (editing == "true") { + if (editing === "true") { const listItems = request_headers.query.listItemText; const linkItems = request_headers.query.linkItemURL; session_data.pagestore.editLinkBlock(docName, title, listItems, linkItems, position, request_headers.query.blockNum); @@ -137,7 +137,7 @@ Location: wtv-author:/show-blocks?docName=${docName}` break; case "27": - if (editing == "true") { + if (editing === "true") { session_data.pagestore.editBreakBlock(docName, position, request_headers.query.blockNum); headers = `300 OK wtv-expire-all: wtv-author:/block-preview diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-title.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-title.js index d798a34c..870115e3 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-title.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/save-title.js @@ -3,7 +3,7 @@ const minisrv_service_file = true; const docName = request_headers.query.docName; const docTitle = request_headers.query.docTitle; -if (docTitle.length == 0) { +if (docTitle.length === 0) { headers = "400 You must enter a title for your page. Please enter a title and try again." } else { const pagedata = session_data.pagestore.loadPage(docName); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/scrapbook-add.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/scrapbook-add.js index 207f3d96..4a4cc92b 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/scrapbook-add.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-author/scrapbook-add.js @@ -48,7 +48,7 @@ if (!request_headers.query.mediaData && !request_headers.query.mediaPath) { function isValidImageType(contentType, url) { // Check content-type header or file extension if (contentType) { - return contentType === 'image/jpeg' || contentType == 'image/jpg' || contentType === 'image/gif'; + return contentType === 'image/jpeg' || contentType === 'image/jpg' || contentType === 'image/gif'; } return url.endsWith('.jpg') || url.endsWith('.jpeg') || url.endsWith('.gif'); } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-chat/home.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-chat/home.js index eb431618..c21edab8 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-chat/home.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-chat/home.js @@ -109,12 +109,12 @@ Chat Home - + - + diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/content/DownloadScreen.tmpl.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/content/DownloadScreen.tmpl.js index 07638031..a6e476d8 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/content/DownloadScreen.tmpl.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/content/DownloadScreen.tmpl.js @@ -12,7 +12,7 @@ let diskmap_data = {}; if (!request_headers.query.url) { Object.keys(service_vaults).forEach(function (g) { - if (diskmap_json_file != null) return; + if (diskmap_json_file !== null) return; diskmap_json_file = service_vaults[g] + "/" + service_name + "/" + diskmap_dir + diskmap + ".json"; if (!fs.existsSync(diskmap_json_file)) diskmap_json_file = null; }); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/sync.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/sync.js index 1a9ab904..aae49370 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/sync.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-disk/sync.js @@ -3,12 +3,12 @@ const minisrv_service_file = true; const diskmap = request_headers.query[wtvshared.getCaseInsensitiveKey("DiskMap", request_headers.query)]; const wtvdl = new WTVDisk(minisrv_config, service_name); -const force_update = (request_headers.query.force == "true") ? true : false; -const no_delete = (request_headers.query.dont_delete_files == "true") ? true : false; +const force_update = (request_headers.query.force === "true") ? true : false; +const no_delete = (request_headers.query.dont_delete_files === "true") ? true : false; const content_dir = "content/" const diskmap_dir = content_dir + "diskmaps/"; -if (request_headers['wtv-request-type'] == 'download') { +if (request_headers['wtv-request-type'] === 'download') { function generateDownloadList(diskmap_group_name, update_list, diskmap_group_data) { wtvdl.reset(); @@ -34,7 +34,7 @@ if (request_headers['wtv-request-type'] == 'download') { if (force_update && !no_delete) { // don't delete Browser partition, ever, but allow deleting of Browser partition subdirs if (!diskmap_group_data.base.match(/disk\/browser(\/)?$/i)) { - if (diskmap_group_data.client_group_data.path.toLowerCase() == diskmap_group_data.base.toLowerCase()) { + if (diskmap_group_data.client_group_data.path.toLowerCase() === diskmap_group_data.base.toLowerCase()) { wtvdl.delete(diskmap_group_data.base, null); } else { wtvdl.delete(diskmap_group_data.base, diskmap_group_data.client_group_data.group); @@ -60,7 +60,7 @@ if (request_headers['wtv-request-type'] == 'download') { Object.keys(update_list).forEach(function (k) { // file { "action": "delete" } // Useful to purge files we no longer want on the client - if (update_list[k].action != "DELETE" && update_list[k].action != "DELETEONLY") { + if (update_list[k].action !== "DELETE" && update_list[k].action !== "DELETEONLY") { // skip deleting valid files if we aren't specifically requesting their deletion if (update_list[k].checksum_match && !force_update) return; if (!update_list[k].invalid && !force_update) return; @@ -75,7 +75,7 @@ if (request_headers['wtv-request-type'] == 'download') { Object.keys(update_list).forEach(function (k) { if (update_list[k].checksum_match && !force_update) return; if (!update_list[k].invalid && !force_update) return; - if (update_list[k].action == "DELETEONLY") return; + if (update_list[k].action === "DELETEONLY") return; if (update_list[k].display) wtvdl.display(update_list[k].display); switch (update_list[k].action) { case "PUT": @@ -98,7 +98,7 @@ if (request_headers['wtv-request-type'] == 'download') { Object.keys(update_list).forEach(function (k) { if (update_list[k].checksum_match && !force_update) return; if (!update_list[k].invalid && !force_update) return; - if (update_list[k].action == "DELETEONLY") return; + if (update_list[k].action === "DELETEONLY") return; wtvdl.rename(update_list[k].file.replace(diskmap_group_data.base, ""), update_list[k].file.replace(diskmap_group_data.base, ""), diskmap_group_name, diskmap_group_name, update_list[k].rename || update_list[k].original_filename || null); }); @@ -143,7 +143,7 @@ if (request_headers['wtv-request-type'] == 'download') { let post_data_current_checksum = false; let post_data_last_checkup_time = 0; Object.keys(post_data).forEach(function (k) { - if (post_data[k].slice(0, 7) == "file://") { + if (post_data[k].slice(0, 7) === "file://") { entry_type = "folder"; post_data_current_file = false; post_data_current_version = false; @@ -185,13 +185,13 @@ if (request_headers['wtv-request-type'] == 'download') { break; } } else { - if (!entry_type && post_data[k] != "") { + if (!entry_type && post_data[k] !== "") { entry_type = "file"; post_data_current_file = post_data[k]; } - if (post_data[k] == "" && entry_type) { - const post_data_current_path = ((entry_type == "file") ? (post_data_current_directory + post_data_current_file) : post_data_current_directory); + if (post_data[k] === "" && entry_type) { + const post_data_current_path = ((entry_type === "file") ? (post_data_current_directory + post_data_current_file) : post_data_current_directory); const index = post_data_current_path.replace(/[\:\/]/g, "_").toLowerCase() + "_" + post_data_current_group; if (index.match(/\/$/)) entry_type = "folder"; if (!post_data_fileinfo[index]) post_data_fileinfo[index] = {}; @@ -215,7 +215,7 @@ if (request_headers['wtv-request-type'] == 'download') { if (!diskmap_group_data.files[k].location) diskmap_group_data.files[k].location = wtvshared.makeSafePath(diskmap_group_data.location,diskmap_group_data.files[k].file.replace(diskmap_group_data.base, ""), true); let diskmap_data_file = null; Object.keys(service_vaults).forEach(function (g) { - if (diskmap_data_file != null) return; + if (diskmap_data_file !== null) return; diskmap_data_file = service_vaults[g] + "/" + service_name + "/" + diskmap_group_data.files[k].location; if (!fs.existsSync(diskmap_data_file) || !fs.lstatSync(diskmap_data_file).isFile()) diskmap_data_file = null; }); @@ -232,7 +232,7 @@ if (request_headers['wtv-request-type'] == 'download') { diskmap_group_data.files[k].action = (diskmap_group_data.files[k].action) ? diskmap_group_data.files[k].action.toUpperCase() : "GET"; // we need the checksum of the uncompressed data - if (wtvshared.getFileExt(diskmap_data_file).toLowerCase() == "gz") { + if (wtvshared.getFileExt(diskmap_data_file).toLowerCase() === "gz") { const diskmap_data_filename = path.basename(diskmap_data_file); const gunzipped = zlib.gunzipSync(diskmap_file_data); diskmap_group_data.files[k].checksum = CryptoJS.MD5(CryptoJS.lib.WordArray.create(gunzipped)).toString(CryptoJS.enc.Hex).toLowerCase(); @@ -256,14 +256,14 @@ if (request_headers['wtv-request-type'] == 'download') { Object.keys(wtv_download_list).forEach(function (k) { wtv_download_list[k].version = newest_file_epoch; Object.keys(post_data_fileinfo).forEach(function (g) { - if (post_data_fileinfo[g].file == wtv_download_list[k].file || post_data_fileinfo[g].file == wtv_download_list[k].base) { + if (post_data_fileinfo[g].file === wtv_download_list[k].file || post_data_fileinfo[g].file === wtv_download_list[k].base) { diskmap_group_data.group_exists = true; - if (wtv_download_list[k].checksum && wtv_download_list[k].checksum.toLowerCase() == post_data_fileinfo[g].checksum) wtv_download_list[k].invalid = false; - else if (post_data_fileinfo[g].version == wtv_download_list[k].version && post_data_fileinfo[g].state !== "invalid") wtv_download_list[k].invalid = false; + if (wtv_download_list[k].checksum && wtv_download_list[k].checksum.toLowerCase() === post_data_fileinfo[g].checksum) wtv_download_list[k].invalid = false; + else if (post_data_fileinfo[g].version === wtv_download_list[k].version && post_data_fileinfo[g].state !== "invalid") wtv_download_list[k].invalid = false; } }); }); - const diskmap_group_name = (diskmap_subgroup == null) ? diskmap_primary_group : diskmap_primary_group + "-" + diskmap_subgroup; + const diskmap_group_name = (diskmap_subgroup === null) ? diskmap_primary_group : diskmap_primary_group + "-" + diskmap_subgroup; diskmap_group_data.client_group_data = client_group_data[diskmap_group_name] || null; output_data = generateDownloadList(diskmap_group_name, wtv_download_list, diskmap_group_data); return output_data; @@ -272,12 +272,12 @@ if (request_headers['wtv-request-type'] == 'download') { if (diskmap && request_headers.query.group) { let diskmap_json_file = null; Object.keys(service_vaults).forEach(function (g) { - if (diskmap_json_file != null) return; + if (diskmap_json_file !== null) return; diskmap_json_file = service_vaults[g] + "/" + service_name + "/" + diskmap_dir + diskmap + ".json"; if (!fs.existsSync(diskmap_json_file)) diskmap_json_file = null; }); - if (diskmap_json_file != null) { + if (diskmap_json_file !== null) { try { // read diskmap const json_stats = fs.lstatSync(diskmap_json_file); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/add.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/add.js index 42be1b59..79b40392 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/add.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/add.js @@ -24,7 +24,7 @@ if (request_headers.post_data) { function getTitle(url) { return new Promise(function (resolve, reject) { let page_title = "Web Page"; - const request_type = (url.slice(0, 5) == "https") ? "https" : "http"; + const request_type = (url.slice(0, 5) === "https") ? "https" : "http"; let proxy_agent = null; switch (request_type) { case "https": @@ -40,7 +40,7 @@ function getTitle(url) { } const request = proxy_agent.get(url, options, (response) => { let req_data = ''; - if (response.statusCode == 301 || response.statusCode == 302) { + if (response.statusCode === 301 || response.statusCode === 302) { redirects++; if (redirects < max_redirects) resolve(getTitle(response.headers.location)); else reject(`Too many redirects. Max: ${max_redirects}, Current: ${redirects}`); @@ -107,7 +107,7 @@ async function saveFavorite(favstore, title, folder, imagetype, favurl) { image = "canned/favorite_default.gif" } - if (favoritenum == minisrv_config.services[service_name].max_favorites_per_folder) { + if (favoritenum === minisrv_config.services[service_name].max_favorites_per_folder) { headers = `400 You can only have ${minisrv_config.services[service_name].max_favorites_per_folder} favorites in a folder. Discard some favorites or choose a different folder, then try again.` } else { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-favorites.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-favorites.js index ebd3d4e0..386583ba 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-favorites.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-favorites.js @@ -6,11 +6,11 @@ const query = request_headers.query const discardAll = request_headers.query.DiscardAll let strName; -if (discardAll != "Discard All") +if (discardAll !== "Discard All") { for(strName in query) { - if (strName != "favorite_folder_name") + if (strName !== "favorite_folder_name") break; } @@ -24,7 +24,7 @@ if (request_headers.query.ForwardToBrowser) Connection: Keep-Alive Content-Type: text/html Location: wtv-favorite:/serve-browser?favorite_folder_name=${folder}` -} else if (strName != "getCaseInsensitiveKey") { +} else if (strName !== "getCaseInsensitiveKey") { const favorite = session_data.favstore.getFavorite(folder, strName); if (errpage) { @@ -33,7 +33,7 @@ Location: wtv-favorite:/serve-browser?favorite_folder_name=${folder}` } else { if (!request_headers.query.confirm_remove) { let message, removeurl; - if (discardAll == "Discard All") + if (discardAll === "Discard All") { message = `Are you sure you want to discard all favorites in this folder?`; removeurl = request_headers.request_url + "&confirm_remove=true&DiscardAll=Discard All"; @@ -58,7 +58,7 @@ Location: ${confirmAlert}` } else { const gourl = `wtv-favorite:/serve-discard-favorites?favorite_folder_name=${folder}`; - if (discardAll == "Discard All") + if (discardAll === "Discard All") { session_data.favstore.clearFolder(folder); } else { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-folders.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-folders.js index 75ea5c0c..5c9c21fb 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-folders.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-discard-folders.js @@ -33,7 +33,7 @@ Location: wtv-favorite:/favorite` } else { if (!request_headers.query.confirm_remove) { let message = ''; - if (numoffavorites == 0) { + if (numoffavorites === 0) { message = `Are you sure you want to remove ${folder}?`; } else { message = `Removing ${folder} will also remove the ${numoffavorites} favorites it contains.`; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-move-favorites.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-move-favorites.js index 35b67d12..9f805114 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-move-favorites.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-move-favorites.js @@ -12,14 +12,14 @@ else { // one favorite const favid = request_headers.query.favoriteid; const favfolder = request_headers.query.favoritefolder; - if (folder != favfolder) session_data.favstore.moveFavorite(folder, favfolder, favid); + if (folder !== favfolder) session_data.favstore.moveFavorite(folder, favfolder, favid); } else { - if (request_headers.query.favoriteid.length == request_headers.query.favoritefolder.length) { - // both queries should have the same number of entries + if (request_headers.query.favoriteid.length === request_headers.query.favoritefolder.length) { + // both queries should have the same number of entries Object.keys(request_headers.query.favoriteid).forEach(function (k) { const favid = request_headers.query.favoriteid[k]; const favfolder = request_headers.query.favoritefolder[k]; - if (folder != favfolder) session_data.favstore.moveFavorite(folder, favfolder, favid); + if (folder !== favfolder) session_data.favstore.moveFavorite(folder, favfolder, favid); }) } else { error_occured = true; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-samples-page.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-samples-page.js index a418aea4..d3685f63 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-samples-page.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/commit-samples-page.js @@ -13,23 +13,22 @@ totalfavorites = folder_array.length; if (totalfavorites < 14) { - if (createFun == "true") + if (createFun === "true") session_data.favstore.createTemplateFolder("Fun"); - if (createMoney == "true") + if (createMoney === "true") session_data.favstore.createTemplateFolder("Money"); - if (createMovies == "true") + if (createMovies === "true") session_data.favstore.createTemplateFolder("Movies"); - if (createNews == "true") + if (createNews === "true") session_data.favstore.createTemplateFolder("News"); - if (createRecommended == "true") + if (createRecommended === "true") session_data.favstore.createTemplateFolder("Recommended"); - console.log("FUGHFVJSGHJFDGIJUFDSHGFJDSKHJKLGFHJKHDJKHJKLGF " + createRecommended) - if (createReference == "true") + if (createReference === "true") session_data.favstore.createTemplateFolder("Reference"); headers = `300 OK diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite-index.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite-index.js index 1cb88a3f..268584ec 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite-index.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite-index.js @@ -2,7 +2,7 @@ const minisrv_service_file = true; const favstore_exists = session_data.favstore.favstoreExists(); -if (favstore_exists != true) +if (favstore_exists !== true) { session_data.favstore.createFavstore(); headers = `300 OK @@ -13,7 +13,7 @@ const folder_array = session_data.favstore.getFolders(); const url = request_headers.request; const key = url.split('?')[1] const scfav = session_data.favstore.getShortcutKey(key); -if (!scfav.id || scfav.id == "none") { +if (!scfav.id || scfav.id === "none") { headers = `400 You have not assigned a favorite to ${key}` } else { const fav = session_data.favstore.getFavorite(scfav.folder, scfav.id); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite.js index 9bc5b220..834d78f2 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/favorite.js @@ -2,16 +2,15 @@ const minisrv_service_file = true; const favstore_exists = session_data.favstore.favstoreExists(); -if (favstore_exists != true) +if (favstore_exists !== true) { session_data.favstore.createFavstore(); headers = `300 OK +wtv-expire-all: wtv-favorite:/favorite Location: wtv-favorite:/favorite` } else { const folder_array = session_data.favstore.getFolders(); -const totalfavorites = folder_array.length; -const stopdrawing = false; headers = `200 OK Connection: Keep-Alive @@ -151,8 +150,8 @@ for ${session_data.getSessionData("subscriber_username") || "You"} let kval = 0; // process evens Object.keys(folder_array).forEach(function (k) { - if (k == 0) return; // skip 0 since it was processed above - if (parseInt(k) % 2 == 0) { + if (parseInt(k)=== 0) return; // skip 0 since it was processed above + if (parseInt(k) % 2 === 0) { // even // Left Middle data += `
Server:
Port:
@@ -171,7 +170,7 @@ for ${session_data.getSessionData("subscriber_username") || "You"} // process end if total is even if (folder_array.length > 1) { - if (folder_array.length % 2 == 0) { + if (folder_array.length % 2 === 0) { data += `
@@ -182,7 +181,7 @@ for ${session_data.getSessionData("subscriber_username") || "You"} } // process middle (folder 2 (id 1)) - if (folder_array.length == 1) { + if (folder_array.length === 1) { // no folder 2 data += `
@@ -223,8 +222,8 @@ for ${session_data.getSessionData("subscriber_username") || "You"} // process odds Object.keys(folder_array).forEach(function (k) { - if (k == 1) return; // skip 1 since it was processed above - if (parseInt(k) % 2 != 0) { + if (parseInt(k) === 1) return; // skip 1 since it was processed above + if (parseInt(k) % 2 !== 0) { // odd // Right Middle data += `
@@ -242,7 +241,7 @@ for ${session_data.getSessionData("subscriber_username") || "You"} // process end if total is odd if (folder_array.length > 1) { - if (folder_array.length % 2 != 0) { + if (folder_array.length % 2 !== 0) { data += `
diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-arrange-favorites.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-arrange-favorites.js index 8199ff5f..6f391059 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-arrange-favorites.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-arrange-favorites.js @@ -188,7 +188,7 @@ by name only. diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-browser.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-browser.js index a5de707d..59a38f82 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-browser.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-browser.js @@ -207,7 +207,7 @@ Object.keys(favarray).forEach(function (k) { data += `
`; - if (favarray[k].imagetype == "url") + if (favarray[k].imagetype === "url") data += `
`; else data += `
`; @@ -218,7 +218,7 @@ ${favarray[k].title}
`; - if ((parseInt(k) + 1) % 3 == 0) { + if ((parseInt(k) + 1) % 3 === 0) { // every 3 objects data += `
diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-choose-shortcut-favorites.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-choose-shortcut-favorites.js index 461f51f7..1aa4c751 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-choose-shortcut-favorites.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-choose-shortcut-favorites.js @@ -112,7 +112,7 @@ let fav; for (let i = 1; i <= 8; i++) { const key = "F" + i; const scfav = session_data.favstore.getShortcutKey(key); - if (scfav && scfav.id != "none") { + if (scfav && scfav.id !== "none") { fav = session_data.favstore.getFavorite(scfav.folder, scfav.id); } else { fav = { image: "wtv-home:/ROMCache/Spacer.gif", title: "Not assigned" }; @@ -135,7 +135,7 @@ ${fav.title}
`; -if (fav.title != favoritedata.title) { +if (fav.title !== favoritedata.title) { data += `  ${key}` } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-discard-favorites.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-discard-favorites.js index ab68d8d2..de634434 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-discard-favorites.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-discard-favorites.js @@ -125,7 +125,7 @@ Discard favorites
` -if (favoritenum == 0) +if (favoritenum === 0) { data += "   There are no favorites to discard in this folder."; } else { @@ -133,7 +133,7 @@ for (let i = 0; i < favoritenum; i++) { data += `
` -if (favarray[i].imagetype == "url") +if (favarray[i].imagetype === "url") data += `
` else data += `
` @@ -190,7 +190,7 @@ data += `
` -if (favoritenum != 0) +if (favoritenum !== 0) { data += `
` } -if (totalfavorites == 1) +if (totalfavorites === 1) data += `
@@ -175,7 +175,7 @@ data += `
` -if (totalfavorites == 1) +if (totalfavorites === 1) data += "   You cannot delete your last folder." data += `


diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-move-favorites.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-move-favorites.js index 4608f6c0..e61ef36e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-move-favorites.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-move-favorites.js @@ -12,7 +12,7 @@ let folderlist = `
` -if (favoritenum == 0) +if (favoritenum === 0) { data += "   There are no favorites to move in this folder."; } else { @@ -148,7 +148,7 @@ for (let i = 0; i < favoritenum; i++) { data += `
` -if (favarray[i].imagetype == "url") +if (favarray[i].imagetype === "url") data += `
` else data += `
` @@ -165,7 +165,7 @@ data += `
` -if (favoritenum == 0) +if (favoritenum === 0) { data += "   There are no favorites to rename in this folder."; } else { @@ -134,7 +134,7 @@ for (let i = 0; i < favoritenum; i++) { data += `

` -if (favarray[i].imagetype == "url") +if (favarray[i].imagetype === "url") data += `
` else data += `
` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-samples-page.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-samples-page.js index 9ee03408..15d107db 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-samples-page.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-samples-page.js @@ -104,7 +104,7 @@ by going to the folder and choosing Organize.
` -if (session_data.favstore.folderExists("Fun") == true) +if (session_data.favstore.folderExists("Fun") === true) { data += ` @@ -124,7 +124,7 @@ if (session_data.favstore.folderExists("Fun") == true)  Fun ` } -if (session_data.favstore.folderExists("Money") == true) +if (session_data.favstore.folderExists("Money") === true) { data += ` @@ -147,7 +147,7 @@ if (session_data.favstore.folderExists("Money") == true)
` -if (session_data.favstore.folderExists("Movies") == true) +if (session_data.favstore.folderExists("Movies") === true) { data += ` @@ -167,7 +167,7 @@ if (session_data.favstore.folderExists("Movies") == true)  Movies ` } -if (session_data.favstore.folderExists("News") == true) +if (session_data.favstore.folderExists("News") === true) { data += ` @@ -191,7 +191,7 @@ data += `
` -if (session_data.favstore.folderExists("Recommended") == true) +if (session_data.favstore.folderExists("Recommended") === true) { data += ` @@ -211,7 +211,7 @@ if (session_data.favstore.folderExists("Recommended") == true)  Recommended ` } -if (session_data.favstore.folderExists("Reference") == true) +if (session_data.favstore.folderExists("Reference") === true) { data += ` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcut-list.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcut-list.js index d1a8d454..b2b797eb 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcut-list.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcut-list.js @@ -77,7 +77,7 @@ let fav; for (let i = 1; i <= 8; i++) { const key = "F" + i; const scfav = session_data.favstore.getShortcutKey(key); - if (scfav && scfav.id != "none") { + if (scfav && scfav.id !== "none") { fav = session_data.favstore.getFavorite(scfav.folder, scfav.id); } else { fav = { image: "wtv-home:/ROMCache/Spacer.gif", title: "Not assigned" }; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcuts-favorites.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcuts-favorites.js index 1dd8d1c2..5145d9da 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcuts-favorites.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-favorite/serve-shortcuts-favorites.js @@ -113,7 +113,7 @@ Assign shortcut to favorite
` -if (favoritenum == 0) +if (favoritenum === 0) { data += "   There are no favorites to move in this folder."; } else { @@ -141,7 +141,7 @@ for (let i = 0; i < favoritenum; i++) { -
` -if (favarray[i].imagetype == "url") +if (favarray[i].imagetype === "url") data += `
` else data += `
` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/content/content-serve.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/content/content-serve.js index f1ac736e..068cc40d 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/content/content-serve.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/content/content-serve.js @@ -6,7 +6,7 @@ const request_path = request_headers.request_url.replace(service_name + ":/", "" const romtype = session_data.get("wtv-client-rom-type"); const bootver = session_data.get("wtv-client-bootrom-version") -if ((romtype == "bf0app" || !romtype) && (bootver == "105" || !bootver)) { +if ((romtype === "bf0app" || !romtype) && (bootver === "105" || !bootver)) { // assume old classic in flash mode, override user setting and send tellyscript // because it is required to proceed in flash mode bf0app_update = true; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/current-noflash.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/current-noflash.js index f621026e..eeb4ecd6 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/current-noflash.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/current-noflash.js @@ -15,7 +15,7 @@ let bf0app_update = true; if (request_headers.query.path) request_path = request_headers.query.path; else request_path = default_build_to_send; -if (session_data.get("wtv-client-rom-type") == "bf0app" && session_data.get("wtv-client-bootrom-version") == "105") { +if (session_data.get("wtv-client-rom-type") === "bf0app" && session_data.get("wtv-client-bootrom-version") === "105") { // assume old classic in flash mode, override user setting and send tellyscript // because it is required to proceed in flash mode bf0app_update = true; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-by-path.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-by-path.js index cc717105..3761c35b 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-by-path.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-by-path.js @@ -7,7 +7,7 @@ const request_path = request_headers.query.path; const romtype = session_data.get("wtv-client-rom-type"); const bootver = session_data.get("wtv-client-bootrom-version"); -if ((romtype == "bf0app" || !romtype) && (bootver == "105" || !bootver)) { +if ((romtype === "bf0app" || !romtype) && (bootver === "105" || !bootver)) { // assume old classic in flash mode, override user setting and send tellyscript // because it is required to proceed in flash mode bf0app_update = true; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-lc2-page.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-lc2-page.js index a312ec33..876c10cd 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-lc2-page.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/get-lc2-page.js @@ -7,7 +7,7 @@ if (!request_headers.query.path) { headers = errpage[0]; data = errpage[1]; } else { - if (request_headers.Referer == service_name + ":/lc2-download-complete?") { + if (request_headers.Referer === service_name + ":/lc2-download-complete?") { headers = `200 OK Content-type: text/html minisrv-no-mail-count: true @@ -34,7 +34,7 @@ async function processLC2DownloadPage(flashrom_info, headers, numparts = null) { sendToClient(socket, headers, data); return false; } - if (numparts != null) flashrom_info.part_count = parseInt(numparts); + if (numparts !== null) flashrom_info.part_count = parseInt(numparts); if (!flashrom_info.part_count) flashrom_info.part_count = parseInt(flashrom_info.message.slice(flashrom_info.message.length - 4).replace(/\D/g, '')); if (parseInt(flashrom_info.part_number) >= 0 && flashrom_info.rompath && flashrom_info.next_rompath) { if (!flashrom_info.message && flashrom_info.is_bootrom) { @@ -129,7 +129,7 @@ Your ${session_data.getBoxName()} is being
updated automatically.

This will take about ${downloadTime} minutes and
then you can use your ${session_data.getBoxName()} again. `; - if (flashrom_info.is_bootrom && flashrom_info.part_number == (flashrom_info.part_count - 1)) { + if (flashrom_info.is_bootrom && flashrom_info.part_number === (flashrom_info.part_count - 1)) { data += `

The system will pause for about 30 seconds at the end of this update. Please do not interrupt the system diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/initiate-lc2-download.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/initiate-lc2-download.js index 7531c1c0..a800dca9 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/initiate-lc2-download.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/initiate-lc2-download.js @@ -3,7 +3,7 @@ const minisrv_service_file = true; if (request_headers.query.path) { let url = service_name + ":/get-lc2-page?path=" + encodeURIComponent(request_headers.query.path); const romtype = session_data.get("wtv-client-rom-type"); - if (romtype == "bf0app") { + if (romtype === "bf0app") { url = "client:updateflash?ipaddr=" + minisrv_config.services[service_name].host + "&port=" + minisrv_config.services[service_name].port + "&path=" + encodeURIComponent(service_name + ":/" + request_headers.query.path); if (request_headers.query.numparts) url += encodeURIComponent("?numparts=" + request_headers.query.numparts); } else { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/noflash.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/noflash.js index e3f52f01..7678be71 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/noflash.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-flashrom/noflash.js @@ -15,7 +15,7 @@ const bf0app_update = true; if (request_headers.query.path) request_path = request_headers.query.path; else request_path = default_build_to_send; -if (session_data.get("wtv-client-rom-type") == "bf0app" && session_data.get("wtv-client-bootrom-version") == "105") { +if (session_data.get("wtv-client-rom-type") === "bf0app" && session_data.get("wtv-client-bootrom-version") === "105") { // assume old classic in flash mode, override user setting and send tellyscript // because it is required to proceed in flash mode session_data.set("bf0app_update", bf0app_update); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/ValidateLogin.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/ValidateLogin.js index 7a45c257..8272c7be 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/ValidateLogin.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/ValidateLogin.js @@ -5,7 +5,7 @@ let challenge_response, gourl, wtvsec_login; const hasPendingTransfer = session_data.hasPendingTransfer() if (hasPendingTransfer) { - if (hasPendingTransfer.type == "target") { + if (hasPendingTransfer.type === "target") { const xferSession = new WTVClientSessionData(minisrv_config, hasPendingTransfer.ssid); xferSession.user_id = 0 const primary_username = xferSession.listPrimaryAccountUsers()['subscriber']['subscriber_username']; @@ -21,7 +21,7 @@ if (hasPendingTransfer) { const errpage = wtvshared.doRedirect(transferPendingDest); headers = errpage[0]; data = errpage[1]; - } else if (hasPendingTransfer.type == "source") { + } else if (hasPendingTransfer.type === "source") { const transferPendingSrc = new clientShowAlert({ 'image': minisrv_config.config.service_logo, 'message': "There is a pending transfer of this account to " + hasPendingTransfer.ssid + ". In order to use this box, you need to complete or cancel the transfer.", @@ -58,11 +58,11 @@ wtv-visit: client:hangupphone` } let errpage; if (socket.ssid !== null) { - if (wtvsec_login.ticket_b64 == null) { + if (wtvsec_login.ticket_b64 === null) { challenge_response = wtvsec_login.challenge_response; client_challenge_response = request_headers["wtv-challenge-response"] || null; if (challenge_response && client_challenge_response) { - if (challenge_response.toString(CryptoJS.enc.Base64) == client_challenge_response) { + if (challenge_response.toString(CryptoJS.enc.Base64) === client_challenge_response) { console.log(" * wtv-challenge-response success for " + wtvshared.filterSSID(socket.ssid)); wtvsec_login.PrepareTicket(); gourl = "wtv-head-waiter:/login-stage-two?"; @@ -84,8 +84,8 @@ wtv-visit: client:hangupphone` } } if (!errpage) { - if (user_id != null && !request_headers.query.initial_login && !request_headers.query.user_login && !request_headers.query.relogin && !request_headers.query.reconnect) { - if (request_headers.query.password == "") { + if (user_id !== null && !request_headers.query.initial_login && !request_headers.query.user_login && !request_headers.query.relogin && !request_headers.query.reconnect) { + if (request_headers.query.password === "") { headers = `403 Please enter your password and try again minisrv-no-mail-count: true`; } else if (session_data.validateUserPassword(request_headers.query.password)) { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/choose-user.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/choose-user.js index c15c5638..4f254236 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/choose-user.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/choose-user.js @@ -82,10 +82,10 @@ let accounts_listed = 0; for (const [key, value] of Object.entries(accounts)) { let user_id; data += "

"; - if (key == "subscriber") user_id = 0; + if (key === "subscriber") user_id = 0; else user_id = key.replace("user", ''); data += ``; - if (key == "subscriber") data += `${value['subscriber_username']}`; + if (key === "subscriber") data += `${value['subscriber_username']}`; else data += `${value['subscriber_username']}` data += " "; const userSession = new WTVClientSessionData(minisrv_config, socket.ssid); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/finalize-security.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/finalize-security.js index 3b1ed3ee..4a16065f 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/finalize-security.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/finalize-security.js @@ -7,7 +7,7 @@ if (socket.ssid && session_data) { socket_sessions[socket.id].wtvsec.ticket_b64 = request_headers["wtv-ticket"]; //socket_sessions[socket.id].secure == true; } - } else if (socket_sessions[socket.id].wtvsec.ticket_b64 == null) { + } else if (socket_sessions[socket.id].wtvsec.ticket_b64 === null) { // TODO: client should have a ticket and send it back by now, if not we should handle this correctly } } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login-stage-two.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login-stage-two.js index 7a1488c3..60b5e26e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login-stage-two.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login-stage-two.js @@ -54,7 +54,7 @@ else { if (session_data.getSessionData("subscriber_smtp_password") === null) { session_data.setUserSMTPPassword(wtvshared.generatePassword(16)); } - if (session_data.user_id == 0) { + if (session_data.user_id === 0) { const accounts = session_data.listPrimaryAccountUsers(); let offline_user_list_str = "\n"; let i = 0; @@ -167,7 +167,7 @@ wtv-inactive-timeout: 1440 headers += "wtv-home-url: " + home_url + "\n"; } - if (session_data.get('wtv-need-upgrade') != 'true' && !request_headers.query.reconnect && !limitedLogin && !limitedLoginRegistered) + if (session_data.get('wtv-need-upgrade') !== 'true' && !request_headers.query.reconnect && !limitedLogin && !limitedLoginRegistered) headers += "wtv-settings-url: wtv-setup:/get\n"; if (!limitedLogin && !limitedLoginRegistered) { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login.js index 80fd3a27..034ea042 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-head-waiter/login.js @@ -14,7 +14,7 @@ let send_to_relogin = true; if (session_data) { if (request_headers["wtv-ticket"]) { - if (session_data.data_store.wtvsec_login.ticket_b64 == null) { + if (session_data.data_store.wtvsec_login.ticket_b64 === null) { if (request_headers["wtv-ticket"].length > 8) { session_data.data_store.wtvsec_login.DecodeTicket(request_headers["wtv-ticket"]); session_data.data_store.wtvsec_login.ticket_b64 = request_headers["wtv-ticket"]; @@ -25,7 +25,7 @@ if (session_data) { if (session_data.data_store.wtvsec_login) { const client_challenge_response = request_headers["wtv-challenge-response"] || null; if (challenge_response && client_challenge_response) { - if (challenge_response.toString(CryptoJS.enc.Base64).slice(0, 85) == client_challenge_response.slice(0, 85)) { + if (challenge_response.toString(CryptoJS.enc.Base64).slice(0, 85) === client_challenge_response.slice(0, 85)) { console.log(" * wtv-challenge-response success for " + socket.ssid); session_data.data_store.wtvsec_login.PrepareTicket(); send_to_relogin = false; @@ -50,7 +50,7 @@ Expires: Wed, 09 Oct 1991 22:00:00 GMT wtv-expire-all: wtv-head-waiter: `+ getServiceString('wtv-log') + ` wtv-log-url: wtv-log:/log`; - if (challenge_header != "") headers += "\n" + challenge_header; + if (challenge_header !== "") headers += "\n" + challenge_header; headers += ` wtv-country: US wtv-language-header: en-US,en diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addressbook.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addressbook.js index 49fddf88..504f1d35 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addressbook.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addressbook.js @@ -4,7 +4,7 @@ const action = request_headers.query.action; let address_book = null address_book = session_data.getSessionData("address_book") -if (address_book == null) { +if (address_book === null) { session_data.setSessionData("address_book", []) address_book = []; } @@ -625,9 +625,9 @@ text="E7CE4A" font=proportional name="nickname" value="`; - if (action == 'editfromheader') { + if (action === 'editfromheader') { data += request_headers.query.nickname - } else if (action == 'edit' && request_headers.query.id) { + } else if (action === 'edit' && request_headers.query.id) { data += address_book[request_headers.query.id].name } data += `" @@ -652,9 +652,9 @@ font=proportional nosoftbreaks nohardbreaks name="address" value="`; - if (action == 'editfromheader') { + if (action === 'editfromheader') { data += request_headers.query.address - } else if (action == 'edit' && request_headers.query.id) { + } else if (action === 'edit' && request_headers.query.id) { data += address_book[request_headers.query.id].address } data += `" @@ -784,7 +784,7 @@ Location: wtv-mail:/addressbook`; break; case "discard": - if (address_book.length == 1) { + if (address_book.length === 1) { address_book = [] } else { address_book.splice(request_headers.query.id, 1) diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addresslist.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addresslist.js index 6cc336c8..5c44d681 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addresslist.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/addresslist.js @@ -8,7 +8,7 @@ minisrv-no-mail-count: true`; const address_book = session_data.getSessionData("address_book") -if (session_data.getSessionData("address_book") != null) { +if (session_data.getSessionData("address_book") !== null) { data = `` for (let i = 0; i < address_book.length; i++) { data += address_book[i].name + '\0' + address_book[i].address + '\0' diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/get-attachment.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/get-attachment.js index ae828dcf..4b0c3d4a 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/get-attachment.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/get-attachment.js @@ -2,8 +2,8 @@ const minisrv_service_file = true; let errpage, message; const messageid = request_headers.query.message_id; -const attachment_id = request_headers.query.attachment_id; -if (!attachment_id && attachment_id != 0) errpage = wtvshared.doErrorPage(400, "Attachment ID required."); +const attachment_id = parseInt(request_headers.query.attachment_id); +if (!attachment_id && attachment_id !== 0) errpage = wtvshared.doErrorPage(400, "Attachment ID required."); else { message = session_data.mailstore.getMessageByID(messageid); if (!message) errpage = wtvshared.doErrorPage(400, "Invalid Message ID"); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/listmail.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/listmail.js index 00ce9bf4..c20e6384 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/listmail.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/listmail.js @@ -58,14 +58,14 @@ if (!intro_seen && !request_headers.query.intro_seen) { const total_unread_message_count = session_data.mailstore.countUnreadMessages(mailbox); let message_list_string = null; - if (total_message_count == 0) { + if (total_message_count === 0) { message_list_string = "No new mail messages for "; } else { if (total_unread_message_count > 0) { - message_list_string = total_unread_message_count + " new mail message" + ((total_message_count != 1) ? 's' : ''); - if (total_message_count - total_unread_message_count > 0) message_list_string += ", " + (total_message_count - total_unread_message_count) + " mail message" + (((total_message_count - total_unread_message_count) != 1) ? 's' : '') + " for "; - } else { - message_list_string = total_message_count + " mail message" + ((total_message_count != 1) ? 's' : '') + " for "; + message_list_string = total_unread_message_count + " new mail message" + ((total_message_count !== 1) ? 's' : ''); + if (total_message_count - total_unread_message_count > 0) message_list_string += ", " + (total_message_count - total_unread_message_count) + " mail message" + (((total_message_count - total_unread_message_count) !== 1) ? 's' : '') + " for "; + } else { + message_list_string = total_message_count + " mail message" + ((total_message_count !== 1) ? 's' : '') + " for "; } } @@ -281,7 +281,7 @@ ${username}@${minisrv_config.config.service_name} `; Object.keys(message_list).forEach(function (k) { const message = message_list[k]; - if (typeof message.subject == "object" && message.subject) message.subject = wtvshared.decodeBufferText(message.subject); + if (typeof message.subject === "object" && message.subject) message.subject = wtvshared.decodeBufferText(message.subject); message.known_sender = session_data.isAddressInAddressBook(message.from_addr); let message_font_open = ""; let message_font_close = ""; @@ -319,7 +319,7 @@ ${message_font_close} }); } else { data += ` - No ${(mailbox_name == "Inbox") ? `new e-mail messages for + No ${(mailbox_name === "Inbox") ? `new e-mail messages for
diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/readmail.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/readmail.js index 145534dd..f6420671 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/readmail.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/readmail.js @@ -47,7 +47,7 @@ Content-type: text/html`; } if (message.signature) message_colors = session_data.mailstore.getSignatureColors(message.signature); - if (typeof message.subject == "object" && message.subject) message.subject = wtvshared.decodeBufferText(message.subject); + if (typeof message.subject === "object" && message.subject) message.subject = wtvshared.decodeBufferText(message.subject); data = ` -
${username}@${minisrv_config.config.service_name}
`; - if (message.from_name != message.from_addr) { + if (message.from_name !== message.from_addr) { data += `${wtvshared.htmlEntitize(message.from_addr)} (${wtvshared.htmlEntitize(message.from_name)})`; } else { data += `${wtvshared.htmlEntitize(message.from_addr)}`; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/sendmail.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/sendmail.js index 750ad814..5622ac90 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/sendmail.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/sendmail.js @@ -7,7 +7,7 @@ const intro_seen = session_data.mailstore.checkMailIntroSeen(); if (!intro_seen && !request_headers.query.intro_seen) { // user is trying to bypass the intro screen headers = "300 OK\nLocation: wtv-mail:/DiplomaMail?came-from=" + encodeURIComponent(request_headers.request_url); -} else if (request_headers.query.clear == "true") { +} else if (request_headers.query.clear === "true") { let gourl; if (request_headers.Referer) gourl = request_headers.Referer.replace(/[\?\&]clear\=true/, ''); @@ -105,8 +105,8 @@ Location: ${gourl}`; } } - if (request_headers.query.togglesign == "true") no_signature = false; - if (request_headers.query.togglesign == "false") no_signature = true; + if (request_headers.query.togglesign === "true") no_signature = false; + if (request_headers.query.togglesign === "false") no_signature = true; if (mail_draft_attachments) { if (mail_draft_attachments.message_snapshot_data) message_snapshot_data = mail_draft_attachments.message_snapshot_data; @@ -136,10 +136,10 @@ Content-Type: audio/wav`; 'noback': true, }).getURL(); - if ((typeof request_headers.query.sendoff !== 'undefined' && request_headers.query.sendoff != false) || request_headers.query.saveoff || request_headers.query.get_snap || request_headers.query.get_gab) { + if ((typeof request_headers.query.sendoff !== 'undefined' && request_headers.query.sendoff !== false) || request_headers.query.saveoff || request_headers.query.get_snap || request_headers.query.get_gab) { let from_addr = address; const signature = session_data.getSessionData("subscriber_signature") || null; - if (typeof request_headers.query.sendoff !== 'undefined' && request_headers.query.sendoff != false) { + if (typeof request_headers.query.sendoff !== 'undefined' && request_headers.query.sendoff !== false) { const attachments = []; @@ -148,7 +148,7 @@ Content-Type: audio/wav`; 'mime': 'image/jpeg', 'filename': 'snapshot.jpg' } - if (typeof message_snapshot_data == "object") { + if (typeof message_snapshot_data === "object") { attachment.content = new Buffer.from(message_snapshot_data).toString('base64'); attachment.is_base64 = true; } else @@ -163,7 +163,7 @@ Content-Type: audio/wav`; 'filename': 'voicemail.wav' } - if (typeof message_voicemail_data == "object") { + if (typeof message_voicemail_data === "object") { attachment.content = new Buffer.from(message_voicemail_data).toString('base64'); attachment.is_base64 = true; } else @@ -196,7 +196,7 @@ Content-Type: audio/wav`; wtvnews.initializeUsenet(service_config.upstream_address, service_config.upstream_port, service_config.upstream_tls || null); } from_addr = userdisplayname + " <" + from_addr + ">"; - if (signature && signature != "" && !no_signature) { + if (signature && signature !== "" && !no_signature) { if (signature.indexOf('') >= 0) { attachments.push({ "mime": 'text/html', @@ -299,13 +299,13 @@ wtv-expire-all: wtv-mail:/sendmail`; headers = `200 OK Content-type: text/html`; mail_draft_data = session_data.getSessionData((newsgroup) ? "usenet_draft_attachments" : "mail_draft_attachments") || {}; - if (request_headers.query.snapping == "false") { + if (request_headers.query.snapping === "false") { headers += "\nwtv-expire-all: cache:snapshot.jpg"; if (mail_draft_data.message_snapshot_data) mail_draft_data.message_snapshot_data = null; session_data.setSessionData((newsgroup) ? "usenet_draft_attachments" : "mail_draft_attachments", mail_draft_data); } - if (request_headers.query.gabbing == "false") { + if (request_headers.query.gabbing === "false") { headers += "\nwtv-expire-all: cache:voicemail.wav"; if (mail_draft_data.message_voicemail_data) mail_draft_data.message_voicemail_data = null; session_data.setSessionData((newsgroup) ? "usenet_draft_attachments" : "mail_draft_attachments", mail_draft_data); @@ -617,7 +617,7 @@ link=${message_colors.link} vlink=${message_colors.vlink} vspace=0 hspace=0>`; - if (session_data.getSessionData("subscriber_signature") && session_data.getSessionData("subscriber_signature") != "" && !no_signature) { + if (session_data.getSessionData("subscriber_signature") && session_data.getSessionData("subscriber_signature") !== "" && !no_signature) { data += wtvshared.sanitizeSignature(session_data.getSessionData("subscriber_signature")); } if (msg_url) { @@ -642,7 +642,7 @@ Included Page: ${wtvshared.htmlEntitize(msg_url_title).repl
`; - if (!session_data.getSessionData("subscriber_signature") || session_data.getSessionData("subscriber_signature") == "") { + if (!session_data.getSessionData("subscriber_signature") || session_data.getSessionData("subscriber_signature") === "") { data += ` `; } else if (no_signature) { data += ` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/verify-address.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/verify-address.js index 5093f533..2cbc900b 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/verify-address.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-mail/verify-address.js @@ -15,7 +15,7 @@ const ok = '1'; if (request_headers.query.address) { const address_split = request_headers.query.address.split("@"); const domain = address_split[1]; - if (domain != "escargot.chat" && domain != "escargot.live") data = fail + if (domain !== "escargot.chat" && domain !== "escargot.live") data = fail else data = ok; } else { data = fail; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/get-attachment.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/get-attachment.js index febabeb2..0fb18b4c 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/get-attachment.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/get-attachment.js @@ -4,7 +4,7 @@ request_is_async = true; let errpage = null; const group = request_headers.query.group; const attachment_id = parseInt(request_headers.query.attachment_id); -if ((!attachment_id && attachment_id != 0) || !group || !request_headers.query.article) { +if ((!attachment_id && attachment_id !== 0) || !group || !request_headers.query.article) { errpage = wtvshared.doErrorPage(400, "Attachment ID required."); sendToClient(socket, errpage[0], errpage[1]); } else { @@ -32,13 +32,13 @@ if ((!attachment_id && attachment_id != 0) || !group || !request_headers.query.a wtvnews.selectGroup(group).then((response) => { wtvnews.getArticle(article).then((response) => { wtvnews.quitUsenet(); - if (response.code == 220) { + if (response.code === 220) { const message_data = wtvnews.parseAttachments(response); if (message_data.attachments) { if (attachment_id < message_data.attachments.length) { const attachment = message_data.attachments[attachment_id]; const encoding = attachment.content_encoding.toLowerCase() - if (encoding == 'base64') { + if (encoding === 'base64') { data = Buffer.from(attachment.data, encoding); headers = "200 OK\n" headers += "Content-Type: " + attachment.content_type + "\n"; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/lobby.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/lobby.js index 5ffabb27..c2e779d3 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/lobby.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/lobby.js @@ -117,12 +117,12 @@ function printGroup(group) { } // evens -Object.keys(featuredGroups).forEach((k) => { if (k % 2 == 0) { data += printGroup(featuredGroups[k]); } }); +Object.keys(featuredGroups).forEach((k) => { if (k % 2 === 0) { data += printGroup(featuredGroups[k]); } }); if (featuredGroups.length > 1) data += ``; // odds -Object.keys(featuredGroups).forEach((k) => { if (k % 2 != 0) data += printGroup(featuredGroups[k]); }); +Object.keys(featuredGroups).forEach((k) => { if (k % 2 !== 0) data += printGroup(featuredGroups[k]); }); data += ` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/news.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/news.js index 72cedf36..d6a70dc3 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/news.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-news/news.js @@ -28,9 +28,9 @@ async function throwError(e) { function isToday (chkdate) { const today = new Date() - return chkdate.getDate() == today.getDate() && - chkdate.getMonth() == today.getMonth() && - chkdate.getFullYear() == today.getFullYear() + return chkdate.getDate() === today.getDate() && + chkdate.getMonth() === today.getMonth() && + chkdate.getFullYear() === today.getFullYear() } async function WebTVListGroup(group) { @@ -47,7 +47,7 @@ async function WebTVListGroup(group) { limit_per_page = (page_end - (limit_per_page / (page + 1))) + limit_per_page; } wtvnews.listGroup(group, page, limit_per_page).then((response) => { - if (response.code == 211) { + if (response.code === 211) { const NGCount = response.group.number; const NGArticles = response.group.articleNumbers; page_start = (limit_per_page * page) + 1; @@ -193,11 +193,11 @@ Group: ${request_headers.query.group} ` - if (NGCount == 0) { + if (NGCount === 0) { data += `This group has no postings`; } else { data += NGCount + " posting"; - if (NGCount != 1) + if (NGCount !== 1) data += "s" } data += ` @@ -210,7 +210,7 @@ Group: ${request_headers.query.group}
-${(page > 0) ? `` : ``} +${(page > 0) ? `` : ``} @@ -218,7 +218,7 @@ ${(page > 0) ? ` -${(page_end < NGCount) ? `` : ``} +${(page_end < NGCount) ? `` : ``}
@@ -337,7 +337,7 @@ wtv-expire-all: wtv-news:/news?group=${group}&article=`; if (attachments) { if (Object.keys(attachments).length > 0) { Object.keys(attachments).forEach((k) => { - if (attachments[k].filename == "wtv_signature.html" && attachments[k].content_type.match(/text\/html/)) { + if (attachments[k].filename === "wtv_signature.html" && attachments[k].content_type.match(/text\/html/)) { signature = attachments[k].data; signature_index = k; return false; @@ -350,7 +350,7 @@ wtv-expire-all: wtv-news:/news?group=${group}&article=`; if (message_body.indexOf(" From: `; - if (message.from_name != message.from_addr) { + if (message.from_name !== message.from_addr) { data += `${wtvshared.htmlEntitize(message.from_addr)} `; } else { data += `${wtvshared.htmlEntitize(response.article.headers.FROM)}`; @@ -630,7 +630,7 @@ From: if (attachments) { if (attachments[0]) { - if (attachments[0].filename == "message.html") { + if (attachments[0].filename === "message.html") { body_data += wtvshared.sanitizeSignature(attachments[0].data); delete attachments[0]; } @@ -789,14 +789,14 @@ vspace=0>
-${(response.length == 0) ? "No " : ""}Discussion groups found +${(response.length === 0) ? "No " : ""}Discussion groups found
`; - if (response.length == 0) { + if (response.length === 0) { data += `There are no discussion groups that match your request. Do you want to look for something else?`; } else { response.forEach((group) => { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-passport/messengerlogin.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-passport/messengerlogin.js index 9a91af0f..e9d9e374 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-passport/messengerlogin.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-passport/messengerlogin.js @@ -14,7 +14,7 @@ if (messenger_email && messenger_password) { const password = session_data.decryptPassword(messenger_password); const challenge = request_headers.request.split('?')[1]; - if (request_headers.request.split('?')[1].slice(0, 3) != "ct=") { + if (request_headers.request.split('?')[1].slice(0, 3) !== "ct=") { console.log(" *** Logging into Messenger via MSNP3") data = crypto.createHash('md5').update(request_headers.request.split('?')[1] + password).digest("hex"); } else { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAccountInfo.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAccountInfo.js index cf19a784..b2373f1d 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAccountInfo.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAccountInfo.js @@ -16,7 +16,7 @@ if (!request_headers.query.registering) { else if (!wtvr.checkUsernameSanity(request_headers.query.subscriber_username)) errpage = wtvshared.doErrorPage(400, "The username you have chosen contains invalid characters. Please choose a username with only letters, numbers, _ or -. Also, please be sure your username begins with a letter."); else if (!wtvr.checkUsernameAvailable(request_headers.query.subscriber_username)) errpage = wtvshared.doErrorPage(400, "The username you have selected is not available. Please select another username."); else if (!request_headers.query.subscriber_contact) errpage = wtvshared.doErrorPage(400, "Please enter your contact information."); - else if (request_headers.query.subscriber_contact_method == "") errpage = wtvshared.doErrorPage(400, "Please select the type of contact information you provided."); + else if (request_headers.query.subscriber_contact_method === "") errpage = wtvshared.doErrorPage(400, "Please select the type of contact information you provided."); if (errpage) { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAgreement.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAgreement.js index d7bd7a02..ee79f810 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAgreement.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-register/ValidateAgreement.js @@ -40,11 +40,11 @@ AutoCaps selected value="${request_headers.query.subscriber_contact || ""}"> CONTACT INFO TYPE: `; const form_data = ` diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/accounts.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/accounts.js index e9bd3933..93271091 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/accounts.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/accounts.js @@ -1,7 +1,7 @@ const minisrv_service_file = true; session_data.loadSessionData(); -if (session_data.user_id != 0) { +if (session_data.user_id !== 0) { const errpage = wtvshared.doErrorPage(400, "You are not authorized to edit the primary account."); headers = errpage[0]; data = errpage[1]; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-name.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-name.js index fdc86424..ebf1aa65 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-name.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-name.js @@ -2,7 +2,7 @@ const minisrv_service_file = true; let errpage; -if (session_data.user_id != 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); +if (session_data.user_id !== 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); else if (session_data.getNumberOfUserAccounts() > minisrv_config.config.user_accounts.max_users_per_account) errpage = wtvshared.doErrorPage(400, "You are not authorized to add more than " + minisrv_config.config.user_accounts.max_users_per_account + ` account${minisrv_config.config.user_accounts.max_users_per_account > 1 ? 's' : ''}.`); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-password.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-password.js index a490f14a..7ca03d65 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-password.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user-password.js @@ -3,7 +3,7 @@ let errpage = null; const wtvr = new WTVRegister(minisrv_config, SessionStore); -if (session_data.user_id != 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); +if (session_data.user_id !== 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); else if (!request_headers.query.user_name) errpage = wtvshared.doErrorPage(400, "Please enter a username."); else if (request_headers.query.user_name.length < minisrv_config.config.user_accounts.min_username_length) errpage = wtvshared.doErrorPage(400, "Please choose a username with " + minisrv_config.config.user_accounts.min_username_length + " or more characters."); else if (request_headers.query.user_name.length > minisrv_config.config.user_accounts.max_username_length) errpage = wtvshared.doErrorPage(400, "Please choose a username with " + minisrv_config.config.user_accounts.max_username_length + " or less characters."); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user.js index 956fc8b1..62ca9ffa 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/add-user.js @@ -4,7 +4,7 @@ let errpage; if (Object.keys(session_data.listPrimaryAccountUsers()).length >= minisrv_config.config.user_accounts.max_users_per_account) { errpage = wtvshared.doErrorPage(400, "You are not authorized to add more than " + minisrv_config.config.user_accounts.max_users_per_account + ` account${minisrv_config.config.user_accounts.max_users_per_account > 1 ? 's' : ''}.`); } -else if (session_data.user_id != 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); +else if (session_data.user_id !== 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); if (errpage) { diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/choose-bg-songs.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/choose-bg-songs.js index b5e64dc6..1a7b1d1f 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/choose-bg-songs.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/choose-bg-songs.js @@ -88,7 +88,7 @@ Object.keys(categories).forEach(function (k) { const catID = categories[k].id; const songsInCat = wtvbgm.getCategorySongList(catID); if (songsInCat.length > 0) { - if (catsListed == divide) { + if (catsListed === divide) { data += ` `; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-password.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-password.js index 2b9c44a9..d13acd23 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-password.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-password.js @@ -3,18 +3,18 @@ let userSession = null; session_data.loadSessionData(); -let user_id = (request_headers.query.user_id) ? request_headers.query.user_id : session_data.user_id; +let user_id = (request_headers.query.user_id) ? parseInt(request_headers.query.user_id) : session_data.user_id; // security -if (session_data.user_id != 0 && session_data.user_id != user_id) { +if (session_data.user_id !== 0 && session_data.user_id !== parseInt(request_headers.query.user_id)) { user_id = null; // force unset const errpage = wtvshared.doErrorPage(400, "You are not authorized to change the selected user's password."); headers = errpage[0]; data = errpage[1]; } -if (user_id != null) { - if (session_data.user_id == request_headers.query.user_id) userSession = session_data; +if (user_id !== null) { + if (session_data.user_id === user_id) userSession = session_data; else { userSession = new WTVClientSessionData(minisrv_config, socket.ssid); userSession.user_id = user_id; @@ -34,7 +34,7 @@ Content-Type: text/html`; -Change ${(user_id == session_data.user_id) ? 'your' : 'user'} password +Change ${(user_id === session_data.user_id) ? 'your' : 'user'} password @@ -73,7 +73,7 @@ Change ${(user_id == session_data.user_id) ? 'your' : 'user'} password -Change ${(user_id == session_data.user_id) ? 'your' : 'user'} password +Change ${(user_id === session_data.user_id) ? 'your' : 'user'} password
@@ -161,5 +161,4 @@ value=Done name="Done" usestyle width=103> `; } -} -if (userSession) userSession = null; \ No newline at end of file +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-begin.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-begin.js index 42884b35..98fddd99 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-begin.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-begin.js @@ -3,27 +3,27 @@ session_data.loadSessionData(); let userSession, user_id; if (request_headers.query.user_id) { - user_id = request_headers.query.user_id; + user_id = parseInt(request_headers.query.user_id); } else { user_id = session_data.user_id; } // security -if (session_data.user_id != 0 && session_data.user_id != request_headers.query.user_id) { +if (session_data.user_id !== 0 && session_data.user_id !== parseInt(request_headers.query.user_id)) { user_id = null; // force unset const errpage = wtvshared.doErrorPage(400, "You are not authorized to edit the selected user."); headers = errpage[0]; data = errpage[1]; } -if (user_id != null) { +if (user_id !== null) { headers = `200 OK Connection: Keep-Alive Content-Type: text/html wtv-expire-all: wtv-setup:/edit-user wtv-noback-all: wtv-setup:/edit-user` - if (session_data.user_id == request_headers.query.user_id) userSession = session_data; + if (session_data.user_id === user_id) userSession = session_data; else { userSession = new WTVClientSessionData(minisrv_config, socket.ssid); userSession.user_id = user_id; @@ -39,7 +39,7 @@ wtv-noback-all: wtv-setup:/edit-user` -Changing ${(user_id == 0) ? 'subscriber' : 'user'} information +Changing ${(user_id === 0) ? 'subscriber' : 'user'} information @@ -79,7 +79,7 @@ noscroll> -${(user_id == 0) ? 'Subscriber' : 'User'} information +${(user_id === 0) ? 'Subscriber' : 'User'} information
@@ -161,5 +161,4 @@ value=Done name="Done" usestyle width=103> `; } -} -if (userSession) userSession = null; \ No newline at end of file +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-name.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-name.js index 52ab18bd..ae55762e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-name.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/edit-user-name.js @@ -2,18 +2,18 @@ const minisrv_service_file = true; let userSession = null; session_data.loadSessionData(); -let user_id = (request_headers.query.user_id) ? request_headers.query.user_id : session_data.user_id; +let user_id = (request_headers.query.user_id) ? parseInt(request_headers.query.user_id) : session_data.user_id; // security -if (session_data.user_id != 0 && session_data.user_id != request_headers.query.user_id) { +if (session_data.user_id !== 0 && session_data.user_id !== parseInt(request_headers.query.user_id)) { user_id = null; // force unset const errpage = wtvshared.doErrorPage(400, "You are not authorized to change the selected user's password."); headers = errpage[0]; data = errpage[1]; } -if (user_id != null) { - if (session_data.user_id == request_headers.query.user_id) userSession = session_data; +if (user_id !== null) { + if (session_data.user_id === request_headers.query.user_id) userSession = session_data; else { userSession = new WTVClientSessionData(minisrv_config, socket.ssid); userSession.user_id = user_id; @@ -146,5 +146,4 @@ value=Done name="Done" usestyle width=103> `; } -} -if (userSession) userSession = null; \ No newline at end of file +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/keyboard.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/keyboard.js index 14873152..8308ef8c 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/keyboard.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/keyboard.js @@ -96,7 +96,7 @@ appear on your screen.

`; -if (settings_obj['setup-keyboard'] == "standard") { +if (settings_obj['setup-keyboard'] === "standard") { data += ''; } else { data += ''; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/mail-signature.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/mail-signature.js index 9d5c1a95..8fd234e2 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/mail-signature.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/mail-signature.js @@ -12,7 +12,7 @@ Content-Type: text/html` let signature = session_data.getSessionData("subscriber_signature"); if (request_headers.query.mail_signature) { - if (signature != request_headers.query.mail_signature) { + if (signature !== request_headers.query.mail_signature) { session_data.setSessionData("subscriber_signature", (request_headers.query.mail_signature) ? request_headers.query.mail_signature : ""); session_data.saveSessionData(); signature = request_headers.query.mail_signature; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger-enable.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger-enable.js index b79a9147..5e7373c3 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger-enable.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger-enable.js @@ -1,7 +1,7 @@ const minisrv_service_file = true; let justenabled, enablestatus; -if (!session_data.getSessionData("messenger_enabled") == 1) { +if (!session_data.getSessionData("messenger_enabled") === 1) { session_data.setSessionData("messenger_enabled", 1); session_data.saveSessionData; justenabled = "true"; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger.js index e83953a8..34aac313 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/messenger.js @@ -47,7 +47,7 @@ function ShowMessengerPanel()
@@ -69,7 +69,7 @@ Messenger
Messenger is currently `; -if (session_data.getSessionData("messenger_enabled") == 1) { +if (session_data.getSessionData("messenger_enabled") === 1) { data += "on" } else { data += "off" @@ -81,7 +81,7 @@ if (session_data.getSessionData("messenger_enabled") == 1) {
Turn messenger `; -if (!session_data.getSessionData("messenger_enabled") == 1) { +if (!session_data.getSessionData("messenger_enabled") === 1) { data += "on" } else { data += "off" diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/remove-users.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/remove-users.js index 3ef3fe6e..e3a56b18 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/remove-users.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/remove-users.js @@ -1,10 +1,10 @@ const minisrv_service_file = true; let errpage; -if (Object.keys(session_data.listPrimaryAccountUsers()).length == 1) { +if (Object.keys(session_data.listPrimaryAccountUsers()).length === 1) { errpage = wtvshared.doErrorPage(400, "There are no more users to remove."); } -else if (session_data.user_id != 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); +else if (session_data.user_id !== 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); if (errpage) { headers = errpage[0]; data = errpage[1]; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/screen.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/screen.js index c9f3896f..890617df 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/screen.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/screen.js @@ -71,22 +71,23 @@ Television
-Center
-Center WebTV on your screen
`; +Picture
+Adjust brightness, contrast, and sharpness
+`; // old classic apparently can do Screen Border -if (session_data.get("wtv-client-rom-type") == "bf0app") { +if (session_data.get("wtv-client-rom-type") === "bf0app") { data += `
Border
-Change the color of the screen border
`; -} +Change the color of the screen border
-data += `

-Picture
-Adjust brightness, contrast, and sharpness
+Center
+Center WebTV on your screen
`; +} +data += `
diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/set-bg.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/set-bg.js index c1f19950..3d869494 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/set-bg.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/set-bg.js @@ -96,7 +96,7 @@ Choose the songs that you'd like to include. let songsListed = 0; const divide = Math.round(musicList.length / 2, 0); Object.keys(musicList).forEach(function (k) { - if (songsListed == divide) { + if (songsListed === divide) { data += ` `; } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/setup.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/setup.js index e7255c31..3b0bcb6e 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/setup.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/setup.js @@ -105,11 +105,11 @@ for (let i = 0; i < settings.length; i += 2) { data += `
${(settings[i][0] != "") ? `€ ${settings[i][1]}` : `  `} +${(settings[i][0] !== "") ? `€ ${settings[i][1]}` : `  `} ` if (i + 1 < settings.length) { - data += (settings[i + 1][0] != "") ? `€ ${settings[i + 1][1]}` : `  ` + data += (settings[i + 1][0] !== "") ? `€ ${settings[i + 1][1]}` : `  ` } else { // require even number of settings data += "  " diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/transfer-account.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/transfer-account.js index b1f8b7d4..98f1e158 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/transfer-account.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/transfer-account.js @@ -1,7 +1,7 @@ const minisrv_service_file = true; // security -if (session_data.user_id != 0 && session_data.user_id != request_headers.query.user_id) { +if (session_data.user_id !== 0 && session_data.user_id !== parseInt(request_headers.query.user_id)) { const errpage = wtvshared.doErrorPage(400, "You are not authorized to transfer this account. Please log in as the primary user."); headers = errpage[0]; data = errpage[1]; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user-done.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user-done.js index eb6bcda4..730e01c0 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user-done.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user-done.js @@ -2,7 +2,7 @@ const minisrv_service_file = true; let userSession = null; let errpage = null; -if (session_data.user_id != 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); +if (session_data.user_id !== 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); // seperate if statements as to not overwrite the first error if multiple occur @@ -71,6 +71,4 @@ wtv-expire: wtv-setup:/accounts Location: wtv-setup:/accounts`; } } -} - -if (userSession) userSession = null; \ No newline at end of file +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user.js index f2ae465a..46f88213 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-add-user.js @@ -1,7 +1,7 @@ const minisrv_service_file = true; let errpage = null; -if (session_data.user_id != 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); +if (session_data.user_id !== 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to add users to this account."); // seperate if statements as to not overwrite the first error if multiple occur @@ -129,7 +129,7 @@ display_name=${request_headers.query.display_name}& user_name=${request_headers.query.user_name}& user_password=${request_headers.query.user_password}& user_password2=${request_headers.query.user_password2}">`; - if ((request_headers.query.user_password) == "") { + if ((request_headers.query.user_password) === "") { data += `No password`; } else { data += `Has password`; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-bg-song-category.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-bg-song-category.js index 029af94e..c8c8ca22 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-bg-song-category.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-bg-song-category.js @@ -8,13 +8,13 @@ if (request_headers.query && session_data) { if (request_headers.request_url.indexOf('?') >= 0) { const category = (request_headers.query.category) ? request_headers.query.category : null; - if (category == null) music_obj.enableCategories = []; + if (category === null) music_obj.enableCategories = []; else { const cat = wtvbgm.categories[parseInt(category) - 1]; if (cat) { const toRemove = []; Object.keys(music_obj.enableSongs).forEach(function (k) { - if (wtvbgm.getSongCategory(parseInt(music_obj.enableSongs[k])) == parseInt(category)) toRemove.push(k); + if (wtvbgm.getSongCategory(parseInt(music_obj.enableSongs[k])) === parseInt(category)) toRemove.push(k); }); toRemove.forEach(function (v) { music_obj.enableSongs.splice(v, 1, ""); @@ -28,10 +28,10 @@ if (request_headers.query && session_data) { const qraw = _qraw.split("&"); for (let i = 0; i < qraw.length; i++) { const qraw_split = qraw[i].split("="); - if (qraw_split.length == 2) { + if (qraw_split.length === 2) { const k = qraw_split[0]; - if (k == "enableCategory") music_obj['enableCategories'].push(decodeURIComponent(qraw[i].split("=")[1].replace(/\+/g, "%20"))); - if (k == "enableSong") music_obj['enableSongs'].push(decodeURIComponent(qraw[i].split("=")[1].replace(/\+/g, "%20"))); + if (k === "enableCategory") music_obj['enableCategories'].push(decodeURIComponent(qraw[i].split("=")[1].replace(/\+/g, "%20"))); + if (k === "enableSong") music_obj['enableSongs'].push(decodeURIComponent(qraw[i].split("=")[1].replace(/\+/g, "%20"))); } } } @@ -39,7 +39,7 @@ if (request_headers.query && session_data) { music_obj.enableCategories = [...new Set(music_obj.enableCategories.filter(value => Object.keys(value).length !== 0))]; music_obj.enableSongs = [...new Set(music_obj.enableSongs.filter(value => Object.keys(value).length !== 0))]; music_obj = Object.assign({}, music_obj) - if ((Object.keys(music_obj.enableCategories).length != Object.keys(old_music_obj.enableCategories).length) || (Object.keys(music_obj.enableSongs).length != Object.keys(old_music_obj.enableSongs).length)) { + if ((Object.keys(music_obj.enableCategories).length !== Object.keys(old_music_obj.enableCategories).length) || (Object.keys(music_obj.enableSongs).length !== Object.keys(old_music_obj.enableSongs).length)) { // something changed session_data.setSessionData("wtv-bgmusic", music_obj); session_data.saveSessionData(); diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-name.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-name.js index 9a8fe410..23356edc 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-name.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-name.js @@ -2,19 +2,19 @@ const minisrv_service_file = true; let userSession; session_data.loadSessionData(); -let user_id = (request_headers.query.user_id) ? request_headers.query.user_id : session_data.user_id; +let user_id = (request_headers.query.user_id) ? parseInt(request_headers.query.user_id) : session_data.user_id; // security -if (session_data.user_id != 0 && session_data.user_id != request_headers.query.user_id) { +if (session_data.user_id !== 0 && session_data.user_id !== parseInt(request_headers.query.user_id)) { user_id = null; // force unset const errpage = wtvshared.doErrorPage(400, "You are not authorized to change the selected user's password."); headers = errpage[0]; data = errpage[1]; } -if (user_id != null) { +if (user_id !== null) { - if (session_data.user_id == request_headers.query.user_id) userSession = session_data; + if (session_data.user_id === parseInt(request_headers.query.user_id)) userSession = session_data; else { userSession = new WTVClientSessionData(minisrv_config, socket.ssid); userSession.user_id = user_id; @@ -35,5 +35,4 @@ wtv-expire: wtv-setup:/edit-user-begin?user_id=${user_id} wtv-expire: wtv-setup:/edit-user-name?user_id=${user_id} Location: wtv-setup:/edit-user-begin?user_id=${user_id}`; } -} -if (userSession) userSession = null; \ No newline at end of file +} \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-password.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-password.js index 491383f0..4c5712fc 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-password.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-change-password.js @@ -5,14 +5,14 @@ session_data.loadSessionData(); let user_id = null; if (request_headers.query.user_id) { - user_id = request_headers.query.user_id; + user_id = parseInt(request_headers.query.user_id); } else { errpage = wtvshared.doErrorPage(400, "User was not specified."); headers = errpage[0]; data = errpage[1]; } -if (session_data.user_id != 0 && session_data.user_id != request_headers.query.user_id) { +if (session_data.user_id !== 0 && session_data.user_id !== parseInt(request_headers.query.user_id)) { user_id = null; // force unset errpage = wtvshared.doErrorPage(400, "You are not authorized to edit the selected user."); headers = errpage[0]; @@ -24,10 +24,10 @@ if (user_id && !errpage) { Connection: Keep-Alive Content-Type: text/html` userSession = null; - if (session_data.user_id == request_headers.query.user_id) userSession = session_data; + if (session_data.user_id === parseInt(request_headers.query.user_id)) userSession = session_data; else { userSession = new WTVClientSessionData(minisrv_config, socket.ssid); - userSession.user_id = user_id;`` + userSession.user_id = user_id; } if (!userSession.loadSessionData()) { @@ -36,7 +36,7 @@ Content-Type: text/html` data = errpage[1]; } else { - if (request_headers.query.password.length == 0 && request_headers.query.password_verify.length == 0) { + if (request_headers.query.password.length === 0 && request_headers.query.password_verify.length === 0) { userSession.disableUserPassword(); headers = `300 OK Content-type: text/html @@ -76,5 +76,3 @@ if (errpage) { headers = errpage[0]; data = errpage[1]; } - -if (userSession) userSession = null; \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-mail-signature.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-mail-signature.js index 1559d5fc..f73c300a 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-mail-signature.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-mail-signature.js @@ -2,7 +2,7 @@ const minisrv_service_file = true; if (request_headers.query && session_data) { const signature = session_data.getSessionData("subscriber_signature"); - if (request_headers.query.mail_signature != signature) { + if (request_headers.query.mail_signature !== signature) { session_data.setSessionData("subscriber_signature", (request_headers.query.mail_signature) ? request_headers.query.mail_signature : ""); session_data.saveSessionData(); } diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-remove-users.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-remove-users.js index 3e505c9a..e415bfef 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-remove-users.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-remove-users.js @@ -1,10 +1,10 @@ const minisrv_service_file = true; let errpage; -if (Object.keys(session_data.listPrimaryAccountUsers()).length == 1) { +if (Object.keys(session_data.listPrimaryAccountUsers()).length === 1) { errpage = wtvshared.doErrorPage(400, "There are no more users to remove."); } -else if (session_data.user_id != 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to remove users from this account."); +else if (session_data.user_id !== 0) errpage = wtvshared.doErrorPage(400, "You are not authorized to remove users from this account."); const usersToRemove = []; Object.keys(request_headers.query).forEach(function (k) { @@ -21,7 +21,7 @@ if (errpage) { } else { if (!request_headers.query.confirm_remove) { let message = ''; - if (usersToRemove.length == 1) { + if (usersToRemove.length === 1) { const userSession = new WTVClientSessionData(minisrv_config, socket.ssid); userSession.switchUserID(usersToRemove[0]); const userName = userSession.getSessionData("subscriber_username"); @@ -61,7 +61,7 @@ Location: ${confirmAlert}` }) const num_accounts = session_data.getNumberOfUserAccounts(); let gourl = "wtv-setup:/remove-users?"; - if (num_accounts == 1) gourl = "wtv-setup:/accounts?"; + if (num_accounts === 1) gourl = "wtv-setup:/accounts?"; headers = `300 OK Connection: Keep-Alive diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-transfer-account.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-transfer-account.js index 70c5feb0..cd83de9a 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-transfer-account.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-setup/validate-transfer-account.js @@ -3,7 +3,7 @@ const minisrv_service_file = true; const wtvr = new WTVRegister(minisrv_config); // security -if (session_data.user_id != 0 && session_data.user_id != request_headers.query.user_id) { +if (session_data.user_id !== 0 && session_data.user_id !== parseInt(request_headers.query.user_id)) { const errpage = wtvshared.doErrorPage(400, "You are not authorized to transfer this account. Please log in as the primary user."); headers = errpage[0]; data = errpage[1]; diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/info.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/info.js index 2daaff9f..ca49dfd7 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/info.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/info.js @@ -2,7 +2,7 @@ const minisrv_service_file = true; let client_caps = null; -if (socket.ssid != null) { +if (socket.ssid !== null) { if (session_data.capabilities) { client_caps = session_data.capabilities.get(); } @@ -90,37 +90,37 @@ switch (chipVersionStr >> 0x18) { // determine box video type let video; -if ((sysConfigHex & 8) == 0) video = "NTSC"; +if ((sysConfigHex & 8) === 0) video = "NTSC"; else video = "PAL"; // determine box storage type let storage; -if ((sysConfigHex & 4) == 0) storage = "disk"; +if ((sysConfigHex & 4) === 0) storage = "disk"; else storage = "flash"; // determine box CPU endianness let endianness; -if ((sysConfigHex & 0x80000) == 0) endianness = "little"; +if ((sysConfigHex & 0x80000) === 0) endianness = "little"; else endianness = "big"; // determine box CPU type let cpu; -if ((sysConfigHex & 0x100000) == 0) cpu = 5230; +if ((sysConfigHex & 0x100000) === 0) cpu = 5230; else cpu = 4640; // determine box CPU clock multiplier let cpuMult; -if ((sysConfigHex & 0x20000) == 0) cpuMult = 3; +if ((sysConfigHex & 0x20000) === 0) cpuMult = 3; else cpuMult = 2; // determine smartcard 0 support let sc0; -if ((sysConfigHex & 0x400000) == 0) sc0 = "supported"; +if ((sysConfigHex & 0x400000) === 0) sc0 = "supported"; else sc0 = "not supported"; //determine smartcard 1 support let sc1; -if ((sysConfigHex & 0x200000) == 0) sc1 = "supported"; +if ((sysConfigHex & 0x200000) === 0) sc1 = "supported"; else sc1 = "not supported"; // ========================= FCS SYSCONFIG DECODE START ========================= @@ -130,47 +130,47 @@ else sc1 = "not supported"; // determine box CPU output bufs let outputBufs; -if ((sysConfigHex & 0x2000) == 0) outputBufs = 100; +if ((sysConfigHex & 0x2000) === 0) outputBufs = 100; else outputBufs = 50; // determine box SGRAM speed function getSGSpeed() { const SGRAMand = sysConfigHex & 0xc00000; - if (SGRAMand == 0x400000) return 66; + if (SGRAMand === 0x400000) return 66; else if (0x400000 < SGRAMand) - if (SGRAMand == 0x800000) return 77; - else if (SGRAMand == 0xc00000) return 83; // potentially incorrect but looks like it should return 83MHz on known existing hardware - else if (SGRAMand == 0) return 100; + if (SGRAMand === 0x800000) return 77; + else if (SGRAMand === 0xc00000) return 83; // potentially incorrect but looks like it should return 83MHz on known existing hardware + else if (SGRAMand === 0) return 100; } // determine box audio chip type let audio; -if ((sysConfigHex & 0xc0000) == 0xc0000) audio = "AKM4310/4309"; +if ((sysConfigHex & 0xc0000) === 0xc0000) audio = "AKM4310/4309"; else audio = "Unknown"; // determine box audio clock source let audioClk; -if ((sysConfigHex & 0x20000) == 0) audioClk = "SPOT"; +if ((sysConfigHex & 0x20000) === 0) audioClk = "SPOT"; else audioClk = "External"; // determine box video chip function getVideoChip() { const videoChipAnd = sysConfigHex & 0x600; - if (videoChipAnd == 0x200) return "Bt851"; + if (videoChipAnd === 0x200) return "Bt851"; else if (videoChipAnd < 0x201 && videoChipAnd !== 0) return "Unknown"; - else if (videoChipAnd == 0x400) return "Bt852"; + else if (videoChipAnd === 0x400) return "Bt852"; else return "Philips7187/Bt866"; } // determine box video type let videoB; -if ((sysConfigHex & 0x800) == 0) videoB = "PAL"; +if ((sysConfigHex & 0x800) === 0) videoB = "PAL"; else videoB = "NTSC"; // determine box video clock source let videoClk; -if ((sysConfigHex & 0x10000) == 0) videoClk = "External"; +if ((sysConfigHex & 0x10000) === 0) videoClk = "External"; else videoClk = "SPOT"; // determine box board type @@ -193,17 +193,17 @@ else bank0Type = "Flash"; // determine bank 0 mode let bank0Mode; -if ((sysConfigHex & 0x40000000) == 0) bank0Mode = "Normal"; +if ((sysConfigHex & 0x40000000) === 0) bank0Mode = "Normal"; else bank0Mode = "PageMode"; // determine bank 1 type let bank1Type; -if ((sysConfigHex & 0x8000000) == 0) bank1Type = "Flash"; +if ((sysConfigHex & 0x8000000) === 0) bank1Type = "Flash"; else bank1Type = "Mask"; // determine bank 1 mode let bank1Mode; -if ((sysConfigHex & 0x40000000) == 0) bank1Mode = "Normal"; +if ((sysConfigHex & 0x40000000) === 0) bank1Mode = "Normal"; else bank1Mode = "PageMode"; data = ` @@ -326,7 +326,7 @@ data = `
`
     // TODO: finish FCS decode
-    if (romType == "bf0app" && sysConfigHex !== "0xNaN") {
+    if (romType === "bf0app" && sysConfigHex !== "0xNaN") {
         data += `CPU Clk Mult = 2x Bus Clk, CPU output bufs @ ${outputBufs}%
 ROM Bank 0:  ${bank0Type}, ${bank0Mode}, 120ns/60ns
 ROM Bank 1:  ${bank1Type}, ${bank1Mode}, 150ns/75ns
diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/tricks.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/tricks.js
index 1756c7cc..21b86ec2 100644
--- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/tricks.js
+++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-tricks/tricks.js
@@ -46,11 +46,11 @@ for (let i = 0; i < tricks.length; i += 2) {
 	data += `
${(tricks[i][0] != "") ? `€ ${tricks[i][1]}` : `  `} +${(tricks[i][0] !== "") ? `€ ${tricks[i][1]}` : `  `} ` if (i + 1 < tricks.length) { - data += (tricks[i + 1][0] != "") ? `€ ${tricks[i + 1][1]}` : `  ` + data += (tricks[i + 1][0] !== "") ? `€ ${tricks[i + 1][1]}` : `  ` } else { // require even number of tricks data += "  " diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtvchat/catchall.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtvchat/catchall.js index 6201aac8..e497d2de 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtvchat/catchall.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtvchat/catchall.js @@ -5,7 +5,7 @@ delete urldata[0]; urldata = urldata.join(":").slice(1); console.log(urldata); -while (urldata.slice(0, 1) == "/") urldata = urldata.slice(1); +while (urldata.slice(0, 1) === "/") urldata = urldata.slice(1); let server = urldata.split('/')[0]; let port = 6667; diff --git a/zefie_wtvp_minisrv/includes/classes/WTVAdmin.js b/zefie_wtvp_minisrv/includes/classes/WTVAdmin.js index 3369ec17..65f50ca4 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVAdmin.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVAdmin.js @@ -51,7 +51,7 @@ class WTVAdmin { * @returns {number} The result of the ban operation */ banSSID(ssid, admin_ssid = null) { - if (ssid == admin_ssid) { + if (ssid === admin_ssid) { return this.REASON_NOSELF; } else { const fake_config = this.wtvshared.getUserConfig(); @@ -60,7 +60,7 @@ class WTVAdmin { let entry_exists = false; const self = this; 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; } @@ -85,7 +85,7 @@ class WTVAdmin { if (!fake_config.config.ssid_block_list) fake_config.config.ssid_block_list = []; if (typeof ssid === 'string') { Object.keys(fake_config.config.ssid_block_list).forEach(function (k) { - if (fake_config.config.ssid_block_list[k].toLowerCase() == ssid.toLowerCase()) { + if (fake_config.config.ssid_block_list[k].toLowerCase() === ssid.toLowerCase()) { fake_config.config.ssid_block_list.splice(k, 1); config_changed = true } @@ -93,7 +93,7 @@ class WTVAdmin { } else { Object.keys(fake_config.config.ssid_block_list).forEach(function (k) { Object.keys(ssid).forEach(function (j) { - if (fake_config.config.ssid_block_list[k].toLowerCase() == ssid[j].toLowerCase()) { + if (fake_config.config.ssid_block_list[k].toLowerCase() === ssid[j].toLowerCase()) { fake_config.config.ssid_block_list.splice(k, 1); config_changed = true } @@ -139,14 +139,14 @@ class WTVAdmin { checkPassword(password) { if (this.pcservices) { if (this.minisrv_config.config.pc_admin.password) { - return (password == this.minisrv_config.config.pc_admin.password); + return (password === this.minisrv_config.config.pc_admin.password); } else { // no password set return true; } } else { if (this.minisrv_config.services[this.service_name].password) { - return (password == this.minisrv_config.services[this.service_name].password); + return (password === this.minisrv_config.services[this.service_name].password); } else { // no password set return true; @@ -184,13 +184,13 @@ class WTVAdmin { if (this.minisrv_config.services[this.service_name].authorized_ssids) { const self = this; 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") { 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 } else { const ssid = k; - if (ssid == self.wtvclient.ssid) { + if (ssid === self.wtvclient.ssid) { allowed_ssid = true; Object.keys(self.minisrv_config.services[self.service_name].authorized_ssids[k]).forEach(function (j) { if (self.wtvshared.isInSubnet(self.clientAddress, self.minisrv_config.services[self.service_name].authorized_ssids[k][j])) { @@ -247,7 +247,7 @@ class WTVAdmin { const temp_session_data_file = self.fs.readFileSync(search_dir + self.path.sep + file, 'Utf8'); 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]]; } } catch (e) { @@ -317,7 +317,7 @@ class WTVAdmin { let isBanned = false; if (this.minisrv_config.config.ssid_block_list) { 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) { isBanned = true; } }); diff --git a/zefie_wtvp_minisrv/includes/classes/WTVAuthor.js b/zefie_wtvp_minisrv/includes/classes/WTVAuthor.js index 202b6808..d7a7efb0 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVAuthor.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVAuthor.js @@ -102,7 +102,7 @@ class WTVAuthor { this.debug("createPage", "pagenum", pagenum) this.debug("createPage", "pagelen", pagelen) } - if (pages.length == 0) { + if (pages.length === 0) { pagenum = 0 pagefile = pagenum + this.pageFileExt; } else { @@ -130,7 +130,7 @@ class WTVAuthor { // Encode page data into JSON let returnval = pages.length this.fs.writeFileSync(pagefileout, JSON.stringify(pagedata)); - if (returnval != 0) { + if (returnval !== 0) { const npages = this.fs.readdirSync(pagestorepath) returnval = npages.length - 1; } @@ -203,7 +203,7 @@ class WTVAuthor { case "snapshot": case "scrapbook": - if (state == "publishing") { + if (state === "publishing") { block = this.generatePublishImageBlock(number, page); } else { templatePath = this.wtvshared.getServiceDep('wtv-author/blocks/snapshot_block.njk', true); @@ -212,7 +212,7 @@ class WTVAuthor { break; case "clipart": - if (state == "publishing") { + if (state === "publishing") { block = this.generatePublishImageBlock(number, page); } else { templatePath = this.wtvshared.getServiceDep('wtv-author/blocks/clipart_block.njk', true); @@ -296,35 +296,35 @@ class WTVAuthor { const pagedata = this.loadPage(pagenum); let 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 = "Choose this to add a title to your document" else title = pagedata.title // Set the page style with too many paramaters this.setStyle(pagedata.style, title, pagedata.description, state, pagenum); let html = this.header - if (page == 1) { - if (pagedata.showtitle == true){ + if (page === 1) { + if (pagedata.showtitle === true){ html += this.titheader } } html += this.tabstart // 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++) { 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++) { html += this.generateBlock(i, pagenum, state) - if (this.afterblock1 && i == 0) { + if (this.afterblock1 && i === 0) { html += this.afterblock1 } } } else { for (let i = 0; i < pagedata.blocks.length; i++) { html += this.generateBlock(i, pagenum, state) - if (this.afterblock1 && i == 0) { + if (this.afterblock1 && i === 0) { html += this.afterblock1 } } @@ -345,7 +345,7 @@ class WTVAuthor { const pages = this.fs.readdirSync(pagestorepath) const page = pages[pagenum] 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) } if (!result) return false; @@ -402,7 +402,7 @@ class WTVAuthor { const blocks = pagedata.blocks; blocks.splice(position, 1); this.editPage(pagedata, pagenum); - if (block.type == "break") + if (block.type === "break") this.generateBreakList(pagenum) return true; } @@ -411,7 +411,7 @@ class WTVAuthor { if (this.minisrv_config.services['wtv-author'].public_domain) { return this.minisrv_config.services['wtv-author'].public_domain; } else { - if (this.minisrv_config.services['wtv-author'].publish_mode == "service") { + if (this.minisrv_config.services['wtv-author'].publish_mode === "service") { const target_service = this.minisrv_config.services[this.minisrv_config.services['wtv-author'].publish_dest]; if (target_service) { return target_service.host + ":" + target_service.port; @@ -432,7 +432,7 @@ class WTVAuthor { getPublishDir() { let destDir = false; - if (this.minisrv_config.services['wtv-author'].publish_mode == "service") { + if (this.minisrv_config.services['wtv-author'].publish_mode === "service") { const target_service = this.minisrv_config.services[this.minisrv_config.services['wtv-author'].publish_dest]; if (target_service) { if (!target_service.pc_services) { @@ -448,7 +448,7 @@ class WTVAuthor { 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") { destDir = this.minisrv_config.services['wtv-author'].publish_dest; } else { console.error("Invalid service configuration: invalid publish_mode."); @@ -461,7 +461,7 @@ class WTVAuthor { unpublishPage(pagenum) { const pagedata = this.loadPage(pagenum) const destDir = this.getPublishDir(); - if (pagedata.published != true) { + if (pagedata.published !== true) { return "This page is not published." } const publishname = pagedata.publishname; @@ -489,7 +489,7 @@ class WTVAuthor { const destDir = this.getPublishDir(); let publishname, fileout; - if (pagedata.published != true) { + if (pagedata.published !== true) { publishname = pagedata.title.slice(0, 50).replaceAll(" ", "").replace(/[^A-Za-z0-9]/g, "-"); pagedata.publishname = publishname; this.editPage(pagedata, pagenum); @@ -505,7 +505,7 @@ class WTVAuthor { this.fs.mkdirSync(destDir + this.wtvclient.session_store.subscriber_username + '/' + publishname + "/media/", { recursive: true }) for (let i = 1; i < pagedata.pagebreaks.length + 2; i++) { const pagehtml = this.generatePage("publishing", pagenum, i) - if (i == 1) + if (i === 1) fileout = "index.html" else fileout = "page" + i + ".html" @@ -613,8 +613,8 @@ class WTVAuthor { pagedata.blocks[oldposition].caption = caption pagedata.blocks[oldposition].size = size pagedata.blocks[oldposition].style = style - - if (oldposition != position) + + if (oldposition !== position) this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position); this.editPage(pagedata, pagenum); @@ -646,22 +646,22 @@ class WTVAuthor { const blocks = pagedata.blocks - if (photo != null) { + if (photo !== null) { const base64photo = new Buffer.from(photo).toString('base64') blocks[oldposition].photo = base64photo } - if (type != null) { + if (type !== null) { blocks[oldposition].type = type } - if (title != null) + if (title !== null) blocks[oldposition].title = title - if (caption != null) + if (caption !== null) blocks[oldposition].caption = caption - if (oldposition != position) { + if (oldposition !== position) { this.wtvshared.moveObjectKey(blocks, oldposition,position); } @@ -696,10 +696,10 @@ class WTVAuthor { pagedata.blocks[oldposition].size = size pagedata.blocks[oldposition].dividerBefore = dividerBefore pagedata.blocks[oldposition].dividerAfter = dividerAfter - - if (oldposition != position) - this.wtvshared.moveObjectKey(pagedata.blocks, oldposition,position); - + + if (oldposition !== position) + this.wtvshared.moveObjectKey(pagedata.blocks, oldposition, position); + this.editPage(pagedata, pagenum); return true; } @@ -727,10 +727,10 @@ class WTVAuthor { pagedata.blocks[oldposition].title = title pagedata.blocks[oldposition].items = items - - if (oldposition != position) - this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position); - + + if (oldposition !== position) + this.wtvshared.moveObjectKey(pagedata.blocks, oldposition, position); + this.editPage(pagedata, pagenum); return true; } @@ -745,7 +745,7 @@ class WTVAuthor { const url = linkItems[i] const name = listItems[i] - if (url == "http://") { + if (url === "http://") { continue loop; } else { const subblock = { @@ -778,8 +778,8 @@ class WTVAuthor { for (let i = 0; i < linkItems.length; i++) { const url = linkItems[i] const name = listItems[i] - - if (url == "http://") { + + if (url === "http://") { continue loop; } else { const subblock = { @@ -792,10 +792,10 @@ class WTVAuthor { pagedata.blocks[oldposition].title = title pagedata.blocks[oldposition].items = items - - if (oldposition != position) - this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position); - + + if (oldposition !== position) + this.wtvshared.moveObjectKey(pagedata.blocks, oldposition, position); + this.editPage(pagedata, pagenum); return true; } @@ -818,10 +818,10 @@ class WTVAuthor { editBreakBlock(pagenum, position, oldposition) { const pagedata = this.loadPage(pagenum); if (!pagedata) return false; - - if (oldposition != position) - this.wtvshared.moveObjectKey(pagedata.blocks,oldposition,position); - + + if (oldposition !== position) + this.wtvshared.moveObjectKey(pagedata.blocks, oldposition, position); + this.editPage(pagedata, pagenum); this.generateBreakList(pagenum); return true; @@ -832,7 +832,7 @@ class WTVAuthor { const breaks = []; for (let i = 0; i < pagedata.blocks.length; i++) { const type = pagedata.blocks[i].type - if (type == "break") + if (type === "break") breaks.push(i) } pagedata.pagebreaks = breaks; diff --git a/zefie_wtvp_minisrv/includes/classes/WTVBGMusic.js b/zefie_wtvp_minisrv/includes/classes/WTVBGMusic.js index 0d4d3201..cd1396ba 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVBGMusic.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVBGMusic.js @@ -1259,9 +1259,9 @@ class WTVBGMusic { // check if we need to set defaults let setDefaults = force_default; 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; - else if (music_obj.enableSongs.length == 0) setDefaults = true; + else if (music_obj.enableSongs.length === 0) setDefaults = true; if (setDefaults === true) { // set up defaults @@ -1355,10 +1355,10 @@ class WTVBGMusic { musiclist[k].id = k; if (String(category).length === 1) { // 3 digit song id - if (parseInt(k.slice(0, 1)) == parseInt(category) && String(k).length === 3) songList.push(musiclist[k]); + if (parseInt(k.slice(0, 1)) === parseInt(category) && String(k).length === 3) songList.push(musiclist[k]); } else if (String(category).length === 2) { // 4 digit song id - if (parseInt(k.slice(0, 2)) == parseInt(category) && String(k).length === 4) songList.push(musiclist[k]); + if (parseInt(k.slice(0, 2)) === parseInt(category) && String(k).length === 4) songList.push(musiclist[k]); } }); return songList.filter(value => Object.keys(value).length !== 0); @@ -1385,7 +1385,7 @@ class WTVBGMusic { const music_obj = this.getMusicObj(); let enabled = false; music_obj.enableCategories.forEach(function (v) { - if (parseInt(v) == parseInt(category)) { + if (parseInt(v) === parseInt(category)) { enabled = true; } }); @@ -1396,7 +1396,7 @@ class WTVBGMusic { const music_obj = this.getMusicObj(); let enabled = false; music_obj.enableSongs.forEach(function (v) { - if (parseInt(v) == parseInt(song)) { + if (parseInt(v) === parseInt(song)) { if (checkCat) { const songCategory = this.getSongCategory(song); if (this.isCategoryEnabled(songCategory)) { diff --git a/zefie_wtvp_minisrv/includes/classes/WTVClientCapabilities.js b/zefie_wtvp_minisrv/includes/classes/WTVClientCapabilities.js index 5db1ad1e..9b9626e5 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVClientCapabilities.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVClientCapabilities.js @@ -89,7 +89,7 @@ class WTVClientCapabilities { const capabilities = []; // might want to pass without a flag to get the table - if (wtv_capability_flags != null) { + if (wtv_capability_flags !== null) { // define function to convert hex string to binary string (0s & 1s) const hex2bin = function (hex) { @@ -118,7 +118,7 @@ class WTVClientCapabilities { // process bitfield and set capabilities Object.keys(bitfield).forEach(function (k) { // Convert binary to boolean, 0 to false, 1 to true - const bitfield_result = (bitfield[k] == "1") + const bitfield_result = (bitfield[k] === "1") // set flags based on position of bit try { diff --git a/zefie_wtvp_minisrv/includes/classes/WTVClientSessionData.js b/zefie_wtvp_minisrv/includes/classes/WTVClientSessionData.js index e94ed14c..7d2a0f13 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVClientSessionData.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVClientSessionData.js @@ -148,7 +148,7 @@ class WTVClientSessionData { if (addresses) { for (let i = 0; i < addresses.length; i++) { console.log(addr.toLowerCase(), addresses[i].address.toLowerCase()) - if (addr.toLowerCase() == addresses[i].address.toLowerCase()) { + if (addr.toLowerCase() === addresses[i].address.toLowerCase()) { return true; } } @@ -157,7 +157,7 @@ class WTVClientSessionData { } findFreeUserSlot() { - 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); if (this.fs.existsSync(master_directory)) { for (let i = 0; i < this.minisrv_config.config.user_accounts.max_users_per_account; i++) { @@ -171,17 +171,17 @@ class WTVClientSessionData { } getDisplayName() { - return (this.user_id == 0) ? this.getSessionData("subscriber_name") : this.getSessionData("display_name"); + return (this.user_id === 0) ? this.getSessionData("subscriber_name") : this.getSessionData("display_name"); } getNumberOfUserAccounts() { if (!this.isRegistered()) return false; - if (this.user_id != 0) return false; // subscriber only command + if (this.user_id !== 0) return false; // subscriber only command return Object.keys(this.listPrimaryAccountUsers()).length; } listPrimaryAccountUsers() { - 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 account_data = []; @@ -191,7 +191,7 @@ class WTVClientSessionData { if (f.startsWith("user")) { const user_file = this.path.resolve(master_directory + this.path.sep + f + this.path.sep + f + ".json"); if (self.fs.existsSync(user_file)) { - if (f == "user0") { + if (f === "user0") { account_data['subscriber'] = JSON.parse(this.fs.readFileSync(user_file)); account_data['subscriber'].user_id = 0; } @@ -283,14 +283,14 @@ class WTVClientSessionData { const pending_file = this.getUserStoreDirectory(true) + this.path.sep + "pending_transfer.json"; const file = this.fs.readFileSync(pending_file) const ssidobj = JSON.parse(file); - if (ssidobj.type != "target") return false; // Only allow completion from target + if (ssidobj.type !== "target") return false; // Only allow completion from target const source_ssid = ssidobj.ssid const old_account = this.getAccountStoreDirectory() + this.path.sep + source_ssid const new_account = this.getUserStoreDirectory(true); this.fs.cpSync(old_account, new_account, { filter: (source, _destination) => { - return source != "pending_transfer.json"; - }, + return source !== "pending_transfer.json"; + }, recursive: true }); this.fs.rmSync(old_account, { recursive: true }) @@ -304,7 +304,7 @@ class WTVClientSessionData { const ssidobj = JSON.parse(this.fs.readFileSync(pending_file)); console.log(ssidobj) if (dtype) { - (ssidobj.type == dtype) ? ssidobj.ssid : false; + (ssidobj.type === dtype) ? ssidobj.ssid : false; } else { return ssidobj; @@ -543,7 +543,7 @@ class WTVClientSessionData { let cookie_data; if (!this.checkCookies()) this.resetCookies(); if (!domain) return false; - else if (typeof (domain) == 'object') { + else if (typeof (domain) === 'object') { // accept array as first argument if (domain.domain && domain.path && domain.expires && domain.data) cookie_data = domain; else return false; @@ -564,7 +564,7 @@ class WTVClientSessionData { // see if we have a cookie for this domain/path Object.keys(this.session_store.cookies).forEach(function (k) { if (cookie_index >= 0) return; - if (domain == self.session_store.cookies[k].domain && path == self.session_store.cookies[k].path) cookie_index = k; + if (domain === self.session_store.cookies[k].domain && path === self.session_store.cookies[k].path) cookie_index = k; }); // otherwise add a new one if (cookie_index === -1) cookie_index = this.countCookies(); @@ -586,8 +586,8 @@ class WTVClientSessionData { let result = false; Object.keys(this.session_store['cookies']).forEach(function (k) { if (result !== false) return; - if (self.session_store['cookies'][k].domain == domain && - self.session_store['cookies'][k].path == path) { + if (self.session_store['cookies'][k].domain === domain && + self.session_store['cookies'][k].path === path) { const current_epoch_utc = Date.parse((new Date()).toUTCString()); const cookie_expires_epoch_utc = Date.parse(new Date(Date.parse(self.session_store['cookies'][k].expires)).toUTCString()); @@ -621,7 +621,7 @@ class WTVClientSessionData { return true; } if (!domain) return false; - else if (typeof (domain) == 'object') { + else if (typeof (domain) === 'object') { // accept array as first argument if (domain.domain && domain.path) { path = domain.path; @@ -633,7 +633,7 @@ class WTVClientSessionData { const self = this; Object.keys(this.session_store['cookies']).forEach(function (k) { - if (self.session_store['cookies'][k].domain == domain && self.session_store['cookies'][k].path == path) { + if (self.session_store['cookies'][k].domain === domain && self.session_store['cookies'][k].path === path) { delete self.session_store['cookies'][k]; self.storeSessionData(); result = true; @@ -649,7 +649,7 @@ class WTVClientSessionData { */ checkCookies() { if (!this.session_store.cookies) return false; - else if (this.session_store.cookies == []) return false; + else if (this.session_store.cookies.length === 0) return false; return true; } @@ -677,7 +677,7 @@ class WTVClientSessionData { } } catch (e) { // Don't log error 'file not found', it just means the client isn't registered yet - if (e.code != "ENOENT") console.error(" # Error loading session data for", this.wtvshared.filterSSID(this.ssid), e); + if (e.code !== "ENOENT") console.error(" # Error loading session data for", this.wtvshared.filterSSID(this.ssid), e); // also wipe any existing session_store this.session_store = {}; return false; @@ -723,7 +723,7 @@ class WTVClientSessionData { validateUserPassword(passwd) { if (!this.getUserPasswordEnabled()) return true; // no password is set so always validate - return (this.encodePassword(passwd) == this.getSessionData("subscriber_password")); + return (this.encodePassword(passwd) === this.getSessionData("subscriber_password")); } isUserLoggedIn() { @@ -761,7 +761,7 @@ class WTVClientSessionData { if (!this.fs.existsSync(storeDir)) this.mkdirRecursive(storeDir); if (sessionToStore.password_valid) delete sessionToStore.password_valid; // do not save validity state of password login, resets when session expires - if (json_save_data != json_load_data) this.fs.writeFileSync(storeDir + "user" + this.user_id + ".json", JSON.stringify(sessionToStore), "Utf8"); + if (json_save_data !== json_load_data) this.fs.writeFileSync(storeDir + "user" + this.user_id + ".json", JSON.stringify(sessionToStore), "Utf8"); return true; } catch (e) { console.error(" # Error saving session data for", this.wtvshared.filterSSID(this.ssid), e); @@ -904,11 +904,9 @@ class WTVClientSessionData { switch (this.get("wtv-client-rom-type")) { case "US-DTV-disk-0MB-16MB-softmodem-CPU5230": case "US-DTV-disk-0MB-32MB-softmodem-CPU5230": - return "UltimateTV Satellite receiver"; - case "US-WEBSTAR-disk-0MB-8MB-softmodem-CPU5230": case "US-WEBSTAR-disk-0MB-16MB-softmodem-CPU5230": - return "WebTV Satellite receiver"; + return "satellite receiver"; case "US-LC2-flashdisk-0MB-16MB-softmodem-CPU5230": case "US-LC2-disk-0MB-8MB": @@ -922,10 +920,10 @@ class WTVClientSessionData { case "JP-LC2-disk-0MB-8MB-CPU5230": case "JP-LC2-disk-0MB-16MB-CPU5230": case "JP-LC2-flash-2MB-8MB-CPU5230": - return "WebTV Plus receiver"; + return "Plus receiver"; default: - return "WebTV Internet receiver"; + return "Internet terminal"; } } @@ -954,7 +952,7 @@ class WTVClientSessionData { ssid_access_list_ip_override = true; } } else { - if (self.clientAddress == self.minisrv_config.config.ssid_ip_allow_list[self.ssid][k]) { + if (self.clientAddress === self.minisrv_config.config.ssid_ip_allow_list[self.ssid][k]) { // remoteAddr directly matches IP ssid_access_list_ip_override = true; } @@ -972,7 +970,7 @@ class WTVClientSessionData { // process whitelist first if (self.ssid && self.minisrv_config.config.ssid_allow_list) { - const ssid_is_in_whitelist = self.minisrv_config.config.ssid_allow_list.findIndex(element => element == self.ssid); + const ssid_is_in_whitelist = self.minisrv_config.config.ssid_allow_list.findIndex(element => element === self.ssid); if (ssid_is_in_whitelist === -1) { // no whitelist match, but lets see if the remoteAddress is allowed checkSSIDIPWhitelist(self.ssid, false); @@ -981,7 +979,7 @@ class WTVClientSessionData { // now check blacklist if (self.ssid && self.minisrv_config.config.ssid_block_list) { - const ssid_is_in_blacklist = self.minisrv_config.config.ssid_block_list.findIndex(element => element == self.ssid); + const ssid_is_in_blacklist = self.minisrv_config.config.ssid_block_list.findIndex(element => element === self.ssid); if (ssid_is_in_blacklist !== -1) { // blacklist match, but lets see if the remoteAddress is allowed checkSSIDIPWhitelist(self.ssid, true); @@ -1000,7 +998,7 @@ class WTVClientSessionData { isAuthorized(url, whitelist = 'lockdown', ignore_lockdown = false) { // not in lockdown so just return true - if (whitelist == 'lockdown' && !this.lockdown && !ignore_lockdown) return true; + if (whitelist === 'lockdown' && !this.lockdown && !ignore_lockdown) return true; // in lockdown, check whitelisted urls const self = this; @@ -1057,25 +1055,25 @@ class WTVClientSessionData { const romtype = this.get("wtv-client-rom-type"); const brandId = this.ssid.charAt(8) - if (brandId == 0) - if (url && romtype == "US-DTV-disk-0MB-32MB-softmodem-CPU5230") + if (brandId === 0) + if (url && romtype === "US-DTV-disk-0MB-32MB-softmodem-CPU5230") return "Sony/DirecTV"; else return "Sony"; - else if (brandId == 1) + else if (brandId === 1) if (url && isPlus === true) return "Philips-Plus"; else return "Philips"; - else if (brandId == 4) + else if (brandId === 4) return "Mitsubishi"; - else if (brandId == 5) + else if (brandId === 5) return "Philips-Mont"; - else if (brandId == 7) + else if (brandId === 7) return "Samsung"; - else if (brandId == 9) + else if (brandId === 9) if (url) - if (romtype == "US-DTV-disk-0MB-32MB-softmodem-CPU5230") + if (romtype === "US-DTV-disk-0MB-32MB-softmodem-CPU5230") return "Thomson/DirecTV"; else return "Thomson"; diff --git a/zefie_wtvp_minisrv/includes/classes/WTVDisk.js b/zefie_wtvp_minisrv/includes/classes/WTVDisk.js index 9137e887..d2094604 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVDisk.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVDisk.js @@ -159,9 +159,9 @@ class WTVDownloadList { this.download_list += `group: ${group}-UPDATE\n`; this.download_list += `location: ${source}\n`; this.download_list += `file-permission: ${file_permission}\n`; - if (checksum != null) this.download_list += `wtv-checksum: ${checksum}\n`; - if (uncompressed_size != null) this.download_list += `wtv-uncompressed-filesize: ${uncompressed_size}\n`; - this.download_list += `service-source-location: /webtv/content/${source.slice(source.indexOf('-') + 1, source.indexOf(':/'))}d/${source.slice(source.indexOf(':/') + 2)}\n`; + if (checksum !== null) this.download_list += `wtv-checksum: ${checksum}\n`; + if (uncompressed_size !== null) this.download_list += `wtv-uncompressed-filesize: ${uncompressed_size}\n`; + this.download_list += `service-source-location: /webtv/content/${source.slice(source.indexOf('-') + 1, source.indexOf(':/'))}d/${source.slice(source.indexOf(':/') + 2)}\n`; this.download_list += `client-dest-location: ${path}\n\n`; } @@ -180,10 +180,10 @@ class WTVDownloadList { } getGroupDataFromClientPost(post_data) { - if (typeof post_data == 'string') post_data = post_data.split("\n\n"); + if (typeof post_data === 'string') post_data = post_data.split("\n\n"); const group_data = []; post_data.forEach(function (v) { - if (v.slice(0, 4) == "file") { + if (v.slice(0, 4) === "file") { const block_split = v.split("\n"); const group_data_entry = {}; group_data_entry.path = block_split[0]; diff --git a/zefie_wtvp_minisrv/includes/classes/WTVFavorites.js b/zefie_wtvp_minisrv/includes/classes/WTVFavorites.js index ed9887f1..b6678789 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVFavorites.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVFavorites.js @@ -87,7 +87,7 @@ class WTVFavorites { const self = this; if (folder_templates[folder]) { Object.keys(folder_templates[folder]).forEach(function (k) { - self.createFavorite(folder_templates[folder][k].title, folder_templates[folder][k].url, folder, (folder_templates[folder][k].image_type == "image/wtv-bitmap") ? atob(folder_templates[folder][k].image) : folder_templates[folder][k].image, folder_templates[folder][k].image_type); + self.createFavorite(folder_templates[folder][k].title, folder_templates[folder][k].url, folder, (folder_templates[folder][k].image_type === "image/wtv-bitmap") ? atob(folder_templates[folder][k].image) : folder_templates[folder][k].image, folder_templates[folder][k].image_type); }) } } @@ -95,12 +95,12 @@ class WTVFavorites { createDefaultFolders() { const brandId = this.ssid.charAt(8); this.createTemplateFolder("Recommended"); - if (brandId == 7) + if (brandId === 7) this.createTemplateFolder("Personal (Samsung)"); else this.createTemplateFolder("Personal"); - - if (brandId == 0) + + if (brandId === 0) this.createTemplateFolder("Sony"); } @@ -145,7 +145,7 @@ class WTVFavorites { const favoriteid = this.createFavoriteID(); const favoritefile = favoriteid + this.favFileExt; const favoritefileout = folderpath + favoritefile; - if (imagetype != "url") + if (imagetype !== "url") image = btoa(image); title = decodeURIComponent(title).replaceAll("+", " "); @@ -307,7 +307,7 @@ class WTVFavorites { const keydata = JSON.parse(this.fs.readFileSync(favoritefileout)); const keys = Object.keys(keydata); for (let i = 0; i < keys.length; i++) { - if (keydata[keys[i]].id == favoriteid) { + if (keydata[keys[i]].id === favoriteid) { return { key: keys[i], folder: keydata[keys[i]].folder }; } } @@ -419,7 +419,7 @@ class WTVFavorites { } break; } - if (oldkey != "none") { + if (oldkey !== "none") { keydata[oldkey].folder = null; keydata[oldkey].id = null; } diff --git a/zefie_wtvp_minisrv/includes/classes/WTVFlashrom.js b/zefie_wtvp_minisrv/includes/classes/WTVFlashrom.js index 93e68bdf..d1c37906 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVFlashrom.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVFlashrom.js @@ -66,7 +66,7 @@ class WTVFlashrom { flashrom_info.magic = part_header.toString('hex', 0, 4); flashrom_info.valid_flashrom = false; - if (flashrom_info.magic == flashrom_magic) flashrom_info.valid_flashrom = true; + if (flashrom_info.magic === flashrom_magic) flashrom_info.valid_flashrom = true; if (!flashrom_info.valid_flashrom) console.error(" * Warning! FlashROM File Magic (" + flashrom_info.magic + ") did not match expected magic (" + flashrom_magic + ")..."); //if (this.minisrv_config.config.debug_flags.debug && !this.no_debug) console.log(" # FlashROM File Magic (" + flashrom_info.magic + "), expected magic (" + flashrom_magic + "), OK = " + flashrom_info.valid_flashrom + "..."); @@ -88,7 +88,7 @@ class WTVFlashrom { flashrom_info.part_number = data.readUInt16BE(28); if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Curr Part Number :", flashrom_info.part_number); - flashrom_info.is_last_part = ((flashrom_info.byte_progress + flashrom_info.part_total_size) == flashrom_info.total_parts_size) ? true : false; + flashrom_info.is_last_part = ((flashrom_info.byte_progress + flashrom_info.part_total_size) === flashrom_info.total_parts_size) ? true : false; if (flashrom_info.is_last_part) { if (this.minisrv_config.config.debug_flags.debug && !this.minisrv_config.config.debug_flags.quiet && !this.no_debug) console.log(" # Flashrom Curr Part is Last:", flashrom_info.is_last_part); @@ -117,7 +117,7 @@ class WTVFlashrom { const flashrom_info = this.getFlashromInfo(data, request_path) if (flashrom_info.is_bootrom) headers += "Content-Type: binary/x-wtv-bootrom"; // maybe? else headers += "Content-Type: binary/x-wtv-flashblock"; - if (flashrom_info.next_rompath != null && this.bf0app_update) headers += "\nwtv-visit: " + flashrom_info.next_rompath; + if (flashrom_info.next_rompath !== null && this.bf0app_update) headers += "\nwtv-visit: " + flashrom_info.next_rompath; headers += "\nminisrv-no-mail-count: true"; callback(data, headers); } @@ -132,7 +132,7 @@ class WTVFlashrom { let headers, data, flashrom_file_path = null; const self = this; Object.keys(self.service_vaults).forEach(function (g) { - if (flashrom_file_path != null) return; + if (flashrom_file_path !== null) return; flashrom_file_path = self.service_vaults[g] + "/" + self.service_name + "/" + request_path; if (!self.fs.existsSync(flashrom_file_path)) flashrom_file_path = null; }); @@ -160,11 +160,11 @@ class WTVFlashrom { res.on('end', function () { if (self.minisrv_config.config.debug_flags.debug) console.log(` * minisrv FlashROM Server HTTP Status: ${res.statusCode} ${res.statusMessage}`) - if (res.statusCode == 200) { + if (res.statusCode === 200) { data = Buffer.from(data_hex, 'hex'); - } else if (res.statusCode == 206) { + } else if (res.statusCode === 206) { data = self.getFlashromInfo(Buffer.from(data_hex, 'hex'), request_path); - } else if (res.statusCode == 404) { + } else if (res.statusCode === 404) { const errpage = self.wtvshared.doErrorPage(404, "The service could not find the requested ROM on the minisrv FlashROM server.") headers = errpage[0]; data = errpage[1]; @@ -173,7 +173,7 @@ class WTVFlashrom { headers = errpage[0]; data = errpage[1]; } - if (!headers && res.statusCode != 206) { + if (!headers && res.statusCode !== 206) { self.sendToClient(data, request_path, callback); } else { callback(data, headers); @@ -182,7 +182,7 @@ class WTVFlashrom { }); req.end(); } else { - this.doLocalFlashROM(flashrom_file_path, request_path, callback, ((length != 0) ? true : false)); + this.doLocalFlashROM(flashrom_file_path, request_path, callback, ((length !== 0) ? true : false)); } } } diff --git a/zefie_wtvp_minisrv/includes/classes/WTVGuide.js b/zefie_wtvp_minisrv/includes/classes/WTVGuide.js index 3c737625..9083f8e7 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVGuide.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVGuide.js @@ -70,7 +70,7 @@ class WTVGuide { start = start + search.length; const original_start = start; // handle - if (definition.charAt(start) != ">") { + if (definition.charAt(start) !== ">") { start++; // +1 to skip = end = definition.indexOf(">", start); if (end === -1) break; // malformed tag, exit loop @@ -99,10 +99,7 @@ class WTVGuide { // replaces with the friendly name of the type of unit the user has while (definition.indexOf("") >= 0) { const romtype = this.session_data.get("wtv-client-rom-type"); - let boxname = ""; - 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.capabilities.get("client-has-tv-experience")) boxname = "WebTV Plus receiver"; - else boxname = "WebTV Internet terminal"; + const boxname = this.wtvshared.getBoxName(romtype); definition = definition.replace(/\/g, boxname); } // replaces with either "WebTV" or "WebTV Plus" depending on user box type diff --git a/zefie_wtvp_minisrv/includes/classes/WTVIRC.js b/zefie_wtvp_minisrv/includes/classes/WTVIRC.js deleted file mode 100644 index 6665b2de..00000000 --- a/zefie_wtvp_minisrv/includes/classes/WTVIRC.js +++ /dev/null @@ -1,4719 +0,0 @@ -const net = require('net'); -const dns = require('dns'); -const tls = require('tls'); -const fs = require('fs'); -const path = require('path'); -const { get } = require('http'); -const WTVShared = require('./WTVShared.js').WTVShared; - -class WTVIRC { - /* - * @constructor - * @class WTVIRC - * zefIRCd - A node.js IRC server implementation - * Tested with WebTV, KvIRC and mIRC. - * Supports unencrypted and encrypted (SSL) connections on the same port. - * It supports basic commands like NICK, USER, JOIN, PART, PRIVMSG, NOTICE, TOPIC, AWAY, MODE, KICK, and PING. - * Basic IRCOp functionality is included. - * hybridircd compatible server link protocol (tested with Anope IRC Services, and partially with hybridircd itself). - * Channel modes are supported, including invite-only, topic protection, password protection, and user modes (op/halfop/voice), and more. - * SSL only channel mode +Z is supported. As is usermode +Z (no DMs from non-SSL users) - * - * TODO: Test for crashes with arbitrary data, or malformed commands (especially SSL handshake, or server interface). - * - * @param {Object} minisrv_config - The configuration object for minisrv. - * @param {string} [host='localhost'] - The host to bind the IRC server to. - * @param {number} [port=6667] - The port to bind the IRC server to. - * @param {boolean} [debug=false] - Whether to enable debug mode for logging. - */ - constructor(minisrv_config, host = 'localhost', port = 6667, debug = false) { - this.minisrv_config = minisrv_config; - this.wtvshared = new WTVShared(minisrv_config); - this.version = '0.2.7'; - // Try to get git commit from environment variable or file, fallback to null if not available - this.git_commit = this.getGitRevision(); - if (this.git_commit) { - this.version += `-${this.git_commit}`; - } - this.host = host; - this.port = port; - this.debug = debug; - this.server = null; - this.clients = []; - this.channelData = new Map(); - this.usernames = new Map(); // nickname -> username - this.usertimestamps = new Map(); // nickname -> timestamp since last message - this.usermodes = new Map(); // nickname -> Array of modes (e.g. ['w', 'i']) - this.usersignontimestamps = new Map(); // nickname -> timestamp since user signed on - this.nicknames = new Map(); // socket -> nickname - this.awaymsgs = new Map(); // nickname -> away message - this.servers = new Map(); // socket -> server information - this.serverusers = new Map(); // server -> Set of users connected to this server - this.reservednicks = []; - this.klines = []; - this.accounts = new Map(); // nickname -> account name - this.hostnames = new Map(); // nickname -> hostname - this.realhosts = new Map(); // nickname -> real IP address - this.uniqueids = new Map(); // nickname -> unique ID mapping - this.userinfo = new Map(); // nickname -> user info (e.g. real name) - this.logdata = []; - this.max_log_lines = 50; - this.default_channel_modes = ['n','t']; - this.default_user_modes = ['x']; - this.server_start_time = this.getDate(); - this.allowed_common_characters = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','_','-']; - this.allowed_chan_characters = [...this.allowed_common_characters, '.']; - this.allowed_nick_characters = [...this.allowed_common_characters, '[',']','{','}','\\','|','^','-','~']; - this.irc_config = minisrv_config.config.irc || {}; - this.channelprefixes = this.irc_config.channel_prefixes || ['#']; - this.servername = this.irc_config.server_hostname || 'irc.local'; - this.network = this.irc_config.network || 'minisrv'; - this.oper_username = this.irc_config.oper_username || 'minisrv'; - this.oper_password = this.irc_config.oper_password || 'changeme573_PLEASE_CHANGE_THIS_PASSWORD'; - this.oper_enabled = this.irc_config.oper_enabled || false; // Default to off for security - this.irc_motd = this.irc_config.motd || [ - 'Welcome to the zefIRCd IRC server, powered by minisrv.', - 'This server is powered by Node.js, and the minisrv project.', - '', - 'For more information, visit:', - 'https://github.com/zefie/zefie_wtvp_minisrv' - ]; - this.nicklen = this.irc_config.nick_len || 31; - this.maxbans = this.irc_config.max_bans || 100; - this.maxlimit = this.irc_config.max_limit || 50; - this.maxexcept = this.irc_config.max_except || 100; - this.maxinvite = this.irc_config.max_invite || 100; - this.maxkeylen = this.irc_config.max_keylen || 24; - this.channellimit = this.irc_config.channel_limit || 10; - this.channellen = this.irc_config.channel_len || 32; - this.topiclen = this.irc_config.topic_len || 255; - this.kicklen = this.irc_config.kick_len || 255; - this.awaylen = this.irc_config.away_len || 200; - this.enable_tls = this.irc_config.enable_ssl || false; - this.maxtargets = this.irc_config.max_targets || 4; - this.socket_timeout = 75; // Default socket timeout to 75 seconds, most clients will send PINGs every 60 seconds, so this should be enough to catch lost connections - this.server_hello = this.irc_config.server_hello || `zefIRCd v${this.version} IRC server powered by minisrv`; - this.serverId = this.irc_config.server_id || '00A'; // Default server ID, can be overridden in config - this.allow_public_vhosts = this.irc_config.allow_public_vhosts || false; // Default to false for security - this.kick_insecure_users_on_secure = this.irc_config.kick_insecure_users_on_secure || true; // If true, users without SSL connections will be kicked from a channel when +Z is applied - this.hide_version = this.irc_config.hide_version || false; // If true, the server will not send its version in the MOTD - this.clientpeak = 0; - this.globalpeak = 0; - this.socketpeak = 0; - this.modeparamlimit = 5; // Technically we have no limit, but this is a good default for most IRC clients - this.max_message_len = 512; // RFC2812 standard maximum message length (including \r\n) - this.reject_overlength_messages = this.irc_config.reject_overlength_messages || true; // If true, messages longer than max_message_len will be rejected, if false, they will be truncated to max_message_len - this.totalConnections = 0; - this.supported_channel_modes = "Ibe,k,l,CNOQRSTVZcimnprt"; - this.supported_user_modes = "BRZciorswxz"; - this.supported_prefixes = ["ohv", "@%+"]; - this.supported_client_caps = ['chghost', 'away-notify', 'echo-message', 'invite-notify', 'multi-prefix', 'userhost-in-names', 'account-notify', 'extended-join']; - this.supported_server_caps = ['TBURST', 'EOB', 'IE', 'EX']; - this.enable_webtv_command_hacks = this.irc_config.enable_webtv_command_hacks || true; - this.supported_webtv_command_hacks = ["MODE", "KICK"]; // You could technically add any command currently supported by the IRCd here, such as OPER, KILL, KLINE, etc. - - // Rate limiting configuration - this.rate_limit_enabled = this.irc_config.rate_limit_enabled || true; - this.max_messages_per_second = this.irc_config.max_messages_per_second || 5; - this.message_counts = new Map(); // socket -> {count, resetTime} - - // Brute force protection - this.failed_auth_attempts = new Map(); // IP -> {count, lockoutUntil} - this.max_auth_attempts = this.irc_config.max_auth_attempts || 3; - this.auth_lockout_duration = this.irc_config.auth_lockout_duration || 300; // 5 minutes - - // Connection limits - this.connections_per_ip = new Map(); // IP -> count - this.max_connections_per_ip = this.irc_config.max_connections_per_ip || 3; - - // Security logging - this.security_log_enabled = this.irc_config.security_log_enabled || true; - this.security_events = []; - this.session_store_path = this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + path.sep + 'minisrv_internal_irc'); - this.klines_path = this.session_store_path + path.sep + 'klines.json'; - this.caps = [ - `AWAYLEN=${this.awaylen} CASEMAPPING=rfc1459 BOT=B CHANMODES=${this.supported_channel_modes} CHANNELLEN=${this.channellen} CHANTYPES=${this.channelprefixes.join('')} PREFIX=(${this.supported_prefixes[0]})${this.supported_prefixes[1]} USERMODES=${this.supported_user_modes} MAXLIST=b:${this.maxbans},e:${this.maxexcept},i:${this.maxinvite},k:${this.maxkeylen},l:${this.maxlimit}`, - `CHARSET=ascii MODES=${this.modeparamlimit} EXCEPTS=e INVEX=I NETWORK=${this.network} CHANLIMIT=${this.channelprefixes.join('')}:${this.channellimit} NICKLEN=${this.nicklen} TOPICLEN=${this.topiclen} KICKLEN=${this.kicklen}` - ]; - } - - start() { - this.loadKLinesFromFile(); - - if (this.enable_tls) { - this.supported_client_caps.push('tls'); - } - if (this.irc_config.channels) { - for (const channel of this.irc_config.channels) { - this.createChannel(channel.name); - if (channel.modes && Array.isArray(channel.modes)) { - const channelData = this.channelData.get(channel.name); - if (channelData) { - channelData.modes = [...channel.modes]; - } - } - if (channel.topic) { - const channelData = this.channelData.get(channel.name); - if (channelData) { - channelData.topic = channel.topic; - } - } - } - } - this.server_start_time = this.getDate(); - this.server = net.createServer(async socket => { - - // Detect SSL handshake and wrap socket if needed - socket.once('data', async firstChunk => { - this.totalConnections++; - - // Check connection limits per IP - const clientIP = socket.remoteAddress; - const currentConnections = this.connections_per_ip.get(clientIP) || 0; - if (currentConnections >= this.max_connections_per_ip) { - this.debugLog('warn', `Connection limit exceeded for IP ${clientIP}`); - socket.write(`:${this.servername} ERROR :Too many connections from your IP\r\n`); - socket.end(); - return; - } - this.connections_per_ip.set(clientIP, currentConnections + 1); - - socket.removeAllListeners('data'); - socket.pause(); - socket.on('error', (err) => { - this.debugLog('error', `Socket error: ${err.message}`); - this.terminateSession(socket, true); - }); - socket.on('timeout', () => { - this.debugLog('warn', `Socket timeout for ${socket.remoteAddress}`); - this.terminateSession(socket, true); - }); - // Check if the first byte indicates SSL/TLS handshake (0x16 for TLS Handshake) - if (Buffer.isBuffer(firstChunk) ? firstChunk[0] === 0x16 : firstChunk.charCodeAt(0) === 0x16) { - if (!this.enable_tls) { - // If SSL is not enabled, close the socket - await this.safeWriteToSocket(socket, `:${this.servername} 421 * :TLS is not enabled on this server\r\n`); - this.terminateSession(socket, true); - return; - } - - // SSL detected, upgrade socket to TLS - const keyBuffer = fs.readFileSync(this.wtvshared.parseConfigVars(this.irc_config.ssl_cert.key)); - const certBuffer = fs.readFileSync(this.wtvshared.parseConfigVars(this.irc_config.ssl_cert.cert)); - const secureSocket = new tls.TLSSocket(socket, { - isServer: true, - ALPNProtocols: ['irc'], - secureContext: tls.createSecureContext({ - key: keyBuffer, - cert: certBuffer, - }), - }); - socket.push(firstChunk); - - secureSocket.on('error', (err) => { - this.debugLog('error', `Secure socket error: ${err.message}`); - this.terminateSession(secureSocket, true); - }); - - secureSocket.on('close', () => { - this.terminateSession(secureSocket, false); - }); - - // Only start processing after handshake is complete - secureSocket.on('secure', async () => { - this.debugLog('info', 'Secure connection (SSL) established with '+ socket.remoteAddress); - socket.removeAllListeners(); - await this.initializeSocket(secureSocket, true); - - }); - secureSocket.resume(); - return; - } else { - // Not SSL, re-emit the data event for normal processing - await this.initializeSocket(socket); - socket.emit('data', firstChunk.toString('ascii')); - socket.resume(); - this.clientpeak = Math.max(this.clientpeak, this.clients.length); - return; - } - }); - }); - this.server.listen(this.port, this.host, () => { - this.debugLog('info', `zefIRCd ${this.version} server started on port ${this.host}:${this.port}`); - }); - } - - async safeWriteToSocket(socket, data) { - if (!socket || !data) { - this.debugLog('error', 'writeToSocket called with invalid parameters:', socket, data); - return; - } - if (typeof data !== 'string') { - data = data.toString('ascii'); - } - if (data.length > this.max_message_len) { - data = data.slice(0, this.max_message_len - 2) + '\r\n'; - this.debugLog('warn', `Data length exceeds max_message_len (${this.max_message_len}), truncating: ${data.length} > ${this.max_message_len}`); - } - - // Add timeout to prevent infinite loop - let waitCount = 0; - const maxWaitIterations = 1000; // 10 seconds max wait - while (socket.writable === false && waitCount < maxWaitIterations) { - await new Promise(resolve => setTimeout(resolve, 10)); - waitCount++; - } - - if (socket.writable === false) { - this.debugLog('error', 'Socket not writable after timeout, aborting write'); - return; - } - socket.write(data); - } - - checkRateLimit(socket) { - if (!this.rate_limit_enabled || socket.isserver || this.isIRCOp(socket.nickname)) { - return true; // No rate limiting for servers or IRCOps - } - - const now = Date.now(); - const socketId = socket.remoteAddress + ':' + socket.remotePort; - - if (!this.message_counts.has(socketId)) { - this.message_counts.set(socketId, { count: 1, resetTime: now + 1000 }); - return true; - } - - const rateLimitData = this.message_counts.get(socketId); - - if (now > rateLimitData.resetTime) { - // Reset the counter - rateLimitData.count = 1; - rateLimitData.resetTime = now + 1000; - return true; - } - - if (rateLimitData.count >= this.max_messages_per_second) { - return false; // Rate limit exceeded - } - - rateLimitData.count++; - return true; - } - - checkAuthAttempts(socket) { - const ip = socket.realhost || socket.remoteAddress; - const now = Date.now(); - - if (!this.failed_auth_attempts.has(ip)) { - return true; - } - - const authData = this.failed_auth_attempts.get(ip); - if (authData.lockoutUntil && now < authData.lockoutUntil) { - return false; // Still locked out - } - - return true; - } - - recordAuthFailure(socket) { - const ip = socket.realhost || socket.remoteAddress; - const now = Date.now(); - - if (!this.failed_auth_attempts.has(ip)) { - this.failed_auth_attempts.set(ip, { count: 1, lockoutUntil: null }); - return; - } - - const authData = this.failed_auth_attempts.get(ip); - authData.count++; - - if (authData.count >= this.max_auth_attempts) { - authData.lockoutUntil = now + (this.auth_lockout_duration * 1000); - this.debugLog('warn', `IP ${ip} locked out for ${this.auth_lockout_duration} seconds due to failed auth attempts`); - } - } - - clearAuthFailures(socket) { - const ip = socket.realhost || socket.remoteAddress; - this.failed_auth_attempts.delete(ip); - } - - sanitizeInput(input, type = 'general') { - if (typeof input !== 'string') { - return ''; - } - - // Remove control characters except \r\n - input = input.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, ''); - - switch (type) { - case 'nickname': - // IRC nicknames: A-Z a-z 0-9 [ ] \ ` _ ^ { | } - return input.replace(/[^A-Za-z0-9\[\]\\`_^{|}]/g, '').slice(0, this.nicklen); - - case 'channel': - // Channel names: start with #, no spaces, commas, or control chars - if (!input.startsWith('#')) return ''; - return input.replace(/[^A-Za-z0-9#\-_.]/g, '').slice(0, this.channellen); - - case 'message': - // Messages: no control chars, reasonable length - return input.slice(0, 512); - - case 'username': - // Usernames: alphanumeric and some special chars - return input.replace(/[^A-Za-z0-9\-_.]/g, '').slice(0, 32); - - default: - return input.slice(0, 512); - } - } - - validateCommand(command, params) { - if (!command || typeof command !== 'string') { - return false; - } - - // Command must be uppercase letters only - if (!/^[A-Z]+$/.test(command)) { - return false; - } - - // Reasonable command length - if (command.length > 20) { - return false; - } - - // Parameters validation - if (params && Array.isArray(params)) { - for (const param of params) { - if (typeof param !== 'string' || param.length > 512) { - return false; - } - } - } - - return true; - } - - logSecurityEvent(event, socket, details = {}) { - if (!this.security_log_enabled) return; - - const securityEvent = { - timestamp: new Date().toISOString(), - event: event, - ip: socket ? (socket.realhost || socket.remoteAddress) : 'unknown', - nickname: socket ? socket.nickname : 'unknown', - details: details - }; - - this.security_events.push(securityEvent); - - // Keep only last 1000 security events in memory - if (this.security_events.length > 1000) { - this.security_events.shift(); - } - - // Log to console/file if needed - this.debugLog('security', `Security Event: ${event} from ${securityEvent.ip} (${securityEvent.nickname})`); - - // Write to security log file if configured - if (this.irc_config.security_log_file) { - const fs = require('fs'); - fs.appendFileSync(this.irc_config.security_log_file, JSON.stringify(securityEvent) + '\n'); - } - } - - - async initializeSocket(socket, secure = false, oldSocket = null) { - if (this.debug) { - // debug output for socket data - const originalWrite = socket.write.bind(socket); - socket.write = function (...args) { - var log_args = args.map(arg => { - if (typeof arg === 'string') { - return arg.replace(/\r\n/g, '').replace(/\n/g, ''); - } - return arg; - }); - console.log('<', ...log_args); - return originalWrite(...args); - }; - } - if (oldSocket) { - socket.registered = oldSocket.registered; - socket.nickname = oldSocket.nickname; - socket.username = oldSocket.username; - socket.isserver = oldSocket.isserver; - socket.is_srv_authorized = oldSocket.is_srv_authorized; - socket.signedoff = oldSocket.signedoff; - socket.hostname_resolved = oldSocket.hostname_resolved; - socket.realhost = oldSocket.realhost; - socket.client_version = oldSocket.client_version; - socket.client_caps = oldSocket.client_caps || []; - socket.host = oldSocket.host; - socket.timestamp = oldSocket.timestamp; - socket.uniqueId = oldSocket.uniqueId; - } else { - socket.registered = false; - socket.nickname = ''; - socket.username = ''; - socket.isserver = false; - socket.is_srv_authorized = false; - socket.signedoff = false; - socket.hostname_resolved = false; - socket.realhost = socket.remoteAddress; - socket.client_version = ''; - socket.client_caps = []; - socket.host = this.filterHostname(socket, socket.remoteAddress); - socket.timestamp = this.getDate(); - socket.uniqueId = `${this.serverId}${this.generateUniqueId(socket)}`; - } - - socket.secure = secure; - socket.upgrading_to_tls = false; - socket.error_count = 0; - socket.lastseen = this.getDate(); - await this.doInitialHandshake(socket); - - socket.on('data', async data => { - socket.lastseen = this.getDate(); - await this.processSocketData(socket, data); - }); - - socket.on('end', () => { - this.terminateSession(socket, false); - }); - - socket.on('error', () => { - this.terminateSession(socket, true); - }); - - socket.on('close', () => { - this.terminateSession(socket, false); - }); - - // Start a loop to check for idle clients and send PING if needed - socket._idleInterval = setInterval(async () => { - if (socket.signedoff) { - clearInterval(socket._idleInterval); - return; - } - const now = this.getDate(); - if ((now - socket.lastseen) > this.socket_timeout + 10) { - // Over 10 seconds has passed since we sent our PING, assume lost - this.debugLog('warn', `Socket ${socket.remoteAddress} has been idle for too long, terminating session`); - if (socket.nickname) { - await this.broadcastUser(socket.nickname, `:${socket.nickname}!${socket.username}@${socket.host} QUIT :Ping timeout (${now - socket.lastseen} seconds)\r\n`, socket); - await this.broadcastToAllServers(`:${socket.uniqueId} QUIT :Ping timeout (${now - socket.lastseen} seconds)\r\n`, serverSocket); - } - socket.signedoff = true; - this.terminateSession(socket, true); - return; - } else if ((now - socket.lastseen) > this.socket_timeout) { - // Client has been idle for too long, send PING - if (socket.isserver) { - await this.safeWriteToSocket(socket, `:${this.serverId} PING ${this.serverId} ${this.servername}\r\n`); - } else { - await this.safeWriteToSocket(socket, `PING :${this.servername}\r\n`); - } - return; - } - }, 10000); // check every 5 seconds - - this.clients.push(socket); - this.clientpeak = Math.max(this.clientpeak, this.clients.length); - } - - async processServerData(socket, line) { - // Handle server-specific commands - const parts = line.split(' '); - if (parts[0] == `:${socket.uniqueId}`) { - parts.shift(); // Remove the unique ID prefix - } - if (parts.length < 1) return; // Invalid command - const command = parts[0].toUpperCase(); - switch (command) { - case 'PASS': - // Handle PASS command from server - if (parts.length < 2) { - this.debugLog('warn', 'Invalid PASS command from server'); - return; - } - const password = parts[1]; - const servers = this.irc_config.servers || {}; - let matchedServer = null; - Object.entries(servers).forEach(async ([key, serverObj]) => { - if (serverObj.password && serverObj.password === password) { - matchedServer = serverObj; - this.debugLog('info', `Server ${serverObj.name || key} matched with provided password`); - await this.safeWriteToSocket(socket, `PASS ${serverObj.password}\r\n`); - socket.is_srv_authorized = true; - var totalSockets = this.clients.length + this.servers.size; - this.socketpeak = Math.max(this.socketpeak, totalSockets); - return; - } - }); - if (!matchedServer) { - this.debugLog('warn', 'Invalid server password provided'); - await this.safeWriteToSocket(socket, `:${this.servername} :ERROR :Invalid server password\r\n`); - socket.error_count++; - setTimeout((socket) => { - if (socket) { - socket.error_count--; - } - }, 60000); - if (socket.error_count >= 5) { - await this.safeWriteToSocket(socket, `:${this.servername} :ERROR :Too many errors, disconnecting\r\n`); - this.terminateSession(socket, true); - } - return; - } - socket.serverinfo = matchedServer - return; - case 'CAPAB': - if (!this.checkRegistered(socket, true)) { - break; - } - // Handle CAPAB command from server - if (parts.length < 2) { - this.debugLog('warn', 'Invalid CAPAB command from server'); - break; - } - var capabilities = parts.slice(1).join(' ').slice(1); // Remove leading ':' - capabilities = capabilities.split(' '); - this.debugLog('info', `Received CAPAB from server: ${capabilities.join(' ')}`); - var output_reply = []; - for (const cap of capabilities) { - if (this.supported_server_caps.includes(cap)) { - output_reply.push(cap); - } else { - this.debugLog('warn', `Unsupported server capability: ${cap}`); - } - } - await this.safeWriteToSocket(socket, `CAPAB :${output_reply.join(' ')}\r\n`); - break; - case 'SERVER': - if (!this.checkRegistered(socket, true)) { - break; - } - // Handle SERVER command from server - if (parts.length < 6) { - this.debugLog('warn', 'Invalid SERVER command from server'); - break; - } - var serverName = parts[1]; - var serverNumber = parts[2]; - var serverId = parts[3]; - var serverExtra = parts[4] - var serverInfo = parts.slice(5).join(' '); - socket.isserver = true; - this.clients = this.clients.filter(c => c !== socket); - this.clientpeak = this.clientpeak - 1; - socket.registered = true; - socket.servername = serverName; - socket.uniqueId = serverId; - socket.serverIdent = line; - this.servers.set(socket, serverName) - await this.safeWriteToSocket(socket, `SERVER ${this.servername} 1 ${this.serverId} + :${this.server_hello}\r\n`); - for (const [sock, nickname] of this.nicknames.entries()) { - if (!sock || !nickname) continue; - const uniqueId = sock.uniqueId; - const signonTime = Math.floor(this.usersignontimestamps.get(nickname) || this.getDate()); - const userModes = this.getUserModes(nickname); - const username = this.usernames.get(nickname) || ''; - await this.safeWriteToSocket(socket, `:${this.serverId} UID ${nickname} 1 ${signonTime} +${userModes} ${username} ${sock.host} ${sock.realhost} ${sock.remoteAddress} ${uniqueId} * :${sock.userinfo}\r\n`); - } - for (const [channel, channelObj] of this.channelData.entries()) { - const modes = channelObj.modes; - for (const user of channelObj.users) { - let userPrefix = ''; - if (channelObj.ops.has(user)) { - userPrefix = '@'; - } else if (channelObj.halfops.has(user)) { - userPrefix = '%'; - } else if (channelObj.voices.has(user)) { - userPrefix = '+'; - } - const userUniqueId = this.uniqueids.get(user); - if (userUniqueId) { - await this.safeWriteToSocket(socket, `:${this.serverId} SJOIN ${this.getDate()} ${channel} +${modes.join('')} :${userPrefix}${userUniqueId}\r\n`); - } - } - } - - await this.broadcastToAllServers(socket.serverIdent, socket); - // Send EOB to the server - await this.safeWriteToSocket(socket, `:${this.serverId} EOB \r\n`); - break; - case 'SVINFO': - if (!this.checkRegistered(socket, true)) { - break; - } - // Handle SVINFO command from server - if (parts.length < 4) { - this.debugLog('warn', 'Invalid SVINFO command from server'); - return; - } - const serverInfoMessage = `:${this.serverId} SVINFO 6 6 0 ${this.getDate()}\r\n`; - await this.safeWriteToSocket(socket, serverInfoMessage); - break - case 'PING': - // Respond to PING with PONG - var pong = parts.slice(1).join(' '); - if (pong.startsWith(':')) { - pong = pong.slice(1); // Remove leading ':' - } - await this.safeWriteToSocket(socket, `:${this.serverId} PONG ${pong}\r\n`); - break; - case 'PONG': - // Ignore PONG from server - break; - case 'RESV': - if (!this.checkRegistered(socket)) { - break; - } - // Handle RESV command from server - if (parts.length < 2) { - this.debugLog('warn', 'Invalid RESV command from server'); - break; - } - const targetMask = parts[1]; - const expiry = parseInt(parts[2]) || 0; - const reservedNick = parts[3]; - var reason = parts.slice(4).join(' ') || ''; - if (!this.reservednicks.includes(reservedNick)) { - this.reservednicks.push(reservedNick); - } - if (expiry > 0) { - setTimeout(() => { - const index = this.reservednicks.indexOf(reservedNick); - if (index !== -1) { - this.reservednicks.splice(index, 1); - this.debugLog('info', `Reservation for ${reservedNick} expired`); - } - }, expiry * 1000); - } - await this.broadcastToAllServers(`:${socket.servername} RESV ${targetMask} ${expiry} ${reservedNick} :${reason}\r\n`, socket); - break; - case 'UID': - if (!this.checkRegistered(socket)) { - break; - } - // Handle UID command from server - if (parts.length < 10) { - this.debugLog('warn', 'Invalid UID command from server'); - break; - } - var nickname = parts[1]; - const server_Id = parts[2]; - const timestamp = parseInt(parts[3]) || 0; - const userModes = parts[4].replace("/\+/g","").split(''); - var username = parts[5]; - var hostname = parts[6]; - const ipaddress = parts[7]; - const ipaddress2 = parts[8]; - const userUniqueId = parts[9]; - var userinfo = parts.slice(10).join(' ').slice(1); // Remove leading ':' - this.addRemoteServerUser(socket, nickname); - this.addUserUniqueId(nickname, userUniqueId); - this.globalpeak = Math.max(this.globalpeak, this.countGlobalUsers()); - this.usersignontimestamps.set(nickname, timestamp); - this.usernames.set(nickname, username); - this.hostnames.set(nickname, hostname); - this.realhosts.set(nickname, ipaddress2); - this.userinfo.set(nickname, userinfo); - for (const mode of userModes) { - this.setUserMode(nickname, mode, true); - } - await this.broadcastToAllServers(`:${socket.servername} UID ${nickname} ${server_Id} ${timestamp} +${userModes.join('')} ${username} ${hostname} ${ipaddress} ${ipaddress2} ${userUniqueId} * :${userinfo}\r\n`, socket); - break; - case 'SVSHOST': - if (!this.checkRegistered(socket)) { - break; - } - // Handle SVSHOST command from server - if (parts.length < 4) { - this.debugLog('warn', 'Invalid SVSHOST command from server'); - break; - } - var uniqueId = parts[1]; - var hostname = parts[3]; - var targetSocket = this.findSocketByUniqueId(uniqueId); - if (!targetSocket) { - this.debugLog('warn', `No socket found for unique ID ${uniqueId}`); - break; - } - this.hostnames.set(this.findUserByUniqueId(uniqueId), hostname); - targetSocket.host = hostname; - if (targetSocket.client_caps && targetSocket.client_caps.includes('CHGHOST')) { - await this.safeWriteToSocket(targetSocket, `:${targetSocket.nickname}!${targetSocket.username}@${targetSocket.host} CHGHOST ${targetSocket.username} ${targetSocket.host}\r\n`); - } - await this.safeWriteToSocket(targetSocket, `:${this.servername} 396 ${targetSocket.nickname} ${targetSocket.host} :is now your visible host\r\n`); - await this.broadcastToAllServers(`:${socket.servername} SVSHOST ${uniqueId} ${hostname}\r\n`, socket); - break; - case 'SVSACCOUNT': - if (!this.checkRegistered(socket)) { - break; - } - if (parts.length < 4) { - this.debugLog('warn', 'Invalid SVSACCOUNT command from server'); - break; - } - var uniqueId = parts[1]; - var accountName = parts[3]; - var nickname = this.findUserByUniqueId(uniqueId); - if (!nickname) { - this.debugLog('warn', `No user found for unique ID ${uniqueId}`); - break; - } - if (accountName === '*') { - // Remove account association - this.accounts.delete(nickname); - } else { - this.accounts.set(nickname, accountName); - } - var targetSocket = this.findSocketByUniqueId(uniqueId); - if (!targetSocket) { - this.debugLog('warn', `No socket found for unique ID ${uniqueId}`); - break; - } - if (targetSocket.client_caps && targetSocket.client_caps.includes('account-notify')) { - await this.safeWriteToSocket(targetSocket, `:${targetSocket.nickname}!${targetSocket.username}@${targetSocket.host} ACCOUNT ${accountName}\r\n`); - } - break; - case 'SVSNICK': - if (!this.checkRegistered(socket)) { - break; - } - // Handle SVSNICK command from server - if (parts.length < 5) { - this.debugLog('warn', 'Invalid SVSNICK command from server'); - break; - } - var oldNick = this.findUserByUniqueId(parts[1]); - var newNick = parts[3]; - var targetSocket = this.findSocketByUniqueId(parts[1]); - await this.broadcastUser(oldNick, `:${oldNick}!${this.usernames.get(oldNick)}@${targetSocket.host} NICK :${newNick}\r\n`); - this.processNickChange(targetSocket, newNick); - await this.broadcastToAllServers(line, socket); - break; - case 'SJOIN': - if (!this.checkRegistered(socket)) { - break; - } - var channel = parts[2]; - var modes = parts[3]; - var uniqueId = parts[4]; - if (uniqueId.startsWith(':')) { - uniqueId = uniqueId.slice(1); // Remove leading ':' - } - if (!uniqueId) { - await this.broadcastToAllServers(`:${socket.servername} SJOIN ${this.getDate()} ${channel} +${modes} :\r\n`, socket); - break; - } - while (['@', '%', '+'].includes(uniqueId[0])) { - uniqueId = uniqueId.slice(1); - } - var userSocket = this.findSocketByUniqueId(uniqueId); - var nickname = this.findUserByUniqueId(uniqueId); - var username = this.usernames.get(nickname) || nickname; - var hostname = this.hostnames.get(nickname) - if (!this.channelData.has(channel)) { - this.createChannel(channel); - } - if (!this.channelData.get(channel).users.has(nickname)) { - this.channelData.get(channel).users.add(nickname); - } - if (nickname && username && hostname) { - await this.broadcastChannel(channel, `:${nickname}!${username}@${hostname} JOIN ${channel}\r\n`, userSocket); - } - await this.broadcastToAllServers(`:${socket.servername} SJOIN ${this.getDate()} ${channel} +${modes} :${uniqueId}\r\n`, socket); - break; - case 'SQUIT': - await this.broadcastToAllServers(`:${socket.servername} SQUIT ${parts[1]} :${parts.slice(2).join(' ').slice(1)}\r\n`, socket); - this.servers.delete(socket); - break; - case (command.match(/^\d{3}$/) || {}).input: - if (!this.checkRegistered(socket)) { - break; - } - // Numeric reply from server - // Numeric replies are usually in the format: : - var senderID = parts[1] - var targetSocket = this.findSocketByUniqueId(senderID); - if (!targetSocket) { - this.debugLog('warn', `No socket found for unique ID ${senderID}`); - break; - } - var responded = false; - switch (command) { - case '307': - // WHOIS AWAY reply - if (parts.length < 3) { - this.debugLog('warn', 'Invalid WHOIS AWAY reply from server'); - break; - } - var whoisNick = parts[2]; - var awayMessage = parts.slice(3).join(' '); - if (awayMessage.startsWith(':')) { - awayMessage = awayMessage.slice(1); - } - await this.safeWriteToSocket(targetSocket, `:${socket.servername} 307 ${whoisNick} ${whoisNick} :${awayMessage}\r\n`); - responded = true; - break; - case '311': - // WHOIS reply - var whoisNick = parts[2]; - var whoisUser = parts[3]; - var whoisHost = parts[4]; - var whoisServer = parts[5]; - var whoisRealname = parts.slice(6).join(' '); - if (whoisRealname.startsWith(':')) { - whoisRealname = whoisRealname.slice(1); - } - await this.safeWriteToSocket(targetSocket, `:${socket.servername} 311 ${whoisNick} ${whoisNick} ${whoisUser} ${whoisHost} ${whoisServer} :${whoisRealname}\r\n`); - responded = true; - break; - case '312': - // WHOIS SERVER reply - var serverID = parts[1]; - var whoisNick = parts[2]; - var serverName = parts[2]; - var serverInfo = parts.slice(3).join(' '); - if (serverInfo.startsWith(':')) { - serverInfo = serverInfo.slice(1); - } - await this.safeWriteToSocket(targetSocket, `:${socket.servername} 312 ${whoisNick} ${serverName} :${serverInfo}\r\n`); - responded = true; - break; - case '313': - // WHOIS operator reply - if (parts.length < 3) { - this.debugLog('warn', 'Invalid WHOIS operator reply from server'); - break; - } - var whoisNick = parts[2]; - var message = parts.slice(3).join(' '); - if (message.startsWith(':')) { - message = message.slice(1); - } - await this.safeWriteToSocket(targetSocket, `:${socket.servername} 313 ${whoisNick} ${whoisNick} :${message}\r\n`); - responded = true; - break; - case '317': - // WHOIS idle reply - if (parts.length < 4) { - this.debugLog('warn', 'Invalid WHOIS idle reply from server'); - break; - } - var whoisNick = parts[2]; - var idleTime = parts[3]; - var signonTime = parts[4]; - await this.safeWriteToSocket(targetSocket, `:${socket.servername} 317 ${whoisNick} ${whoisNick} ${idleTime} ${signonTime} :seconds idle, signon time\r\n`); - responded = true; - break; - case '318': - // WHOIS end of reply - if (parts.length < 2) { - this.debugLog('warn', 'Invalid WHOIS end of reply from server'); - break; - } - var whoisNick = parts[1]; - await this.safeWriteToSocket(targetSocket, `:${socket.servername} 318 ${whoisNick} :End of WHOIS list\r\n`); - responded = true; - break; - } - if (responded) { - break; - } - if (parts.length < 4) { - this.debugLog('warn', 'Invalid numeric reply from server'); - break; - } - const numericCode = parts[0]; - const targetID = parts[1]; - var numericMessage = parts.slice(3).join(' '); - if (numericMessage.startsWith(':')) { - numericMessage = numericMessage.slice(1); // Remove leading ':' - } - - if (!targetSocket) { - this.debugLog('warn', `No socket found for target unique ID ${targetID}`); - break; - } - await this.safeWriteToSocket(targetSocket, `:${socket.serverinfo.name} ${numericCode} ${targetID} :${numericMessage}\r\n`); - break; - default: - if (!this.checkRegistered(socket)) { - break; - } - if (command.startsWith(':')) { - // part out the line to "sourceUniqueId command targetUniqueId :message" - var sourceUniqueId = parts[0].slice(1); // Remove the leading ':' - var nickname = this.findUserByUniqueId(sourceUniqueId); - if (!nickname) { - this.debugLog('warn', `No nickname found for unique ID ${sourceUniqueId}`); - break; - } - var srvCommand = parts[1]; - let whoisNick; - switch (srvCommand) { - case 'QUIT': - var user_name = this.usernames.get(nickname) || nickname; - var message = parts.slice(2).join(' ').slice(1); // Remove leading ':' - // Remove user from the server's user list - const serverUsers = this.serverusers.get(socket); - if (serverUsers && typeof serverUsers.delete === 'function') { - const nickToRemove = this.findUserByUniqueId(sourceUniqueId); - serverUsers.delete(nickToRemove); - this.cleanupUserSession(nickToRemove); - } - await this.broadcastToAllServers(`:${nickname}!${user_name}@${this.servername} QUIT :${message}\r\n`, socket); - break; - case 'JOIN': - var channel = this.findChannel(parts[3]); - if (!channel || !this.channelData.has(channel)) { - channel = parts[3]; - this.createChannel(channel); - } - var userSocket = this.findSocketByUniqueId(sourceUniqueId); - if (!userSocket) { - this.debugLog('warn', `No socket found for source unique ID ${sourceUniqueId}`); - break; - } - var username = this.usernames.get(nickname) || nickname; - if (!this.channelData.get(channel).users.has(nickname)) { - this.channelData.get(channel).users.add(nickname); - } - await this.broadcastChannelJoin(channel, userSocket); - await this.broadcastToAllServers(`:${sourceUniqueId} JOIN ${channel}\r\n`, socket); - break; - case 'PART': - var channel = this.findChannel(parts[2]); - if (!channel) { - this.debugLog('warn', `No channel found for PART command: ${parts[2]}`); - break; - } - if (this.channelData.get(channel).ops.has(nickname)) { - this.channelData.get(channel).ops.delete(nickname); - } - if (this.channelData.get(channel).halfops.has(nickname)) { - this.channelData.get(channel).halfops.delete(nickname); - } - if (this.channelData.get(channel).voices.has(nickname)) { - this.channelData.get(channel).voices.delete(nickname); - } - - var username = this.usernames.get(nickname) || nickname; - var hostname = this.hostnames.get(nickname); - await this.broadcastChannel(channel, `:${nickname}!${username}@${hostname} PART ${channel} :${parts.slice(4).join(' ')}\r\n`, userSocket); - if (this.channelData.has(channel) && this.channelData.get(channel).users.size === 0) { - this.deleteChannel(channel); - } - await this.broadcastToAllServers(`:${sourceUniqueId} PART ${channel} :${parts.slice(4).join(' ')}\r\n`, socket); - break; - case 'GLOBOPS': - var message = parts.slice(3).join(' '); - await this.broadcastToAllServers(`:${sourceUniqueId} GLOBOPS :${message}`, socket); - break; - case 'TBURST': - // Handle TBURST command from server - if (parts.length < 6) { - this.debugLog('warn', `Invalid TBURST command from server: ${line}`); - break; - } - var channel = parts[3]; - var topic = parts.slice(6).join(' '); - if (topic.startsWith(':')) { - topic = topic.slice(1); - } - if (!this.channelData.has(channel)) { - this.createChannel(channel); - } - this.channelData.get(channel).topic = topic; - await this.broadcastChannel(channel, `:${nickname} TOPIC ${channel} :${topic}\r\n`); - await this.broadcastToAllServers(`:${sourceUniqueId} TBURST ${channel} :${topic}\r\n`, socket); - break; - case 'KILL': - // Handle KILL command from server - if (parts.length < 3) { - this.debugLog('warn', `Invalid KILL command from server: ${line}`); - break; - } - var targetUniqueId = parts[2]; - var targetSocket = this.findSocketByUniqueId(targetUniqueId); - var targetNickname = this.findUserByUniqueId(targetUniqueId); - var sourceUsername = this.usernames.get(nickname) || nickname; - var reason = parts.slice(3).join(' '); - await this.safeWriteToSocket(targetSocket, `:${nickname}!${sourceUsername}@${socket.serverinfo.name} KILL ${targetNickname} :${reason}\r\n`); - await this.broadcastUser(targetNickname, `:${nickname}!${sourceUsername}@${socket.serverinfo.name} KILL ${targetNickname} :${reason}\r\n`, targetSocket); - await this.broadcastToAllServers(`:${sourceUniqueId} KILL ${targetUniqueId} :${reason}\r\n`, socket); - await this.broadcastConnection(socket, `Killed: ${reason}`); - this.terminateSession(targetSocket, true); - break; - case 'MODE': - var targetUniqueId = parts[2]; - if (this.channelprefixes.some(prefix => targetUniqueId.startsWith(prefix))) { - var targetChannel = this.findChannel(targetUniqueId) - if (!targetChannel) { - this.debugLog('warn', `No channel found for MODE command: ${line}`); - break; - } - // It's a channel, broadcast to all users in the channel - if (this.channelData.has(targetChannel)) { - var modes = parts[3]; - await this.processChannelModes(nickname, targetChannel, modes, parts.slice(4), socket); - } - break; - } - var targetSocket = this.findSocketByUniqueId(targetUniqueId); - if (!targetSocket) { - this.debugLog('warn', `No socket found for target unique ID ${targetUniqueId}`); - break; - } - await this.safeWriteToSocket(targetSocket, `:${targetSocket.nickname} MODE ${targetSocket.nickname} ${parts.slice(2).join(' ')}\r\n`); - if (this.clientIsWebTV(targetSocket) && this.enable_webtv_command_hacks) { - await this.sendWebTVNoticeTo(targetSocket, `The network has set your user mode: ${parts.slice(3).join(' ')}`); - } - await this.broadcastToAllServers(`:${sourceUniqueId} MODE ${targetUniqueId} ${parts.slice(3).join(' ')}\r\n`, socket); - break; - case 'NICK': - if (parts.length < 3) { - this.debugLog('warn', 'Invalid NICK command from server'); - break; - } - var targetSocket = this.findSocketByUniqueId(sourceUniqueId); - if (!targetSocket) { - this.debugLog('warn', `No socket found for source unique ID ${sourceUniqueId}`); - break; - } - var oldNick = targetSocket.nickname; - var newNick = parts[2]; - - if (this.nicknames.has(newNick)) { - await this.safeWriteToSocket(targetSocket, `:${this.servername} 433 ${oldNick} ${newNick} :Nickname is already in use\r\n`); - break; - } - this.processNickChange(targetSocket, newNick); - await this.broadcastUser(oldNick, `:${targetSocket.nickname}!${targetSocket.username}@${targetSocket.host} NICK :${newNick}\r\n`, targetSocket); - await this.broadcastToAllServers(`:${sourceUniqueId} NICK ${newNick}\r\n`, socket); - break; - case 'TOPIC': - if (parts.length < 3) { - this.debugLog('warn', 'Invalid TOPIC command from server'); - break; - } - var channel = this.findChannel(parts[2]); - if (!channel || !this.channelData.has(channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${nickname} ${channel} :No such channel\r\n`); - break; - } - var topic = parts.slice(3).join(' '); - if (topic.startsWith(':')) { - topic = topic.slice(1); // Remove leading ':' - } - this.channelData.get(channel).topic = topic; - var username = this.usernames.get(nickname) || nickname; - var hostname = this.hostnames.get(nickname) || ''; - await this.broadcastChannel(channel, `:${nickname}!${username}@${hostname} TOPIC ${channel} :${topic}\r\n`, targetSocket); - await this.broadcastToAllServers(`:${sourceUniqueId} TOPIC ${channel} :${topic}\r\n`, socket); - break; - case 'PRIVMSG': - case 'NOTICE': - var targetUniqueId = parts[2]; - var message = parts.slice(3).join(' '); - if (message.startsWith(':')) { - message = message.slice(1); // Remove leading ':' - } - var sourceSocket = this.findSocketByUniqueId(sourceUniqueId); - if (!sourceSocket) { - this.debugLog('warn', `No socket found for source unique ID ${sourceUniqueId}`); - break; - } - var sourceUsername = this.usernames.get(nickname) || nickname; - const host = this.hostnames.get(nickname) || socketSource.host; - if (this.channelprefixes.some(prefix => targetUniqueId.startsWith(prefix))) { - // It's a channel, broadcast to all users in the channel except the source - if (this.channelData.has(targetUniqueId)) { - const users = this.channelData.get(targetUniqueId).users; - for (const user of users) { - const userSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); - if (userSocket && userSocket.uniqueId !== sourceUniqueId) { - const host = this.hostnames.get(user) || socketSource.host; - await this.sendThrottled(userSocket, [`:${nickname}!${sourceUsername}@${host} ${srvCommand} ${targetUniqueId} :${message}\r\n`], 30); - await this.broadcastToAllServers(`:${sourceUniqueId} ${srvCommand} ${targetUniqueId} :${message}\r\n`, socket); - } - } - } - break; - } - var targetSocket = this.findSocketByUniqueId(targetUniqueId); - if (!targetSocket) { - this.debugLog('warn', `No socket found for target unique ID ${targetUniqueId}`); - break; - } - var targetNickname = this.getUsernameFromUniqueId(targetUniqueId); - if (message.startsWith(':')) { - message = message.slice(1); // Remove leading ':' - } - if (this.clientIsWebTV(targetSocket)) { - srvCommand = 'PRIVMSG'; - } - await this.sendThrottled(targetSocket, [`:${nickname}!${sourceUsername}@${host} ${srvCommand} ${targetNickname} :${message}\r\n`], 30); - await this.broadcastToAllServers(`:${sourceUniqueId} ${srvCommand} ${targetUniqueId} :${message}\r\n`, socket); - break; - case "WHOIS": - if (parts.length < 3) { - this.debugLog('warn', 'Invalid WHOIS command from server'); - break; - } - var targetUniqueId = parts[2]; - var targetSocket = this.findSocketByUniqueId(targetUniqueId); - if (!targetSocket) { - this.debugLog('warn', `No socket found for target unique ID ${targetUniqueId}`); - break; - } - var targetUniqueId = parts[2]; - whoisNick = this.findUserByUniqueId(targetUniqueId); - if (!whoisNick) { - whoisNick = parts[3].slice(1); // Remove leading ':' - } - const whoisSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s).toLowerCase() === whoisNick.toLowerCase()); - if (whoisSocket) { - whoisNick = whoisSocket.nickname; - const whois_username = this.usernames.get(whoisNick); - var userinfo = this.userinfo.get(whoisNick) || whoisSocket.userinfo || ''; - output_lines = []; - output_lines.push(`:${this.serverId} 311 ${targetUniqueId} ${whoisNick} ${whois_username} ${whoisSocket.host} * :${userinfo}\r\n`); - if (this.awaymsgs.has(whoisNick)) { - output_lines.push(`:${this.serverId} 301 ${targetUniqueId} ${whoisNick} :${this.awaymsgs.get(whoisNick)}\r\n`); - } - const userChannels = []; - for (const [ch, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(whoisNick)) { - let prefix = ''; - var chanops = this.channelData.get(ch).ops; - var chanhalfops = this.channelData.get(ch).halfops; - var chanvoices = this.channelData.get(ch).voices; - const modes = this.channelData.get(ch).modes; - if ((modes.includes('p') || modes.includes('s')) && (!this.channelData.has(ch) || !this.channelData.get(ch).users.has(socket.nickname))) { - continue; // Skip listing this channel if it's private/secret and user is not in it - } - if (chanops.has(whoisNick)) { - prefix = '@'; - } else if (chanhalfops.has(whoisNick)) { - prefix = '%'; - } else if (chanvoices.has(whoisNick)) { - prefix = '+'; - } - userChannels.push(prefix + ch); - } - } - output_lines.push(`:${this.serverId} 312 ${targetUniqueId} ${whoisNick} ${this.servername} :zefIRCd v${this.version}\r\n`); - if (this.isIRCOp(whoisNick)) { - output_lines.push(`:${this.serverId} 313 ${targetUniqueId} ${whoisNick} :is an IRC operator\r\n`); - } - if (usermodes && this.getUserModes(whoisNick).includes('s')) { - output_lines.push(`:${this.serverId} 671 ${targetUniqueId} ${whoisNick} :is using a secure connection\r\n`); - } - if (usermodes && this.getUserModes(whoisNick).includes('r')) { - output_lines.push(`:${this.serverId} 307 ${targetUniqueId} ${whoisNick} :is a registered nick\r\n`); - } - var now = this.getDate(); - var userTimestamp = whoisSocket.lastspoke || now; - var idleTime = now - userTimestamp; - output_lines.push(`:${this.serverId} 317 ${targetUniqueId} ${whoisNick} ${idleTime} ${this.usersignontimestamps.get(whoisNick) || 0} :seconds idle, signon time\r\n`); - if (userChannels.length > 0) { - output_lines.push(`:${this.serverId} 319 ${targetUniqueId} ${whoisNick} :${userChannels.join(' ')}\r\n`); - } - output_lines.push(`:${this.serverId} 318 ${targetUniqueId} ${whoisNick} :End of /WHOIS list\r\n`); - await this.sendThrottled(socket, output_lines); - } - break; - case "SVSJOIN": - if (parts.length < 3) { - this.debugLog('warn', 'Invalid SVSJOIN command from server'); - break; - } - var targetUniqueId = parts[2]; - var channelName = this.findChannel(parts[3]); - var targetSocket = this.findSocketByUniqueId(targetUniqueId); - var username = this.usernames.get(targetSocket.nickname) || socket.nickname; - var hostname = this.hostnames.get(targetSocket.nickname) || ''; - if (!channelName ||!this.channelData.has(channelName)) { - channelName = parts[3]; - this.createChannel(channelName); - } - if (!this.channelData.get(channelName).users.has(targetSocket.nickname)) { - this.channelData.get(channelName).users.add(targetSocket.nickname); - } - await this.broadcastChannelJoin(channelName, targetSocket); - //this.broadcastToAllServers(`:${sourceUniqueId} SVSJOIN ${channelName} ${targetUniqueId}\r\n`, socket); - var chan_modes = this.channelData.get(channelName).modes; - let modeString = ''; - let modeParams = []; - for (const m of chan_modes) { - if (m === 'k' && this.channelData.get(channelName).key) { - modeString += 'k'; - modeParams.push(this.channelData.get(channelName).key); - } else if (m === 'l' && this.channelData.get(channelName).limit) { - modeString += 'l'; - modeParams.push(this.channelData.get(channelName).limit); - } else if (typeof m === 'string' && m.length === 1 && m !== 'k' && m !== 'l') { - modeString += m; - } - } - if (modeString.length > 0) { - await this.safeWriteToSocket(targetSocket, `:${this.servername} 324 ${nickname} ${channelName} +${modeString}${modeParams.length ? ' ' + modeParams.join(' ') : ''}\r\n`); - } - await this.broadcastToAllServers(`:${this.serverId} SJOIN ${this.getDate()} ${channelName} +${modeString}${modeParams.length ? ' ' + modeParams.join(' ') : ''} ${targetUniqueId}\r\n`); - break; - case "SVSMODE": - if (parts.length < 4) { - this.debugLog('warn', 'Invalid SVSMODE command from server'); - break; - } - var targetUniqueId = parts[2]; - var targetSocket = this.findSocketByUniqueId(targetUniqueId); - var targetNickname = targetSocket.nickname; - var modes = parts[4].split(''); - let adding = true; - for (const char of modes.join('')) { - if (char === '+') { - adding = true; - } else if (char === '-') { - adding = false; - } else { - if (adding) { - this.setUserMode(targetNickname, char, true); - } else { - this.setUserMode(targetNickname, char, false); - } - } - } - var username = this.usernames.get(nickname); - var hostname = this.hostnames.get(nickname); - await this.safeWriteToSocket(targetSocket, `:${nickname}!${username}@${hostname} MODE ${targetSocket.nickname} ${modes.join('')}\r\n`); - await this.broadcastToAllServers(`:${sourceUniqueId} SVSMODE ${targetUniqueId} ${modes.join('')}\r\n`, socket); - break; - default: - if (!this.checkRegistered(socket)) { - break; - } - this.debugLog('warn', `Unhandled server command from ${sourceUniqueId} to ${targetUniqueId}: ${srvCommand} ${message}`); - } - } - } - } - - async processSocketData(socket, data) { - var output_lines = []; // Declare once at function scope - - if (socket.signedoff) { - return; - } - if (socket.upgrading_to_tls) { - socket.removeAllListeners() - socket.pause(); - socket.on('error', (err) => { - this.debugLog('error', 'Error during TLS upgrade: ' + err.message); - this.terminateSession(socket, true); - }); - - if (Buffer.isBuffer(data) ? data[0] === 0x16 : data.charCodeAt(0) === 0x16) { - if (!this.enable_tls) { - // If SSL is not enabled, close the socket - await this.safeWriteToSocket(socket, `:${this.servername} 421 * :TLS is not enabled on this server\r\n`); - this.terminateSession(socket, true); - return; - } - - // SSL detected, upgrade socket to TLS - const keyBuffer = fs.readFileSync(this.wtvshared.parseConfigVars(this.irc_config.ssl_cert.key)); - const certBuffer = fs.readFileSync(this.wtvshared.parseConfigVars(this.irc_config.ssl_cert.cert)); - // Remove from this.clients if present - - this.clients = this.clients.filter(c => c !== socket); - const secureSocket = new tls.TLSSocket(socket, { - isServer: true, - ALPNProtocols: ['irc'], - secureContext: tls.createSecureContext({ - key: keyBuffer, - cert: certBuffer, - }), - }); - socket.push(data); - - secureSocket.on('error', (err) => { - this.terminateSession(secureSocket, true); - }); - - secureSocket.on('close', () => { - this.terminateSession(secureSocket, false); - }); - - // Only start processing after handshake is complete - secureSocket.on('secure', async () => { - this.debugLog('info', 'Secure connection (STARTTLS) established with '+ socket.remoteAddress); - socket.removeAllListeners('error'); - await this.initializeSocket(secureSocket, true, socket); - // Remove the original socket from clients - this.clients = this.clients.filter(c => c !== socket); - this.clientpeak = Math.max(this.clientpeak, this.clients.length); - }); - secureSocket.resume(); - } else { - socket.resume(); - await this.safeWriteToSocket(socket, `:${this.servername} 421 * :Invalid TLS handshake\r\n`); - this.terminateSession(socket, true); - } - socket.upgrading_to_tls = false; - return; - } - // Ensure data is a string - if (typeof data !== 'string') { - if (Buffer.isBuffer(data)) { - data = data.toString('ascii'); - } else if (data && typeof data.toString === 'function') { - data = data.toString(); - } else { - return; // Invalid data, ignore - } - } - const lines = data.split(/\r\n|\n/).filter(Boolean); - for (let line of lines) { - if (this.debug) { - console.log(`> ${line}`); - } - - // Rate limiting check for non-server connections - if (!socket.isserver && !this.checkRateLimit(socket)) { - this.debugLog('warn', `Rate limit exceeded for ${socket.remoteAddress}, disconnecting`); - this.logSecurityEvent('RATE_LIMIT_EXCEEDED', socket, { limit: this.max_messages_per_second }); - await this.safeWriteToSocket(socket, `:${this.servername} ERROR :Rate limit exceeded\r\n`); - this.terminateSession(socket, true); - return; - } - - if (socket.isserver) { - await this.processServerData(socket, line); - continue; - } - // Check for server prefix (e.g., :00B) and extract command - let prefix = null; - if (line.startsWith(':')) { - const spaceIdx = line.indexOf(' '); - - if (spaceIdx > 0) { - prefix = line.slice(1, spaceIdx); - if (!socket.uniqueId) { - socket.uniqueId = prefix; - } else if (socket.uniqueId !== prefix) { - if (!socket.isserver) { - socket.uniqueId = prefix; - } else { - this.debugLog('warn', `Socket uniqueId mismatch: ${socket.uniqueId} !== ${prefix}`); - this.debugLog('warn', line); - continue; - } - } - } - this.processServerData(socket, line); - continue; - } - - // initial commands before we assign socket.isserver = true - const serverCommands = ['PASS', 'CAPAB', 'SERVER', 'SVINFO']; - const firstWord = line.trim().split(' ')[0].toUpperCase(); - if (!prefix && serverCommands.includes(firstWord)) { - this.processServerData(socket, line); - continue; - } - - - const [command, ...params] = line.trim().split(' '); - - // Validate command and parameters - if (!this.validateCommand(command.toUpperCase(), params)) { - this.logSecurityEvent('INVALID_COMMAND', socket, { command, params }); - await this.safeWriteToSocket(socket, `:${this.servername} 421 ${socket.nickname || '*'} ${command} :Unknown command\r\n`); - continue; - } - - switch (command.toUpperCase()) { - case 'OPER': - if (!socket.secure) { - await this.safeWriteToSocket(socket, `:${this.servername} 464 ${socket.nickname} :SSL required for OPER\r\n`); - } - if (!this.checkRegistered(socket)) { - break; - } - if (!this.checkAuthAttempts(socket)) { - await this.safeWriteToSocket(socket, `:${this.servername} 491 ${socket.nickname} :Too many failed attempts. Try again later.\r\n`); - this.logSecurityEvent('OPER_LOCKOUT', socket, { attempts: this.failed_auth_attempts.get(socket.realhost || socket.remoteAddress) }); - break; - } - if (!this.oper_enabled) { - await this.safeWriteToSocket(socket, `:${this.servername} 491 ${socket.nickname} :This server does not support IRC operators\r\n`); - break; - } - if (params.length < 2) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} OPER :Not enough parameters\r\n`); - break; - } - const [operName, operPassword] = params; - if (operName !== this.oper_username) { - await this.safeWriteToSocket(socket, `:${this.servername} 491 ${socket.nickname} :No permission\r\n`); - this.debugLog('warn', `Invalid oper name attempt: ${operName} from ${socket.nickname} (${socket.username}@${socket.realhost})`); - this.logSecurityEvent('OPER_FAILED_USERNAME', socket, { provided_username: operName }); - this.recordAuthFailure(socket); - break; - } - // Use timing-safe comparison to prevent timing attacks - const providedPassword = Buffer.from(operPassword, 'utf8'); - const actualPassword = Buffer.from(this.oper_password, 'utf8'); - const passwordMatch = providedPassword.length === actualPassword.length && - require('crypto').timingSafeEqual(providedPassword, actualPassword); - - if (!passwordMatch) { - await this.safeWriteToSocket(socket, `:${this.servername} 464 ${socket.nickname} :Password incorrect\r\n`); - this.debugLog('warn', `Invalid oper password attempt from ${socket.nickname} (${socket.username}@${socket.realhost}) (using oper name ${operName})`); - this.logSecurityEvent('OPER_FAILED_PASSWORD', socket, { username: operName }); - this.recordAuthFailure(socket); - break; - } - this.clearAuthFailures(socket); - this.logSecurityEvent('OPER_SUCCESS', socket, { username: operName }); - this.setUserMode(socket.nickname, 'o', true); - await this.safeWriteToSocket(socket, `:${this.servername} 381 ${socket.nickname} :You are now an IRC operator\r\n`); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +o\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +o\r\n`); - this.debugLog('info', `IRC operator ${socket.nickname} (${socket.username}@${socket.realhost}) has logged in with oper name ${operName}`); - break; - case 'UPTIME': - if (!this.checkRegistered(socket)) { - break; - } - const uptime = this.getDate() - this.server_start_time; - const days = Math.floor(uptime / 86400); - const hours = Math.floor((uptime % 86400) / 3600); - const minutes = Math.floor((uptime % 3600) / 60); - const seconds = uptime % 60; - await this.safeWriteToSocket(socket, `:${this.servername} 242 ${socket.nickname} :Server uptime is ${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds\r\n`); - break; - case 'SECURITY': - if (!this.checkRegistered(socket)) { - break; - } - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - break; - } - - // Show security statistics - let output_lines = []; - output_lines.push(`:${this.servername} NOTICE ${socket.nickname} :=== Security Report ===\r\n`); - output_lines.push(`:${this.servername} NOTICE ${socket.nickname} :Active connections per IP: ${this.connections_per_ip.size}\r\n`); - output_lines.push(`:${this.servername} NOTICE ${socket.nickname} :Failed auth attempts tracked: ${this.failed_auth_attempts.size}\r\n`); - output_lines.push(`:${this.servername} NOTICE ${socket.nickname} :Security events logged: ${this.security_events.length}\r\n`); - output_lines.push(`:${this.servername} NOTICE ${socket.nickname} :Rate limit violations: ${this.security_events.filter(e => e.event === 'RATE_LIMIT_EXCEEDED').length}\r\n`); - output_lines.push(`:${this.servername} NOTICE ${socket.nickname} :=== End Report ===\r\n`); - - await this.sendThrottled(socket, output_lines); - break; - case 'KICK': - if (!this.checkRegistered(socket)) { - break; - } - var channel = this.findChannel(params[0]); - var targetNick = this.findUser(params[1]); - if (!channel || !targetNick) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${params[1]} :No such nick/channel\r\n`); - break; - } - // Check if the user is a channel operator - if (this.channelData.get(channel).ops instanceof Set && this.channelData.get(channel).ops.has(socket.nickname)) { - // Allow kick - } else if (this.channelData.get(channel).halfops instanceof Set && this.channelData.get(channel).halfops.has(socket.nickname)) { - // Only allow kick if the target is NOT a channel operator - if (this.channelData.get(channel).ops instanceof Set && this.channelData.get(channel).ops.has(targetNick)) { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${socket.nickname} ${channel} :You cannot kick a channel operator\r\n`); - break; - } - // Allow kick - } else { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${socket.nickname} ${channel} :You're not channel operator\r\n`); - break; - } - if (params.length < 2) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} KICK :Not enough parameters\r\n`); - break; - } - socket.lastspoke = this.getDate(); - - - if (!this.channelData.has(channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${channel} :No such channel\r\n`); - break; - } - if (!this.channelData.get(channel).users.has(targetNick)) { - await this.safeWriteToSocket(socket, `:${this.servername} 441 ${socket.nickname} ${targetNick} :They aren't on that channel\r\n`); - break; - } - // Check if channel mode +Q (no kicks) is set - var chan_modes = this.channelData.get(channel).modes; - if (chan_modes.includes('Q')) { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${socket.nickname} ${channel} :Cannot kick users, channel is +Q (no kicks allowed)\r\n`); - break; - } - this.channelData.get(channel).users.delete(targetNick); - var targetSocket = Array.from(this.clients).find(s => this.nicknames.get(s) === targetNick); - if (params.length > 2) { - let reason = params.slice(2).join(' '); - if (reason.startsWith(':')) { - reason = reason.slice(1); - } - await this.safeWriteToSocket(targetSocket, `:${socket.nickname}!${socket.username}@${socket.host} KICK ${channel} ${targetNick} :${reason}\r\n`); - await this.broadcastChannel(channel, `:${socket.nickname}!${socket.username}@${socket.host} KICK ${channel} ${targetNick} :${reason}\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} KICK ${channel} ${targetSocket.uniqueId} :${reason}\r\n`); - break; - } else { - await this.safeWriteToSocket(targetSocket, `:${socket.nickname}!${socket.username}@${socket.host} KICK ${channel} ${targetNick}\r\n`); - await this.broadcastChannel(channel, `:${socket.nickname}!${socket.username}@${socket.host} KICK ${channel} ${targetNick}\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} KICK ${channel} ${targetSocket.uniqueId}\r\n`); - } - break; - case 'TOPIC': - if (!this.checkRegistered(socket)) { - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} TOPIC :Not enough parameters\r\n`); - break; - } - var channel = this.findChannel(params[0]); - if (!channel) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${params[0]} :No such channel\r\n`); - break; - } - var chan_modes = this.channelData.get(channel).modes; - if (chan_modes.includes('t')) { - if (this.channelData.get(channel).ops instanceof Set && this.channelData.get(channel).ops.has(socket.nickname)) { - // Allow topic - } else { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${socket.nickname} ${channel} :You're not channel operator\r\n`); - break; - } - } - socket.lastspoke = this.getDate(); - if (!this.channelData.has(channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${channel} :No such channel\r\n`); - break; - } - if (params.length > 1) { - var topic = params.slice(1).join(' '); - if (topic.startsWith(':')) { - topic = topic.slice(1); - } - this.channelData.get(channel).topic = topic; - await this.safeWriteToSocket(socket, `:${this.servername} 332 ${socket.nickname} ${channel} :${topic}\r\n`); - await this.broadcastChannel(channel, `:${socket.nickname}!${socket.username}@${socket.host} TOPIC ${channel} :${topic}\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} TOPIC ${channel} :${topic}\r\n`); - } else { - const topic = this.channelData.get(channel).topic; - await this.safeWriteToSocket(socket, `:${this.servername} 331 ${socket.nickname} ${channel} :${topic}\r\n`); - } - break; - case 'AWAY': - if (!this.checkRegistered(socket)) { - break; - } - socket.lastspoke = this.getDate(); - if (params.length > 0) { - if (params.length > this.awaylen) { - await this.safeWriteToSocket(socket, `:${this.servername} 417 ${socket.nickname} ${channel} :Away message is too long\r\n`); - break; - } - await this.safeWriteToSocket(socket, `:${this.servername} 306 ${socket.nickname} :You are now marked as away\r\n`); - let awayMsg = params.join(' '); - if (awayMsg.startsWith(':')) { - awayMsg = awayMsg.slice(1); - } - this.awaymsgs.set(socket.nickname, awayMsg); - await this.broadcastUserIfCap(socket, `:${socket.nickname}!${socket.username}@${socket.host} AWAY :${awayMsg}\r\n`, socket, 'away-notify'); - await this.broadcastToAllServers(`:${socket.uniqueId} AWAY :${awayMsg}\r\n`); - } else { - await this.safeWriteToSocket(socket, `:${this.servername} 305 ${socket.nickname} :You are no longer marked as away\r\n`); - this.awaymsgs.delete(socket.nickname); - await this.broadcastUserIfCap(socket, `:${socket.nickname}!${socket.username}@${socket.host} AWAY\r\n`, socket, 'away-notify'); - await this.broadcastToAllServers(`:${socket.uniqueId} AWAY\r\n`); - } - break; - case 'CAP': - // Attempt to map any client caps with our supported caps - if (params[0] && params[0].toUpperCase() === 'LS') { - const capsString = this.supported_client_caps.map(cap => cap.toLowerCase()).join(' '); - await this.safeWriteToSocket(socket, `:${this.servername} CAP ${socket.uniqueId} LS :${capsString}\r\n`); - } - if (params[0] && params[0].toUpperCase() === 'REQ') { - socket.client_caps = params.slice(1).map(cap => { - if (cap.startsWith(':')) { - return cap.slice(1).toLowerCase(); - } - return cap.toLowerCase(); - }); - var supportedCaps = this.supported_client_caps.filter(cap => socket.client_caps.includes(cap.toLowerCase())); - if (params.length > 1) { - // params[1] is the first cap, may be prefixed with ':' - // Remove ':' from first cap if present - let reqCaps = params.slice(1).map(cap => cap.startsWith(':') ? cap.slice(1).toLowerCase() : cap.toLowerCase()); - // Only include supported caps, in the order requested - supportedCaps = reqCaps.filter(cap => this.supported_client_caps.includes(cap)); - } - await this.safeWriteToSocket(socket, `:${this.servername} CAP ${socket.uniqueId} ACK :${supportedCaps.join(' ').toLowerCase()}\r\n`); - this.debugLog('info', `Client with uniqueId ${socket.uniqueId} requested capabilities: ${supportedCaps.join(', ')}`); - } - break; - case 'MODE': - if (!this.checkRegistered(socket)) { - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} MODE :Not enough parameters\r\n`); - break; - } - var isChannel = true; - channel = this.findChannel(params[0]); - if (!channel) { - isChannel = false; - channel = this.findUser(params[0]); - } - if (!channel) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${params[0]} :No such nick/channel\r\n`); - break; - } - if (!this.channelData.has(channel)) { - isChannel = false; - } - // Check if 'channel' is actually a user (nickname) instead of a channel name - let isUser = false; - for (const prefix of this.channelprefixes) { - if (channel.startsWith(prefix)) { - isUser = false; - break; - } else { - isUser = true; - } - } - if (!isChannel && !isUser) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${channel} :No such channel or user\r\n`); - break; - } - const mode = params[1]; - if (isUser) { - // User mode handling - if (!this.isIRCOp(socket.nickname) && channel !== socket.nickname) { - await this.safeWriteToSocket(socket, `:${this.servername} 502 ${socket.nickname} :Cannot set modes on other users\r\n`); - } else { - - var usermodes = this.getUserModes(channel); - if (!mode) { - // List user modes - if (usermodes.length === 0) { - await this.safeWriteToSocket(socket, `:${this.servername} 324 ${socket.nickname} ${channel} :No modes set\r\n`); - } else { - const modes = usermodes.map(m => (m.startsWith('+') ? m : '+' + m)).join(' '); - await this.safeWriteToSocket(socket, `:${this.servername} 324 ${socket.nickname} ${channel} :${modes}\r\n`); - } - } else if (mode.startsWith('+x')) { - if (usermodes.includes('x')) { - break; - } - this.setUserMode(socket.nickname, 'x', true); - socket.host = this.filterHostname(socket, socket.realhost); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +x\r\n`); - if (socket.client_caps && socket.client_caps.includes('CHGHOST')) { - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} CHGHOST ${socket.username} ${socket.host}\r\n`); - } - await this.safeWriteToSocket(socket, `:${this.servername} 396 ${socket.nickname} ${socket.host} :is now your visible host\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +x\r\n`); - } else if (mode.startsWith('-x')) { - if (!usermodes.includes('x')) { - break; - } - this.setUserMode(socket.nickname, 'x', false); - socket.host = socket.realhost - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -x\r\n`); - if (socket.client_caps && socket.client_caps.includes('CHGHOST')) { - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} CHGHOST ${socket.username} ${socket.host}\r\n`); - } - await this.safeWriteToSocket(socket, `:${this.servername} 396 ${socket.nickname} ${socket.host} :is now your visible host\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -x\r\n`); - } else if (mode.startsWith('+w')) { - if (usermodes.includes('w')) { - break; - } - this.setUserMode(socket.nickname, 'w', true); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +w\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +w\r\n`); - } else if (mode.startsWith('-w')) { - if (!usermodes.includes('w')) { - break; - } - this.setUserMode(socket.nickname, 'w', false); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -w\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -w\r\n`); - } else if (mode.startsWith('+c')) { - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `User ${socket.nickname} attempted to set +c mode without being an IRC operator`); - break; - } - if (usermodes.includes('c')) { - break; - } - this.setUserMode(socket.nickname, 'c', true); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +c\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +c\r\n`); - } else if (mode.startsWith('-c')) { - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `User ${socket.nickname} attempted to unset +c mode without being an IRC operator`); - break; - } - if (!usermodes.includes('c')) { - break; - } - this.setUserMode(socket.nickname, 'c', false); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -c\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -c\r\n`); - } else if (mode.startsWith('+i')) { - if (usermodes.includes('i')) { - break; - } - this.setUserMode(socket.nickname, 'i', true); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +i\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +i\r\n`); - } else if (mode.startsWith('-i')) { - if (!usermodes.includes('i')) { - break; - } - this.setUserMode(socket.nickname, 'i', false); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -i\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -i\r\n`); - } else if (mode.startsWith('+s')) { - if (usermodes.includes('s')) { - break; - } - this.setUserMode(socket.nickname, 's', true); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +s\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +s\r\n`); - } else if (mode.startsWith('-s')) { - if (!usermodes.includes('s')) { - break; - } - this.setUserMode(socket.nickname, 's', false); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -s\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -s\r\n`); - } else if (mode.startsWith('+B')) { - if (usermodes.includes('B')) { - break; - } - this.setUserMode(socket.nickname, 'B', true); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +B\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +B\r\n`); - } else if (mode.startsWith('-B')) { - if (!usermodes.includes('B')) { - break; - } - this.setUserMode(socket.nickname, 'B', false); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -B\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -B\r\n`); - } else if (mode.startsWith('+R')) { - if (usermodes.includes('R')) { - break; - } - this.setUserMode(socket.nickname, 'R', true); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +R\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +R\r\n`); - } else if (mode.startsWith('-R')) { - if (!usermodes.includes('R')) { - break; - } - this.setUserMode(socket.nickname, 'R', false); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -R\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -R\r\n`); - } else if (mode.startsWith('+z') || mode.startsWith('-z')) { - await this.safeWriteToSocket(socket, `:${this.servername} 472 ${socket.nickname} ${mode.slice(1)} :is set by the server and cannot be changed\r\n`); - } else if (mode.startsWith('+r') || mode.startsWith('-r')) { - await this.safeWriteToSocket(socket, `:${this.servername} 472 ${socket.nickname} ${mode.slice(1)} :is set by the server and cannot be changed\r\n`); - } else if (mode.startsWith('+Z')) { - if (!socket.secure) { - await this.safeWriteToSocket(socket, `:${this.servername} 472 ${socket.nickname} ${mode.slice(1)} :You must be secure to set this mode\r\n`); - break; - } - if (usermodes.includes('Z')) { - break; - } - this.setUserMode(socket.nickname, 'Z', true); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} +Z\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} +Z\r\n`); - } else if (mode.startsWith('-Z')) { - if (!socket.secure) { - await this.safeWriteToSocket(socket, `:${this.servername} 472 ${socket.nickname} ${mode.slice(1)} :You must be secure to set this mode\r\n`); - break; - } - if (!usermodes.includes('Z')) { - break; - } - this.setUserMode(socket.nickname, 'Z', false); - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${socket.nickname} -Z\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} MODE ${socket.uniqueId} -Z\r\n`); - } else { - await this.safeWriteToSocket(socket, `:${this.servername} 472 ${socket.nickname} ${mode.slice(1)} :is unknown mode char to me\r\n`); - } - } - break; - } - if (!mode) { - // List channel modes - if (!this.checkRegistered(socket)) { - break; - } - let validPrefix = this.channelprefixes.some(prefix => channel.startsWith(prefix)); - if (!validPrefix) { - await this.safeWriteToSocket(socket, `:${this.servername} 476 ${socket.nickname} ${channel} :Bad channel mask\r\n`); - break; - } - if (!this.channelData.has(channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${channel} :No such channel\r\n`); - break; - } - var chan_modes = this.channelData.get(channel).modes; - - chan_modes = chan_modes.map(mode => { - if (typeof mode === 'string' && !mode.startsWith('+')) { - return '+' + mode; - } - return mode; - }); - if (chan_modes.length > 0) { - var params2 = []; - // Batch all modes into a single 324 reply - var modeString = - chan_modes.map(m => { - // For modes with parameters (like k or l) - if (typeof m === 'string' && (m === '+k' || m === '+l')) { - if (m === '+l') { - params2.push(this.channelData.get(channel).limit); - } else if (m === '+k') { - params2.push(this.channelData.get(channel).key); - } - return m.replace(/^\+/, ''); - } - return m.replace(/^\+/, ''); // Remove leading '+' for other modes - }) - .join(''); - params2.forEach(param => { - if (param) { - modeString += ` ${param}`; - } - }); - await this.safeWriteToSocket(socket, `:${this.servername} 324 ${socket.nickname} ${channel} +${modeString}\r\n`); - } else { - await this.safeWriteToSocket(socket, `:${this.servername} 324 ${socket.nickname} ${channel}\r\n`); - } - await this.safeWriteToSocket(socket, `:${this.servername} 329 ${socket.nickname} ${channel} ${this.channelData.get(channel).timestamp || M}\r\n`); - break; - } else { - // Process channel mode changes - await this.processChannelModes(socket.nickname, channel, mode, params.slice(2), socket); - break; - } - case 'NICK': - var old_nickname = socket.nickname; - var new_nickname = params[0]; - if (new_nickname && new_nickname.startsWith(':')) { - new_nickname = new_nickname.slice(1); - } - if (!new_nickname || new_nickname.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 431 * :No nickname\r\n`); - break; - } - - // Sanitize nickname input - const sanitized_nickname = this.sanitizeInput(new_nickname, 'nickname'); - if (sanitized_nickname !== new_nickname || sanitized_nickname.length === 0) { - await this.safeWriteToSocket(socket, `:${this.servername} 432 * ${new_nickname} :Erroneus nickname (invalid characters)\r\n`); - this.logSecurityEvent('INVALID_NICKNAME', socket, { provided: new_nickname, sanitized: sanitized_nickname }); - break; - } - new_nickname = sanitized_nickname; - - if (new_nickname.length > this.nicklen) { - await this.safeWriteToSocket(socket, `:${this.servername} 432 * ${new_nickname} :Erroneus nickname (too long)\r\n`); - break; - } - if (this.findUser(new_nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 433 * ${new_nickname} :Nickname is already in use\r\n`); - break; - } - for (const prefix of this.channelprefixes) { - if (new_nickname.startsWith(prefix)) { - await this.safeWriteToSocket(socket, `:${this.servername} 432 * ${new_nickname} :Erroneus nickname (you are not a channel)\r\n`); - return; - } - } - for (let i = 0; i < new_nickname.length; i++) { - if (!this.allowed_nick_characters.includes(new_nickname[i])) { - await this.safeWriteToSocket(socket, `:${this.servername} 432 * ${new_nickname} :Erroneus nickname (invalid character)\r\n`); - return; - } - } - if (this.reservednicks && Array.isArray(this.reservednicks)) { - if (this.reservednicks.some(nick => nick.toLowerCase() === new_nickname.toLowerCase())) { - await this.safeWriteToSocket(socket, `:${this.servername} 432 * ${new_nickname} :This nickname is reserved\r\n`); - break; - } - } - // Prevent nick change if user is in any channel with +N mode - let inNoNickChangeChannel = false; - for (const [ch, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(socket.nickname)) { - const chanModes = this.channelData.get(ch).modes; - if (chanModes.includes('N')) { - inNoNickChangeChannel = true; - break; - } - } - } - if (inNoNickChangeChannel) { - await this.safeWriteToSocket(socket, `:${this.servername} 447 * :You cannot change your nickname while in a +N (no nick change) channel\r\n`); - break; - } - - if (!socket.nickname) { - // If no nickname is set, set it now - socket.nickname = new_nickname; - this.nicknames.set(socket, socket.nickname); - } else if (socket.nickname != new_nickname) { - this.processNickChange(socket, new_nickname); - if (socket.registered) { - await this.safeWriteToSocket(socket, `:${old_nickname}!${socket.username}@${socket.host} NICK :${new_nickname}\r\n`); - await this.broadcastUser(socket.nickname, `:${old_nickname}!${socket.username}@${socket.host} NICK :${new_nickname}\r\n`, socket); - await this.broadcastToAllServers(`:${socket.uniqueId} NICK ${new_nickname} :${this.getDate()}\r\n`); - } - } - if (!socket.registered && socket.nickname && socket.username) { - var totalSockets = this.clients.length + this.servers.size; - var totalSockets = this.clients.length + this.servers.size; - this.socketpeak = Math.max(this.socketpeak, totalSockets); - this.usernames.set(socket.nickname, socket.username); - socket.lastspoke = this.getDate(); - this.usersignontimestamps.set(socket.nickname, socket.timestamp); - this.doLogin(socket.nickname, socket); - } - break; - case 'USER': - if (params.length < 4) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} USER :Not enough parameters\r\n`); - this.addSocketError(socket); - break; - } - socket.username = params[0]; - socket.userinfo = params.slice(3).join(' ').replace(/^:/, ''); - if (!socket.registered && socket.nickname && socket.username) { - var totalSockets = this.clients.length + this.servers.size; - this.socketpeak = Math.max(this.socketpeak, totalSockets); - this.usernames.set(socket.nickname, socket.username); - socket.lastspoke = this.getDate(); - this.usersignontimestamps.set(socket.nickname, socket.timestamp); - this.doLogin(socket.nickname, socket); - } - break; - case 'JOIN': - var key = null; - if (!this.checkRegistered(socket)) { - break; - } - channel = params[0]; - if (params.length == 2) { - key = params[1]; - } - if (channel.includes(',')) { - var channels = channel.split(','); - } else { - var channels = [channel]; - } - for (var ch of channels) { - // Simulate a JOIN command for each channel - for (let i = 0; i < ch.length; i++) { - if (i == 0 && !this.channelprefixes.includes(ch[0])) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${ch} :No such channel\r\n`); - return; - } - if (this.channelprefixes.includes(ch[1])) { - ch = ch.slice(1); // Remove double prefix - } - for (let j = 0; j < ch.slice(1).length; j++) { - if (!this.allowed_chan_characters.includes(ch.slice(1)[j])) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${ch} :No such channel\r\n`); - return; - } - } - } - if (this.getUserChannelCount(socket.nickname) >= this.channellimit) { - await this.safeWriteToSocket(socket, `:${this.servername} 405 ${socket.nickname} ${ch} :Too many channels\r\n`); - continue; // Skip joining this channel - } - var validChannel = false; - this.channelprefixes.forEach(prefix => { - if (ch.startsWith(prefix)) { - validChannel = true; - } - }); - if (!validChannel) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${ch} :No such channel\r\n`); - continue; // Skip this channel - } - if (ch.length < 2 || ch.length > this.channellen) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${ch} :No such channel\r\n`); - continue; // Skip this channel - } - let foundChannel = null; - for (const existingChannel of this.channelData.keys()) { - if (existingChannel.toLowerCase() === ch.toLowerCase()) { - foundChannel = existingChannel; - break; - } - } - if (foundChannel) { - ch = foundChannel; - } else { - this.createChannel(ch, socket.nickname); - } - - var joinLine = ''; - if (key) { - joinLine = `JOIN ${ch} ${key}`; - } else { - joinLine = `JOIN ${ch}`; - } - const [command, ...params] = joinLine.trim().split(' '); - - const chmodes = this.channelData.get(ch).modes; - if (this.isBanned(ch, socket)) { - await this.safeWriteToSocket(socket, `:${this.servername} 474 ${socket.nickname} ${ch} :Cannot join channel (+b)\r\n`); - continue; // Skip joining this channel - } - // Check if the user is in too many channels - if (chmodes.includes('k')) { - const channelKey = this.channelData.get(ch).key; - // The key must be provided as the second parameter in the JOIN command - // params[1] is the key for the first channel, params[2] for the second, etc. - // For simplicity, assume only one channel per JOIN or the key is always params[1] - const providedKey = params[1]; - if (!providedKey || providedKey !== channelKey) { - var code = (this.clientIsWebTV(socket) ? 474 : 475); - await this.safeWriteToSocket(socket, `:${this.servername} ${code} ${socket.nickname} ${ch} :Cannot join channel (+k)\r\n`); - continue; // Skip joining this channel - } - } - if (chmodes.includes('l')) { - // Channel has a user limit (+l) - const limit = this.channelData.get(ch).limit; - if (limit !== null && this.channelData.get(ch).users.size >= limit) { - await this.safeWriteToSocket(socket, `:${this.servername} 471 ${socket.nickname} ${ch} :Cannot join channel (+l)\r\n`); - continue; // Skip joining this channel - } - } - if (chmodes.includes('i')) { - // Channel is invite-only (+i) - const invited = this.channelData.get(ch).inviteexceptions; - let isInvited = false; - for (const inviteMask of invited) { - isInvited = this.checkMask(inviteMask, socket); - if (isInvited) { - break; // Stop checking if we found a match - } - } - if (!this.channelData.get(ch).invites.has(socket.nickname) && !isInvited) { - await this.safeWriteToSocket(socket, `:${this.servername} 473 ${socket.nickname} ${ch} :Cannot join channel (+i)\r\n`); - continue; // Skip joining this channel - } - if (!this.channelData.get(ch).invites.has(socket.nickname)) { - this.channelData.get(ch).invites.delete(socket.nickname); - } - } - if (chmodes.includes('O')) { - if (!this.isIRCOp(socket.nickname)) { - var code = (this.clientIsWebTV(socket) ? 474 : 404); - await this.safeWriteToSocket(socket, `:${this.servername} ${code} ${socket.nickname} ${ch} :Cannot join channel (+O)\r\n`); - continue; // Skip joining this channel - } - } - if (chmodes.includes('S')) { - // Channel is restricted to users with a secure connection (+S) - if (!socket.secure) { - var code = (this.clientIsWebTV(socket) ? 474 : 468); - await this.safeWriteToSocket(socket, `:${this.servername} ${code} ${socket.nickname} ${ch} :Cannot join channel (+S)\r\n`); - continue; // Skip joining this channel - } - } - if (chmodes.includes('R')) { - // Channel is registered users only (+R) - if (!this.getUserModes(socket.nickname).includes('r')) { - var code = (this.clientIsWebTV(socket) ? 474 : 447); - await this.safeWriteToSocket(socket, `:${this.servername} ${code} ${socket.nickname} ${ch} :Cannot join channel (+R)\r\n`); - continue; // Skip joining this channel - } - } - - // If we reach here, the user can join the channel - // Reuse the JOIN logic for each channel - // Only run the code after $PLACEHOLDER$ for each channel - // (excluding the code before $PLACEHOLDER$ to avoid duplicate checks) - // You can refactor this logic into a helper if needed - socket.lastspoke = this.getDate(); - if (!this.channelData.has(ch)) { - this.createChannel(ch, socket.nickname); - } - var channelObj = this.channelData.get(ch); - channelObj.users.add(socket.nickname); - await this.broadcastChannelJoin(ch, socket); - - let modes = channelObj.modes; - let prefix = ''; - if (channelObj.ops.has(socket.nickname)) { - if (socket.client_caps.includes('multi-prefix')) { - prefix += '@'; - } else { - prefix = '@'; - } - } - if (channelObj.halfops.has(socket.nickname)) { - if (socket.client_caps.includes('multi-prefix')) { - prefix += '%'; - } else { - if (!prefix) { - prefix = '%'; - } - } - } - if (channelObj.voices.has(socket.nickname)) { - if (socket.client_caps.includes('multi-prefix')) { - prefix += '+'; - } else { - if (!prefix) { - prefix = '+'; - } - } - } - await this.broadcastToAllServers(`:${this.serverId} SJOIN ${this.getDate()} ${ch} +${modes.join('')} :${prefix}${socket.uniqueId}\r\n`); - if (channelObj.topic) { - const topic = channelObj.topic; - if (topic) { - await this.safeWriteToSocket(socket, `:${this.servername} 332 ${socket.nickname} ${ch} :${topic}\r\n`); - } - } - var users = this.getUsersInChannel(ch); - output_lines = []; - var prefixRegex = new RegExp(`^[${this.supported_prefixes[1]}]`); - if (users.length > 0) { - users.sort((a, b) => { - // Remove any prefixes for comparison - const cleanA = a.replace(prefixRegex, ''); - const cleanB = b.replace(prefixRegex, ''); - // Get privilege for each user - var channelObj = this.channelData.get(ch); - function getPriv(user) { - if (channelObj.ops.has(user)) return 1; - if (channelObj.halfops.has(user)) return 2; - if (channelObj.voices.has(user)) return 3; - return 4; - } - const privA = getPriv(cleanA); - const privB = getPriv(cleanB); - if (privA !== privB) return privA - privB; - // If same privilege, sort alphabetically (case-insensitive) - return cleanA.localeCompare(cleanB, undefined, { sensitivity: 'base' }); - }); - if (socket.client_caps.includes('userhost-in-names')) { - const userHosts = users.map(user => { - var nick = this.findUser(user.replace(prefixRegex, '')); - var username = this.usernames.get(nick) || 'unknown'; - var host = this.hostnames.get(nick) || 'unknown'; - return `${user}!${username}@${host}`; - }); - output_lines.push(`:${this.servername} 353 ${socket.nickname} = ${ch} :${userHosts.join(' ')}\r\n`); - } else { - output_lines.push(`:${this.servername} 353 ${socket.nickname} = ${ch} :${users.join(' ')}\r\n`); - } - } - output_lines.push(`:${this.servername} 366 ${socket.nickname} ${ch} :End of /NAMES list\r\n`); - await this.sendThrottled(socket, output_lines, 0); - if (this.isReservedChannel(ch)) { - if (this.checkIfReservedChannelOp(socket, ch)) { - this.channelData.get(ch).ops.add(socket.nickname); - await this.broadcastChannel(ch, `:${socket.nickname}!${socket.username}@${socket.host} MODE ${ch} +o ${socket.nickname}\r\n`); - } - } - var awaymsg = this.awaymsgs.get(socket.nickname); - if (awaymsg) { - await this.broadcastUserIfCap(socket, `:${socket.nickname}!${socket.username}@${socket.host} AWAY :${awaymsg}\r\n`, socket, 'away-notify'); - } - if ( - this.irc_config && - Array.isArray(this.irc_config.channels) - ) { - const channel_data = this.irc_config.channels.find(cfg => cfg.name === ch); - if (channel_data && channel_data.intro) { - // Send intro messages (array of lines) to the joining user only - for (const line of channel_data.intro) { - await this.safeWriteToSocket(socket, `:${ch}!system@${this.servername} PRIVMSG ${ch} :${line}\r\n`); - } - } - } - if (this.clientIsWebTV(socket) && this.enable_webtv_command_hacks) { - output_lines = []; - var channelObj = this.channelData.get(ch); - output_lines.push("You have joined " + ch); - output_lines.push("Current channel modes: +" + channelObj.modes.join('')); - let isOp = channelObj.ops.has(socket.nickname); - let isHalfOp = channelObj.halfops.has(socket.nickname); - let isVoice = channelObj.voices.has(socket.nickname); - if (isOp) { - output_lines.push("You are a channel operator (@) in " + ch); - } else if (isHalfOp) { - output_lines.push("You are a channel half-operator (%) in " + ch); - } else if (isVoice) { - output_lines.push("You are voiced (+) in " + ch); - } - this.sendWebTVSpoofedActionTo(socket, ch, output_lines); - } - } - break; - case 'NAMES': - if (!this.checkRegistered(socket)) { - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} NAMES :Not enough parameters\r\n`); - break; - } - channel = this.findChannel(params[0]); - if (!channel || !this.channelData.has(channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${channel} :No such channel\r\n`); - break; - } - var users = this.getUsersInChannel(channel); - output_lines = []; - if (users.length > 0) { - if (socket.client_caps.includes('userhost-in-names')) { - const userHosts = users.map(user => { - var prefixRegex = new RegExp(`^[${this.supported_prefixes[1]}]`); - var nick = this.findUser(user.replace(prefixRegex, '')); - var username = this.usernames.get(nick) || 'unknown'; - var host = this.hostnames.get(nick) || 'unknown'; - return `${user}!${username}@${host}`; - }); - output_lines.push(`:${this.servername} 353 ${socket.nickname} = ${ch} :${userHosts.join(' ')}\r\n`); - } else { - output_lines.push(`:${this.servername} 353 ${socket.nickname} = ${ch} :${users.join(' ')}\r\n`); - } - } - output_lines.push(`:${this.servername} 366 ${socket.nickname} ${channel} :End of /NAMES list\r\n`); - await this.sendThrottled(socket, output_lines); - break; - case 'PART': - if (!this.checkRegistered(socket)) { - break; - } - channel = this.findChannel(params[0]); - if (!this.channelData.has(channel) || !this.channelData.get(channel).users.has(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 442 ${socket.nickname} ${channel} :You're not on that channel\r\n`); - break; - } - if (this.channelData.get(channel).ops.has(socket.nickname)) { - this.channelData.get(channel).ops.delete(socket.nickname); - } - if (this.channelData.get(channel).halfops.has(socket.nickname)) { - this.channelData.get(channel).halfops.delete(socket.nickname); - } - if (this.channelData.get(channel).voices.has(socket.nickname)) { - this.channelData.get(channel).voices.delete(socket.nickname); - } - socket.lastspoke = this.getDate(); - if (params.length == 2) { - let reason = params.join(' '); - if (reason.startsWith(':')) { - reason = reason.slice(1); - } - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} PART ${channel} :${reason}\r\n`); - await this.broadcastChannel(channel, `:${socket.nickname}!${socket.username}@${socket.host} PART ${channel} :${reason}\r\n`, socket); - } else { - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} PART ${channel}\r\n`); - await this.broadcastChannel(channel, `:${socket.nickname}!${socket.username}@${socket.host} PART ${channel}\r\n`, socket); - } - if (this.channelData.has(channel)) { - this.channelData.get(channel).users.delete(socket.nickname); - if (this.channelData.get(channel).users.size === 0) { - this.deleteChannel(channel); - } - } - await this.broadcastToAllServers(`:${socket.uniqueId} PART ${channel}\r\n`); - break; - case 'INVITE': - if (!this.checkRegistered(socket)) { - break; - } - if (params.length < 2) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} INVITE :Not enough parameters\r\n`); - break; - } - const invitee = this.findUser(params[0]); - channel = this.findChannel(params[1]); - if (!invitee || !channel) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${params[0]} :No such nick/channel\r\n`); - break; - } - if (!this.channelData.has(channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${channel} :No such channel\r\n`); - break; - } - if (!this.channelData.get(channel).ops.has(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${socket.socket.nickname} ${channel} :You're not channel operator\r\n`); - break; - } - if (!this.nicknames.has(socket)) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${invitee} :No such nick/channel\r\n`); - break; - } - const inviteeSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === invitee); - if (!inviteeSocket) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${invitee} :No such nick/channel\r\n`); - break; - } - if (!this.channelData.has(channel) || !this.channelData.get(channel).users.has(invitee)) { - if (this.channelData.get(channel).modes.includes('V')) { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${socket.nickname} ${channel} :Cannot invite users, channel is +V (no invites allowed)\r\n`); - break; - } - const invited = this.channelData.get(channel).invites; - invited.add(invitee); - await this.safeWriteToSocket(socket, `:${this.servername} 341 ${socket.nickname} ${invitee} ${channel} :Invited to channel\r\n`); - await this.broadcastUserIfCapAndChanOp(socket, `:${socket.nickname}!${socket.username}@${socket.host} INVITE ${invitee} ${channel}`, socket, 'invite-notify', channel); - await this.safeWriteToSocket(inviteeSocket, `:${this.servername} 341 ${socket.nickname} ${invitee} ${channel} :You have been invited to join ${channel}\r\n`); - break; - } else { - await this.safeWriteToSocket(socket, `:${this.servername} 443 ${socket.nickname} ${invitee} ${channel} :${invitee} is already on that channel\r\n`); - break; - } - case 'LIST': - if (!this.checkRegistered(socket)) { - break; - } let channelsToList; - if (params.length > 0 && params[0]) { - channelsToList = params[0].split(',').filter(ch => ch.length > 0); - } else { - channelsToList = Array.from(this.channelData.keys()); - } - await this.safeWriteToSocket(socket, `:${this.servername} 321 ${socket.nickname} :Channel :Users :Topic\r\n`); - for (const channel of channelsToList) { - if (!this.channelprefixes.some(prefix => channel.startsWith(prefix))) { - continue; // Skip invalid channel names - } - var modes = this.channelData.get(channel).modes; - if (modes.includes('p')) { - if (!this.channelData.has(channel) || !this.channelData.get(channel).users.has(socket.nickname)) { - continue; // Skip if user is not in the channel - } - } - if (modes.includes('s')) { - if (!this.channelData.has(channel) || !this.channelData.get(channel).users.has(socket.nickname)) { - continue; // Skip if user is not in the channel - } - } - const users = this.getUsersInChannel(channel); - const topic = this.channelData.get(channel).topic; - await this.safeWriteToSocket(socket, `:${this.servername} 322 ${socket.nickname} ${channel} ${users.length} :${topic}\r\n`); - } - await this.safeWriteToSocket(socket, `:${this.servername} 323 ${socket.nickname} :End of /LIST\r\n`); - break; - case 'WHO': - if (!this.checkRegistered(socket)) { - break; - } - if (!params[0]) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} WHO :Not enough parameters\r\n`); - break; - } - const target = this.findChannel(params[0]); - if (!target) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${params[0]} :No such nick/channel\r\n`); - break; - } - - var isChannel = false; - for (const prefix of this.channelprefixes) { - if (target.startsWith(prefix)) { - isChannel = true; - break; - } - } - if (isChannel) { - // WHO for channel - const modes = this.channelData.get(target).modes - if ((modes.includes('p') || modes.includes('s')) && (!this.channelData.has(target) || !this.channelData.get(target).users.has(socket.nickname))) { - await this.safeWriteToSocket(socket, `:${this.servername} 315 ${socket.nickname} ${target} :End of /WHO list\r\n`); - break; - } - if (this.channelData.has(target)) { - const users = this.channelData.get(target).users; - for (const user of users) { - let cleanUser = user; - if (!user) { - continue; // Skip empty users - } - if (['@', '%', '+'].includes(cleanUser[0])) { - cleanUser = cleanUser.slice(1); - } - var hostname = this.hostnames.get(cleanUser); - var username = this.usernames.get(cleanUser) || cleanUser; - var whoisSocket = Array.from(this.nicknames.keys()).find( - s => this.nicknames.get(s).toLowerCase() === cleanUser.toLowerCase() - ); - if (!whoisSocket) { - // try to get server socket - whoisSocket = this.getRemoteServerUserSocket(cleanUser); - } - var userSecure = false; - if (whoisSocket) { - userSecure = whoisSocket.secure; - } - let prefix = ''; - var channelObj = this.channelData.get(target); - if (channelObj.ops.has(cleanUser)) { - prefix = '@'; - } else if (channelObj.halfops.has(cleanUser)) { - prefix = '%'; - } else if (channelObj.voices.has(cleanUser)) { - prefix = '+'; - } - var userinfo = this.userinfo.get(cleanUser) || cleanUser; - var flags = `${(this.awaymsgs.has(cleanUser)) ? 'G' : 'H'}${(this.isIRCOp(cleanUser)) ? '*' : ''}${(userSecure) ? 'z' : ''}` - var secondsIdle = (this.getDate() - whoisSocket.lastspoke); - await this.safeWriteToSocket(socket, `:${this.servername} 352 ${socket.nickname} ${target} ${username} ${hostname} ${this.servername} ${cleanUser} ${flags} 0 ${secondsIdle} 0 :${userinfo}\r\n`); - } - } - await this.safeWriteToSocket(socket, `:${this.servername} 315 ${socket.nickname} ${target} :End of /WHO list\r\n`); - } else { - // WHO for nickname - output_lines = []; - if (target.includes('*') || target.includes('?')) { - // Wildcard mask search for nicknames - const maskRegex = new RegExp('^' + target.replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i'); - let found = false; - for (const [sock, nick] of this.nicknames.entries()) { - if (maskRegex.test(nick)) { - if (this.getUserModes(nick).includes('s')) { - continue; - } - found = true; - output_lines.push(`:${this.servername} 352 ${socket.nickname} * ${nick} ${sock.host} ${this.servername} ${nick} ${(this.awaymsgs.has(nick)) ? 'G' : 'H'}${(sock.secure) ? 'z' : ''} :0 ${sock.userinfo}\r\n`); - } - } - if (!found) { - output_lines.push(`:${this.servername} 401 ${socket.nickname} ${target} :No such nick/channel\r\n`); - } - output_lines.push(`:${this.servername} 315 ${socket.nickname} ${target} :End of /WHO list\r\n`); - await this.sendThrottled(socket, output_lines); - break; - } else { - var whoisSocket = Array.from(this.nicknames.keys()).find( - s => this.nicknames.get(s).toLowerCase() === target.toLowerCase() - ); - if (whoisSocket) { - if (this.getUserModes(whoisSocket.nickname).includes('s')) { - // Skip invisible users - output_lines.push(`:${this.servername} 315 ${socket.nickname} ${target} :End of /WHO list\r\n`); - break; - } - output_lines.push(`:${this.servername} 352 ${socket.nickname} * ${whoisSocket.nickname} ${whoisSocket.host} ${this.servername} ${whoisSocket.nickname} ${(this.awaymsgs.has(target)) ? 'G' : 'H'}${(whoisSocket.secure) ? 'z' : ''} :0 ${whoisSocket.userinfo}\r\n`); - } else { - output_lines.push(`:${this.servername} 401 ${socket.nickname} ${target} :No such nick/channel\r\n`); - } - output_lines.push(`:${this.servername} 315 ${socket.nickname} ${target} :End of /WHO list\r\n`); - await this.sendThrottled(socket, output_lines); - break; - } - } - break; - case 'PRIVMSG': - if (!this.checkRegistered(socket)) { - break; - } - socket.lastspoke = this.getDate(); - if (params[0]) { - const target = params[0]; - let targets = target.includes(',') ? target.split(',') : [target]; - if (targets.length > this.maxtargets) { - await this.safeWriteToSocket(socket, `:${this.servername} 407 ${socket.nickname} :Too many targets. Maximum allowed is ${this.maxtargets}\r\n`); - return; - } - for (var t of targets) { - if (t === this.servername) { - var msg = line.slice(line.indexOf(':', 1) + 1); - if (msg.startsWith("\x01VERSION")) { - await this.safeWriteToSocket(socket, `:${this.servername} NOTICE ${socket.nickname} :${this.servername} zefIRCd ${this.version} - zefIRCd IRC server - a part of the zefie minisrv project\r\n`); - break; - } - if (msg.startsWith("\x01PING")) { - await this.safeWriteToSocket(socket, `:${this.servername} NOTICE ${socket.nickname} :\x01PING ${this.getDate()}\r\n`); - break; - } - if (msg.startsWith("\x01TIME")) { - const dateObj = new Date(); - const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - const pad = n => n.toString().padStart(2, '0'); - const formattedDate = `${dayNames[dateObj.getDay()]} ${monthNames[dateObj.getMonth()]} ${pad(dateObj.getDate())} ${pad(dateObj.getHours())}:${pad(dateObj.getMinutes())}:${pad(dateObj.getSeconds())} ${dateObj.getFullYear()}`; - await this.safeWriteToSocket(socket, `:${this.servername} NOTICE ${socket.nickname} :\x01TIME ${formattedDate}\x01\r\n`); - break; - } - } - let isChan = false; - for (const prefix of this.channelprefixes) { - if (t.startsWith(prefix)) { - isChan = true; - t = this.findChannel(t); - break; - } - } - if (!t) { - t = this.findUser(t); - isChan = false; - } - if (!t) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${t} :No such nick/channel\r\n`); - continue; - } - var channelObj = this.channelData.get(t); - var msg = line.slice(line.indexOf(':', 1) + 1); - if (isChan) { - // Channel message - if (channelObj.modes.includes('m')) { - // Channel is moderated (+m) - - if (!channelObj.voices.has(socket.nickname && !channelObj.ops.has(socket.nickname) && !channelObj.halfops.has(socket.nickname))) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+m)\r\n`); - continue; - } - } - if (channelObj.modes.includes('n')) { - // Channel is no-external-messages (+n) - if (!channelObj.users.has(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+n)\r\n`); - continue; - } - } - if (channelObj.modes.includes('c')) { - // Block all IRC control codes (ASCII 0x00-0x1F except \r and \n) - if (/[\x00-\x09\x0B\x0C\x0E-\x1F]/.test(msg)) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+c)\r\n`); - continue; - } - } - if (channelObj.modes.includes('C')) { - // channel blocks CTCP, detect if the message contains CTCPS - if (msg.includes('\x01')) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+C)\r\n`); - continue; - } - } - if (channelObj.modes.includes('O')) { - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+O)\r\n`); - } - } - } - if (isChan) { - if (!this.channelData.has(t)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${t} :No such channel\r\n`); - continue; - } - if (this.clientIsWebTV(socket) && msg.startsWith('/') && this.enable_webtv_command_hacks) { - var wtvcmd = msg.slice(1).split(' '); - if (wtvcmd[0].length > 0) { - if (this.supported_webtv_command_hacks.includes(wtvcmd[0].toUpperCase())) { - var wtvstr = `${wtvcmd[0].toUpperCase()} ${wtvcmd.splice(1).join(' ')}\r\n`; - this.processSocketData(socket, wtvstr); - } - } - continue; - } - await this.broadcastChannel(t, `:${socket.nickname}!${socket.username}@${socket.host} PRIVMSG ${t} :${msg}\r\n`, socket); - await this.broadcastToAllServers(`:${socket.uniqueId} PRIVMSG ${t} :${msg}\r\n`); - } else { - if (this.awaymsgs.has(t)) { - await this.safeWriteToSocket(socket, `:${this.servername} 301 ${socket.nickname} ${t} :${this.awaymsgs.get(t)}\r\n`); - } - var targetSock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s).toLowerCase() === t.toLowerCase()); - if (!targetSock) { - // check remote servers - targetSock = this.getRemoteServerUserSocket(t); - if (targetSock) { - const sender_id = this.getUniqueId(socket.nickname); - const unique_id = this.getUniqueId(t); - targetSock.write(`:${sender_id} PRIVMSG ${unique_id} :${msg}\r\n`); - break; - } - } - if (!targetSock) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${t} :No such nick/channel\r\n`); - continue; - } - var targetUserModes = this.getUserModes(t); - var usermodes = this.getUserModes(socket.nickname); - if (targetUserModes.includes('R')) { - if (!usermodes.includes('r')) { - await this.safeWriteToSocket(socket, `:${this.servername} 447 ${socket.nickname} ${t} :Cannot send to user (+R)\r\n`); - continue; - } - } - if (targetUserModes.includes('Z') && !socket.secure) { - await this.safeWriteToSocket(socket, `:${this.servername} 484 ${socket.nickname} ${t} :Cannot send to user (+Z)\r\n`); - continue; - } - if (!usermodes || usermodes === true) { - usermodes = []; - } - if (usermodes.includes('Z') && !targetUserModes.includes('Z')) { - await this.safeWriteToSocket(socket, `:${this.servername} 484 ${socket.nickname} ${t} :Cannot send to non-+Z user while you are +Z\r\n`); - continue; - } - targetSock.write(`:${socket.nickname}!${socket.username}@${socket.host} PRIVMSG ${targetSock.nickname} :${msg}\r\n`); - if (socket.client_caps.includes('echo-message')) { - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} PRIVMSG ${targetSock.nickname} :${msg}\r\n`); - } - } - } - return; - } - break; - case 'NOTICE': - if (!this.checkRegistered(socket, false, true) && params[0] !== this.servername) { - break; - } - socket.lastspoke = this.getDate(); - if (params[0]) { - const target = params[0]; - let targets = target.includes(',') ? target.split(',') : [target]; - if (targets.length > this.maxtargets) { - await this.safeWriteToSocket(socket, `:${this.servername} 407 ${socket.nickname} :Too many targets. Maximum allowed is ${this.maxtargets}\r\n`); - return; - } - for (const t of targets) { - let isChan = false; - if (t === this.servername) { - // client responding to a system message - var msg = line.slice(line.indexOf(':', 1) + 1); - if (msg.startsWith('\x01VERSION')) { - socket.client_version = msg.replace('\x01VERSION ', '').replace('\x01', ''); - break; - } - } - for (const prefix of this.channelprefixes) { - if (t.startsWith(prefix)) { - isChan = true; - t = this.findChannel(t); - break; - } - } - if (!t) { - t = this.findUser(t); - isChan = false; - } - if (!t) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${t} :No such nick/channel\r\n`); - continue; - } - var channelObj = this.channelData.get(t); - var msg = line.slice(line.indexOf(':', 1) + 1); - if (isChan) { - if (!this.channelData.has(t)) { - await this.safeWriteToSocket(socket, `:${this.servername} 403 ${socket.nickname} ${t} :No such channel\r\n`); - continue; - } - // Channel notice - if (channelObj.modes.includes('n')) { - // Channel is no-external-messages (+n) - if (!this.channelData.get(t).users.has(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+n)\r\n`); - continue; - } - } - if (channelObj.modes.includes('c')) { - // channel blocks color, detect if the message contains color codes - if (/[\x00-\x09\x0B\x0C\x0E-\x1F]/.test(msg)) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+c)\r\n`); - continue; - } - } - if (channelObj.modes.includes('C')) { - // channel blocks CTCP, detect if the message contains CTCPS - if (msg.includes('\x01')) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+C)\r\n`); - continue; - } - } - if (channelObj.modes.includes('T')) { - if ( - !channelObj.ops.has(socket.nickname) && - !channelObj.halfops.has(socket.nickname) && - !channelObj.voices.has(socket.nickname) - ) { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${socket.nickname} ${t} :Cannot send to channel (+T)\r\n`); - continue; - } - } - if (channelObj.modes.includes('O')) { - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 404 ${socket.nickname} ${t} :Cannot send to channel (+O)\r\n`); - } - } - await this.broadcastChannel(t, `:${socket.nickname}!${socket.username}@${socket.host} NOTICE ${t} :${msg}\r\n`, socket); - await this.broadcastToAllServers(`:${socket.uniqueId} NOTICE ${t} :${msg}\r\n`); - } else { - // Assume it's a nick, check if it exists - var targetSock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s).toLowerCase() === t.toLowerCase()); - if (!targetSock) { - // check remote servers - targetSock = this.getRemoteServerUserSocket(t); - if (targetSock) { - const sender_id = this.getUniqueId(socket.nickname); - const unique_id = this.getUniqueId(t); - targetSock.write(`:${sender_id} PRIVMSG ${unique_id} :${msg}\r\n`); - break; - } - } - if (!targetSock) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${t} :No such nick/channel\r\n`); - continue; - } - var targetUserModes = this.getUserModes(t); - var usermodes = this.getUserModes(socket.nickname); - if (targetUserModes.includes('R')) { - if (!usermodes.includes('r')) { - await this.safeWriteToSocket(socket, `:${this.servername} 447 ${socket.nickname} ${t} :Cannot send to user (+R)\r\n`); - continue; - } - } - if (targetUserModes.includes('Z') && !socket.secure) { - await this.safeWriteToSocket(socket, `:${this.servername} 484 ${socket.nickname} ${t} :Cannot send to user (+Z)\r\n`); - continue; - } - if (!usermodes || usermodes === true) { - usermodes = []; - } - if (usermodes.includes('Z') && !targetUserModes.includes('Z')) { - await this.safeWriteToSocket(socket, `:${this.servername} 484 ${socket.nickname} ${t} :Cannot send to non-+Z user while you are +Z\r\n`); - continue; - } - var cmd = 'NOTICE'; - if (this.clientIsWebTV(targetSock)) { - cmd = 'PRIVMSG'; // WebTV clients do not support NOTICE, use PRIVMSG instead - } - targetSock.write(`:${socket.nickname}!${socket.username}@${socket.host} ${cmd} ${targetSock.nickname} :${msg}\r\n`); - if (socket.client_caps.includes('echo-message')) { - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} PRIVMSG ${targetSock.nickname} :${msg}\r\n`); - } - } - } - return; - } - break; - case 'SYSTEM': - if (!this.checkRegistered(socket)) { - break; - } - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `SYSTEM command attempted by non-IRCOp: ${socket.nickname}`); - break; - } - var type = params[0] ? params[0].toUpperCase() : ''; - output_lines = []; - switch (type) { - case "HELP": - output_lines.push(`:${this.servername} 200 ${socket.nickname} :Available commands:\r\n`); - output_lines.push(`:${this.servername} 200 ${socket.nickname} : HELP - Show this help message\r\n`); - output_lines.push(`:${this.servername} 200 ${socket.nickname} : LOG - Show server log data\r\n`); - output_lines.push(`:${this.servername} 200 ${socket.nickname} : KLINES - Show KLINE data\r\n`); - output_lines.push(`:${this.servername} 200 ${socket.nickname} : CHANNELS - Show channel data\r\n`); - output_lines.push(`:${this.servername} 200 ${socket.nickname} :End of help data\r\n`); - break; - case "LOG": - this.logdata.forEach((logEntry) => { - output_lines.push(`:${this.servername} 200 ${socket.nickname} :${logEntry}\r\n`); - }); - output_lines.push(`:${this.servername} 200 ${socket.nickname} :End of log data\r\n`); - break; - case "KLINES": - if (this.klines.length === 0) { - output_lines.push(`:${this.servername} 200 ${socket.nickname} :No KLINES found\r\n`); - break; - } - output_lines.push(`:${this.servername} 200 ${socket.nickname} :KLINE data:\r\n`); - for (const kline of this.klines) { - output_lines.push(`:${this.servername} 200 ${socket.nickname} :Mask: ${kline.mask}, Expiry: ${kline.expiry}, Reason: ${kline.reason}\r\n`); - } - output_lines.push(`:${this.servername} 200 ${socket.nickname} :End of KLINE data\r\n`); - break; - case 'CHANNELS': - for (const [channelName, channelObj] of this.channelData.entries()) { - output_lines.push(`:${this.servername} 200 :Channel: ${channelName}\r\n`); - for (const [key, value] of Object.entries(channelObj)) { - let valStr; - if (value instanceof Set) { - valStr = Array.from(value).join(', '); - } else if (typeof value === 'object' && value !== null) { - valStr = JSON.stringify(value); - } else { - valStr = String(value); - } - output_lines.push(`:${this.servername} 200 : ${key}: ${valStr}\r\n`); - } - } - break; - default: - output_lines.push(`:${this.servername} 500 ${socket.nickname} :Unknown debug command\r\n`); - break; - } - await this.sendThrottled(socket, output_lines); - break; - case 'PING': - await this.safeWriteToSocket(socket, `PONG ${params.join(' ')}\r\n`); - break; - case 'KLINE': - if (!this.checkRegistered(socket)) { - break; - } - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `KLINE command attempted by non-IRCOp: ${socket.nickname}`); - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} KLINE :Not enough parameters\r\n`); - break; - } - var targetMask = params[0]; - var expiry = this.getDate() + 3600; - var reasonParam = 1; - if (!isNaN(parseInt(targetMask))) { - expiry = this.getDate() + parseInt(targetMask); - targetMask = params[1]; - reasonParam = 2; - } - if (this.klines.findIndex(k => k.mask === targetMask) !== -1) { - await this.safeWriteToSocket(socket, `:${this.servername} 200 ${socket.nickname} ${targetMask} :KLINE already exists for this mask\r\n`); - break; - } - var reason = params.slice(reasonParam).join(' ') || ''; - var kline = { - "mask": targetMask, - "expiry": expiry, - "reason": reason - } - this.klines.push(kline); - this.saveKLinesToFile(); - if (reason) { - await this.safeWriteToSocket(socket, `:${this.servername} 381 ${socket.nickname} :KLINE added for ${targetMask} (duration ${expiry - this.getDate()} seconds) [${reason}]\r\n`); - } else { - await this.safeWriteToSocket(socket, `:${this.servername} 381 ${socket.nickname} :KLINE added for ${targetMask} (duration ${expiry - this.getDate()} seconds)\r\n`); - } - await this.scanUsersForKLines(); - break; - case 'UNKLINE': - if (!this.checkRegistered(socket)) { - break; - } - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `UNKLINE command attempted by non-IRCOp: ${socket.nickname}`); - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} UNKLINE :Not enough parameters\r\n`); - break; - } - var targetMask = params[0]; - if (this.klines.findIndex(k => k.mask === targetMask) == -1) { - await this.safeWriteToSocket(socket, `:${this.servername} 200 ${socket.nickname} ${targetMask} :No such KLINE\r\n`); - break; - } - const klineIndex = this.klines.findIndex(k => k.mask === targetMask); - if (klineIndex !== -1) { - this.klines.splice(klineIndex, 1); - } - await this.safeWriteToSocket(socket, `:${this.servername} 381 ${socket.nickname} :KLINE removed for ${targetMask}\r\n`); - break; - case 'WHOIS': - if (!this.checkRegistered(socket)) { - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} WHOIS :Not enough parameters\r\n`); - break; - } - var whoisNick = params[0]; - var nickCheck = this.findUser(whoisNick); - if (nickCheck) { - whoisNick = nickCheck; - var whoisSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s)=== whoisNick); - const whois_username = this.usernames.get(whoisNick); - var userinfo = this.userinfo.get(whoisNick) || whoisSocket.userinfo || 'unknown'; - await this.safeWriteToSocket(socket, `:${this.servername} 311 ${socket.nickname} ${whoisNick} ${whois_username} ${whoisSocket.host} * :${userinfo}\r\n`); - if (this.awaymsgs.has(whoisNick)) { - await this.safeWriteToSocket(socket, `:${this.servername} 301 ${socket.nickname} ${whoisNick} :${this.awaymsgs.get(whoisNick)}\r\n`); - } - const userChannels = []; - - output_lines = []; - for (const [ch, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(whoisNick)) { - let prefix = ''; - var chanops = channelObj.ops; - var chanhalfops = channelObj.halfops; - var chanvoices = channelObj.voices; - var modes = channelObj.modes; - - if ((modes.includes('p') || modes.includes('s')) && (!this.channelData.has(ch) || !this.channelData.get(ch).users.has(socket.nickname))) { - continue; // Skip listing this channel if it's private/secret and user is not in it - } - if (chanops.has(whoisNick)) { - if (socket.client_caps.includes('multi-prefix')) { - prefix += '@'; - } else { - prefix = '@'; - } - } - if (chanhalfops.has(whoisNick)) { - if (socket.client_caps.includes('multi-prefix')) { - prefix += '%'; - } else { - if (!prefix) { - prefix = '%'; - } - } - } - if (chanvoices.has(whoisNick)) { - if (socket.client_caps.includes('multi-prefix')) { - prefix += '+'; - } else { - if (!prefix) { - prefix = '+'; - } - } - } - userChannels.push(prefix + ch); - } - } - output_lines.push(`:${this.servername} 312 ${socket.nickname} ${whoisNick} ${this.servername} :zefIRCd-${this.version}\r\n`); - if (this.isIRCOp(whoisNick)) { - output_lines.push(`:${this.servername} 313 ${socket.nickname} ${whoisNick} :is an IRC operator\r\n`); - } - usermodes = this.getUserModes(whoisNick); - if (usermodes && usermodes.includes('s')) { - output_lines.push(`:${this.servername} 671 ${socket.nickname} ${whoisNick} :is using a secure connection\r\n`); - } - if (usermodes && usermodes.includes('r')) { - output_lines.push(`:${this.servername} 307 ${socket.nickname} ${whoisNick} :is a registered nick\r\n`); - } - if (usermodes && usermodes.includes('B')) { - output_lines.push(`:${this.servername} 335 ${socket.nickname} ${whoisNick} :is a bot\r\n`); - } - const now = this.getDate(); - const userTimestamp = whoisSocket.lastspoke || now; - 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`); - if (userChannels.length > 0) { - output_lines.push(`:${this.servername} 319 ${socket.nickname} ${whoisNick} :${userChannels.join(' ')}\r\n`); - } - output_lines.push(`:${this.servername} 318 ${socket.nickname} ${whoisNick} :End of /WHOIS list\r\n`); - await this.sendThrottled(socket, output_lines); - } else { - // Check if whoisNick is a remote server user - let foundRemote = false; - for (const [srvSocket, users] of this.serverusers.entries()) { - if (users && typeof users.has === 'function' - ? Array.from(users).some(u => typeof u === 'string' && u.toLowerCase() === whoisNick.toLowerCase()) - : Array.isArray(users) && users.some(u => typeof u === 'string' && u.toLowerCase() === whoisNick.toLowerCase()) - ) { - // Found remote user - const sender_id = this.getUniqueId(socket.nickname); - const unique_id = this.getUniqueId(whoisNick); - await this.safeWriteToSocket(srvSocket, `:${sender_id} WHOIS :${unique_id}\r\n`); - foundRemote = true; - break; - } - } - if (!foundRemote) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${whoisNick} :No such nick/channel\r\n`); - } - } - break; - case 'KILL': - if (!this.checkRegistered(socket)) { - break; - } - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `KILL command attempted by non-IRCOp: ${socket.nickname}`); - break; - } - if (params.length < 2) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} KILL :Not enough parameters\r\n`); - break; - } - const target_nick = this.findUser(params[0]); - if (!target_nick) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${params[0]} :No such nick/channel\r\n`); - break; - } - - const killReason = params.slice(1).join(' '); - let cleanKillReason = killReason; - if (cleanKillReason.startsWith(':')) { - cleanKillReason = cleanKillReason.slice(1); - } - targetSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === target_nick); - if (!targetSocket) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${socket.nickname} ${target_nick} :No such nick/channel\r\n`); - break; - } - - // Broadcast the KILL message to all users - await this.broadcastUser(target_nick, `:${socket.nickname}!${socket.username}@${socket.host} KILL ${target_nick} :${cleanKillReason}\r\n`); - this.terminateSession(targetSocket, true); - break; - case 'QUIT': - if (!this.checkRegistered(socket)) { - break; - } - for (const [ch, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(socket.nickname)) { - channelObj.ops.delete(socket.nickname); - channelObj.halfops.delete(socket.nickname); - channelObj.voices.delete(socket.nickname); - } - } - if (params.length > 0) { - let reason = params.join(' '); - if (reason.startsWith(':')) { - reason = reason.slice(1); - } - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} QUIT :${reason}\r\n`); - await this.broadcastUser(socket.nickname, `:${socket.nickname}!${socket.username}@${socket.host} QUIT :${reason}\r\n`, socket); - await this.broadcastToAllServers(`:${socket.uniqueId} QUIT :${reason}\r\n`); - await this.broadcastConnection(socket, `Quit: ${reason}`); - socket.signedoff = true; - } else { - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} QUIT\r\n`); - await this.broadcastUser(socket.nickname, `:${socket.nickname}!${socket.username}@${socket.host} QUIT\r\n`, socket); - await this.broadcastToAllServers(`:${socket.uniqueId} QUIT :Client disconnected\r\n`); - await this.broadcastConnection(socket, 'Quit: Client disconnected'); - socket.signedoff = true; - } - this.terminateSession(socket, true); - break; - case 'MOTD': - if (!this.checkRegistered(socket)) { - break; - } - await this.doMOTD(socket.nickname, socket); - break; - case 'VERSION': - if (!this.checkRegistered(socket)) { - break; - } - await this.safeWriteToSocket(socket, `:${this.servername} 351 ${socket.nickname} ${this.servername} zefIRCd ${this.version} :zefIRCd IRC server - a part of the zefie minisrv project\r\n`); - break; - case 'WALLOPS': - if (!this.checkRegistered(socket)) { - break; - } - if (!this.isIRCOp(socket.nickname)) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `WALLOPS command attempted by non-IRCOp: ${socket.nickname}`); - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} WALLOPS :Not enough parameters\r\n`); - break; - } - let wallopsMessage = params.join(' '); - if (wallopsMessage.startsWith(':')) { - wallopsMessage = wallopsMessage.slice(1); - } - await this.broadcastWallops(`:${socket.nickname}!${socket.username}@${socket.host} WALLOPS :${wallopsMessage}\r\n`); - case 'VHOST': - if (!this.checkRegistered(socket)) { - break; - } - if (!this.isIRCOp(socket.nickname) && !this.allow_public_vhosts) { - await this.safeWriteToSocket(socket, `:${this.servername} 481 ${socket.nickname} :Permission denied - you are not an IRC operator\r\n`); - this.debugLog('warn', `VHOST command attempted by non-IRCOp: ${socket.nickname}`); - break; - } - if (params.length < 1) { - await this.safeWriteToSocket(socket, `:${this.servername} 461 ${socket.nickname} VHOST :Not enough parameters\r\n`); - break; - } - const newVHost = params[0]; - if (!newVHost || !/^[a-zA-Z0-9.-]+$/.test(newVHost)) { - await this.safeWriteToSocket(socket, `:${this.servername} 501 ${socket.nickname} :Invalid VHost format\r\n`); - break; - } - // Prevent setting VHost to an IP address (IPv4 or IPv6) - const ipv4Pattern = /^(?:\d{1,3}\.){3}\d{1,3}$/; - const ipv6Pattern = /^([a-fA-F0-9:]+:+)+[a-fA-F0-9]+$/; - if (ipv4Pattern.test(newVHost) || ipv6Pattern.test(newVHost)) { - await this.safeWriteToSocket(socket, `:${this.servername} 501 ${socket.nickname} :VHost cannot be an IP address\r\n`); - break; - } - dns.lookup(newVHost, async (err, address) => { - if (!err && address) { - await this.safeWriteToSocket(socket, `:${this.servername} 501 ${socket.nickname} :VHost must not resolve to a real IP (resolved to: ${address})\r\n`); - return; - } - // Set the new VHost for the socket - socket.host = newVHost; - if (socket.client_caps && socket.client_caps.includes('CHGHOST')) { - await this.safeWriteToSocket(socket, `:${socket.nickname}!${socket.username}@${socket.host} CHGHOST ${socket.username} ${socket.host}\r\n`); - } - await this.safeWriteToSocket(socket, `:${this.servername} 396 ${socket.nickname} :Your VHost has been changed to ${socket.host}\r\n`); - }); - break; - case 'STARTTLS': - socket.upgrading_to_tls = true; - await this.safeWriteToSocket(socket, `:${this.servername} 670 ${socket.uniqueId} :STARTTLS successful, go ahead with TLS handshake\r\n`); - break; - default: - // Ignore unknown commands - break; - } - } - } - - deleteChannel(channel) { - // Cleans up the channel from all lists - if (!this.isReservedChannel(channel)) { - this.channelData.delete(channel); - this.debugLog('info', `Channel ${channel} deleted`); - } - } - - cleanupUserSession(nickname) { - this.usersignontimestamps.delete(nickname); - this.usernames.delete(nickname); - this.usermodes.delete(nickname); - this.awaymsgs.delete(nickname); - this.accounts.delete(nickname); - this.userinfo.delete(nickname); - this.deleteUserUniqueId(nickname); - for (const [ch, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(nickname)) { - channelObj.users.delete(nickname); - } - if (channelObj.ops.has(nickname)) { - channelObj.ops.delete(nickname); - } - if (channelObj.halfops.has(nickname)) { - channelObj.halfops.delete(nickname); - } - if (channelObj.voices.has(nickname)) { - channelObj.voices.delete(nickname); - } - if (channelObj.invites.has(nickname)) { - channelObj.invites.delete(nickname); - } - if (channelObj.users.size === 0) { - this.deleteChannel(ch); - } - } - } - - - async terminateSession(socket, close = false) { - // Cleans up the user session and removes them from all channels - const nickname = this.nicknames.get(socket); - if (nickname) { - if (!socket.signedoff) { - let serverSocket = null; - for (const [srvSocket, users] of this.serverusers.entries()) { - if (users && typeof users.has === 'function' && users.has(nickname)) { - // Don't send QUIT to this server, as it owns the user - serverSocket = srvSocket; - continue; - } - } - await this.broadcastUser(nickname, `:${nickname}!${socket.username}@${socket.host} QUIT :Client disconnected\r\n`, socket); - await this.broadcastToAllServers(`:${socket.uniqueId} QUIT :Client disconnected\r\n`, serverSocket); - socket.signedoff = true; // Just in case - } - this.cleanupUserSession(nickname); - this.nicknames.delete(socket); - } - if (socket.isserver) { - const srvUsers = this.serverusers.get(socket) || []; - for (const nickname of srvUsers) { - // Remove all user data for this server - this.debugLog('debug', `Removing user ${nickname} from server ${socket.servername}`); - if (users && typeof users.delete === 'function') { - users.delete(nickname); - } - this.cleanupUserSession(nickname); - } - this.servers.delete(socket); - this.serverusers.delete(socket); - } else { - this.clients = this.clients.filter(c => c !== socket); - } - if (socket._idleInterval) { - clearInterval(socket._idleInterval); - socket._idleInterval = null; - } - - // Clean up rate limiting data - const socketId = socket.remoteAddress + ':' + socket.remotePort; - this.message_counts.delete(socketId); - - // Clean up connection count per IP - const clientIP = socket.remoteAddress; - if (this.connections_per_ip.has(clientIP)) { - const currentCount = this.connections_per_ip.get(clientIP); - if (currentCount <= 1) { - this.connections_per_ip.delete(clientIP); - } else { - this.connections_per_ip.set(clientIP, currentCount - 1); - } - } - - if (close) { - socket.end(); - } - } - - async sendWebTVNotice(message) { - // Send a WebTV Global Notice to all WebTV clients - await this.broadcastToAllWebTVClients(`:${this.servername} NOTICE * :${message}\r\n`); - } - - async sendWebTVNoticeTo(socket, message) { - // Sends a WebTV Global Notice to the specified socket - if (Array.isArray(message)) { - message = message.map(line => `:${this.servername} NOTICE * :${line}\r\n`); - await this.sendThrottled(socket, message); - return; - } - await this.safeWriteToSocket(socket, `:${this.servername} NOTICE * :${message}\r\n`); - } - - async sendWebTVSpoofedActionTo(socket, channel, message) { - if (!Array.isArray(message)) { - message = [message]; - } - if (this.clientIsWebTV(socket)) { - message.forEach(async (line) => { - const msg = line.split(' '); - const firstWord = msg[0]; - const action = msg.slice(1).join(' '); - const message = [`:${firstWord}!system@webtv PRIVMSG ${channel} :\x01ACTION ${action}\x01\r\n`]; - await this.sendThrottled(socket, message); - }); - return; - } - } - - getUserChannelCount(username) { - // returns the number of channels a user is in - let count = 0; - for (const [channel, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(username)) { - count++; - } - } - return count; - } - - getUsersInChannel(channel) { - // Returns an array of users in a specific channel, with modes applied - if (this.channelData.has(channel)) { - const channelObj = this.channelData.get(channel); - const ops = channelObj.ops || new Set(); - const halfops = channelObj.halfops || new Set(); - const voices = channelObj.voices || new Set(); - return Array.from(channelObj.users).map(user => { - if (ops.has(user)) return '@' + user; - if (halfops.has(user)) return '%' + user; - if (voices.has(user)) return '+' + user; - return user; - }); - } - } - - async broadcastUser(username, message, exceptSocket = null) { - // Broadcast a message to all users in any channels that the specified user is in, except the one specified - const alreadyNotified = []; - for (const [channel, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(username)) { - for (const user of channelObj.users) { - const sock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); - if (alreadyNotified.includes(sock)) { - continue; - } - if (sock && sock !== exceptSocket) { - await this.safeWriteToSocket(sock, message); - alreadyNotified.push(sock); - } - } - } - } - } - - async broadcastChannel(channel, message, exceptSocket = null) { - // Broadcast a message to all users in a specific channel, except the one specified - const alreadyNotified = []; - if (this.channelData.has(channel)) { - const channelObj = this.channelData.get(channel); - for (const user of channelObj.users) { - // +Z (secureonly): Restricts private message (PRIVMSG) or notice (NOTICE) reception/sending to users with a secure connection (TLS). - if (channelObj.modes.includes('Z') && (message.includes('PRIVMSG') || message.includes('NOTICE'))) { - const user_modes = this.getUserModes(user); - if (user_modes.includes('z')) { - const sock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); - if (alreadyNotified.includes(sock)) { - continue; - } - if (sock && sock !== exceptSocket) { - await this.safeWriteToSocket(sock, message); - alreadyNotified.push(sock); - } - } - } - else { - const sock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); - if (alreadyNotified.includes(sock)) { - continue; - } - if (sock && sock !== exceptSocket) { - sock.write(message); - alreadyNotified.push(sock); - } - } - } - } - } - - async broadcastChannelWebTV(channel, message, exceptSocket = null) { - // Broadcast a message to all WebTV users in a specific channel, except the one specified - const alreadyNotified = []; - if (this.channelData.has(channel)) { - const channelObj = this.channelData.get(channel); - for (const user of channelObj.users) { - const socket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); - if (alreadyNotified.includes(socket)) { - continue; - } - // Only send to WebTV clients - if (socket && socket !== exceptSocket && this.clientIsWebTV(socket)) { - this.sendWebTVSpoofedActionTo(socket, channel, message) - alreadyNotified.push(socket); - } - } - } - } - - async broadcastChannelJoin(channel, sourceSocket, exceptSocket = null) { - // Broadcast a channel join message to all users in the channel, except the one specified - channel = this.findChannel(channel); - if (!channel) { - this.debugLog('warn', `Attempted to broadcast join to non-existent channel: ${channel}`); - return; - } - if (this.channelData.has(channel)) { - const channelObj = this.channelData.get(channel); - for (const user of channelObj.users) { - const sock = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); - if (sock && sock !== exceptSocket) { - if (sock.client_caps && sock.client_caps.includes('extended-join')) { - const account = this.accounts.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`); - } else { - await this.safeWriteToSocket(sock,`:${sourceSocket.nickname}!${sourceSocket.username}@${sourceSocket.host} JOIN ${channel}\r\n`); - } - } - } - } else { - this.debugLog('warn', `Attempted to broadcast join to non-existent channel: ${channel}`); - } - } - - async broadcastToAllServers(message, exceptSocket = null) { - // Broadcast a message to all server sockets, except the one specified - for (const [srvSocket, serverName] of this.servers.entries()) { - if (srvSocket && srvSocket !== exceptSocket) { - await this.safeWriteToSocket(srvSocket, message); - } - } - } - - async broadcastWallops(message) { - // Broadcast a message to all users with 'w' or 'o' user modes - for (const [socket, nickname] of this.nicknames.entries()) { - const usermodes = this.getUserModes(nickname); - if (usermodes.includes('w') || usermodes.includes('o')) { - await this.safeWriteToSocket(socket, message); - } - } - } - - async broadcastToAllClients(message, exceptSocket = null) { - // Broadcast a message to all connected clients, except the one specified - for (const client of this.clients) { - if (client !== exceptSocket) { - await this.safeWriteToSocket(client, message); - } - } - } - - async broadcastToAllWebTVClients(message, exceptSocket = null) { - // Broadcast a message to all connected WebTV clients, except the one specified - for (const client of this.clients) { - if (client !== exceptSocket && this.clientIsWebTV(client)) { - await this.safeWriteToSocket(client, message); - } - } - } - - isIRCOp(nickname) { - // Check if the user is an IRC operator - if (!this.getUserModes(nickname)) return false; - const modes = this.getUserModes(nickname); - if (Array.isArray(modes)) { - return modes.includes('o'); - } - return false; - } - - isSpyingOnConnections(nickname) { - if (!this.getUserModes(nickname)) return false; - const modes = this.getUserModes(nickname); - if (Array.isArray(modes)) { - return modes.includes('c'); - } - return false; - } - - createChannel(channel, creator) { - // Create a new channel with the specified creator - if (!this.channelData.has(channel)) { - this.channelData.set(channel, { - users: new Set(), - ops: new Set([creator]), - halfops: new Set(), - voices: new Set(), - topic: '', - bans: new Set(), - exemptions: new Set(), - invites: new Set(), - modes: [...this.default_channel_modes], - mlock: [], - limit: null, - key: null, - timestamp: this.getDate() - }); - } - } - - checkMask(mask, socket) { - // Check if a mask matches a user's socket - const host = socket.host; - const realhost = socket.realhost; - const realaddress = socket.remoteAddress; - const nickname = this.nicknames.get(socket); - let fullMask = `*!*@${host}`; - let fullMask2 = `*!*@${realhost}`; - let fullMask3 = `*!*@${realaddress}`; - let userIdent; - if (nickname) { - userIdent = this.usernames.get(nickname) || nickname; - fullMask = `${nickname}!${userIdent}@${host}`; - fullMask2 = `${nickname}!${userIdent}@${realhost}`; - fullMask3 = `${nickname}!${userIdent}@${realaddress}`; - } - - - // If mask does not contain '!', treat as nickname or username only - if (!mask.includes('!')) { - // Wildcard match for just the nickname or username - // Try matching against both nickname and username - const maskRegex = new RegExp('^' + mask.replace(/\*/g, '.*').replace(/\?/g, '.') + '$', 'i'); - return maskRegex.test(nickname) || maskRegex.test(userIdent); - } - - // If mask contains '!', match against full mask (nick!user@host) - // Split mask into nick, user, host - const [maskNick, rest] = mask.split('!', 2); - const [maskUser, maskHost] = (rest || '').split('@', 2); - - // Split fullMask into nick, user, host - const [fullNick, fullRest] = fullMask.split('!', 2); - const [fullUser, fullHost] = (fullRest || '').split('@', 2); - - // Build regex for each part, defaulting to '*' if missing - const nickRegex = new RegExp('^' + (maskNick || '*').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'); - let matches = nickRegex.test(fullNick) && userRegex.test(fullUser) && hostRegex.test(fullHost); - if (!matches && fullMask2) { - // Try matching against the real host if available - const [fullNick2, fullRest2] = fullMask2.split('!', 2); - const [fullUser2, fullHost2] = (fullRest2 || '').split('@', 2); - matches = nickRegex.test(fullNick2) && userRegex.test(fullUser2) && hostRegex.test(fullHost2); - } - if (!matches && fullMask3) { - // Try matching against the real IP if available - const [fullNick3, fullRest3] = fullMask3.split('!', 2); - const [fullUser3, fullHost3] = (fullRest3 || '').split('@', 2); - matches = nickRegex.test(fullNick3) && userRegex.test(fullUser3) && hostRegex.test(fullHost3); - } - return matches; - } - - filterHostname(socket, hostname) { - // Masks the user's hostname or IP for privacy - const username = this.nicknames.get(socket); - let modes = null; - if (username) { - modes = this.getUserModes(username); - } - if (modes) { - if (Array.isArray(modes) && modes.includes('x')) { - // Masked hostname for +x users - if (typeof hostname === 'string') { - // Mask everything except the first and last octet for IPv4 - // Mask IP-like subdomains (e.g., 1-1-1-1.domain.com) - const ipSubdomainMatch = hostname.match(/^(\d+)-(\d+)-(\d+)-(\d+)\./); - if (ipSubdomainMatch) { - return `${ipSubdomainMatch[1]}-x-x-${ipSubdomainMatch[4]}.${hostname.split('.').slice(1).join('.')}`; - } - const ipv4Match = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); - if (ipv4Match) { - return `${ipv4Match[1]}.x.x.${ipv4Match[4]}`; - } - // For hostnames, mask all but the first and last label - const parts = hostname.split('.'); - if (parts.length > 2) { - return `${parts[0]}.x.${parts[parts.length - 1]}`; - } - // Otherwise, just return 'hidden.host' - return 'hidden.host'; - } - } - } - return hostname; - } - - isBanned(channel, socket) { - // Check if a user is banned from a channel - const nickname = this.nicknames.get(socket); - channel = this.findChannel(channel); - if (!channel) { - return false; - } - if (this.channelData.has(channel).bans) { - const bans = this.channelData.get(channel).bans; - // Check if the user's mask matches any ban mask - let isUserBanned = false; - for (const banMask of bans) { - isUserBanned = this.checkMask(banMask, socket); - if (isUserBanned) { - if (this.channelexemptions.has(channel)) { - const exemptions = this.channelexemptions.get(channel); - for (const exemptMask of exemptions) { - isUserBanned = !this.checkMask(exemptMask, socket); - if (!isUserBanned) { - break; - } - } - } - } - } - return isUserBanned; - } - return false; - } - - findSocketByUniqueId(uniqueId) { - // Find a socket related to a unique ID - for (const [socket, nickname] of this.nicknames.entries()) { - if (socket.uniqueId === uniqueId) { - // client socket - return socket; - } - } - for (const [srvSocket, users] of this.serverusers.entries()) { - const searchID = this.findUserByUniqueId(uniqueId); - if (users.has(searchID)) { - // server socket - return srvSocket; - } - } - return null; - } - - findUserByUniqueId(uniqueId) { - // Find a user by their unique ID - let uniqueids = this.uniqueids || new Map(); - if (!uniqueids || uniqueids === true) { - uniqueids = new Map(); - } - for (const [nickname, id] of uniqueids.entries()) { - if (id === uniqueId) { - return nickname; - } - } - for (const [socket, users] of this.serverusers.entries()) { - for (const user of users) { - if (this.getUniqueId(user) === uniqueId) { - return user; - } - } - } - return null; - } - - addUserUniqueId(nickname, uniqueId) { - // Add or update the unique ID for a user - if (!this.uniqueids || this.uniqueids === true) { - this.uniqueids = new Map(); - } - this.uniqueids.set(nickname, uniqueId); - } - - deleteUserUniqueId(nickname) { - // Remove the unique ID for a user - if (this.uniqueids && this.uniqueids.has(nickname)) { - this.uniqueids.delete(nickname); - } - } - - async doMOTD(nickname, socket = null) { - // Sends the Message of the Day (MOTD) to the user - const output_lines = []; - output_lines.push(`:${this.servername} 375 ${nickname} :${this.servername} message of the day\r\n`); - 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`); - } - if (typeof this.irc_motd === 'string' && this.irc_motd.length > 0) { - output_lines.push(`:${this.servername} 372 ${nickname} :${this.irc_motd}\r\n`); - } else if (Array.isArray(this.irc_motd) && this.irc_motd.length > 0) { - for (let line of this.irc_motd) { - if (line === '') { - line = '-'; - } - output_lines.push(`:${this.servername} 372 ${nickname} :- ${line}\r\n`); - } - } else { - output_lines.push(`:${this.servername} 372 ${nickname} :No message of the day is set\r\n`); - } - output_lines.push(`:${this.servername} 376 ${nickname} :End of /MOTD command\r\n`); - if (socket) { - await this.sendThrottled(socket, output_lines); - } else { - return output_lines; - } - } - - isReservedChannel(channel) { - // Check if the channel is a reserved channel - if (this.irc_config.channels && Array.isArray(this.irc_config.channels)) { - return this.irc_config.channels.some(ch => ch.name === channel); - } - return false; - } - - checkIfReservedChannelOp(socket, channel) { - // Check if the channel is a reserved channel and if the user is an operator for that channel - if (this.isReservedChannel(channel)) { - const reservedChannel = this.irc_config.channels.find(ch => ch.name === channel); - // reservedChannel.ops is an array of masks - if (reservedChannel && reservedChannel.ops && Array.isArray(reservedChannel.ops)) { - for (const mask of reservedChannel.ops) { - if (this.checkMask(mask, socket)) { - return true; // User is an operator for this reserved channel - } - } - } - } - return false; // User is not an operator for this reserved channel - } - - isRemoteServerUser(socket, username) { - // Check if the user is a remote server user - let serverUsers = this.serverusers.get(socket) || new Set(); - if (!serverUsers || serverUsers === true) { - serverUsers = new Set(); - } - for (const user of serverUsers) { - if (typeof user === 'string' && user.toLowerCase() === username.toLowerCase()) { - return true; - } - } - return false; - } - - addRemoteServerUser(socket, username) { - // Add a remote server user to the serverusers map - if (!this.serverusers.has(socket)) { - this.serverusers.set(socket, new Set()); - } - this.serverusers.get(socket).add(username); - } - - getRemoteServerUserSocket(username) { - // Find the socket of a remote server user by username - for (const [socket, users] of this.serverusers.entries()) { - for (const user of users) { - if (typeof user === 'string' && user.toLowerCase() === username.toLowerCase()) { - return socket; - } - } - } - return null; - } - - - - getUsernameFromUniqueId(uniqueId) { - // Find the username associated with a unique ID - for (const [socket, nickname] of this.nicknames.entries()) { - if (socket.uniqueId === uniqueId) { - return nickname; - } - } - for (const [nick, id] of this.uniqueids.entries()) { - if (id === uniqueId) { - return nick; - } - } - return null; - } - - getUniqueId(username) { - // Find the unique ID for a given username - const socket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s).toLowerCase() === username.toLowerCase()); - if (socket) { - return socket.uniqueId; - } else { - for (const [nick, id] of this.uniqueids.entries()) { - if (nick.toLowerCase() === username.toLowerCase()) { - return id; - } - } - } - return null; - } - - countGlobalUsers() { - // Counts the total number of users across all clients and server users - let globalUsers = this.clients.length; - for (const users of this.serverusers.values()) { - if (users && typeof users.size === 'number') { - globalUsers += users.size; - } else if (Array.isArray(users)) { - globalUsers += users.length; - } - } - return globalUsers; - } - - processNickChange(socket, newNick) { - // Handles nickname changes, assumes the newNick is already validated - // Update all channel user lists to use channelData - for (const [ch, channelObj] of this.channelData.entries()) { - if (channelObj.users.has(socket.nickname)) { - channelObj.users.delete(socket.nickname); - channelObj.users.add(newNick); - } - } - this.usernames.set(newNick, this.usernames.get(socket.nickname) || socket.nickname); - this.usernames.delete(socket.nickname); - this.nicknames.set(socket, newNick); - this.nicknames.delete(socket.nickname); - this.addUserUniqueId(newNick, socket.uniqueId); - this.deleteUserUniqueId(socket.nickname); - this.usermodes.set(newNick, this.getUserModes(socket.nickname) || []); - this.usermodes.delete(socket.nickname); - if (this.awaymsgs.has(socket.nickname)) { - this.awaymsgs.set(newNick, this.awaymsgs.get(socket.nickname) || ''); - this.awaymsgs.delete(socket.nickname); - } - this.usersignontimestamps.set(newNick, this.usersignontimestamps.get(socket.nickname) || this.getDate()); - this.usersignontimestamps.delete(socket.nickname); - socket.nickname = newNick; - } - - generateUniqueId(socket) { - // Generate a unique ID - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - let id = ''; - for (let i = 0; i < 6; i++) { - id += chars.charAt(Math.floor(Math.random() * chars.length)); - } - if (this.uniqueids.has(id)) { - // If the ID already exists, generate a new one - return this.generateUniqueId(socket); - } - return id; - } - - async sendThrottled(socket, lines, delayMs = 1) { - for (const line of lines) { - await new Promise(res => setTimeout(res, delayMs)); - if (socket.writable) { - await this.safeWriteToSocket(socket, line); - } - } - } - - getDate() { - // Returns the current timestamp in seconds - return Math.floor(Date.now() / 1000) - } - - findChannel(channel) { - // Normalize the channel name to lowercase for case-insensitive comparison - let foundChannel = null; - for (const existingChannel of this.channelData.keys()) { - if (existingChannel.toLowerCase() === channel.toLowerCase()) { - foundChannel = existingChannel; - break; - } - } - return foundChannel; - } - - findUser(username) { - // Normalize the username to lowercase for case-insensitive comparison - let foundUser = null; - if (typeof username !== 'string') { - return null; - } - for (const [socket, nick] of this.nicknames.entries()) { - if (nick.toLowerCase() === username.toLowerCase()) { - foundUser = nick; - break; - } - } - return foundUser; - } - - clientIsWebTV(socket) { - // Check if the client is a WebTV client based on the client version - if (socket.client_version.includes('WebTV')) { - return true; - } - return false; - } - - async broadcastUserIfCap(socket, message, exceptSocket = null, client_cap) { - if (socket.client_caps.includes(client_cap)) { - await this.broadcastUser(socket.nickname, message, exceptSocket); - } - } - - async broadcastUserIfCapAndChanOp(socket, message, exceptSocket = null, client_cap, channel) { - if (socket.client_caps.includes(client_cap)) { - // Check if the user is an operator in the specified channel - channel = this.findChannel(channel); - if (!channel) { - this.debugLog('warn', `Attempted to broadcast to channel ${channel} that does not exist.`); - return; - } - const channelObj = this.channelData.get(channel); - const isOp = channelObj.ops.has(socket.nickname) || false; - const isHalfOp = channelObj.halfops.has(socket.nickname) || false; - if (isOp || isHalfOp) { - await this.broadcastUser(socket.nickname, message, exceptSocket); - } - } - } - - async broadcastConnection(clientSocket, quitMsg = null) { - // Broadcasts a connection message to all clients with mode +c - for (const [index, socket] of this.clients.entries()) { - if (socket !== clientSocket && this.isSpyingOnConnections(socket.nickname)) { - if (quitMsg) { - await this.sendWebTVNoticeTo(socket, `*** Notice --- Client exiting: ${clientSocket.nickname} (${clientSocket.username}@${clientSocket.host}) [${clientSocket.remoteAddress}] [${quitMsg}]`); - this.debugLog('info', `Client exiting: ${clientSocket.nickname} (${clientSocket.username}@${clientSocket.host}) [${clientSocket.remoteAddress}] [${quitMsg}]`); - } else { - await this.sendWebTVNoticeTo(socket, `*** Notice --- Client connecting: ${clientSocket.nickname} (${clientSocket.username}@${clientSocket.host}) [${clientSocket.remoteAddress}] {users} [${clientSocket.userinfo}] <${clientSocket.uniqueId}>`); - this.debugLog('info', `Client connecting: ${clientSocket.nickname} (${clientSocket.username}@${clientSocket.host}) [${clientSocket.remoteAddress}] {users} [${clientSocket.userinfo}] <${clientSocket.uniqueId}>`); - } - } - } - } - - getUserModes(nickname) { - // Returns the user modes for a given nickname - let foundSocket = null; - for (const [socket, nick] of this.nicknames.entries()) { - if (nick.toLowerCase() === nickname.toLowerCase()) { - foundSocket = socket; - nickname = socket.nickname; // Ensure we use the correct nickname - break; - } - } - if (!foundSocket) { - // Also search this.serverusers for remote users (case-insensitive) - for (const [srvSocket, users] of this.serverusers.entries()) { - if (users && typeof users.forEach === 'function') { - for (const user of users) { - if (typeof user === 'string' && user.toLowerCase() === nickname.toLowerCase()) { - foundSocket = srvSocket; - nickname = user; - break; - } - } - } else if (Array.isArray(users)) { - for (const user of users) { - if (typeof user === 'string' && user.toLowerCase() === nickname.toLowerCase()) { - foundSocket = srvSocket; - nickname = user; - break; - } - } - } - if (foundSocket) break; - } - } - if (!foundSocket) { - return null; - } - const modes = this.usermodes.get(nickname); - if (!modes || modes === true) { - this.usermodes.set(nickname, [...this.default_user_modes]); - } - return this.usermodes.get(nickname); - } - - setUserMode(nickname, mode, adding) { - // Sets a user mode for a given nickname - const modes = this.getUserModes(nickname); - if (adding) { - if (!modes.includes(mode)) { - modes.push(mode); - } - } else { - const index = modes.indexOf(mode); - if (index !== -1) { - modes.splice(index, 1); - } - } - } - - async getHostname(socket) { - // Resolve the hostname for a socket, using reverse DNS lookup - let hostname; - if (socket && socket.remoteAddress) { - try { - hostname = socket.remoteAddress; - hostname = await new Promise((resolve) => { - dns.reverse(socket.remoteAddress, (err, hostnames) => { - if (!err && hostnames && hostnames.length > 0) { - socket.hostname_resolved = true; - this.safeWriteToSocket(socket, `:${this.servername} NOTICE AUTH :*** Hostname found: ${hostnames[0]}\r\n`); - resolve(hostnames[0]); - } else { - if (!err) { - err = 'Domain name not found'; - } - socket.hostname_resolved = true; - this.safeWriteToSocket(socket, `:${this.servername} NOTICE AUTH :*** Could not resolve your hostname: ${err}; using your IP address (${socket.remoteAddress}) instead.\r\n`); - resolve(socket.remoteAddress); - } - }); - }); - } catch (e) { - this.debugLog('error', `Error resolving hostname for ${socket.remoteAddress}: ${e}`); - socket.hostname_resolved = true; - await this.safeWriteToSocket(socket, `:${this.servername} NOTICE AUTH :*** Could not resolve your hostname: ${e}; using your IP address (${socket.remoteAddress}) instead.\r\n`); - } - return hostname; - } - } - - async doInitialHandshake(socket) { - // Perform the initial handshake with the client - // We pause the socket to prevent sending data before the hostname is resolved - await this.safeWriteToSocket(socket, `:${this.servername} NOTICE AUTH :*** Looking up your hostname\r\n`); - socket.pause(); - socket.host = await this.getHostname(socket); - socket.resume(); - socket.realhost = socket.host; - } - - async scanSocketForKLine(socket) { - for (const kline of this.klines) { - if (this.checkMask(kline.mask, socket)) { - if (kline.expiry && kline.expiry > this.getDate()) { - if (kline.reason) { - await this.safeWriteToSocket(socket, `:${this.servername} KILL ${socket.nickname} :K-lined: ${kline.reason}\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} KILL ${socket.uniqueId} :K-lined: ${kline.reason}\r\n`, socket); - } else { - await this.safeWriteToSocket(socket, `:${this.servername} KILL ${socket.nickname} :K-lined\r\n`); - await this.broadcastToAllServers(`:${socket.uniqueId} KILL ${socket.uniqueId} :K-lined\r\n`, socket); - } - this.terminateSession(socket, true); - return true; - } else { - const klineIndex = this.klines.findIndex(k => k.mask === kline.mask); - if (klineIndex !== -1) { - this.klines.splice(klineIndex, 1); - } - this.saveKLinesToFile(); - } - } - } - return false; - } - - async scanUsersForKLines() { - for (const kline of this.klines) { - for (const socket of this.nicknames.keys()) { - if (this.checkMask(kline.mask, socket)) { - if (kline.expiry && kline.expiry > this.getDate()) { - if (kline.reason) { - await this.safeWriteToSocket(socket, `:${this.servername} KILL ${socket.nickname} :K-lined: ${kline.reason}\r\n`); - await this.broadcastUser(socket.nickname, `:${socket.nickname}!${socket.username}@${socket.host} KILL :K-lined: ${kline.reason}\r\n`); - } else { - await this.safeWriteToSocket(socket, `:${this.servername} KILL ${socket.nickname} :K-lined\r\n`); - await this.broadcastUser(socket.nickname, `:${socket.nickname}!${socket.username}@${socket.host} KILL :K-lined\r\n`); - } - await this.broadcastToAllServers(`:${socket.uniqueId} KILL ${socket.uniqueId} :K-lined: ${kline.reason}\r\n`, socket); - this.terminateSession(socket, true); - } else { - const klineIndex = this.klines.findIndex(k => k.mask === kline.mask); - if (klineIndex !== -1) { - this.klines.splice(klineIndex, 1); - } - this.saveKLinesToFile(); - } - } - } - } - } - - saveKLinesToFile() { - // Ensure the session store directory exists - if (!fs.existsSync(this.session_store_path)) { - fs.mkdirSync(this.session_store_path, { recursive: true }); - } - // Save the KLines to a file - fs.writeFileSync(this.klines_path, JSON.stringify(this.klines, null, 2)); - } - - loadKLinesFromFile() { - // Load KLines from a file if it exists - if (fs.existsSync(this.klines_path)) { - const data = fs.readFileSync(this.klines_path, 'utf8'); - this.klines = JSON.parse(data); - } - } - - getGitRevision() { - try { - const gitPath = __dirname + path.sep + ".." + path.sep + ".." + path.sep + ".." + path.sep + ".git" + path.sep - const rev = fs.readFileSync(gitPath + "HEAD").toString().trim(); - if (rev.indexOf(':') === -1) { - return rev.slice(0, 8); - } else { - return fs.readFileSync(gitPath + rev.slice(5)).toString().trim().slice(0, 8) + "-" + rev.split('/').pop(); - } - } catch (e) { - return null; - } - } - - isChannelOp(nickname, channel) { - // Check if the user is a channel operator - channel = this.findChannel(channel); - if (!channel) { - return false; // Channel not found - } - const channelOps = this.channelData.get(channel).ops; - if (channelOps === true) { - return false; - } - if (channelOps.has(nickname)) { - return true; // User is a channel operator - } - // Check if the user is an IRC operator - if (this.isIRCOp(nickname)) { - return true; // IRC operator is considered a channel operator - } - } - - isChannelHalfOp(nickname, channel) { - // Check if the user is a channel half-operator - channel = this.findChannel(channel); - if (!channel) { - return false; // Channel not found - } - const channelHalfOps = this.channelData.get(channel).halfops; - if (channelHalfOps === true) { - return false; - } - if (channelHalfOps.has(nickname)) { - return true; // User is a channel half-operator - } - // Check if the user is an IRC operator - if (this.isIRCOp(nickname)) { - return true; // IRC operator is considered a channel half-operator - } - } - - - processChannelModeParams(channel, mode, target) { - let result = false; - if (!target) { - this.debugLog('warn', `No target specified for mode ${mode} on channel ${channel}`); - return false; - } - if (mode === '+o' || mode === '-o') { - const channelOps = this.channelData.get(channel).ops; - if (mode === '+o') { - if (!channelOps.has(target)) { - channelOps.add(target); - return true; - } - } else if (mode === '-o') { - if (channelOps.has(target)) { - channelOps.delete(target); - return true; - } - } - } else if (mode === '+h' || mode === '-h') { - const channelHalfOps = this.channelData.get(channel).halfops; - if (mode === '+h') { - if (!channelHalfOps.has(target)) { - channelHalfOps.add(target); - return true; - } - } else if (mode === '-h') { - if (channelHalfOps.has(target)) { - channelHalfOps.delete(target); - return true; - } - } - } else if (mode === '+v' || mode === '-v') { - const channelVoices = this.channelData.get(channel).voices; - if (mode === '+v') { - if (!channelVoices.has(target)) { - channelVoices.add(target); - return true; - } - } else if (mode === '-v') { - if (channelVoices.has(target)) { - channelVoices.delete(target); - return true; - } - } - } else if (mode === '+b' || mode === '-b') { - let channelBans = this.channelData.get(channel).bans; - if (mode === '+b') { - if (!channelBans.includes(target)) { - channelBans.push(target); - return true; - } - } else if (mode === '-b') { - if (channelBans.includes(target)) { - channelBans = channelBans.filter(ban => ban !== target); - return true; - } - } - } else if (mode === '+e' || mode === '-e') { - let channelExemptions = this.channelData.get(channel).exemptions; - if (mode === '+e') { - if (!channelExemptions.includes(target)) { - channelExemptions.push(target); - return true; - } - } else if (mode === '-e') { - if (channelExemptions.includes(target)) { - channelExemptions = channelExemptions.filter(exception => exception !== target); - return true; - } - } - } else if (mode === '+I' || mode === '-I') { - let channelInvites = this.channelData.get(channel).inviteexemptions; - if (mode === '+I') { - if (!channelInvites.includes(target)) { - channelInvites.push(target); - return true; - } - } else if (mode === '-I') { - if (channelInvites.includes(target)) { - channelInvites = channelInvites.filter(invite => invite !== target); - return true; - } - } - } else if (mode === '+l' || mode === '-l') { - if (mode === '+l') { - result = this.setChannelMode(channel, 'l', true); - if (result === false && this.channelData.get(channel).limit === parseInt(target)) { - return false; // Mode already set with the same limit - } - this.channelData.get(channel).limit = parseInt(target); - return true; - } else { - result = this.setChannelMode(channel, 'l', false); - if (result === false && this.channelData.get(channel).limit === null) { - return false; // Mode already unset - } - this.channelData.get(channel).limit = null; - return true; - } - } else if (mode === '+k' || mode === '-k') { - if (mode === '+k') { - result = this.setChannelMode(channel, 'k', true); - if (result === false && this.channelData.get(channel).key === target) { - return false; // Mode already set with the same key - } - this.channelData.get(channel).key = target; - return true; - } else { - result = this.setChannelMode(channel, 'k', false); - if (result === false && !this.channelData.get(channel).key) { - return false; // Mode already unset - } - this.channelData.get(channel).key = null; - return true; - } - } - } - - async processChannelModes(nickname, channel, modes, params, socket) { - // Split modes into array and process each character - const modeChars = modes.split(''); - const validModes = []; - const supportedChannelModes = (this.supported_channel_modes.split(',').join('') + this.supported_prefixes[0]).split(''); - let serverModeMsg = ''; - let target = null; - if (socket.isserver) { - const sourceUniqueId = this.uniqueids.get(nickname); - serverModeMsg = `:${sourceUniqueId} MODE ${channel} `; - } else { - if (!this.checkRegistered(socket)) { - return; - } - serverModeMsg = `:${socket.uniqueId} MODE ${channel} `; - } - const username = this.usernames.get(nickname); - const hostname = this.hostnames.get(nickname); - - let modeMsg = `:${nickname}!${username}@${hostname} MODE ${channel} `; - let WTVMsg = `${nickname} has set channel mode `; - let addingFlag = false; - let paramIndex = 0; - const output_lines = []; - if (!socket.isserver) { - if (modeChars.includes('o')) { - if (!this.isIRCOp(nickname) && !this.isChannelOp(nickname, channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${nickname} ${channel} :You're not a channel operator\r\n`); - return; - } - } - else if (modeChars.includes('O')) { - if (!this.isIRCOp(nickname)) - { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${nickname} ${channel} :You're not an IRC operator\r\n`); - return; - } - } else if (modes === 'b') { - // Get the list of channel ban - if (this.channelData.has(channel).bans) { - const bans = this.channelData.has(channel).bans; - for (const ban of bans) { - output_lines.push(`:${this.servername} 367 ${nickname} ${channel} ${ban}\r\n`); - } - } - output_lines.push(`:${this.servername} 368 ${nickname} ${channel} :End of channel ban list\r\n`); - await this.sendThrottled(socket, output_lines); - return; - } else if (modes === 'e') { - // Get the list of channel exemptions - if (this.channelData.has(channel).exemptions) { - const exemptions = this.channelData.has(channel).exemptions; - for (const exemption of exemptions) { - output_lines.push(`:${this.servername} 348 ${nickname} ${channel} ${exemption}\r\n`); - } - } - output_lines.push(`:${this.servername} 349 ${nickname} ${channel} :End of channel exception list\r\n`); - await this.sendThrottled(socket, output_lines); - return; - } else if (modes === 'I') { - // Get the list of channel invites masks - if (this.channelData.has(channel).invites) { - const invites = this.channelData.has(channel).invites; - for (const invite of invites) { - output_lines.push(`:${this.servername} 336 ${nickname} ${channel} ${invite}\r\n`); - } - } - output_lines.push(`:${this.servername} 337 ${nickname} ${channel} :End of channel invite list\r\n`); - await this.sendThrottled(socket, output_lines); - return; - } else { - if (!this.isIRCOp(nickname) && !this.isChannelOp(nickname, channel) && !this.isChannelHalfOp(nickname, channel)) { - await this.safeWriteToSocket(socket, `:${this.servername} 482 ${nickname} ${channel} :You're not a channel operator\r\n`); - return; - } - } - } - for (let j = 0; j < modeChars.length; j++) { - let param = null; - let modeStr = ''; - const mc = modeChars[j]; - let result = false; - if (mc === '+') { - addingFlag = true; - modeMsg += '+'; - WTVMsg += '+'; - serverModeMsg += '+'; - continue; - } else if (mc === '-') { - addingFlag = false; - modeMsg += '-'; - WTVMsg += '-'; - serverModeMsg += '-'; - continue; - } - if (!supportedChannelModes.includes(mc)) { - if (!socket.isserver) { - await this.safeWriteToSocket(socket, `:${this.servername} 472 ${nickname} ${channel} :Unknown channel mode char: ${mc}\r\n`); - } - continue; - } - modeStr += mc; - // Modes that require a parameter - if ([...this.supported_prefixes[0], 'I', 'b', 'e', 'l', 'k'].includes(mc)) { - const plusminus = (addingFlag) ? "+" : "-"; - param = params[paramIndex]; - if (socket.isserver) { - target = this.findUserByUniqueId(param); - } else { - target = this.findUser(param); - } - if ((!target && !socket.isserver) || !this.channelData.get(channel).users.has(target)) { - await this.safeWriteToSocket(socket, `:${this.servername} 401 ${nickname} ${param} :No such nick/channel\r\n`); - return; - } - result = this.processChannelModeParams(channel, plusminus + mc, target, socket); - paramIndex++; - if (!result) { - if (params.length > 0) { - params.shift(); - } - } - } else { - result = this.setChannelMode(channel, mc, addingFlag); - if (addingFlag) { - if (mc === 'S' && this.kick_insecure_users_on_secure) { - // Kick users who do not have user mode +z - const usersInChannel = this.channelData.get(channel).users; - for (const user of usersInChannel) { - const userSocket = Array.from(this.nicknames.keys()).find(s => this.nicknames.get(s) === user); - if (userSocket && !userSocket.secure) { - await this.safeWriteToSocket(userSocket, `:${nickname}!${username}@${socket.host} KICK ${channel} ${userSocket.nickname} :Channel is now +S (SSL-only, +z usermode required)\r\n`); - await this.broadcastChannel(channel, `:${nickname}!${username}@${socket.host} KICK ${channel} ${userSocket.nickname} :Channel is now +S (SSL-only, +z usermode required)\r\n`, userSocket); - await this.broadcastToAllServers(`:${sourceUniqueId} KICK ${channel} ${userSocket.uniqueId} :Channel is now +S (SSL-only, +z usermode required)\r\n`); - this.channelData.get(channel).users.delete(userSocket.nickname); - } - } - } - } - } - if (result) { - WTVMsg += mc; - validModes.push(mc); - if (modeStr.length > 0) { - modeMsg += modeStr; - serverModeMsg += modeStr; - } - } - } - if (params.length > 0) { - for (let i = 0; i < params.length; i++) { - if (socket.isserver) { - modeMsg += ' ' + this.findUserByUniqueId(params[i]); - } else { - modeMsg += ' ' + params[i]; - WTVMsg += ' ' + params[i]; - } - serverModeMsg += ' ' + params[i]; - } - } - if (modeMsg.endsWith('-') || modeMsg.endsWith('+')) { - return; - } - modeMsg += '\r\n'; - if (validModes.length > 0) { - await this.broadcastChannel(channel, modeMsg); - await this.broadcastChannelWebTV(channel, WTVMsg); - await this.broadcastToAllServers(serverModeMsg, socket); - } - } - - async addSocketError(socket) { - socket.error_count++; - if (socket.error_count >= 5) { - if (socket.writable) { - await this.safeWriteToSocket(socket, `:${this.servername} :ERROR :Too many errors, disconnecting\r\n`); - } - this.terminateSession(socket, true); - return; - } - setTimeout((socket) => { - if (socket) { - socket.error_count--; - } - }, 60000); - } - - async checkRegistered(socket, allowUnregistered = false, silent = false) { - let retval = false; - if (socket.isserver) { - if (!socket.is_srv_authorized && (!socket.registered && !allowUnregistered)) { - if (socket.writable && !silent) { - await this.safeWriteToSocket(socket, `:${this.servername} ERROR :Unauthorized\r\n`); - } - this.addSocketError(socket); - } else { - retval = true; // Server is authorized - } - } - if (!socket.registered && (!socket.registered && !allowUnregistered)) { - if (socket.writable && !silent) { - await this.safeWriteToSocket(socket, `:${this.servername} 451 ${socket.uniqueId} :You have not registered\r\n`); - } - this.addSocketError(socket); - } else { - retval = true; // User is registered - } - return retval; - } - - setChannelMode(channel, mode, adding) { - // Updates the channel modes for a given channel - const modes = this.channelData.get(channel).modes; - if (!modes) { - return false; // Channel not found - } - if (adding) { - if (!modes.includes(mode)) { - modes.push(mode); - return true; - } - } else { - const index = modes.indexOf(mode); - if (index !== -1) { - modes.splice(index, 1); - return true; - } - } - return false; // Mode not changed - } - - debugLog(type = 'debug', ...message) { - const parsedMessage = message.map(m => - typeof m === 'object' ? JSON.stringify(m) : String(m) - ).join(' '); - - // Logs debug messages to the console if debugging is enabled - switch (type) { - case 'debug': - this.logdata.push(`[DEBUG] ${parsedMessage}`); - if (this.debug) { - console.log(`[DEBUG] ${parsedMessage}`); - } - break; - case 'warn': - this.logdata.push(`[WARN] ${parsedMessage}`); - if (this.debug) { - console.warn(`[WARN] ${parsedMessage}`); - } - break; - case 'error': - this.logdata.push(`[ERROR] ${parsedMessage}`); - if (this.debug) { - console.error(`[ERROR] ${parsedMessage}`); - } - break; - case 'info': - this.logdata.push(`[INFO] ${parsedMessage}`); - if (this.debug) { - console.info(`[INFO] ${parsedMessage}`); - } - break; - default: - this.logdata.push(`[LOG] ${parsedMessage}`); - if (this.debug) { - console.log(`[LOG] ${parsedMessage}`); - } - } - if (this.logdata.length > this.max_log_lines) { - this.logdata.shift(); - } - } - - async doLogin(nickname, socket) { - if (await this.scanSocketForKLine(socket)) { - return; // If the socket is K-lined, exit early - } - this.addUserUniqueId(nickname, socket.uniqueId); - this.hostnames.set(nickname, socket.host); - this.realhosts.set(nickname, socket.realhost); - await this.safeWriteToSocket(socket, `:${this.servername} PRIVMSG ${socket.nickname} :\x01VERSION\x01\r\n`); - let waited = 0; - while (socket.client_version === '' && waited < 3000) { - await new Promise(res => setTimeout(res, 100)); - waited += 100; - } - const output_lines = []; - 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} 002 ${nickname} :Your host is ${this.servername}, running version zefIRCd v${this.version}\r\n`); - output_lines.push(`:${this.servername} 003 ${nickname} :This server is ready to accept commands\r\n`); - // Sort supported_channel_modes and supported_user_modes alphabetically with capitals first - function sortModesAlphaCapsFirst(modes) { - // Remove commas, split to chars, sort, then re-insert commas if needed - // If input is comma-separated groups, sort each group - return modes - .split(',') - .map(group => { - return group - .split('') - .sort((a, b) => { - // Capital letters first, then lowercase, then numbers/symbols - if (a === b) return 0; - const isACap = a >= 'A' && a <= 'Z'; - const isBCap = b >= 'A' && b <= 'Z'; - const isALower = a >= 'a' && a <= 'z'; - const isBLower = b >= 'a' && b <= 'z'; - if (isACap && !isBCap) return -1; - if (!isACap && isBCap) return 1; - if (isALower && !isBLower) return -1; - if (!isALower && isBLower) return 1; - return a.localeCompare(b); - }) - .join(''); - }) - .join(','); - } - const channelModesParts = this.supported_channel_modes.split(','); - let sortedModesWithParams; - if (channelModesParts.length > 1) { - let modesToSort = channelModesParts.slice(0, -1).join('').split(''); - modesToSort.push(...this.supported_prefixes[0].split('')); - modesToSort = Array.from(new Set(modesToSort)); // remove duplicates - modesToSort.sort(); - sortedModesWithParams = modesToSort.join(''); - } - const channelModes = this.supported_channel_modes.split(',').join('') + this.supported_prefixes[0]; - const sortedChannelModes = sortModesAlphaCapsFirst(channelModes).replace(/,/g, ''); - const sortedUserModes = sortModesAlphaCapsFirst(this.supported_user_modes); - output_lines.push(`:${this.servername} 004 ${nickname} ${this.servername} zefIRCd-${this.version} ${sortedUserModes} ${sortedChannelModes} ${sortedModesWithParams}\r\n`); - for (const caps of this.caps) { - output_lines.push(`:${this.servername} 005 ${caps}\r\n`); - } - socket.registered = true; - output_lines.push(`:${this.servername} 042 ${nickname} ${socket.uniqueId} :your unique ID\r\n`); - - output_lines.push(...(await this.doMOTD(nickname))); - - const visibleClients = Array.from(this.nicknames.values()).filter(nick => { - const modes = this.usermodes.get(nick) || []; - return !modes.includes('i'); - }); - const invisibleClients = Array.from(this.nicknames.values()).filter(nick => { - const modes = this.usermodes.get(nick) || []; - return modes.includes('i'); - }); - const operClients = Array.from(this.nicknames.values()).filter(nick => { - const modes = this.usermodes.get(nick) || []; - return modes.includes('o'); - }); - const serverCount = this.servers.size + 1; // Include this server - output_lines.push(`:${this.servername} 251 ${nickname} :There are ${visibleClients.length} visible users and ${invisibleClients.length} invisible users on this server\r\n`); - if (operClients.length > 0) { - output_lines.push(`:${this.servername} 252 ${nickname} ${operClients.length} :operator(s) online\r\n`); - } - if (this.channelData.size > 0) { - output_lines.push(`:${this.servername} 253 ${nickname} ${this.channelData.size} :channels formed\r\n`); - } - output_lines.push(`:${this.servername} 255 ${nickname} :I have ${this.clients.length} clients and ${serverCount} servers\r\n`); - output_lines.push(`:${this.servername} 265 ${nickname} :Current Local Users: ${this.clients.length} Max: ${this.clientpeak}\r\n`); - const globalUsers = this.countGlobalUsers(); - this.globalpeak = Math.max(this.globalpeak, this.countGlobalUsers()); - const totalSockets = this.clients.length + this.servers.size; - 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} 250 ${nickname} :Highest connection count: ${this.socketpeak} (${this.clientpeak} clients) (${this.totalConnections} connections received)\r\n`); - let usermodes = this.usermodes.get(nickname); - if (!usermodes || usermodes === true) { - usermodes = []; - } - for (const mode of this.default_user_modes) { - if (!usermodes.includes(mode)) { - usermodes.push(mode); - } - } - if (socket.secure) { - usermodes.push('z'); - } - this.usermodes.set(nickname, [...usermodes]); - if (usermodes.includes('x')) { - socket.host = this.filterHostname(socket, socket.realhost); - if (socket.client_caps && socket.client_caps.includes('CHGHOST')) { - output_lines.push(`:${socket.nickname}!${socket.username}@${socket.host} CHGHOST ${socket.username} ${socket.host}\r\n`); - } - output_lines.push(`:${this.servername} 396 ${socket.nickname} ${socket.host} :is now your visible host\r\n`); - } - output_lines.push(`:${this.servername} 221 ${nickname} :+${this.usermodes.get(nickname).join('')}\r\n`); - await this.sendThrottled(socket, output_lines); - for (const [srvSocket, serverName] of this.servers.entries()) { - if (srvSocket) { - // Compose UID message for this client - const nickname = socket.nickname; - const username = socket.username || this.usernames.get(socket.nickname) || socket.nickname; - const uniqueId = socket.uniqueId; - const signonTime = socket.timestamp || this.getDate(); - const userModes = (this.usermodes.get(nickname) || []).join(''); - const userinfo = socket.userinfo || ''; - await this.safeWriteToSocket(srvSocket, `:${this.serverId} UID ${nickname} 1 ${signonTime} +${userModes} ${username} ${socket.host} ${socket.realhost} ${socket.remoteAddress} ${uniqueId} * ${nickname} :${userinfo}\r\n`); - } - } - await this.broadcastConnection(socket); - } -} - -module.exports = WTVIRC; \ No newline at end of file diff --git a/zefie_wtvp_minisrv/includes/classes/WTVMail.js b/zefie_wtvp_minisrv/includes/classes/WTVMail.js index 1e55bb8b..0ee95438 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVMail.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVMail.js @@ -119,7 +119,7 @@ class WTVMail { getMailboxByName(mailbox_name) { let mailbox_id = false; this.mailboxes.every(function (v, k) { - if (v.toLowerCase() == mailbox_name.toLowerCase()) { + if (v.toLowerCase() === mailbox_name.toLowerCase()) { mailbox_id = k; return false; } @@ -238,7 +238,7 @@ class WTVMail { subj = header[1]; break; } - } else if (line == '') end_of_headers = true; + } else if (line === '') end_of_headers = true; else { msg += line.replace(/\$\{(\w{1,})\}/g, function (x) { let out = ''; @@ -327,7 +327,7 @@ class WTVMail { if (v.name.slice((v.name.length - self.msgFileExt.length)) === self.msgFileExt) return v.name.slice(0, (v.name.length - 5)); }); - if (files.length == 0) return false; // no messages + if (files.length === 0) return false; // no messages else { // todo filter previous results when offset const messagelist_out = new Array(); @@ -388,7 +388,7 @@ class WTVMail { const temp_session_data_file = self.fs.readFileSync(search_dir + self.path.sep + file, 'Utf8'); const temp_session_data = JSON.parse(temp_session_data_file); if (temp_session_data.subscriber_username) { - if (temp_session_data.subscriber_username.toLowerCase() == username.toLowerCase()) { + if (temp_session_data.subscriber_username.toLowerCase() === username.toLowerCase()) { // Use the absolute path for replacement since search_dir is now absolute const accounts_dir = self.wtvshared.getAbsolutePath(self.minisrv_config.config.SessionStore + self.path.sep + "accounts" + self.path.sep); let path_after_replace = search_dir.replace(accounts_dir, ''); @@ -505,7 +505,7 @@ class WTVMail { const mailbox_name = this.getMessageMailboxName(messageid); if (!mailbox_name) return false; - const mailboxid = this.mailboxes.findIndex((value) => value == mailbox_name); + const mailboxid = this.mailboxes.findIndex((value) => value === mailbox_name); if (mailboxid !== false) return this.getMessage(mailboxid, messageid); return null; @@ -515,7 +515,7 @@ class WTVMail { // returns true if successful, false if failed. const currentMailbox = this.getMessageMailboxID(messageid); // Same mailbox - if (dest_mailbox_id == currentMailbox) return false; + if (dest_mailbox_id === currentMailbox) return false; // Invalid destination mailbox ID if (dest_mailbox_id > (this.mailboxes.length - 1) || dest_mailbox_id < 0) return false; @@ -540,7 +540,7 @@ class WTVMail { deleteMessage(messageid) { const currentMailbox = this.getMessageMailboxName(messageid); const trashMailbox = this.getMailboxByName(this.trashMailboxName); - if (currentMailbox != trashMailbox) { + if (currentMailbox !== trashMailbox) { // if not in the trash, move it to trash return this.moveMailMessage(messageid, trashMailbox); } else { diff --git a/zefie_wtvp_minisrv/includes/classes/WTVMime.js b/zefie_wtvp_minisrv/includes/classes/WTVMime.js index da54b4d9..647e674f 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVMime.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVMime.js @@ -35,7 +35,7 @@ class WTVMime { if (ssid_session) { // if gzip is enabled... if (this.minisrv_config.config.enable_gzip_compression || this.minisrv_config.config.force_compression_type) { - const is_bf0app = ssid_session.get("wtv-client-rom-type") == "bf0app"; + const is_bf0app = ssid_session.get("wtv-client-rom-type") === "bf0app"; const isOldBuild = this.wtvshared.isOldBuild(ssid_session); let is_softmodem = false; if (ssid_session.get("wtv-client-rom-type")) is_softmodem = ssid_session.get("wtv-client-rom-type").match(/softmodem/); @@ -52,23 +52,23 @@ class WTVMime { // mostly for debugging - if (this.minisrv_config.config.force_compression_type == "lzpf") compression_type = 1; - if (this.minisrv_config.config.force_compression_type == "gzip") compression_type = 2; + if (this.minisrv_config.config.force_compression_type === "lzpf") compression_type = 1; + if (this.minisrv_config.config.force_compression_type === "gzip") compression_type = 2; // do not compress if already encoded if (headers_obj["Content-Encoding"]) return 0; // should we bother to compress? 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"]; if (content_type) { // both lzpf and gzip - if (content_type.match(/^text\//) && content_type != "text/tellyscript") compress_data = true; + if (content_type.match(/^text\//) && content_type !== "text/tellyscript") compress_data = true; else if (content_type.match(/^application\/(x-?)javascript$/)) compress_data = true; - else if (content_type == "application/json") compress_data = true; - if (compression_type == 2) { + else if (content_type === "application/json") compress_data = true; + if (compression_type === 2) { // gzip only if (content_type.match(/^audio\/(x-)?(s3m|mod|xm|midi|wav|wave|aif(f)?)$/)) compress_data = true; // s3m, mod, xm, midi & wav if (content_type.match(/^application\/karaoke$/)) compress_data = true; // midi karaoke diff --git a/zefie_wtvp_minisrv/includes/classes/WTVNews.js b/zefie_wtvp_minisrv/includes/classes/WTVNews.js index ac2f9878..e5603210 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVNews.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVNews.js @@ -37,13 +37,13 @@ class WTVNews { connectUsenet() { return new Promise((resolve, reject) => { this.client.connect().then((response) => { - if (response.code == 200 || response.code == 201) { - if (response.code == 201) this.posting_allowed = false; + if (response.code === 200 || response.code === 201) { + if (response.code === 201) this.posting_allowed = false; if (this.username && this.password) { this.client.authInfoUser(this.username).then((res) => { - if (res.code == "381") { + if (res.code === 381) { res.authInfoPass(this.password).then((res) => { - if (res.code == 281) resolve(true); + if (res.code === 281) resolve(true); else reject(res.description); }).catch((e) => { console.error(" * WTVNews Error:", "Command: connect", e); @@ -124,7 +124,7 @@ class WTVNews { selectGroup(group) { return new Promise((resolve, reject) => { this.client.group(group).then((response) => { - if (response.code == 211) resolve(response); + if (response.code === 211) resolve(response); else reject(`No such group ${group}`); }).catch((e) => { console.error(" * WTVNews Error:", "Command: selectGroup", e); @@ -241,7 +241,7 @@ class WTVNews { let response; if (message.article.headers) { Object.keys(message.article.headers).forEach((k) => { - if (k.toLowerCase() == header.toLowerCase()) { + if (k.toLowerCase() === header.toLowerCase()) { response = message.article.headers[k]; return false; } @@ -253,7 +253,7 @@ class WTVNews { quitUsenet() { return new Promise((resolve, reject) => { this.client.quit().then((response) => { - if (response.code == 205) resolve(true); + if (response.code === 205) resolve(true); else { console.error(" * WTVNews Error:", "Command: quit", response.code); reject(`Unexpected response code ${response.code}`); @@ -290,7 +290,7 @@ class WTVNews { Promise.all(promises).then(() => { this.client.post() .then((response) => { - if (response.code == 340) { + if (response.code === 340) { const articleData = {}; articleData.headers = { 'Relay-Version': "version zefie_wtvp_minisrv " + this.minisrv_config.version + "; site " + this.minisrv_config.config.domain_name, @@ -356,7 +356,7 @@ class WTVNews { const messages = []; const promises = []; for (const article in NGArticles) { - if (article == "getCaseInsensitiveKey" || isNaN(article)) continue; + if (article === "getCaseInsensitiveKey" || isNaN(article)) continue; promises.push(new Promise((resolve, reject) => { this.getHeader(NGArticles[article]).then((data) => { if (data.article) messages.push(data.article) @@ -419,7 +419,7 @@ class WTVNews { section_match = line.match(/^Content-Transfer-Encoding: (.+)/i) if (section_match) attachments[i].content_encoding = section_match[1]; } else { - if (section_type != null) { + if (section_type !== null) { if (section_type.match("text/plain")) message_body += line; else { if (attachments[i].data) attachments[i].data += line; @@ -459,7 +459,7 @@ class WTVNews { const messageId = messages[k].messageId; const ref = messages[k].headers.REFERENCES; if (ref) { - const res = message_id_roots.find(e => e.messageId == ref); + const res = message_id_roots.find(e => e.messageId === ref); if (res) { // see if its attached to a root post if (message_relations[res.messageId]) message_relations[res.messageId].push({ "messageId": messageId, "index": k }); @@ -473,11 +473,11 @@ class WTVNews { if (message_relations[j].length > 0) { Object.keys(message_relations[j]).forEach((h) => { if (found) return; - if (message_relations[j][h].messageId == ref) { + if (message_relations[j][h].messageId === ref) { let searchref = messages[message_relations[j][h].index].headers.REFERENCES || null; let mainref = j; // j is already the main reference messageId while (searchref !== null) { - const searchart = messages.find(e => e.messageId == searchref); + const searchart = messages.find(e => e.messageId === searchref); if (searchart) { mainref = searchart.messageId; searchref = searchart.headers.REFERENCES || null; @@ -495,7 +495,7 @@ class WTVNews { // If not found in relations, add as root (but check for duplicates first) if (!found) { - const existingRoot = message_id_roots.find(e => e.messageId == messageId); + const existingRoot = message_id_roots.find(e => e.messageId === messageId); if (!existingRoot) { message_id_roots.push({ "messageId": messageId, "index": k }); } @@ -504,7 +504,7 @@ class WTVNews { } else { // Check for duplicates before adding as root - const existingRoot = message_id_roots.find(e => e.messageId == messageId); + const existingRoot = message_id_roots.find(e => e.messageId === messageId); if (!existingRoot) { message_id_roots.push({ "messageId": messageId, "index": k }); } diff --git a/zefie_wtvp_minisrv/includes/classes/WTVNewsServer.js b/zefie_wtvp_minisrv/includes/classes/WTVNewsServer.js index 103ac219..0e80378e 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVNewsServer.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVNewsServer.js @@ -40,7 +40,7 @@ class WTVNewsServer { ...nntp_server.prototype, _authenticate: function (session) { // authenticate - if (session.authinfo_user == self.username && session.authinfo_pass == self.password) { + if (session.authinfo_user === self.username && session.authinfo_pass === self.password) { session.posting_allowed = true; return Promise.resolve(true); } @@ -157,7 +157,7 @@ class WTVNewsServer { getHeader(message, header) { if (message.headers) { - const 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]; } return null; @@ -199,7 +199,7 @@ class WTVNewsServer { let response; if (headers) { Object.keys(headers).forEach((k) => { - if (k.toLowerCase() == header.toLowerCase()) { + if (k.toLowerCase() === header.toLowerCase()) { response = k; return false; } @@ -315,10 +315,10 @@ class WTVNewsServer { } } else out = { ...meta } - if (meta.min_index == 0) force_update = true; + if (meta.min_index === 0) force_update = true; if (this.featuredGroups) { Object.keys(this.featuredGroups).forEach((k) => { - if (group == this.featuredGroups[k].name) { + if (group === this.featuredGroups[k].name) { out.wildmat = 'y'; out.description = this.featuredGroups[k].description return false; @@ -329,9 +329,9 @@ class WTVNewsServer { if (force_update || this.doesMetaNeedRefreshing(meta)) { out.total = 0; this.fs.readdirSync(g).forEach(file => { - if (file == "meta.json") return; + if (file === "meta.json") return; 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.max_index) out.max_index = articleNumber; @@ -371,18 +371,18 @@ class WTVNewsServer { try { const articleNumbers = []; this.fs.readdirSync(g).forEach(file => { - if (file == "meta.json") return; + if (file === "meta.json") return; const articleNumber = parseInt(file.split('.')[0]); articleNumbers.push(articleNumber); }); articleNumbers.sort((a, b) => a - b) - const index = articleNumbers.findIndex((e) => e == current) - 1; + const index = articleNumbers.findIndex((e) => e === current) - 1; if (index >= 0) res = articleNumbers[index]; } catch (e) { return e; } if (res) { - if (res == current) return null; + if (res === current) return null; const message = this.getArticle(group, res); if (message.messageId) { res = { "articleNumber": res, "message_id": message.messageId }; @@ -397,12 +397,12 @@ class WTVNewsServer { try { const articleNumbers = []; this.fs.readdirSync(g).forEach(file => { - if (file == "meta.json") return; + if (file === "meta.json") return; const articleNumber = parseInt(file.split('.')[0]); articleNumbers.push(articleNumber); }); articleNumbers.sort((a, b) => a - b) - const index = articleNumbers.findIndex((e) => e == current) + 1; + const index = articleNumbers.findIndex((e) => e === current) + 1; if (index < articleNumbers.length) res = articleNumbers[index]; } catch (e) { return e; @@ -444,11 +444,11 @@ class WTVNewsServer { try { meta = this.getMetadata(group); this.fs.readdirSync(g).forEach(file => { - if (file == "meta.json") return; + if (file === "meta.json") return; const articleNumber = parseInt(file.split('.')[0]); if (articleNumber < start) return; 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; if (articleNumber > out.max_index) out.max_index = articleNumber; diff --git a/zefie_wtvp_minisrv/includes/classes/WTVRegister.js b/zefie_wtvp_minisrv/includes/classes/WTVRegister.js index 582f6b1d..edea5fce 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVRegister.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVRegister.js @@ -16,7 +16,7 @@ class WTVRegister { } getServiceOperator(first_letter_lower = false) { - if (this.service_owner == "a minisrv user") { + if (this.service_owner === "a minisrv user") { if (first_letter_lower) return "the operator of this service"; else return "The operator of this service"; } else { @@ -45,7 +45,7 @@ class WTVRegister { let available = true; if (this.fs.existsSync(directory)) { this.fs.readdirSync(directory).forEach(file => { - if (file.toLowerCase() == ssid.toLowerCase()) { + if (file.toLowerCase() === ssid.toLowerCase()) { available = false; return false; } @@ -97,7 +97,7 @@ class WTVRegister { const temp_session_data_file = self.fs.readFileSync(directory + self.path.sep + file, 'Utf8'); const temp_session_data = JSON.parse(temp_session_data_file); 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; } } diff --git a/zefie_wtvp_minisrv/includes/classes/WTVShared.js b/zefie_wtvp_minisrv/includes/classes/WTVShared.js index 710c7d42..f2c27c21 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVShared.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVShared.js @@ -205,7 +205,7 @@ class WTVShared { * @return {boolean} true if the SSID is valid, false if not */ checkSSID(ssid) { - if (ssid.slice(-2) == this.getSSIDCRC(ssid)) + if (ssid.slice(-2) === this.getSSIDCRC(ssid)) return true; return false; } @@ -412,8 +412,8 @@ class WTVShared { exclusiveFilter: (frame) => { let allowed = true; Object.keys(frame.attribs).forEach((k) => { - if (k == "href" || k == "background" || k == "src") { - allowed = false; + if (k === "href" || k === "background" || k === "src") { + allowed = false; const value = frame.attribs[k]; if (frame.tag !== "a") { @@ -1043,7 +1043,7 @@ class WTVShared { new_obj = this.cloneObj(obj) new_obj["wtv-client-serial-number"] = this.censorSSID(new_obj["wtv-client-serial-number"]); } - return (new_obj != false) ? new_obj : obj; + return (new_obj !== false) ? new_obj : obj; } } return obj; @@ -1127,14 +1127,14 @@ class WTVShared { */ getAbsolutePath(path = '', directory = '.') { // Check if directory is already an absolute path - if (directory.length > 0 && (directory[0] == "/" || (directory.length >= 3 && directory[1] === ':' && directory[2] === this.path.sep))) { + if (directory.length > 0 && (directory[0] === "/" || (directory.length >= 3 && directory[1] === ':' && directory[2] === this.path.sep))) { return this.path.resolve(directory + this.path.sep + path); } try { // start with our absolute path (of app.js) const appdir = this.path.resolve(__dirname + this.path.sep + '..' + this.path.sep + '..') - if (path == '' && directory == '.') { + if (path === '' && directory === '.') { return appdir; } // If the directory is a valid directory, prepend it to the path @@ -1252,7 +1252,7 @@ class WTVShared { if (overrides.exceptions) { Object.keys(overrides.exceptions).forEach((j) => { - if (k != overrides.exceptions[j]) out += self.minisrv_config.services[k].toString(overrides) + "\n"; + if (k !== overrides.exceptions[j]) out += self.minisrv_config.services[k].toString(overrides) + "\n"; }); } else { out += self.minisrv_config.services[k].toString(overrides) + "\n"; diff --git a/zefie_wtvp_minisrv/includes/classes/WTVShenanigans.js b/zefie_wtvp_minisrv/includes/classes/WTVShenanigans.js index d9a6cb65..b89bcd86 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVShenanigans.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVShenanigans.js @@ -41,7 +41,7 @@ class WTVShenanigans { // shenanigans are enabled, so check if the requested shenanigan is within the level enabled Object.keys(shenanigans).forEach((k) => { - if (shenanigans[k] == value) { + if (shenanigans[k] === value) { if (level >= shenanigans[k]) { retval = true; return false; diff --git a/zefie_wtvp_minisrv/includes/config.json b/zefie_wtvp_minisrv/includes/config.json index d64fdc7f..1fea4389 100644 --- a/zefie_wtvp_minisrv/includes/config.json +++ b/zefie_wtvp_minisrv/includes/config.json @@ -61,56 +61,6 @@ "filestore_storage": 16, // Megabytes "scrapbook_storage": 8 // Megabytes }, - "irc": { - "enabled": false, - "port": 1667, - "oper_username": "minisrv", - "oper_password": "changeme573", - "oper_enabled": false, // Don't enable with default credentials! - "channel_limit": 10, - "enable_ssl": true, - "ssl_cert": { - /* self-signed, can be replaced with another cert */ - "cert": "%ServiceDeps%/irc/selfsigned_cert.pem", - "key": "%ServiceDeps%/irc/selfsigned_key.pem" - }, - "channels": [ - { - "name": "#general", - "modes": ["n","t"], - "topic": "General Chat Channel", - "intro": [ - "Welcome to the general chat channel!" - ], - "ops": [ - "*!*@127.0.0.1" - ] - }, - { - "name": "#WebTV", - "modes": ["n", "t", "c", "C", "T"], - "topic": "Welcome to the WebTV channel", - "intro": [ - "Welcome to the WebTV channel!" - ], - "ops": [ - "*!*@127.0.0.1" - ] - }, - { - "name": "#secure", - "modes": ["n", "t", "S", "Z"], - "topic": "SSL only chat", - "intro": [ - "Welcome to zefie's secure hangout", - "Here, all traffic is SSL encrypted." - ], - "ops": [ - "*!*@127.0.0.1" - ] - } - ] - }, "pc_admin": { "enabled": false, "ip_whitelist": [ diff --git a/zefie_wtvp_minisrv/irconly.js b/zefie_wtvp_minisrv/irconly.js deleted file mode 100644 index 3d4a6a38..00000000 --- a/zefie_wtvp_minisrv/irconly.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; -const path = require('path'); -const classPath = path.resolve(__dirname + path.sep + "includes" + path.sep + "classes" + path.sep) + path.sep; -require(classPath + "Prototypes.js"); -const WTVIRC = require(classPath + "WTVIRC.js"); -const { WTVShared, clientShowAlert } = require(classPath + "WTVShared.js"); -const wtvshared = new WTVShared(); // creates minisrv_config - -const minisrv_config = wtvshared.readMiniSrvConfig(true, false, true); -minisrv_config.version = require('./package.json').version; -const ircServer = new WTVIRC(minisrv_config, '0.0.0.0', minisrv_config.config.irc.port, true); -ircServer.start(); \ No newline at end of file diff --git a/zefie_wtvp_minisrv/packer.js b/zefie_wtvp_minisrv/packer.js index ec4bf335..fdab7e8f 100644 --- a/zefie_wtvp_minisrv/packer.js +++ b/zefie_wtvp_minisrv/packer.js @@ -14,7 +14,7 @@ if (process.argv) { if (process.argv[2]) { let reverse = false; let file = process.argv[2]; - if (file == "-d") { + if (file === "-d") { file = process.argv[3]; reverse = true; } diff --git a/zefie_wtvp_minisrv/sync_nntp.js b/zefie_wtvp_minisrv/sync_nntp.js index a1083f47..86bdd1b4 100644 --- a/zefie_wtvp_minisrv/sync_nntp.js +++ b/zefie_wtvp_minisrv/sync_nntp.js @@ -62,7 +62,7 @@ function deleteMissing(group, articles) { fs.readdirSync(g).forEach(file => { const articleNumber = parseInt(file.split('.')[0]); file = g + path.sep + file; - if (!articles.find(e => (e == articleNumber))) { + if (!articles.find(e => (e === articleNumber))) { console.log(" * ", group, "article", articleNumber, "deleted from upstream, removing locally") fs.rmSync(file); } @@ -96,7 +96,7 @@ wtvnews.connectUsenet().then((res) => { wtvnews.getArticle(article, false).then((message) => { res = wtvnewsserver.createArticle(group, article, message); if (res) { - if (res == "exists") { + if (res === "exists") { console.log(" * ", group, "article", article, "already exists") } else { console.log(" * Created", group, "article", article, res) diff --git a/zefie_wtvp_minisrv/test.js b/zefie_wtvp_minisrv/test.js index 6a7813e2..76702015 100644 --- a/zefie_wtvp_minisrv/test.js +++ b/zefie_wtvp_minisrv/test.js @@ -32,13 +32,15 @@ function checkScopeErrors(file) { const eslintConfig = { "parserOptions": { "ecmaVersion": 2022, - "sourceType": "module" + "sourceType": isServiceFile ? "script" : "module" }, "env": { "node": true, "es2022": true }, "rules": { + "eqeqeq": ["warn", "always"], + "no-eq-null": "warn", "no-redeclare": 2, "no-undef": 2, "no-use-before-define": ["error", {"variables": false, "functions": false, "classes": false}], @@ -192,6 +194,31 @@ function checkScopeErrors(file) { { "selector": "CallExpression[callee.type='MemberExpression'][callee.object.type='MemberExpression'][callee.object.property.name='session_data'][callee.property.name='hasCap']", "message": "session_data.hasCap() is deprecated. Use session_data.capabilities.get() instead." + }, + // Type coercion warnings + { + "selector": "BinaryExpression[operator='==='][left.type='Literal'][left.value=/^\\d+$/][left.typeof='number'][right.type='Identifier']", + "message": "Comparing string literal that looks like a number with a variable using strict equality. Consider parseInt() or ensure both operands are the same type." + }, + { + "selector": "BinaryExpression[operator='==='][left.type='Identifier'][right.type='Literal'][right.value=/^\\d+$/][right.typeof='number']", + "message": "Comparing variable with string literal that looks like a number using strict equality. Consider parseInt() or ensure both operands are the same type." + }, + { + "selector": "BinaryExpression[operator='==='][left.type='Literal'][left.typeof='string'][right.type='Literal'][right.typeof='number']", + "message": "Comparing string literal with number literal using strict equality. This will always be false." + }, + { + "selector": "BinaryExpression[operator='==='][left.type='Literal'][left.typeof='number'][right.type='Literal'][right.typeof='string']", + "message": "Comparing number literal with string literal using strict equality. This will always be false." + }, + { + "selector": "BinaryExpression[operator='!=='][left.type='Literal'][left.typeof='string'][right.type='Literal'][right.typeof='number']", + "message": "Comparing string literal with number literal using strict inequality. This will always be true." + }, + { + "selector": "BinaryExpression[operator='!=='][left.type='Literal'][left.typeof='number'][right.type='Literal'][right.typeof='string']", + "message": "Comparing number literal with string literal using strict inequality. This will always be true." } ] } @@ -294,8 +321,10 @@ function checkScopeErrors(file) { fs.writeFileSync(tempConfigPath, JSON.stringify(eslintConfig, null, 2)); // Use ESLint to check for scope-related errors with let/const - const eslintCmd = `npx eslint --no-eslintrc --config "${tempConfigPath}" --format compact "${file}"`; - + // Create a temporary .eslintignore file to exclude files or directories + const eslintIgnorePath = path.join(__dirname, '.eslintignore'); + const eslintCmd = `npx eslint --no-eslintrc --config "${tempConfigPath}" --ignore-path "${eslintIgnorePath}" --format compact "${file}"`; + exec(eslintCmd, (error, stdout, stderr) => { // Clean up temporary config file try {