mirror of
https://github.com/NuSkooler/enigma-bbs.git
synced 2025-08-03 00:12:01 +02:00
* Add FileBaseFilters
* Add HTTP(S) file web server with temp URLs * Get temp web d/l from file list * Add File area filter editor (all file area stuff will be rename to file "base" later) * Concept of "listening servers" vs "login servers" * Ability to get servers by their package name * New MCI: %FN: File Base active filter name * Some ES6 updates * VC resetInitialFocus() to set focus to explicit/detected initial focus field * Limit what is dumped out when logging form data
This commit is contained in:
parent
712cf512f0
commit
a7c0f2b7b0
22 changed files with 1233 additions and 286 deletions
123
core/servers/content/web.js
Normal file
123
core/servers/content/web.js
Normal file
|
@ -0,0 +1,123 @@
|
|||
/* jslint node: true */
|
||||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
const Log = require('../../logger.js').log;
|
||||
const ServerModule = require('../../server_module.js').ServerModule;
|
||||
const Config = require('../../config.js').config;
|
||||
|
||||
// deps
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs');
|
||||
|
||||
const ModuleInfo = exports.moduleInfo = {
|
||||
name : 'Web',
|
||||
desc : 'Web Server',
|
||||
author : 'NuSkooler',
|
||||
packageName : 'codes.l33t.enigma.web.server',
|
||||
};
|
||||
|
||||
class Route {
|
||||
constructor(route) {
|
||||
Object.assign(this, route);
|
||||
|
||||
if(this.method) {
|
||||
this.method = this.method.toUpperCase();
|
||||
}
|
||||
|
||||
try {
|
||||
this.pathRegExp = new RegExp(this.path);
|
||||
} catch(e) {
|
||||
Log.debug( { route : route }, 'Invalid regular expression for route path' );
|
||||
}
|
||||
}
|
||||
|
||||
isValid() {
|
||||
return (
|
||||
this.pathRegExp instanceof RegExp &&
|
||||
( -1 !== [ 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', ].indexOf(this.method) ) ||
|
||||
!_.isFunction(this.handler)
|
||||
);
|
||||
}
|
||||
|
||||
matchesRequest(req) { return req.method === this.method && this.pathRegExp.test(req.url); }
|
||||
|
||||
getRouteKey() { return `${this.method}:${this.path}`; }
|
||||
}
|
||||
|
||||
exports.getModule = class WebServerModule extends ServerModule {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.enableHttp = Config.contentServers.web.http.enabled || true;
|
||||
this.enableHttps = Config.contentServers.web.https.enabled || false;
|
||||
|
||||
this.routes = {};
|
||||
}
|
||||
|
||||
createServer() {
|
||||
if(this.enableHttp) {
|
||||
this.httpServer = http.createServer( (req, resp) => this.routeRequest(req, resp) );
|
||||
}
|
||||
|
||||
if(this.enableHttps) {
|
||||
const options = {
|
||||
cert : fs.readFileSync(Config.contentServers.web.https.certPem),
|
||||
key : fs.readFileSync(Config.contentServers.web.https.keyPem),
|
||||
};
|
||||
|
||||
// additional options
|
||||
Object.assign(options, Config.contentServers.web.https.options || {} );
|
||||
|
||||
this.httpsServer = https.createServer(options, this.routeRequest);
|
||||
}
|
||||
}
|
||||
|
||||
listen() {
|
||||
let ok = true;
|
||||
|
||||
[ 'http', 'https' ].forEach(service => {
|
||||
const name = `${service}Server`;
|
||||
if(this[name]) {
|
||||
const port = parseInt(Config.contentServers.web[service].port);
|
||||
if(isNaN(port)) {
|
||||
ok = false;
|
||||
return Log.warn( { port : Config.contentServers.web[service].port, server : ModuleInfo.name }, `Invalid port (${service})` );
|
||||
}
|
||||
return this[name].listen(port);
|
||||
}
|
||||
});
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
addRoute(route) {
|
||||
route = new Route(route);
|
||||
|
||||
if(!route.isValid()) {
|
||||
Log( { route : route }, 'Cannot add route: missing or invalid required members' );
|
||||
return false;
|
||||
}
|
||||
|
||||
const routeKey = route.getRouteKey();
|
||||
if(routeKey in this.routes) {
|
||||
Log( { route : route }, 'Cannot add route: duplicate method/path combination exists' );
|
||||
return false;
|
||||
}
|
||||
|
||||
this.routes[routeKey] = route;
|
||||
return true;
|
||||
}
|
||||
|
||||
routeRequest(req, resp) {
|
||||
const route = _.find(this.routes, r => r.matchesRequest(req) );
|
||||
return route ? route.handler(req, resp) : this.accessDenied(resp);
|
||||
}
|
||||
|
||||
accessDenied(resp) {
|
||||
resp.writeHead(401, { 'Content-Type' : 'text/html' } );
|
||||
return resp.end('<html><body>Access denied</body></html>');
|
||||
}
|
||||
}
|
|
@ -2,14 +2,14 @@
|
|||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
const Config = require('../../config.js').config;
|
||||
const baseClient = require('../../client.js');
|
||||
const Log = require('../../logger.js').log;
|
||||
const ServerModule = require('../../server_module.js').ServerModule;
|
||||
const userLogin = require('../../user_login.js').userLogin;
|
||||
const enigVersion = require('../../../package.json').version;
|
||||
const theme = require('../../theme.js');
|
||||
const stringFormat = require('../../string_format.js');
|
||||
const Config = require('../../config.js').config;
|
||||
const baseClient = require('../../client.js');
|
||||
const Log = require('../../logger.js').log;
|
||||
const LoginServerModule = require('../../login_server_module.js');
|
||||
const userLogin = require('../../user_login.js').userLogin;
|
||||
const enigVersion = require('../../../package.json').version;
|
||||
const theme = require('../../theme.js');
|
||||
const stringFormat = require('../../string_format.js');
|
||||
|
||||
// deps
|
||||
const ssh2 = require('ssh2');
|
||||
|
@ -18,15 +18,14 @@ const util = require('util');
|
|||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
|
||||
exports.moduleInfo = {
|
||||
const ModuleInfo = exports.moduleInfo = {
|
||||
name : 'SSH',
|
||||
desc : 'SSH Server',
|
||||
author : 'NuSkooler',
|
||||
isSecure : true,
|
||||
packageName : 'codes.l33t.enigma.ssh.server',
|
||||
};
|
||||
|
||||
exports.getModule = SSHServerModule;
|
||||
|
||||
function SSHClient(clientConn) {
|
||||
baseClient.Client.apply(this, arguments);
|
||||
|
||||
|
@ -226,40 +225,45 @@ util.inherits(SSHClient, baseClient.Client);
|
|||
|
||||
SSHClient.ValidAuthMethods = [ 'password', 'keyboard-interactive' ];
|
||||
|
||||
function SSHServerModule() {
|
||||
ServerModule.call(this);
|
||||
}
|
||||
exports.getModule = class SSHServerModule extends LoginServerModule {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
util.inherits(SSHServerModule, ServerModule);
|
||||
createServer() {
|
||||
const serverConf = {
|
||||
hostKeys : [
|
||||
{
|
||||
key : fs.readFileSync(Config.loginServers.ssh.privateKeyPem),
|
||||
passphrase : Config.loginServers.ssh.privateKeyPass,
|
||||
}
|
||||
],
|
||||
ident : 'enigma-bbs-' + enigVersion + '-srv',
|
||||
|
||||
// Note that sending 'banner' breaks at least EtherTerm!
|
||||
debug : (sshDebugLine) => {
|
||||
if(true === Config.loginServers.ssh.traceConnections) {
|
||||
Log.trace(`SSH: ${sshDebugLine}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
SSHServerModule.prototype.createServer = function() {
|
||||
SSHServerModule.super_.prototype.createServer.call(this);
|
||||
this.server = ssh2.Server(serverConf);
|
||||
this.server.on('connection', (conn, info) => {
|
||||
Log.info(info, 'New SSH connection');
|
||||
this.handleNewClient(new SSHClient(conn), conn._sock, ModuleInfo);
|
||||
});
|
||||
}
|
||||
|
||||
const serverConf = {
|
||||
hostKeys : [
|
||||
{
|
||||
key : fs.readFileSync(Config.loginServers.ssh.privateKeyPem),
|
||||
passphrase : Config.loginServers.ssh.privateKeyPass,
|
||||
}
|
||||
],
|
||||
ident : 'enigma-bbs-' + enigVersion + '-srv',
|
||||
|
||||
// Note that sending 'banner' breaks at least EtherTerm!
|
||||
debug : (sshDebugLine) => {
|
||||
if(true === Config.loginServers.ssh.traceConnections) {
|
||||
Log.trace(`SSH: ${sshDebugLine}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
listen() {
|
||||
const port = parseInt(Config.loginServers.ssh.port);
|
||||
if(isNaN(port)) {
|
||||
Log.error( { server : ModuleInfo.name, port : Config.loginServers.ssh.port }, 'Cannot load server (invalid port)' );
|
||||
return false;
|
||||
}
|
||||
|
||||
const server = ssh2.Server(serverConf);
|
||||
server.on('connection', function onConnection(conn, info) {
|
||||
Log.info(info, 'New SSH connection');
|
||||
|
||||
const client = new SSHClient(conn);
|
||||
|
||||
this.emit('client', client, conn._sock);
|
||||
});
|
||||
|
||||
return server;
|
||||
this.server.listen(port);
|
||||
Log.info( { server : ModuleInfo.name, port : port }, 'Listening for connections' );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
const baseClient = require('../../client.js');
|
||||
const Log = require('../../logger.js').log;
|
||||
const ServerModule = require('../../server_module.js').ServerModule;
|
||||
const Config = require('../../config.js').config;
|
||||
const baseClient = require('../../client.js');
|
||||
const Log = require('../../logger.js').log;
|
||||
const LoginServerModule = require('../../login_server_module.js');
|
||||
const Config = require('../../config.js').config;
|
||||
|
||||
// deps
|
||||
const net = require('net');
|
||||
|
@ -16,16 +16,14 @@ const util = require('util');
|
|||
|
||||
//var debug = require('debug')('telnet');
|
||||
|
||||
exports.moduleInfo = {
|
||||
const ModuleInfo = exports.moduleInfo = {
|
||||
name : 'Telnet',
|
||||
desc : 'Telnet Server',
|
||||
author : 'NuSkooler',
|
||||
isSecure : false,
|
||||
packageName : 'codes.l33t.enigma.telnet.server',
|
||||
};
|
||||
|
||||
exports.getModule = TelnetServerModule;
|
||||
|
||||
|
||||
//
|
||||
// Telnet Protocol Resources
|
||||
// * http://pcmicro.com/netfoss/telnet.html
|
||||
|
@ -767,22 +765,34 @@ Object.keys(OPTIONS).forEach(function(name) {
|
|||
});
|
||||
});
|
||||
|
||||
function TelnetServerModule() {
|
||||
ServerModule.call(this);
|
||||
}
|
||||
exports.getModule = class TelnetServerModule extends LoginServerModule {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
util.inherits(TelnetServerModule, ServerModule);
|
||||
createServer() {
|
||||
this.server = net.createServer( sock => {
|
||||
const client = new TelnetClient(sock, sock);
|
||||
|
||||
TelnetServerModule.prototype.createServer = function() {
|
||||
TelnetServerModule.super_.prototype.createServer.call(this);
|
||||
client.banner();
|
||||
|
||||
const server = net.createServer( (sock) => {
|
||||
const client = new TelnetClient(sock, sock);
|
||||
|
||||
client.banner();
|
||||
this.handleNewClient(client, sock, ModuleInfo);
|
||||
});
|
||||
|
||||
server.emit('client', client, sock);
|
||||
});
|
||||
this.server.on('error', err => {
|
||||
Log.info( { error : err.message }, 'Telnet server error');
|
||||
});
|
||||
}
|
||||
|
||||
return server;
|
||||
listen() {
|
||||
const port = parseInt(Config.loginServers.telnet.port);
|
||||
if(isNaN(port)) {
|
||||
Log.error( { server : ModuleInfo.name, port : Config.loginServers.telnet.port }, 'Cannot load server (invalid port)' );
|
||||
return false;
|
||||
}
|
||||
|
||||
this.server.listen(port);
|
||||
Log.info( { server : ModuleInfo.name, port : port }, 'Listening for connections' );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue