diff --git a/core/bbs.js b/core/bbs.js index 9cc7d96f..a61d10fa 100644 --- a/core/bbs.js +++ b/core/bbs.js @@ -3,7 +3,7 @@ // ENiGMA½ var conf = require('./config.js'); -var modules = require('./modules.js'); +var moduleUtil = require('./module_util.js'); var logger = require('./logger.js'); var miscUtil = require('./misc_util.js'); var database = require('./database.js'); @@ -117,7 +117,7 @@ function startListening() { return []; } - modules.loadModulesForCategory('servers', function onServerModule(err, module) { + moduleUtil.loadModulesForCategory('servers', function onServerModule(err, module) { if(err) { logger.log.info(err); return; @@ -129,7 +129,8 @@ function startListening() { return; } - var server = module.createServer(); + var moduleInst = new module.getModule(); + var server = moduleInst.createServer(); // :TODO: handle maxConnections, e.g. conf.maxConnections diff --git a/core/client.js b/core/client.js index 07378189..cb6c805a 100644 --- a/core/client.js +++ b/core/client.js @@ -2,12 +2,15 @@ 'use strict'; var stream = require('stream'); -var term = require('./client_term.js'); var assert = require('assert'); + +var term = require('./client_term.js'); var miscUtil = require('./misc_util.js'); var ansi = require('./ansi_term.js'); -var logger = require('./logger.js'); +var logger = require('./logger.js'); // :TODO: cleanup and just use Log. +var Log = require('./logger.js').log; var user = require('./user.js'); +var moduleUtil = require('./module_util.js'); exports.Client = Client; @@ -183,6 +186,33 @@ Client.prototype.address = function() { return this.input.address(); }; +Client.prototype.gotoMenuModule = function(name, cb) { + var self = this; + + // Assign a default missing module handler callback if none was provided + cb = miscUtil.valueWithDefault(cb, self.defaultHandlerMissingMod()); + + if(self.currentMenuModule) { + self.currentMenuModule.leave(); + } + + moduleUtil.loadModule(name, 'mods', function onModuleLoaded(err, mod) { + if(err) { + cb(err); + } else { + try { + Log.debug({ moduleName : name }, 'Goto menu module'); + var modInst = new mod.getModule(); + modInst.enter(self); + + self.currentMenuModule = modInst; + } catch(e) { + cb(e); + } + } + }); +}; + /////////////////////////////////////////////////////////////////////////////// // Default error handlers /////////////////////////////////////////////////////////////////////////////// diff --git a/core/config.js b/core/config.js index 5dd608b8..e41c36b9 100644 --- a/core/config.js +++ b/core/config.js @@ -43,7 +43,7 @@ module.exports = { }, ssh : { port : 8889, - enabled : true, + enabled : false, rsaPrivateKey : paths.join(__dirname, './../misc/default_key.rsa'), dsaPrivateKey : paths.join(__dirname, './../misc/default_key.dsa'), } diff --git a/core/connect.js b/core/connect.js index f07ea8c9..55b982d0 100644 --- a/core/connect.js +++ b/core/connect.js @@ -3,7 +3,7 @@ var ansi = require('./ansi_term.js'); var artwork = require('./art.js'); -var modules = require('./modules.js'); +var moduleUtil = require('./module_util.js'); var Log = require('./logger.js').log; var Config = require('./config.js').config; var packageJson = require('../package.json'); @@ -84,7 +84,8 @@ function connectEntry(client) { setTimeout(function onTimeout() { term.write(ansi.clearScreen()); - modules.goto(Config.entryMod, client); + client.gotoMenuModule(Config.entryMod); + //moduleUtil.goto(Config.entryMod, client); }, timeout); }); }, 500); diff --git a/core/menu_module.js b/core/menu_module.js new file mode 100644 index 00000000..89636b9b --- /dev/null +++ b/core/menu_module.js @@ -0,0 +1,29 @@ +/* jslint node: true */ +'use strict'; + +var PluginModule = require('./plugin_module.js').PluginModule; + +exports.MenuModule = MenuModule; + +function MenuModule() { + PluginModule.call(this); + + this.viewControllers = []; +} + +require('util').inherits(MenuModule, PluginModule); + +MenuModule.prototype.enter = function(client) { + +}; + +MenuModule.prototype.leave = function() { + this.viewControllers.forEach(function onVC(vc) { + vc.detachClientEvents(); + }); +}; + +MenuModule.prototype.addViewController = function(vc) { + this.viewControllers.push(vc); + return vc; // allow var vc = this.addViewController(new ViewController(...)); +}; \ No newline at end of file diff --git a/core/modules.js b/core/module_util.js similarity index 74% rename from core/modules.js rename to core/module_util.js index b2ca3464..bb3f8c51 100644 --- a/core/modules.js +++ b/core/module_util.js @@ -3,16 +3,14 @@ var fs = require('fs'); var paths = require('path'); + var conf = require('./config.js'); var miscUtil = require('./misc_util.js'); -var logger = require('./logger.js'); // exports exports.loadModule = loadModule; exports.loadModulesForCategory = loadModulesForCategory; -exports.goto = goto; - function loadModule(name, category, cb) { var config = conf.config; var path = config.paths[category]; @@ -32,12 +30,17 @@ function loadModule(name, category, cb) { try { var mod = require(paths.join(path, name + '.js')); - + if(!mod.moduleInfo) { cb(new Error('module is missing \'moduleInfo\' section')); return; } - + + if(!mod.getModule || typeof mod.getModule !== 'function') { + cb(new Error('Invalid or missing missing \'getModule\' method')); + return; + } + mod.runtime = { config : config }; @@ -46,7 +49,7 @@ function loadModule(name, category, cb) { } catch(e) { cb(e); } -}; +} function loadModulesForCategory(category, cb) { var path = conf.config.paths[category]; @@ -63,23 +66,4 @@ function loadModulesForCategory(category, cb) { loadModule(paths.basename(file, '.js'), category, cb); }); }); -}; - - -function goto(name, client, cb) { - // Assign a default missing module handler callback if none was provided - cb = miscUtil.valueWithDefault(cb, client.defaultHandlerMissingMod()); - - loadModule(name, 'mods', function onMod(err, mod) { - if(err) { - cb(err); - } else { - try { - logger.log.debug({ moduleName : name }, 'Goto module'); - mod.entryPoint(client); - } catch (e) { - cb(e); - } - } - }); -}; +} diff --git a/core/plugin_module.js b/core/plugin_module.js new file mode 100644 index 00000000..7ecb4af9 --- /dev/null +++ b/core/plugin_module.js @@ -0,0 +1,7 @@ +/* jslint node: true */ +'use strict'; + +exports.PluginModule = PluginModule; + +function PluginModule() { +} \ No newline at end of file diff --git a/core/server_module.js b/core/server_module.js new file mode 100644 index 00000000..f754844b --- /dev/null +++ b/core/server_module.js @@ -0,0 +1,19 @@ +/* jslint node: true */ +'use strict'; + +var PluginModule = require('./plugin_module.js').PluginModule; + +exports.ServerModule = ServerModule; + +function ServerModule() { + PluginModule.call(this); + + this.viewControllers = []; +} + +require('util').inherits(ServerModule, PluginModule); + +ServerModule.prototype.createServer = function() { + console.log('ServerModule createServer') + return null; +}; \ No newline at end of file diff --git a/core/servers/ssh.js b/core/servers/ssh.js index caf3dbdf..8c1e0900 100644 --- a/core/servers/ssh.js +++ b/core/servers/ssh.js @@ -25,7 +25,7 @@ function SSHClient(input, output) { this.input.on('authentication', function onAuthentication(ctx) { console.log('auth: ' + ctx.method); - if('password' == ctx.method) { + if('password' === ctx.method) { // :TODO: Log attempts user.authenticate(ctx.username, ctx.password, self, function onAuthResult(isAuth) { if(isAuth) { @@ -34,9 +34,19 @@ function SSHClient(input, output) { ctx.reject(); } }); - } else if('publickey' == ctx.method) { + } else if('publickey' === ctx.method) { console.log('pub key path'); + } else if('keyboard-interactive' === ctx.method) { + ctx.reject(['password']); // :TODO: support this. Allow users to generate a key for use or w/e + + /*} else if('keyboard-interactive' === ctx.method) { + console.log(ctx.submethods); // :TODO: proper logging; handle known types, etc. + + ctx.prompt([ { prompt : 'Password: ', echo : false } ], function onPromptResponses(err, responses) { + console.log(err); + console.log(responses); + });*/ } else { ctx.reject(); } @@ -44,10 +54,10 @@ function SSHClient(input, output) { this.input.on('ready', function onReady() { console.log('Client authenticated'); - }); - this.input.on('session', function onSession(accept, reject) { - var session = accept(); + self.input.on('session', function onSession(accept, reject) { + + }); }); this.input.on('end', function onEnd() { @@ -66,7 +76,8 @@ function createServer() { }; var server = ssh2.Server(serverConf); - server.on('connection', function onConnection(conn) { + server.on('connection', function onConnection(conn, info) { + console.log(info); // :TODO: Proper logging var client = new SSHClient(conn, conn); this.emit('client', client); }); diff --git a/core/servers/telnet.js b/core/servers/telnet.js index 04a825cc..109f08ef 100644 --- a/core/servers/telnet.js +++ b/core/servers/telnet.js @@ -2,14 +2,16 @@ 'use strict'; // ENiGMA½ -var baseClient = require('../client.js'); -var logger = require('../logger.js'); +var baseClient = require('../client.js'); +var logger = require('../logger.js'); +var ServerModule = require('../server_module.js').ServerModule; -var net = require('net'); -var buffers = require('buffers'); -var binary = require('binary'); -var stream = require('stream'); -var assert = require('assert'); +var net = require('net'); +var buffers = require('buffers'); +var binary = require('binary'); +var stream = require('stream'); +var assert = require('assert'); +var util = require('util'); //var debug = require('debug')('telnet'); @@ -19,7 +21,8 @@ exports.moduleInfo = { author : 'NuSkooler' }; -exports.createServer = createServer; +exports.getModule = TelnetServerModule; + // // Telnet Protocol Resources @@ -469,7 +472,7 @@ function TelnetClient(input, output) { }); } -require('util').inherits(TelnetClient, baseClient.Client); +util.inherits(TelnetClient, baseClient.Client); /////////////////////////////////////////////////////////////////////////////// // Telnet Command/Option handling @@ -716,7 +719,7 @@ Object.keys(OPTIONS).forEach(function(name) { }); }); - +/* function createServer() { var server = net.createServer(function onConnection(sock) { var self = this; @@ -729,3 +732,27 @@ function createServer() { return server; } +*/ + +function TelnetServerModule() { + console.log('TelnetServerModule') + ServerModule.call(this); +} + +util.inherits(TelnetServerModule, ServerModule); + +TelnetServerModule.prototype.createServer = function() { + console.log('TelnetServerModule createServer') + TelnetServerModule.super_.prototype.createServer.call(this); + + var server = net.createServer(function onConnection(sock) { + var self = this; + var client = new TelnetClient(sock, sock); + + client.banner(); + + self.emit('client', client); + }); + + return server; +}; \ No newline at end of file diff --git a/mods/matrix.js b/mods/matrix.js index 5dbb587f..a68a9d85 100644 --- a/mods/matrix.js +++ b/mods/matrix.js @@ -1,18 +1,18 @@ /* jslint node: true */ 'use strict'; -var ansi = require('../core/ansi_term.js'); -var art = require('../core/art.js'); -var user = require('../core/user.js'); -var theme = require('../core/theme.js'); -var modules = require('../core/modules.js'); +var ansi = require('../core/ansi_term.js'); +var art = require('../core/art.js'); +var user = require('../core/user.js'); +var theme = require('../core/theme.js'); +var MenuModule = require('../core/menu_module.js').MenuModule; -//var view = require('../core/view.js'); -var textView = require('../core/text_view.js'); +//var view = require('../core/view.js'); +var textView = require('../core/text_view.js'); var editTextView = require('../core/edit_text_view.js'); var ViewController = require('../core/view_controller.js').ViewController; -var async = require('async'); +//var async = require('async'); exports.moduleInfo = { name : 'Matrix', @@ -20,8 +20,63 @@ exports.moduleInfo = { author : 'NuSkooler', }; -exports.entryPoint = entryPoint; +//exports.entryPoint = entryPoint; +exports.getModule = MatrixModule; + +function MatrixModule() { + MenuModule.call(this); +} + +require('util').inherits(MatrixModule, MenuModule); + +MatrixModule.prototype.enter = function(client) { + MatrixModule.super_.prototype.enter.call(this); + + var self = this; + + client.term.write(ansi.resetScreen()); + //client.term.write('\x1b[?33h'); + + theme.displayThemeArt('MATRIX', client, function onMatrix(err, mciMap) { + console.log(mciMap); + if(mciMap.ET1 && mciMap.ET2 && mciMap.BN1 && mciMap.BN2 && mciMap.BN3) { + // + // Form via EditTextViews and ButtonViews + // * ET1 - userName + // * ET2 - password + // * BN1 - Login + // * BN2 - New + // * BN3 - Bye! + // + } else if(mciMap.VM1) { + // + // Menu via VerticalMenuView + // + // * VM1 - menu with the following items: + // 0 - Login + // 1 - New + // 2 - Bye! + // + //var vc = new ViewController(client); + var vc = self.addViewController(new ViewController(client)); + + vc.on('submit', function onSubmit(form) { + console.log(form); + }); + + vc.loadFromMCIMap(mciMap); + vc.setViewOrder(); + // :TODO: Localize + vc.getView(1).setItems(['Login', 'New User', 'Goodbye!']); + vc.getView(1).submit = true; + vc.switchFocus(1); + } + }); +}; + + +/* function entryPoint(client) { client.term.write(ansi.resetScreen()); @@ -50,17 +105,19 @@ function entryPoint(client) { var vc = new ViewController(client); vc.on('submit', function onSubmit(form) { - + console.log(form); }); vc.loadFromMCIMap(mciMap); vc.setViewOrder(); // :TODO: Localize vc.getView(1).setItems(['Login', 'New User', 'Goodbye!']); + vc.getView(1).submit = true; vc.switchFocus(1); } }); } +*/ /* function entryPoint(client) {