diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index 7079473b..b853f425 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -123,7 +123,6 @@ var socket_sessions = new Array(); var ports = []; var pc_ports = []; - // add .reverse() feature to all JavaScript Strings in this application // works for service vault scripts too. if (!String.prototype.reverse) { diff --git a/zefie_wtvp_minisrv/includes/WTVShared.js b/zefie_wtvp_minisrv/includes/WTVShared.js index 7d8854e2..b7cf374c 100644 --- a/zefie_wtvp_minisrv/includes/WTVShared.js +++ b/zefie_wtvp_minisrv/includes/WTVShared.js @@ -14,13 +14,14 @@ class WTVShared { iconv = require('iconv-lite'); parentDirectory = process.cwd() extend = require('util')._extend; + debug = require('debug')('WTVShared') minisrv_config = []; constructor(minisrv_config, quiet = false) { if (minisrv_config == null) this.minisrv_config = this.readMiniSrvConfig(true, !quiet); else this.minisrv_config = minisrv_config; - + if (!String.prototype.reverse) { String.prototype.reverse = function () { var splitString = this.split(""); @@ -59,6 +60,72 @@ class WTVShared { return src; } + parseJSON(json) { + if (!json) return null; + if (typeof json !== 'string') json = json.toString(); + + // from https://github.com/getify/JSON.minify/blob/javascript/minify.json.js + var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g, + in_string = false, + in_multiline_comment = false, + in_singleline_comment = false, + tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc, + prevFrom + ; + + tokenizer.lastIndex = 0; + + while (tmp = tokenizer.exec(json)) { + lc = RegExp.leftContext; + rc = RegExp.rightContext; + if (!in_multiline_comment && !in_singleline_comment) { + tmp2 = lc.substring(from); + if (!in_string) { + tmp2 = tmp2.replace(/(\n|\r|\s)+/g, ""); + } + new_str[ns++] = tmp2; + } + prevFrom = from; + from = tokenizer.lastIndex; + + // found a " character, and we're not currently in + // a comment? check for previous `\` escaping immediately + // leftward adjacent to this match + if (tmp[0] == "\"" && !in_multiline_comment && !in_singleline_comment) { + // perform look-behind escaping match, but + // limit left-context matching to only go back + // to the position of the last token match + // + // see: https://github.com/getify/JSON.minify/issues/64 + tmp2 = lc.substring(prevFrom).match(/\\+$/); + + // start of string with ", or unescaped " character found to end string? + if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) { + in_string = !in_string; + } + from--; // include " character in next catch + rc = json.substring(from); + } + else if (tmp[0] == "/*" && !in_string && !in_multiline_comment && !in_singleline_comment) { + in_multiline_comment = true; + } + else if (tmp[0] == "*/" && !in_string && in_multiline_comment && !in_singleline_comment) { + in_multiline_comment = false; + } + else if (tmp[0] == "//" && !in_string && !in_multiline_comment && !in_singleline_comment) { + in_singleline_comment = true; + } + else if ((tmp[0] == "\n" || tmp[0] == "\r") && !in_string && !in_multiline_comment && in_singleline_comment) { + in_singleline_comment = false; + } + else if (!in_multiline_comment && !in_singleline_comment && !(/\n|\r|\s/.test(tmp[0]))) { + new_str[ns++] = tmp[0]; + } + } + new_str[ns++] = rc; + return JSON.parse(new_str.join("")); + } + isConfiguredService(service) { if (this.minisrv_config.services[service]) { if (!this.minisrv_config.services[service].disabled) return true; @@ -236,12 +303,12 @@ class WTVShared { getUserConfig() { try { var user_config_filename = this.getAbsolutePath("user_config.json", this.parentDirectory); + if (this.fs.lstatSync(user_config_filename)) { try { - var minisrv_user_config = JSON.parse(this.fs.readFileSync(user_config_filename)); + var minisrv_user_config = this.parseJSON(this.fs.readFileSync(user_config_filename)); } catch (e) { - console.error("ERROR: Could not read user_config.json", e); - var throw_me = true; + throw ("ERROR: Could not read user_config.json", e); } } else { var minisrv_user_config = {} @@ -288,7 +355,7 @@ class WTVShared { readMiniSrvConfig(user_config = true, notices = true, reload_notice = false) { if (notices || reload_notice) console.log(" *** Reading global configuration..."); try { - var minisrv_config = JSON.parse(this.fs.readFileSync(this.getAbsolutePath("config.json", __dirname))); + var minisrv_config = this.parseJSON(this.fs.readFileSync(this.getAbsolutePath("config.json", __dirname))); } catch (e) { throw ("ERROR: Could not read config.json", e); } diff --git a/zefie_wtvp_minisrv/includes/config.json b/zefie_wtvp_minisrv/includes/config.json index 05ef88bb..a525fcf5 100644 --- a/zefie_wtvp_minisrv/includes/config.json +++ b/zefie_wtvp_minisrv/includes/config.json @@ -1,48 +1,57 @@ { + /* + STOP! STOP! STOP! + Do NOT edit this file. Instead make a file called "user_config.json" in the same folder as "app.js" + With that, you can override anything defined here. You can copy this config as a template, but should + only leave in things you are actually overriding, in case a future feature update changes any defaults. + */ "config": { - "service_ip": "127.0.0.1", - "bind_ip": "0.0.0.0", + "service_ip": "127.0.0.1", // IP sent to the box (public IP for public service, LAN IP for local testing) + "bind_ip": "0.0.0.0", // IP on your machine to bind to (0.0.0.0 = All Interfaces/IPs) "ServiceVaults": [ + /* Service Vaults: See ServiceVault.md for more info */ "UserServiceVault", "ServiceVault" ], "ServiceTemplates": [ + /* Service Templates: Works like ServiceVaults. See ServiceVault.md for more info */ "UserTemplates", "ServiceDeps/templates" ], - "ServiceDeps": "ServiceDeps", - "SessionStore": "SessionStore", - "SharedROMCache": "SharedROMCache", - "enable_shared_romcache": true, - "service_owner": "a minisrv user", - "service_owner_account": "minisrvuser", - "service_owner_contact": "someone", - "service_owner_contact_method": "something", - "service_name": "WebTV", - "service_logo": "WebTVLogoJewel.gif", - "service_splash_logo": "file://ROM/images/SplashLogo1.gif", - "hide_ssid_in_logs": true, - "filter_passwords_in_logs": true, - "post_percentages": [ 0, 25, 50, 100 ], - "verbosity": 2, - "socket_timeout": 86400, - "post_data_socket_timeout": 30, - "error_log_file": "errors.log", - "catchall_file_name": "catchall.js", - "hide_incomplete_features": true, - "enable_lzpf_compression": true, - "enable_gzip_compression": true, - "show_detailed_splash": true, - "show_diskmap": false, - "unauthorized_url": "wtv-1800:/unauthorized?", - "enable_port_isolation": true, - "allow_guests": true, - "domain_name": "wtv.zefie.com", - "user_accounts": { - "max_users_per_account": 6, - "min_username_length": 5, - "max_username_length": 18, + "ServiceDeps": "ServiceDeps", // Where the Service Dependancies are. Best left unchanged. + "SessionStore": "SessionStore", // Where we store account (session) data. Best left unchanged. + "SharedROMCache": "SharedROMCache", // Shared ROMCache (wtv-service:/ROMCache/, where wtv-service is any configured service). Best left unchanged. + "enable_shared_romcache": true, // Disabling this will cause a lot of problems without manual intervention. Best left unchanged. + "service_owner": "a minisrv user", // Set this to your name or screenname + "service_owner_account": "minisrvuser", // Set this to your account name on your minisrv + "service_owner_contact": "someone", // Set this to your contact (eg email address, twitter handle, etc) + "service_owner_contact_method": "something", // Set this to the contact method (eg email, twitter, etc) + "service_name": "WebTV", // What you want your service to be called + "service_logo": "WebTVLogoJewel.gif", // The logo shown on most service pages and error alerts. Can be absolute path or the name of a file in the SharedROMCache. + "service_splash_logo": "file://ROM/images/SplashLogo1.gif", // The logo shown on the splash screen. Can be absolute path or the name of a file in the SharedROMCache. + "hide_ssid_in_logs": true, // Filter SSIDs with asterisks to prevent accidently leaking user SSIDs when debugging. + "filter_passwords_in_logs": true, // Filter passwords (form fields containing "pass") to prevent accidently leaking user passwords when debugging. + "post_percentages": [ 0, 25, 50, 100 ], // When recieving POST data from the client, we display the progress of the transfer in the console log if the verbosity is high enough. Here you can show more or less updates. + "verbosity": 2, // 0 thru 4, lowest is quietest, higher is more verbose. Best set to 4 if something is going wrong. + "socket_timeout": 86400, // How long after we last gotten a request from a client before we clean up its data. The client can always restore it with the ticket. + "post_data_socket_timeout": 30, // How long until we give up waiting for data from the client in a POST transfer. Too little and POSTs will fail when dialup retrains. Too much and the server may stall waiting. + "error_log_file": "errors.log", // Where to write errors to disk + "catchall_file_name": "catchall.js", // default catchall filename + "hide_incomplete_features": true, // this is barely used and being phase out. leave it unchanged. + "enable_lzpf_compression": true, // Toggle LZPF (old classic) compression. Best left unchanged. + "enable_gzip_compression": true, // Toggle GZIP (all other boxes) compression. Best left unchanged. + "show_detailed_splash": true, // Shows the service name, server version, and user connect speed on the splash page + "show_diskmap": false, // Useful for debugging custom Diskmaps + "unauthorized_url": "wtv-1800:/unauthorized?", // Where to send unauthorized users + "enable_port_isolation": true, // Only respond to services on their correct ports + "allow_guests": true, // Allow users to experience the server without registering + "domain_name": "wtv.zefie.com", // For usenet and future stuff, no need to change just yet + "user_accounts": { // user account settings + "max_users_per_account": 6, // Max total users (including primary) per account + "min_username_length": 5, // minimum username length + "max_username_length": 18, // maximum username length "reserved_names": [ + // reserved account names, users (nor admins) can register these "AccountDisabled", "Demo", "Flash", @@ -50,12 +59,14 @@ ] }, "passwords": { - "enabled": true, - "min_length": 5, - "max_length": 32, - "form_size": 16 + // password configuration + "enabled": true, // allow users to password protect their account + "min_length": 5, // minimum length of user passwords + "max_length": 32, // max length of user passwords + "form_size": 16 // width of the form on the password prompt screen }, "errorMessages": { + // define custom error messages here "400": "${service_name} ran into a technical problem. Please try again.", "401": "Authorization Required.", "403": "The publisher of that page has not authorized you to view it.", @@ -63,6 +74,7 @@ "500": "${service_name} ran into a technical problem. Please try again." }, "lockdownWhitelist": [ + // urls the client can access without being "logged in" "wtv-1800:/preregister", "wtv-head-waiter:/login", "wtv-head-waiter:/ValidateLogin", @@ -80,26 +92,33 @@ ] }, "services": { + // service definitions + "wtv-head-waiter": { + // wtv-head-waiter handles logins "port": 1601, "connections": 1 }, "wtv-tricks": { + // wtv-tricks "port": 1602, "flags": "0x00000004" }, "wtv-star": { + // wtv-star is used for custom logos and internally by WebTV clients for service outages "port": 1603, "flags": "0x00000007" }, "wtv-news": { + // Usenet "port": 1605, - "local_nntp_port": 57319, - "local_nntp_requires_auth": true, + "local_nntp_port": 57319, // Port for internal NNTP + "local_nntp_requires_auth": true, // Needs to be enabled for posting "modules": [ "WTVNews" ], "featuredGroups": [ + // groups featured on wtv-news:/lobby. These groups are automatically created if they do not exist. { "name": "WebTV", "group": "webtv.users", @@ -121,38 +140,44 @@ "description": "Explore the sounds of Beatnik with your WebTV" } ], - "groupMetaRefreshInterval": 86400 + "groupMetaRefreshInterval": 86400 // not yet used }, "wtv-register": { + // wtv-register "port": 1607, "privileged": true }, "wtv-log": { + // wtv-log "port": 1609, "connections": 1, - "write_logs_to_disk": false + "write_logs_to_disk": false // set this to true to save logs to the error_log_file set above }, "wtv-home": { + // wtv-home "port": 1612 }, "wtv-1800": { + // wtv-1800 "port": 1615, "connections": 1, "flags": "0x00000004", - "send_tellyscripts": false + "send_tellyscripts": true // Best left untouched }, "wtv-flashrom": { + // wtv-flashrom "port": 1618, "flags": "0x00000040", "debug": false, - "use_zefie_server": true, - "bf0app_default_rom": "content/artemis-webtv-000/build7377/internal-nondebug/bf0app-part000.rom", - "catchall_file_name": "content-serve.js" + "use_zefie_server": true, // access zefie's repository of flashroms, local roms will still be used if they exist. Best left unchanged. + "bf0app_default_rom": "content/artemis-webtv-000/build7377/internal-nondebug/bf0app-part000.rom", // Can change the default build for bf0app + "catchall_file_name": "content-serve.js" // catchall for ROM part files. Best left untouched }, "wtv-setup": { + // wtv-setup "port": 1613, "flags": "0x00000010", - "passport_service": "wtv-passport", + "passport_service": "wtv-passport", // for messenger "connections": 3, "privileged": true, "modules": [ @@ -161,18 +186,22 @@ ] }, "wtv-music": { + // wtv-music "port": 1656, "connections": 3 }, "wtv-cookie": { + // wtv-cookie (used for http(s) cookies) "port": 1619, "connections": 1 }, "wtv-chat": { + // wtv-chat (used for IRC) "port": 1630, "connections": 3 }, "wtv-disk": { + // wtv-disk (used for DiskMaps) "port": 1635, "connections": 3, "modules": [ @@ -180,6 +209,7 @@ ] }, "wtv-guide": { + // wtv-guide (not yet complete) "port": 1621, "connections": 3, "modules": [ @@ -187,6 +217,7 @@ ] }, "wtv-mail": { + // wtv-mail "port": 1608, "connections": 3, "modules": [ @@ -194,9 +225,11 @@ ] }, "wtv-passport": { + // wtv-password (for messenger) "port": 1654 }, "wtv-favorite": { + // wtv-favorite "port": 1611, "connections": 3, "enable_multi_query": true, @@ -204,44 +237,49 @@ "max_favorites_per_folder": 18 }, "wtv-admin": { + // wtv-admin "port": 1698, "enable_multi_query": true, "privileged": true, - "password": "viRak-7" + "password": "viRak-7" // change to something more unique }, "http": { + // http upstream "port": 1650, "connections": 3, - "use_external_proxy": false, - "external_proxy_is_socks": false, - "external_proxy_host": "127.0.0.1", - "external_proxy_port": 1080, + "use_external_proxy": false, // use an external proxy (WebONE or some other minifying proxy is recommended) + "external_proxy_is_socks": false, // use a socks proxy + "external_proxy_host": "127.0.0.1", // IP address or hostname of proxy + "external_proxy_port": 1080, // Port of proxy "flags": "0x00000001" }, "https": { "port": 1650, "connections": 3, - "use_external_proxy": false, - "external_proxy_is_socks": false, - "external_proxy_host": "127.0.0.1", - "external_proxy_port": 1080, + "use_external_proxy": false, // use an external proxy (WebONE or some other minifying proxy is recommended) + "external_proxy_is_socks": false, // use a socks proxy + "external_proxy_host": "127.0.0.1", // IP address or hostname of proxy + "external_proxy_port": 1080, // Port of proxy "flags": "0x00000001" }, "pc_services": { + // PC Services "port": 1699, - "pc_services": true, - "hide_minisrv_version": true, - "disabled": true, - "servicevault_dir": "http_pc", - "drop_connection_on_wrong_port": false, - "show_verbose_errors": false, + "pc_services": true, // defines service as a PC service + "hide_minisrv_version": true, // hide or show the minisrv version (eg like Apache version, can be hidden to hide known exploits for older version) + "disabled": true, // disabled by default, set disabled: false in user_config.json for this service to enable. + "servicevault_dir": "http_pc", // The service vault dir for the PC Services + "drop_connection_on_wrong_port": false, // If true, resets connection if the PC browser connects to a port that is not PC Services enabled + "show_verbose_errors": false, // extra debugging "privileged": true, - "allow_https": false, - "force_https": false + "allow_https": false, // for future use with LetsEncrypt + "force_https": false // for future use with LetsEncrypt } }, "favorites": { "folder_templates": { + // define user default favorites here + // If image is a URL, it should be an absolute path, or a file under wtv-favorite:/ "Recommended": [ { "title": "DuckDuckGo", diff --git a/zefie_wtvp_minisrv/user_config.example.json b/zefie_wtvp_minisrv/user_config.example.json index 57ba47d1..f36d2700 100644 --- a/zefie_wtvp_minisrv/user_config.example.json +++ b/zefie_wtvp_minisrv/user_config.example.json @@ -16,10 +16,14 @@ "/home/zefie/webtv/ServiceVault" ], "ssid_block_list": [ + // list of SSID's to block "8100000000000000", "8100000000000010" ], "ssid_ip_allow_list": { + // list of SSIDs to allow. Can be in the block list above. + // The IP the SSID is connecting from should be listed under + // the allowed SSID as per this example. Subnets allowed. "8100000000000000": [ "192.168.1.0/24", "127.0.0.1" @@ -57,11 +61,16 @@ "wtv-1800": { "send_tellyscripts": true, "send_tellyscript_ssid_whitelist": [ - "8100000000000000" + // send only these SSIDs a tellyscript + "8100000000000000", + "8120000000000000" ] }, "wtv-admin": { + // demonstrates an override "authorized_ssids": { + // uses the same format as the SSID whitelist above + // SSID match, IP match, AND password are all required to access wtv-admin service. "8100000000000000": [ "192.168.1.0/24", "127.0.0.1" @@ -70,33 +79,42 @@ "password": "my-secure-password" }, "wtv-log": { + // demonstrates an override "write_logs_to_disk": true }, "wtv-some-custom-service": { + // demonstrates adding a new service "port": 1609, "connections": 1 }, "wtv-tricks": { + // this example shows how to point to an external server + // untested "service_ip": "192.168.1.8", "port": 1702, "nobind": true }, "wtv-music": { - "disabled": true + "disabled": true // disable default service wtv-music }, "wtv-author": { "enable_multi_query": true }, "wtv-news": { "disabled": false, - "upstream_address": "192.168.11.8", - "upstream_port": 1699, + "upstream_address": "192.168.11.8", // upstream usenet service + "upstream_port": 1699, // upstream usenet service port "upstream_auth": { + // upstream usenet service auth (delete object and set to null (eg upstream_auth: null) to not use login "username": "myusername", "password": "mypassword" }, - "upstream_tls": true, + "upstream_tls": true, // upstream usenet is ssl (true/false) "local_auth": { + // manually define a username/password for the local built-in NNTP + // otherwise it will be randomly generated. This is useful if you + // want to access the built-in NNTP externally, such as in + // Mozilla Thunderbird "username": "mylocaluser", "password": "mylocalpass" }