From d3a0fb40f94c8cbb3b5bd1835afbf1af8a7275ab Mon Sep 17 00:00:00 2001 From: Nathan Byrd Date: Sun, 1 Oct 2023 21:09:14 +0000 Subject: [PATCH] Started on initial implementation --- core/dropfile.js | 59 +++++++++++++++++++++++++++++++---- core/predefined_mci.js | 9 ++++++ core/string_format.js | 12 +++++-- dropfile_formats/CALLINFO.BBS | 2 +- dropfile_formats/CHAIN.TXT | 2 +- dropfile_formats/DOOR.SYS | 6 ++-- dropfile_formats/DORINFO1.DEF | 2 +- dropfile_formats/TRIBBS.SYS | 18 +++++++++++ dropfile_formats/XTRN.DAT | 2 +- dropfile_formats/door32.sys | 11 +++++++ 10 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 dropfile_formats/TRIBBS.SYS create mode 100644 dropfile_formats/door32.sys diff --git a/core/dropfile.js b/core/dropfile.js index a9e55e1d..2bb51329 100644 --- a/core/dropfile.js +++ b/core/dropfile.js @@ -6,14 +6,19 @@ const Config = require('./config.js').get; const StatLog = require('./stat_log.js'); const UserProps = require('./user_property.js'); const SysProps = require('./system_property.js'); +const paths = require('path'); +const Log = require('./logger.js').log; +const getPredefinedMCIFormatObject = + require('./predefined_mci').getPredefinedMCIFormatObject; +const stringFormat = require('./string_format'); // deps const fs = require('graceful-fs'); -const paths = require('path'); const _ = require('lodash'); const moment = require('moment'); const iconv = require('iconv-lite'); const { mkdirs } = require('fs-extra'); +const { stripMciColorCodes } = require('./color_codes.js'); // // Resources @@ -32,6 +37,12 @@ module.exports = class DropFile { this.client = client; this.fileType = fileType.toUpperCase(); this.baseDir = baseDir; + + + this.dropFileFormatDirectory = paths.join( + __dirname, + 'dropfile_formats' + ); } static dropFileDirectory(baseDir, client) { @@ -60,6 +71,8 @@ module.exports = class DropFile { JUMPER: 'JUMPER.DAT', // 2AM BBS SXDOOR: 'SXDOOR.' + _.pad(this.client.node.toString(), 3, '0'), // System/X, dESiRE INFO: 'INFO.BBS', // Phoenix BBS + SOLARREALMS: 'DOORFILE.SR', + XTRN: 'XTRN.DAT', }[this.fileType]; } @@ -68,11 +81,24 @@ module.exports = class DropFile { } getHandler() { - return { - DOOR: this.getDoorSysBuffer, - DOOR32: this.getDoor32Buffer, - DORINFO: this.getDoorInfoDefBuffer, - }[this.fileType]; + // TODO: Replace with a switch statement once we have binary handlers as well + + // Read the directory containing the dropfile formats, and return undefined if we don't have the format + const fileName = this.fileName(); + if (!fileName) { + Log.info({fileType: this.fileType}, 'Dropfile format not supported.'); + return undefined; + } + const filePath = paths.join(this.dropFileFormatDirectory, fileName); + fs.access(filePath, fs.constants.R_OK, err => { + if (err) { + Log.info({filename: fileName}, 'Dropfile format not found.'); + return undefined; + } + }); + + // Return the handler to get the dropfile, because in the future we may have additional handlers + return this.getDropfile; } getContents() { @@ -80,6 +106,27 @@ module.exports = class DropFile { return handler(); } + getDropfile() { + // Get the filename to read + const fileName = paths.join(this.dropFileFormatDirectory, this.fileName()); + + // Read file, or return empty string if it doesn't exist + fs.readFile(fileName, (err, data) => { + if (err) { + Log.warn({filename: fileName}, 'Error reading dropfile format file.'); + return ''; + } + let text = data; + // Format the data with string_format and predefined_mci + const formatObj = getPredefinedMCIFormatObject(this.client, data); + if (formatObj) { + // Expand the text + text = stringFormat(text, formatObj, true); + } + return text; + }); + } + getDoorInfoFileName() { let x; const node = this.client.node; diff --git a/core/predefined_mci.js b/core/predefined_mci.js index 01d81d90..1018c890 100644 --- a/core/predefined_mci.js +++ b/core/predefined_mci.js @@ -124,6 +124,15 @@ const PREDEFINED_MCI_GENERATORS = { UN: function userName(client) { return client.user.username; }, + UZ: function sanitizedUserName(client) { + return client.user.getSanitizedName(); + }, + UM: function userComment(client) { + return userStatAsString(client, UserProps.UserComment, ''); + }, + LL: function legacyUserLevel(client) { + return client.user.getLegacySecurityLevel().toString(); + }, UI: function userId(client) { return client.user.userId.toString(); }, diff --git a/core/string_format.js b/core/string_format.js index 4f3f4ee9..ca653263 100644 --- a/core/string_format.js +++ b/core/string_format.js @@ -14,6 +14,8 @@ const { formatCountAbbr, } = require('./string_util.js'); +const colorCodes = require('./color_codes.js'); + // deps const _ = require('lodash'); const moment = require('moment'); @@ -210,7 +212,7 @@ function formatNumberHelper(n, precision, type) { function formatNumber(value, tokens) { const fill = tokens.fill || (tokens['0'] ? '0' : ' '); const align = tokens.align || (tokens['0'] ? '=' : '>'); - const width = Number(tokens.width); + const width = Number(tokens.width);value.replace(/\x1b\[[0-9;]*m/g, ''); const type = tokens.type || (tokens.precision ? 'g' : ''); if (['c', 'd', 'b', 'o', 'x', 'X'].indexOf(type) > -1) { @@ -299,6 +301,7 @@ const transformers = { styleSmallI: s => stylizeString(s, 'small i'), styleMixed: s => stylizeString(s, 'mixed'), styleL33t: s => stylizeString(s, 'l33t'), + sanitized: s => stylizeString(s, 'sanitized'), // :TODO: // toMegs(), toKilobytes(), ... @@ -337,7 +340,7 @@ function getValue(obj, path) { throw new KeyError(quote(path)); } -module.exports = function format(fmt, obj) { +module.exports = function format(fmt, obj, stripMciColorCodes = false) { const re = REGEXP_BASIC_FORMAT; re.lastIndex = 0; // reset from prev @@ -369,6 +372,11 @@ module.exports = function format(fmt, obj) { value = transformValue(transformer, value); } + // This is used in cases where the output shouldn't allow color codes + if (stripMciColorCodes) { + value = colorCodes.stripMciColorCodes(value); + } + tokens = tokenizeFormatSpec(formatSpec || ''); if (_.isNumber(value)) { diff --git a/dropfile_formats/CALLINFO.BBS b/dropfile_formats/CALLINFO.BBS index 6eee87cb..63f86e1c 100644 --- a/dropfile_formats/CALLINFO.BBS +++ b/dropfile_formats/CALLINFO.BBS @@ -1,7 +1,7 @@ %UR 4 %SL -1000 +%LL 999 COLOR NOTPROVIDED diff --git a/dropfile_formats/CHAIN.TXT b/dropfile_formats/CHAIN.TXT index a72e6009..efa73421 100644 --- a/dropfile_formats/CHAIN.TXT +++ b/dropfile_formats/CHAIN.TXT @@ -8,7 +8,7 @@ M %DT %SW %SH -1 +%LL 0 0 1 diff --git a/dropfile_formats/DOOR.SYS b/dropfile_formats/DOOR.SYS index 12b2553a..87feb1a1 100644 --- a/dropfile_formats/DOOR.SYS +++ b/dropfile_formats/DOOR.SYS @@ -12,7 +12,7 @@ N 555 555-5555 555 555-5555 NOT PROVIDED -1 +%LL %UC %DT 9999 @@ -33,7 +33,7 @@ Y C:\DATA C:\DATA %SR -%UN +%UZ %CT Y Y @@ -47,6 +47,6 @@ Y %DD 0 0 -A user +%UM %DR 32767 \ No newline at end of file diff --git a/dropfile_formats/DORINFO1.DEF b/dropfile_formats/DORINFO1.DEF index 5bc85aac..3d8049fd 100644 --- a/dropfile_formats/DORINFO1.DEF +++ b/dropfile_formats/DORINFO1.DEF @@ -8,6 +8,6 @@ UNKNOWN UNKNOWN %LO 1 -10 +%LL 999 -1 \ No newline at end of file diff --git a/dropfile_formats/TRIBBS.SYS b/dropfile_formats/TRIBBS.SYS new file mode 100644 index 00000000..344546ce --- /dev/null +++ b/dropfile_formats/TRIBBS.SYS @@ -0,0 +1,18 @@ +%UI +%UN +NOTPROVIDED +%LL +N +Y +999 +555-555-1212 +%LO +%BD +%ND +1 +19200 +0 +N +Y +%BN +%SR \ No newline at end of file diff --git a/dropfile_formats/XTRN.DAT b/dropfile_formats/XTRN.DAT index c3ec2611..bf96399b 100644 --- a/dropfile_formats/XTRN.DAT +++ b/dropfile_formats/XTRN.DAT @@ -10,7 +10,7 @@ C:\DATA Yes %SH 209087929 -1 +%LL 1 %BD M diff --git a/dropfile_formats/door32.sys b/dropfile_formats/door32.sys new file mode 100644 index 00000000..72f71022 --- /dev/null +++ b/dropfile_formats/door32.sys @@ -0,0 +1,11 @@ +1 +1 +19200 +%BN +%UI +%UR +%UN +1 +999 +1 +%ND \ No newline at end of file