WIP work on door fixes, updates, etc.
This commit is contained in:
parent
7bd980c886
commit
f08d6efb97
|
@ -2,16 +2,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const MenuModule = require('./menu_module.js').MenuModule;
|
const MenuModule = require('./menu_module.js').MenuModule;
|
||||||
const DropFile = require('./dropfile.js').DropFile;
|
const DropFile = require('./dropfile.js');
|
||||||
const door = require('./door.js');
|
const Door = require('./door.js');
|
||||||
const theme = require('./theme.js');
|
const theme = require('./theme.js');
|
||||||
const ansi = require('./ansi_term.js');
|
const ansi = require('./ansi_term.js');
|
||||||
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const paths = require('path');
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const mkdirs = require('fs-extra').mkdirs;
|
const getSockHandle = require('getsockethandleaddress'); // black magic
|
||||||
|
|
||||||
// :TODO: This should really be a system module... needs a little work to allow for such
|
// :TODO: This should really be a system module... needs a little work to allow for such
|
||||||
|
|
||||||
|
@ -122,19 +121,18 @@ exports.getModule = class AbracadabraModule extends MenuModule {
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
function prepareDoor(callback) {
|
||||||
|
self.doorInstance = new Door(self.client);
|
||||||
|
return self.doorInstance.prepare(self.config.io || 'stdio', callback);
|
||||||
|
},
|
||||||
function generateDropfile(callback) {
|
function generateDropfile(callback) {
|
||||||
self.dropFile = new DropFile(self.client, self.config.dropFileType);
|
const dropFileOpts = {
|
||||||
var fullPath = self.dropFile.fullPath;
|
fileType : self.config.dropFileType,
|
||||||
|
socketDescriptor : self.getSocketFd(),
|
||||||
|
};
|
||||||
|
|
||||||
mkdirs(paths.dirname(fullPath), function dirCreated(err) {
|
self.dropFile = new DropFile(self.client, dropFileOpts);
|
||||||
if(err) {
|
return self.dropFile.createFile(callback);
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
self.dropFile.createFile(function created(err) {
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
function complete(err) {
|
function complete(err) {
|
||||||
|
@ -150,7 +148,38 @@ exports.getModule = class AbracadabraModule extends MenuModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
runDoor() {
|
runDoor() {
|
||||||
|
this.client.term.write(ansi.resetScreen());
|
||||||
|
|
||||||
|
const exeInfo = {
|
||||||
|
cmd : this.config.cmd,
|
||||||
|
args : this.config.args,
|
||||||
|
io : this.config.io || 'stdio',
|
||||||
|
encoding : this.config.encoding || this.client.term.outputEncoding,
|
||||||
|
dropFile : this.dropFile.fileName,
|
||||||
|
dropFilePath : this.dropFile.fullPath,
|
||||||
|
node : this.client.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
if('socketfd' === this.config.io) {
|
||||||
|
exeInfo.srvSocketFd = this.getSocketFd();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.doorInstance.run(exeInfo, () => {
|
||||||
|
//
|
||||||
|
// Try to clean up various settings such as scroll regions that may
|
||||||
|
// have been set within the door
|
||||||
|
//
|
||||||
|
this.client.term.rawWrite(
|
||||||
|
ansi.normal() +
|
||||||
|
ansi.goto(this.client.term.termHeight, this.client.term.termWidth) +
|
||||||
|
ansi.setScrollRegion() +
|
||||||
|
ansi.goto(this.client.term.termHeight, 0) +
|
||||||
|
'\r\n\r\n'
|
||||||
|
);
|
||||||
|
|
||||||
|
this.prevMenu();
|
||||||
|
});
|
||||||
|
/*
|
||||||
const exeInfo = {
|
const exeInfo = {
|
||||||
cmd : this.config.cmd,
|
cmd : this.config.cmd,
|
||||||
args : this.config.args,
|
args : this.config.args,
|
||||||
|
@ -178,10 +207,11 @@ exports.getModule = class AbracadabraModule extends MenuModule {
|
||||||
|
|
||||||
this.prevMenu();
|
this.prevMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.term.write(ansi.resetScreen());
|
this.client.term.write(ansi.resetScreen());
|
||||||
|
|
||||||
doorInstance.run();
|
doorInstance.run();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
leave() {
|
leave() {
|
||||||
|
@ -194,4 +224,8 @@ exports.getModule = class AbracadabraModule extends MenuModule {
|
||||||
finishedLoading() {
|
finishedLoading() {
|
||||||
this.runDoor();
|
this.runDoor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSocketFd() {
|
||||||
|
return getSockHandle.getAddress(this.client.output._handle); // seriously... black magic :(
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
120
core/door.js
120
core/door.js
|
@ -1,17 +1,128 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
const stringFormat = require('./string_format.js');
|
const stringFormat = require('./string_format.js');
|
||||||
|
const { Errors } = require('./enig_error.js');
|
||||||
|
|
||||||
const events = require('events');
|
|
||||||
const _ = require('lodash');
|
|
||||||
const pty = require('node-pty');
|
const pty = require('node-pty');
|
||||||
const decode = require('iconv-lite').decode;
|
const decode = require('iconv-lite').decode;
|
||||||
const createServer = require('net').createServer;
|
const createServer = require('net').createServer;
|
||||||
|
|
||||||
exports.Door = Door;
|
module.exports = class Door {
|
||||||
|
constructor(client) {
|
||||||
|
this.client = client;
|
||||||
|
this.restored = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare(ioType, cb) {
|
||||||
|
this.io = ioType;
|
||||||
|
|
||||||
|
// we currently only have to do any real setup for 'socket'
|
||||||
|
if('socket' !== ioType) {
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sockServer = createServer(conn => {
|
||||||
|
this.sockServer.getConnections( (err, count) => {
|
||||||
|
|
||||||
|
// We expect only one connection from our DOOR/emulator/etc.
|
||||||
|
if(!this && count <= 1) {
|
||||||
|
this.client.term.output.pipe(conn);
|
||||||
|
|
||||||
|
conn.on('data', this.doorDataHandler.bind(this));
|
||||||
|
|
||||||
|
conn.once('end', () => {
|
||||||
|
return this.restoreIo(conn);
|
||||||
|
});
|
||||||
|
|
||||||
|
conn.once('error', err => {
|
||||||
|
this.client.log.info( { error : err.message }, 'Door socket server connection');
|
||||||
|
return this.restoreIo(conn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.sockServer.listen(0, () => {
|
||||||
|
return cb(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
run(exeInfo, cb) {
|
||||||
|
this.encoding = (exeInfo.encoding || 'cp437').toLowerCase();
|
||||||
|
|
||||||
|
if('socket' === this.io && !this.sockServer) {
|
||||||
|
return cb(Errors.UnexpectedState('Socket server is not running'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatObj = {
|
||||||
|
dropFile : exeInfo.dropFile,
|
||||||
|
dropFilePath : exeInfo.dropFilePath,
|
||||||
|
node : exeInfo.node.toString(),
|
||||||
|
srvPort : this.sockServer ? this.sockServer.address().port.toString() : '-1',
|
||||||
|
userId : this.client.user.userId.toString(),
|
||||||
|
srvSocketFd : exeInfo.srvSocketFd ? exeInfo.srvSocketFd.toString() : '-1',
|
||||||
|
};
|
||||||
|
|
||||||
|
const args = exeInfo.args.map( arg => stringFormat(arg, formatObj) );
|
||||||
|
|
||||||
|
const door = pty.spawn(exeInfo.cmd, args, {
|
||||||
|
cols : this.client.term.termWidth,
|
||||||
|
rows : this.client.term.termHeight,
|
||||||
|
// :TODO: cwd
|
||||||
|
env : exeInfo.env,
|
||||||
|
encoding : null, // we want to handle all encoding ourself
|
||||||
|
});
|
||||||
|
|
||||||
|
if('stdio' === this.io) {
|
||||||
|
this.client.log.debug('Using stdio for door I/O');
|
||||||
|
|
||||||
|
this.client.term.output.pipe(door);
|
||||||
|
|
||||||
|
door.on('data', this.doorDataHandler.bind(this));
|
||||||
|
|
||||||
|
door.once('close', () => {
|
||||||
|
return this.restoreIo(door);
|
||||||
|
});
|
||||||
|
} else if('socket' === this.io) {
|
||||||
|
this.client.log.debug(
|
||||||
|
{ srvPort : this.sockServer.address().port, srvSocketFd : this.sockServerSocket },
|
||||||
|
'Using temporary socket server for door I/O'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
door.once('exit', exitCode => {
|
||||||
|
this.client.log.info( { exitCode : exitCode }, 'Door exited');
|
||||||
|
|
||||||
|
if(this.sockServer) {
|
||||||
|
this.sockServer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we may not get a close
|
||||||
|
if('stdio' === this.io) {
|
||||||
|
this.restoreIo(door);
|
||||||
|
}
|
||||||
|
|
||||||
|
door.removeAllListeners();
|
||||||
|
|
||||||
|
return cb(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
doorDataHandler(data) {
|
||||||
|
this.client.term.write(decode(data, this.encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreIo(piped) {
|
||||||
|
if(!this.restored && this.client.term.output) {
|
||||||
|
this.client.term.output.unpipe(piped);
|
||||||
|
this.client.term.output.resume();
|
||||||
|
this.restored = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
function Door(client, exeInfo) {
|
function Door(client, exeInfo) {
|
||||||
events.EventEmitter.call(this);
|
events.EventEmitter.call(this);
|
||||||
|
|
||||||
|
@ -147,3 +258,4 @@ Door.prototype.run = function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
*/
|
201
core/dropfile.js
201
core/dropfile.js
|
@ -1,16 +1,15 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Config = require('./config.js').config;
|
const Config = require('./config.js').config;
|
||||||
const StatLog = require('./stat_log.js');
|
const StatLog = require('./stat_log.js');
|
||||||
|
|
||||||
var fs = require('graceful-fs');
|
const fs = require('graceful-fs');
|
||||||
var paths = require('path');
|
const paths = require('path');
|
||||||
var _ = require('lodash');
|
const _ = require('lodash');
|
||||||
var moment = require('moment');
|
const moment = require('moment');
|
||||||
var iconv = require('iconv-lite');
|
const iconv = require('iconv-lite');
|
||||||
|
const { mkdirs } = require('fs-extra');
|
||||||
exports.DropFile = DropFile;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Resources
|
// Resources
|
||||||
|
@ -20,53 +19,56 @@ exports.DropFile = DropFile;
|
||||||
// * http://thebbs.org/bbsfaq/ch06.02.htm
|
// * http://thebbs.org/bbsfaq/ch06.02.htm
|
||||||
|
|
||||||
// http://lord.lordlegacy.com/dosemu/
|
// http://lord.lordlegacy.com/dosemu/
|
||||||
|
module.exports = class DropFile {
|
||||||
|
constructor(client, { fileType = 'DORINFO', baseDir = Config.paths.dropFiles, socketDescriptor = null } = {} ) {
|
||||||
|
this.client = client;
|
||||||
|
this.fileType = fileType.toUpperCase();
|
||||||
|
this.baseDir = baseDir;
|
||||||
|
this.socketDescriptor = socketDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
function DropFile(client, fileType) {
|
get fullPath() {
|
||||||
|
return paths.join(this.baseDir, ('node' + this.client.node), this.fileName);
|
||||||
|
}
|
||||||
|
|
||||||
var self = this;
|
get fileName() {
|
||||||
this.client = client;
|
return {
|
||||||
this.fileType = (fileType || 'DORINFO').toUpperCase();
|
DOOR : 'DOOR.SYS', // GAP BBS, many others
|
||||||
|
DOOR32 : 'DOOR32.SYS', // EleBBS / Mystic, Syncronet, Maximus, Telegard, AdeptXBBS, ...
|
||||||
|
CALLINFO : 'CALLINFO.BBS', // Citadel?
|
||||||
|
DORINFO : this.getDoorInfoFileName(), // RBBS, RemoteAccess, QBBS, ...
|
||||||
|
CHAIN : 'CHAIN.TXT', // WWIV
|
||||||
|
CURRUSER : 'CURRUSER.BBS', // RyBBS
|
||||||
|
SFDOORS : 'SFDOORS.DAT', // Spitfire
|
||||||
|
PCBOARD : 'PCBOARD.SYS', // PCBoard
|
||||||
|
TRIBBS : 'TRIBBS.SYS', // TriBBS
|
||||||
|
USERINFO : 'USERINFO.DAT', // Wildcat! 3.0+
|
||||||
|
JUMPER : 'JUMPER.DAT', // 2AM BBS
|
||||||
|
SXDOOR : 'SXDOOR.' + _.pad(this.client.node.toString(), 3, '0'), // System/X, dESiRE
|
||||||
|
INFO : 'INFO.BBS', // Phoenix BBS
|
||||||
|
}[this.fileType];
|
||||||
|
}
|
||||||
|
|
||||||
Object.defineProperty(this, 'fullPath', {
|
isSupported() {
|
||||||
get : function() {
|
return this.getHandler() ? true : false;
|
||||||
return paths.join(Config.paths.dropFiles, ('node' + self.client.node), self.fileName);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'fileName', {
|
getHandler() {
|
||||||
get : function() {
|
return {
|
||||||
return {
|
DOOR : this.getDoorSysBuffer,
|
||||||
DOOR : 'DOOR.SYS', // GAP BBS, many others
|
DOOR32 : this.getDoor32Buffer,
|
||||||
DOOR32 : 'DOOR32.SYS', // EleBBS / Mystic, Syncronet, Maximus, Telegard, AdeptXBBS, ...
|
DORINFO : this.getDoorInfoDefBuffer,
|
||||||
CALLINFO : 'CALLINFO.BBS', // Citadel?
|
}[this.fileType];
|
||||||
DORINFO : self.getDoorInfoFileName(), // RBBS, RemoteAccess, QBBS, ...
|
}
|
||||||
CHAIN : 'CHAIN.TXT', // WWIV
|
|
||||||
CURRUSER : 'CURRUSER.BBS', // RyBBS
|
|
||||||
SFDOORS : 'SFDOORS.DAT', // Spitfire
|
|
||||||
PCBOARD : 'PCBOARD.SYS', // PCBoard
|
|
||||||
TRIBBS : 'TRIBBS.SYS', // TriBBS
|
|
||||||
USERINFO : 'USERINFO.DAT', // Wildcat! 3.0+
|
|
||||||
JUMPER : 'JUMPER.DAT', // 2AM BBS
|
|
||||||
SXDOOR : // System/X, dESiRE
|
|
||||||
'SXDOOR.' + _.pad(self.client.node.toString(), 3, '0'),
|
|
||||||
INFO : 'INFO.BBS', // Phoenix BBS
|
|
||||||
}[self.fileType];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'dropFileContents', {
|
getContents() {
|
||||||
get : function() {
|
const handler = this.getHandler().bind(this);
|
||||||
return {
|
return handler();
|
||||||
DOOR : self.getDoorSysBuffer(),
|
}
|
||||||
DOOR32 : self.getDoor32Buffer(),
|
|
||||||
DORINFO : self.getDoorInfoDefBuffer(),
|
|
||||||
}[self.fileType];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.getDoorInfoFileName = function() {
|
getDoorInfoFileName() {
|
||||||
var x;
|
let x;
|
||||||
var node = self.client.node;
|
const node = this.client.node;
|
||||||
if(10 === node) {
|
if(10 === node) {
|
||||||
x = 0;
|
x = 0;
|
||||||
} else if(node < 10) {
|
} else if(node < 10) {
|
||||||
|
@ -75,54 +77,53 @@ function DropFile(client, fileType) {
|
||||||
x = String.fromCharCode('a'.charCodeAt(0) + (node - 11));
|
x = String.fromCharCode('a'.charCodeAt(0) + (node - 11));
|
||||||
}
|
}
|
||||||
return 'DORINFO' + x + '.DEF';
|
return 'DORINFO' + x + '.DEF';
|
||||||
};
|
}
|
||||||
|
|
||||||
this.getDoorSysBuffer = function() {
|
getDoorSysBuffer() {
|
||||||
var up = self.client.user.properties;
|
const prop = this.client.user.properties;
|
||||||
var now = moment();
|
const now = moment();
|
||||||
var secLevel = self.client.user.getLegacySecurityLevel().toString();
|
const secLevel = this.client.user.getLegacySecurityLevel().toString();
|
||||||
|
|
||||||
// :TODO: fix time remaining
|
// :TODO: fix time remaining
|
||||||
// :TODO: fix default protocol -- user prop: transfer_protocol
|
// :TODO: fix default protocol -- user prop: transfer_protocol
|
||||||
|
|
||||||
return iconv.encode( [
|
return iconv.encode( [
|
||||||
'COM1:', // "Comm Port - COM0: = LOCAL MODE"
|
'COM1:', // "Comm Port - COM0: = LOCAL MODE"
|
||||||
'57600', // "Baud Rate - 300 to 38400" (Note: set as 57600 instead!)
|
'57600', // "Baud Rate - 300 to 38400" (Note: set as 57600 instead!)
|
||||||
'8', // "Parity - 7 or 8"
|
'8', // "Parity - 7 or 8"
|
||||||
self.client.node.toString(), // "Node Number - 1 to 99"
|
this.client.node.toString(), // "Node Number - 1 to 99"
|
||||||
'57600', // "DTE Rate. Actual BPS rate to use. (kg)"
|
'57600', // "DTE Rate. Actual BPS rate to use. (kg)"
|
||||||
'Y', // "Screen Display - Y=On N=Off (Default to Y)"
|
'Y', // "Screen Display - Y=On N=Off (Default to Y)"
|
||||||
'Y', // "Printer Toggle - Y=On N=Off (Default to Y)"
|
'Y', // "Printer Toggle - Y=On N=Off (Default to Y)"
|
||||||
'Y', // "Page Bell - Y=On N=Off (Default to Y)"
|
'Y', // "Page Bell - Y=On N=Off (Default to Y)"
|
||||||
'Y', // "Caller Alarm - Y=On N=Off (Default to Y)"
|
'Y', // "Caller Alarm - Y=On N=Off (Default to Y)"
|
||||||
up.real_name || self.client.user.username, // "User Full Name"
|
prop.real_name || this.client.user.username, // "User Full Name"
|
||||||
up.location || 'Anywhere', // "Calling From"
|
prop.location || 'Anywhere', // "Calling From"
|
||||||
'123-456-7890', // "Home Phone"
|
'123-456-7890', // "Home Phone"
|
||||||
'123-456-7890', // "Work/Data Phone"
|
'123-456-7890', // "Work/Data Phone"
|
||||||
'NOPE', // "Password" (Note: this is never given out or even stored plaintext)
|
'NOPE', // "Password" (Note: this is never given out or even stored plaintext)
|
||||||
secLevel, // "Security Level"
|
secLevel, // "Security Level"
|
||||||
up.login_count.toString(), // "Total Times On"
|
prop.login_count.toString(), // "Total Times On"
|
||||||
now.format('MM/DD/YY'), // "Last Date Called"
|
now.format('MM/DD/YY'), // "Last Date Called"
|
||||||
'15360', // "Seconds Remaining THIS call (for those that particular)"
|
'15360', // "Seconds Remaining THIS call (for those that particular)"
|
||||||
'256', // "Minutes Remaining THIS call"
|
'256', // "Minutes Remaining THIS call"
|
||||||
'GR', // "Graphics Mode - GR=Graph, NG=Non-Graph, 7E=7,E Caller"
|
'GR', // "Graphics Mode - GR=Graph, NG=Non-Graph, 7E=7,E Caller"
|
||||||
self.client.term.termHeight.toString(), // "Page Length"
|
this.client.term.termHeight.toString(), // "Page Length"
|
||||||
'N', // "User Mode - Y = Expert, N = Novice"
|
'N', // "User Mode - Y = Expert, N = Novice"
|
||||||
'1,2,3,4,5,6,7', // "Conferences/Forums Registered In (ABCDEFG)"
|
'1,2,3,4,5,6,7', // "Conferences/Forums Registered In (ABCDEFG)"
|
||||||
'1', // "Conference Exited To DOOR From (G)"
|
'1', // "Conference Exited To DOOR From (G)"
|
||||||
'01/01/99', // "User Expiration Date (mm/dd/yy)"
|
'01/01/99', // "User Expiration Date (mm/dd/yy)"
|
||||||
self.client.user.userId.toString(), // "User File's Record Number"
|
this.client.user.userId.toString(), // "User File's Record Number"
|
||||||
'Z', // "Default Protocol - X, C, Y, G, I, N, Etc."
|
'Z', // "Default Protocol - X, C, Y, G, I, N, Etc."
|
||||||
// :TODO: fix up, down, etc. form user properties
|
// :TODO: fix up, down, etc. form user properties
|
||||||
'0', // "Total Uploads"
|
'0', // "Total Uploads"
|
||||||
'0', // "Total Downloads"
|
'0', // "Total Downloads"
|
||||||
'0', // "Daily Download "K" Total"
|
'0', // "Daily Download "K" Total"
|
||||||
'999999', // "Daily Download Max. "K" Limit"
|
'999999', // "Daily Download Max. "K" Limit"
|
||||||
moment(up.birthdate).format('MM/DD/YY'), // "Caller's Birthdate"
|
moment(prop.birthdate).format('MM/DD/YY'), // "Caller's Birthdate"
|
||||||
'X:\\MAIN\\', // "Path to the MAIN directory (where User File is)"
|
'X:\\MAIN\\', // "Path to the MAIN directory (where User File is)"
|
||||||
'X:\\GEN\\', // "Path to the GEN directory"
|
'X:\\GEN\\', // "Path to the GEN directory"
|
||||||
StatLog.getSystemStat('sysop_username'), // "Sysop's Name (name BBS refers to Sysop as)"
|
StatLog.getSystemStat('sysop_username'), // "Sysop's Name (name BBS refers to Sysop as)"
|
||||||
self.client.user.username, // "Alias name"
|
this.client.user.username, // "Alias name"
|
||||||
'00:05', // "Event time (hh:mm)" (note: wat?)
|
'00:05', // "Event time (hh:mm)" (note: wat?)
|
||||||
'Y', // "If its an error correcting connection (Y/N)"
|
'Y', // "If its an error correcting connection (Y/N)"
|
||||||
'Y', // "ANSI supported & caller using NG mode (Y/N)"
|
'Y', // "ANSI supported & caller using NG mode (Y/N)"
|
||||||
|
@ -136,40 +137,47 @@ function DropFile(client, fileType) {
|
||||||
now.format('hh:mm'), // "Time of Last Call (hh:mm)"
|
now.format('hh:mm'), // "Time of Last Call (hh:mm)"
|
||||||
'9999', // "Maximum daily files available"
|
'9999', // "Maximum daily files available"
|
||||||
// :TODO: fix these stats:
|
// :TODO: fix these stats:
|
||||||
'0', // "Files d/led so far today"
|
'0', // "Files d/led so far today"
|
||||||
'0', // "Total "K" Bytes Uploaded"
|
'0', // "Total "K" Bytes Uploaded"
|
||||||
'0', // "Total "K" Bytes Downloaded"
|
'0', // "Total "K" Bytes Downloaded"
|
||||||
up.user_comment || 'None', // "User Comment"
|
prop.user_comment || 'None', // "User Comment"
|
||||||
'0', // "Total Doors Opened"
|
'0', // "Total Doors Opened"
|
||||||
'0', // "Total Messages Left"
|
'0', // "Total Messages Left"
|
||||||
|
|
||||||
].join('\r\n') + '\r\n', 'cp437');
|
].join('\r\n') + '\r\n', 'cp437');
|
||||||
};
|
}
|
||||||
|
|
||||||
this.getDoor32Buffer = function() {
|
getDoor32Buffer() {
|
||||||
//
|
//
|
||||||
// Resources:
|
// Resources:
|
||||||
// * http://wiki.bbses.info/index.php/DOOR32.SYS
|
// * http://wiki.bbses.info/index.php/DOOR32.SYS
|
||||||
//
|
//
|
||||||
// :TODO: local/serial/telnet need to be configurable -- which also changes socket handle!
|
// :TODO: local/serial/telnet need to be configurable -- which also changes socket handle!
|
||||||
|
const Door32CommTypes = {
|
||||||
|
Local : 0,
|
||||||
|
Serial : 1,
|
||||||
|
Telnet : 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const socketFd = _.isNumber(this.socketDescriptor) ? this.socketDescriptor : -1;
|
||||||
|
const commType = socketFd > -1 ? Door32CommTypes.Telnet : Door32CommTypes.Local;
|
||||||
|
|
||||||
return iconv.encode([
|
return iconv.encode([
|
||||||
'2', // :TODO: This needs to be configurable!
|
commType.toString(),
|
||||||
// :TODO: Completely broken right now -- This need to be configurable & come from temp socket server most likely
|
socketFd.toString(),
|
||||||
'-1', // self.client.output._handle.fd.toString(), // :TODO: ALWAYS -1 on Windows!
|
'115200',
|
||||||
'57600',
|
|
||||||
Config.general.boardName,
|
Config.general.boardName,
|
||||||
self.client.user.userId.toString(),
|
this.client.user.userId.toString(),
|
||||||
self.client.user.properties.real_name || self.client.user.username,
|
this.client.user.properties.real_name || this.client.user.username,
|
||||||
self.client.user.username,
|
this.client.user.username,
|
||||||
self.client.user.getLegacySecurityLevel().toString(),
|
this.client.user.getLegacySecurityLevel().toString(),
|
||||||
'546', // :TODO: Minutes left!
|
'546', // :TODO: Minutes left!
|
||||||
'1', // ANSI
|
'1', // ANSI
|
||||||
self.client.node.toString(),
|
this.client.node.toString(),
|
||||||
].join('\r\n') + '\r\n', 'cp437');
|
].join('\r\n') + '\r\n', 'cp437');
|
||||||
|
}
|
||||||
|
|
||||||
};
|
getDoorInfoDefBuffer() {
|
||||||
|
|
||||||
this.getDoorInfoDefBuffer = function() {
|
|
||||||
// :TODO: fix time remaining
|
// :TODO: fix time remaining
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -178,34 +186,33 @@ function DropFile(client, fileType) {
|
||||||
//
|
//
|
||||||
// Note that usernames are just used for first/last names here
|
// Note that usernames are just used for first/last names here
|
||||||
//
|
//
|
||||||
var opUn = /[^\s]*/.exec(StatLog.getSystemStat('sysop_username'))[0];
|
const opUserName = /[^\s]*/.exec(StatLog.getSystemStat('sysop_username'))[0];
|
||||||
var un = /[^\s]*/.exec(self.client.user.username)[0];
|
const userName = /[^\s]*/.exec(this.client.user.username)[0];
|
||||||
var secLevel = self.client.user.getLegacySecurityLevel().toString();
|
const secLevel = this.client.user.getLegacySecurityLevel().toString();
|
||||||
|
|
||||||
return iconv.encode( [
|
return iconv.encode( [
|
||||||
Config.general.boardName, // "The name of the system."
|
Config.general.boardName, // "The name of the system."
|
||||||
opUn, // "The sysop's name up to the first space."
|
opUserName, // "The sysop's name up to the first space."
|
||||||
opUn, // "The sysop's name following the first space."
|
opUserName, // "The sysop's name following the first space."
|
||||||
'COM1', // "The serial port the modem is connected to, or 0 if logged in on console."
|
'COM1', // "The serial port the modem is connected to, or 0 if logged in on console."
|
||||||
'57600', // "The current port (DTE) rate."
|
'57600', // "The current port (DTE) rate."
|
||||||
'0', // "The number "0""
|
'0', // "The number "0""
|
||||||
un, // "The current user's name, up to the first space."
|
userName, // "The current user's name, up to the first space."
|
||||||
un, // "The current user's name, following the first space."
|
userName, // "The current user's name, following the first space."
|
||||||
self.client.user.properties.location || '', // "Where the user lives, or a blank line if unknown."
|
this.client.user.properties.location || '', // "Where the user lives, or a blank line if unknown."
|
||||||
'1', // "The number "0" if TTY, or "1" if ANSI."
|
'1', // "The number "0" if TTY, or "1" if ANSI."
|
||||||
secLevel, // "The number 5 for problem users, 30 for regular users, 80 for Aides, and 100 for Sysops."
|
secLevel, // "The number 5 for problem users, 30 for regular users, 80 for Aides, and 100 for Sysops."
|
||||||
'546', // "The number of minutes left in the current user's account, limited to 546 to keep from overflowing other software."
|
'546', // "The number of minutes left in the current user's account, limited to 546 to keep from overflowing other software."
|
||||||
'-1' // "The number "-1" if using an external serial driver or "0" if using internal serial routines."
|
'-1' // "The number "-1" if using an external serial driver or "0" if using internal serial routines."
|
||||||
].join('\r\n') + '\r\n', 'cp437');
|
].join('\r\n') + '\r\n', 'cp437');
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
createFile(cb) {
|
||||||
|
mkdirs(paths.dirname(this.fullPath), err => {
|
||||||
DropFile.fileTypes = [ 'DORINFO' ];
|
if(err) {
|
||||||
|
return cb(err);
|
||||||
DropFile.prototype.createFile = function(cb) {
|
}
|
||||||
fs.writeFile(this.fullPath, this.dropFileContents, function written(err) {
|
return fs.writeFile(this.fullPath, this.getContents(), cb);
|
||||||
cb(err);
|
});
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ exports.Errors = {
|
||||||
MissingConfig : (reason, reasonCode) => new EnigError('Missing configuration', -32006, reason, reasonCode),
|
MissingConfig : (reason, reasonCode) => new EnigError('Missing configuration', -32006, reason, reasonCode),
|
||||||
UnexpectedState : (reason, reasonCode) => new EnigError('Unexpected state', -32007, reason, reasonCode),
|
UnexpectedState : (reason, reasonCode) => new EnigError('Unexpected state', -32007, reason, reasonCode),
|
||||||
MissingParam : (reason, reasonCode) => new EnigError('Missing paramater(s)', -32008, reason, reasonCode),
|
MissingParam : (reason, reasonCode) => new EnigError('Missing paramater(s)', -32008, reason, reasonCode),
|
||||||
|
MissingMci : (reason, reasonCode) => new EnigError('Missing required MCI code(s)', -32009, reason, reasonCode),
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.ErrorReasons = {
|
exports.ErrorReasons = {
|
||||||
|
|
|
@ -52,7 +52,8 @@
|
||||||
"uuid-parse": "^1.0.0",
|
"uuid-parse": "^1.0.0",
|
||||||
"ws": "^4.0.0",
|
"ws": "^4.0.0",
|
||||||
"xxhash": "^0.2.4",
|
"xxhash": "^0.2.4",
|
||||||
"yazl": "^2.4.2"
|
"yazl": "^2.4.2",
|
||||||
|
"getsockethandleaddress" : "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
Loading…
Reference in New Issue