From 5883b5ca9b48ac81f9b29ea8fce75eff9311423c Mon Sep 17 00:00:00 2001 From: Deon George Date: Sun, 10 Apr 2022 21:09:59 +1000 Subject: [PATCH] Code formating, fix SBBS no longer has SS_UNUSED, return acts as # --- load/ansiframe.js | 14 +-- load/defs.js | 110 +++++++++++++----- main.js | 290 +++++++++++++++++++++++++++++++--------------- 3 files changed, 284 insertions(+), 130 deletions(-) diff --git a/load/ansiframe.js b/load/ansiframe.js index 32d7e85..9277773 100644 --- a/load/ansiframe.js +++ b/load/ansiframe.js @@ -34,7 +34,7 @@ var ANSI_CANCEL_MSG = '\1n\1h\1GPRESS 2 TO CANCEL'; // Our frame object function ANSIFrame() { this.version=1; // The version of this frame - in case we update functionality and we need to be - // backwards compatible + // backwards compatible this.frame=null; // Frame Number [0-9]+ this.index=null; // Frame Index [a-z] this.owner=0; // The Service Provider owning the frame. @@ -42,13 +42,13 @@ function ANSIFrame() { this.content=''; // The frame content, base64 encoded // Frame's owned by the system where: - // isPublic is FALSE - the user must be logged in to view it - // isPublic is TRUE - can be viewed by non-logged in users + // isPublic is FALSE - the user must be logged in to view it + // isPublic is TRUE - can be viewed by non-logged in users // Frame's owned by Service Providers where: - // isPublic is FALSE - can only be viewed if a user is - // a member of the Service Providers CUG - // isPublic is TRUE - can be viewed by users (if logged in) + // isPublic is FALSE - can only be viewed if a user is + // a member of the Service Providers CUG + // isPublic is TRUE - can be viewed by users (if logged in) this.isPublic=false; // Is this frame accessible to non CUG users // If FALSE user must be a member of the CUG to view the frame @@ -275,7 +275,7 @@ function ANSIFrame() { break; default: - log(LOG_DEBUG,'? CSI: '.matches[2]); + log(LOG_DEBUG,'? CSI: '+matches[2]); } break; diff --git a/load/defs.js b/load/defs.js index 9cea74a..7fa45b5 100644 --- a/load/defs.js +++ b/load/defs.js @@ -2,39 +2,91 @@ * ANSItex definitions */ -var ACTION_EXIT =99; /* Exit the script */ -var ACTION_RELOAD =1; /* Reload the current frame */ -var ACTION_GOTO =2; /* Goto a specific frame */ -var ACTION_BACKUP =3; /* Goto previous frame */ -var ACTION_NEXT =4; /* Goto next frame */ -var ACTION_TERMINATE =5; /* Terminate the session */ -var ACTION_SUBMITRF =6; /* Submit form contents */ -var ACTION_STAR =7; /* Star command entry */ -var ACTION_EDIT =8; /* Edit a frame */ +/* Unit of cost */ +const FRAME_COSTUNIT ='c'; -var MODE_BL =1; /* Typing * command on baseline */ -var MODE_FIELD =2; /* Field Input */ -var MODE_SUBMITRF =3; /* Asking if form should be submitted */ -var MODE_RFNOTSENT =4; /* Response frame not sent */ -var MODE_RFSENT =5; /* Response frame sent */ -var MODE_RFERROR =6; /* Response frame error */ +/** ACTIONS **/ -var FRAME_COSTUNIT ='c'; /* Unit of cost */ +/* Exit the script */ +const ACTION_EXIT =99; +/* Reload the current frame */ +const ACTION_RELOAD =1; +/* Goto a specific frame */ +const ACTION_GOTO =2; +/* Goto previous frame */ +const ACTION_BACKUP =3; +/* Goto next frame */ +const ACTION_NEXT =4; +/* Terminate the session */ +const ACTION_TERMINATE =5; +/* Submit form contents */ +const ACTION_SUBMITRF =6; +/* Star command entry */ +const ACTION_STAR =7; +/* Edit a frame */ +const ACTION_EDIT =8; -var FRAME_TYPE_INFO ='i'; // Information Frame, requires no response after viewed -var FRAME_TYPE_TERMINATE ='t'; // Terminate Frame, contents displayed and then carrier dropped -var FRAME_TYPE_EXTERNAL ='x'; // Frame the calls an External Method - // Contents indicate the method to be called with arguments -var FRAME_TYPE_RESPONSE ='r'; // Response frame, input fields are embedded in the frame and after input the - // response will be submitted to the Service Provider, or to a method -var FRAME_TYPE_LOGIN ='l'; // Login frame, enables the user to authenticate to the system, or to a CUG +/** MODES **/ -var NO_HISTORY_FRAMES =['980a','98b','981a','982a','983a','998a']; -var SYSTEM_OWNER =9; -var INKEY_TIMEOUT =10000; -var INACTIVE_NOLOGIN =30000; -var INACTIVE_LOGIN =5*60000; +/* Typing * command on baseline */ +const MODE_BL =1; +/* Field Input */ +const MODE_FIELD =2; +/* Asking if form should be submitted */ +const MODE_SUBMITRF =3; +/* Response frame not sent */ +const MODE_RFNOTSENT =4; +/* Response frame sent */ +const MODE_RFSENT =5; +/* Response frame error */ +const MODE_RFERROR =6; -var SYSTEM_ZONE =516; +/** FRAME TYPES **/ + +/* Information Frame, requires no response after viewed */ +const FRAME_TYPE_INFO ='i'; +/* Terminate Frame, contents displayed and then carrier dropped */ +const FRAME_TYPE_TERMINATE ='t'; +/** + * Frame the calls an External Method + * Contents indicate the method to be called with arguments + */ +const FRAME_TYPE_EXTERNAL ='x'; +/** + * Response frame, input fields are embedded in the frame and after input the + * response will be submitted to the Service Provider, or to a method + */ +const FRAME_TYPE_RESPONSE ='r'; +/* Login frame, enables the user to authenticate to the system, or to a CUG */ +const FRAME_TYPE_LOGIN ='l'; + +/* Disable *# going backwards for the following frames */ +var NO_HISTORY_FRAMES =['980a','98b','981a','982a','983a','998a']; + +/* Frames prefixed with this are owned by the system */ +const SYSTEM_OWNER =9; +/* Time to wait for a key press */ +const INKEY_TIMEOUT =10000; +/* Idle time for un-authenticated users */ +const INACTIVE_NOLOGIN =30000; +/* Idle time for authenticated users */ +const INACTIVE_LOGIN =5*60000; + +var SYSTEM_ZONE =516; + +/* Home Frame */ +const HOME_FRAME ={frame: 1,index: 'a'}; +/* Login Frame */ +const LOGIN_FRAME ={frame: 98,index: 'a'}; +/* Registration Frame */ +const REGISTER_FRAME ={frame: 981,index: 'a'}; +/* SQRL Login */ +const SQRL_FRAME ={frame: 982,index: 'a'}; +/* Login Failed */ +const LOGIN_FAILED_FRAME ={frame: 983,index: 'a'}; +/* Home page after authentication */ +const HOME_FRAME_AUTH ={frame: 98,index: 'b'}; +/* Home page for initial connection */ +const HOME_FRAME_CONNECT ={frame: 980,index: 'a'}; this; diff --git a/main.js b/main.js index 2eb647e..9eb823e 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,7 @@ log(LOG_DEBUG,'- INIT: ANSITEX'); // Load many SBBS definitions -require('sbbsdefs.js','SS_UNUSED'); +require('sbbsdefs.js','SS_USERON'); // Load text.dat definitions require('text.js','TOTAL_TEXT'); // Key definitions @@ -15,56 +15,139 @@ require('ansitex/load/defs.js','ACTION_EXIT'); require('ansitex/load/ansiframe.js','FRAME_ANSI'); require('ansitex/load/viewdataframe.js','FRAME_VIEWDATA'); -// @TODO LIST -// Returning from chat should refresh the frame -// Supress displays of telegrams +// @todo Returning from chat should refresh the frame +// @todo Suppress displays of telegrams + +/** + * This is our main event loop - we where interact with the user. + * This loop takes care of first connect (unauthenticated users), or after authentication (main shell). + */ while(bbs.online) { + /** + * State of the current action + * - FALSE means we are not doing anything + * - MODE_* is the mode (as defined in defs.js) + * @type number|boolean + */ var mode = false; // Initial mode - // If the user is already on, our start page is 98b - var next_page = user.number ? { frame: 98,index: 'b' } : { frame: 980,index: 'a' }; // Start Frame + /** + * The next page to render + * @type {{frame: number,index: string}} + */ + var next_page = user.name ? HOME_FRAME_AUTH : HOME_FRAME_CONNECT; // Start Frame + /** + * Next action to take + * - FALSE means no action + * - ACTION_* is the action (as defined in defs.js) + * @type {number} + */ var action = ACTION_GOTO; // Initial action - var inkey_timeout = INKEY_TIMEOUT; // Timeout waiting for input - var fo = null; // Current Frame - var fn = null; // Current Field Number for an Input Frame - var fe = null; // Frame to edit - var history = []; // Page history - var cf = null; // Current Input Field + /** + * Variable holding our current key timeout value + * @type {number} + */ + var inkey_timeout = INKEY_TIMEOUT; + + /** + * Current Frame Object that is being displayed to the user + * - VIEWDATAFrame - for viewdata frames + * - ANSIFrame - for ANSItex frames + * @type {ANSIFrame|VIEWDATAFrame} + */ + var fo = null; + + /** + * Current input field being edited when a frame has input fields + * - NULL means we are not inputting on a field + * @type {number|null} + */ + var fn = null; + + /** + * History of frames that the user has seen this session + * @type {array} + */ + var history = []; + + /** + * Current Input Field. + * @type {object} + */ + var cf = null; var cc = null; // Current Control Method - var timeout = false; // Track our inactivity timeout - var timer = time(); - var control = []; // Methods that need to process input - var extendedkey = ''; // Current Extended Key being captured - var viewdata = (client.socket.local_port == 516); + /** + * User has hit the inactivity timeout without any input + * @type {boolean} + */ + var timeout = false; - while (action != ACTION_TERMINATE && action !=ACTION_EXIT) { - bbs.nodesync(); // @todo Stop the display of telegrams + /** + * Time the user hit the inactivity timeout + * @type {number} + */ + var timer = time(); + + /** + * Which command control methods are in play and process input + * @type {array} + */ + var control = []; + + /** + * The command being entered on the bottom line + * @type {string} + */ + var cmd = ''; + + /** + * We are receiving an extended key sequence (like a function key) + * @type {string} + */ + var extendedkey = ''; + + /** + * Our session is a viewdata session or an ansitex session + * @type {boolean} + */ + const viewdata = (client.socket.local_port === 516); + + while (action !== ACTION_TERMINATE && action !== ACTION_EXIT) { + bbs.nodesync(); // @todo Stop the display of telegrams + + /* The current input character */ var read = ''; + /* ESC key sequence received */ var esc = false; // If we have no action, read from the terminal - if (action == false) { - + if (action === false) { + // If a special key sequence is coming... while (esc || ! read) { log(LOG_DEBUG,'- READ START'); + // Wait for a key from the user read = console.inkey(K_NONE,inkey_timeout); - // We are intering a special keyboard char. - if (read == KEY_ESC) { + // We are entering a special keyboard char. + if (read === KEY_ESC) { log(LOG_DEBUG,'- READ SPECIAL KEY COMING'); esc = true; + // We reduce our timeout, and assume the key is a function key. If the user pressed ESC we'll process that later inkey_timeout = 200; - } else if (esc && ! extendedkey && read != '[') { + // If we got the ESC, but no [ then re-put the ESC in the read, we loose the current key + // @todo We loose the current pressed key + } else if (esc && ! extendedkey && read !== '[') { log(LOG_DEBUG,'- READ SPECIAL KEY ABANDONED: ['+read+'] ('+read.charCodeAt(0)+')'); esc = false; inkey_timeout = INKEY_TIMEOUT; read = KEY_ESC; - } else if (esc && extendedkey && (read == '~' || read == ';')) { + // Recognise when the ESC sequence has ended (with a ~ or ;) + } else if (esc && extendedkey && (read === '~' || read === ';')) { switch (extendedkey) { case '[15': read = false; break; // F5 case '[17': read = false; break; // F6 @@ -83,17 +166,22 @@ while(bbs.online) { extendedkey = ''; inkey_timeout = INKEY_TIMEOUT; + // Record the character as an extended key } else if (esc) { log(LOG_DEBUG,'- READ SPECIAL KEY ['+read+'] ('+read.charCodeAt(0)+')'); extendedkey += read; read = false; } - if (read === '' && ! (user.security.exemptions&UFLAG_H) ) { + // Calculate idle timeouts + // If the user has exemption H we dont worry about timeout + if (! read && ! (user.security.exemptions&UFLAG_H) ) { + // Terminate the user if they have been inactive too long. if (time() > timer+((user.number ? INACTIVE_LOGIN : INACTIVE_NOLOGIN)+INKEY_TIMEOUT)/1000) { fo.sendBaseline('INACTIVE',false); bbs.hangup(); + // Idle warning - due to inactivity. } else if (time() > timer+(user.number ? INACTIVE_LOGIN : INACTIVE_NOLOGIN)/1000) { timeout = true; fo.sendBaseline('INACTIVITY',false); @@ -105,6 +193,7 @@ while(bbs.online) { } } else { + // If the user become active during inactivity, clear the baseline message if (timeout) { fo.clearBaseline(false); @@ -119,7 +208,7 @@ while(bbs.online) { } if (esc) { - log(LOG_DEBUG,'- READ SHOULD LOOP'); + log(LOG_DEBUG,'- READ SPECIAL KEY LOOP'); } } } @@ -127,15 +216,19 @@ while(bbs.online) { system.node_list[bbs.node_num-1].action=0xff; // to ensure our node status is updated correctly - if (mode != MODE_BL && control.length) { + // After reading from the terminal, see if we need to pass that input to a control module, + // except if input is on the bottom line + if (mode !== MODE_BL && control.length) { log(LOG_DEBUG,'CONTROL DEBUG: ['+control.length+'] ('+JSON.stringify(control)+')'); cc = control[control.length-1]; log(LOG_DEBUG,'CONTROL START: ['+read+'] ('+cc.getName+')'); + // We pass the read to the control and see if it consumes it. read = cc.handle(read); log(LOG_DEBUG,'CONTROL RETURN: ['+read+'] ('+cc.isComplete+')'); if (cc.isComplete) { control.pop(); + cc = null; log(LOG_DEBUG,'CONTROL COMPLETE: ['+read+'] ('+control.length+')'); } @@ -144,9 +237,9 @@ while(bbs.online) { log(LOG_DEBUG,'MODE START: ['+read.charCodeAt(0)+']'); switch (mode) { + // Normal navigation case false: - log(LOG_DEBUG,'- false: ['+read+']'); - cmd=''; + log(LOG_DEBUG,'- MODE false: ['+read+']'); switch (read) { case '*': action = ACTION_STAR; @@ -163,15 +256,16 @@ while(bbs.online) { case '7': case '8': case '9': - log(LOG_DEBUG,'- false: Key ['+read+'] Route ['+fo.key[read]+']'); + log(LOG_DEBUG,'- MODE false: Key ['+read+'] Route ['+fo.key[read]+']'); if (fo.key[read] !== null) { // If are requesting a home page if (fo.key[read] === 0) { - next_page = { frame: user.number ? 1 : 98,index: 'a' }; + next_page = user.number ? HOME_FRAME : LOGIN_FRAME; } else { - next_page = { frame: fo.key[read] }; + next_page = {frame: fo.key[read],index: 'a'}; } + action = ACTION_GOTO; log(LOG_DEBUG,'- false: Key ['+read+'] ['+pageStr(next_page)+']'); @@ -182,16 +276,19 @@ while(bbs.online) { break; case '_': + // Viewdata terminal's # is an _ character if (! viewdata) break; + /* fallthrough */ case '#': log(LOG_DEBUG,'- false: Key ['+read+'] ['+pageStr(fo)+']'); if (fo.index !== 'z') { - next_page = { frame: fo.frame, index: String.fromCharCode(fo.index.charCodeAt(0)+1) }; + next_page = {frame: fo.frame,index: String.fromCharCode(fo.index.charCodeAt(0)+1)}; action = ACTION_GOTO; } else { fo.sendBaseline('ERR_ROUTE',false); } + break; } @@ -205,22 +302,23 @@ while(bbs.online) { console.write(read); } - // @todo check if CTRL_H is required? - if ((read == CTRL_H || read == KEY_DEL) && cmd.length) { + // If the user pressed backspace + // @todo We should get the user's configuration of backspace + if ((read === CTRL_H || read === KEY_DEL) && cmd.length) { console.backspace(); cmd = cmd.substring(0,cmd.length-1); } - if (cmd == '00') { + if (cmd === '00') { action = ACTION_RELOAD; cmd = ''; fo.cursorOff(); break; } - if (cmd == '01' && ! user.number) { + if (cmd === '01' && ! user.number) { action = ACTION_GOTO; - next_page = { frame: 982,index: 'a' }; + next_page = SQRL_FRAME; break; } @@ -234,8 +332,6 @@ while(bbs.online) { // Edit specific frame if (cmd.match(/^04/) && read.match(/[a-z]/)) { - var page = cmd.substr(2,cmd.length-1); - // If we are not a user if (! user.number) { fo.cursorOff(); @@ -243,11 +339,11 @@ while(bbs.online) { action = false; } else { - fe = { frame: page, index: read }; + next_page = {frame: parseInt(cmd.substr(2,cmd.length-1)),index: read}; fo.cursorOff(); action = ACTION_EDIT; - log(LOG_DEBUG,'- MODE_BL: EDIT ['+JSON.stringify(fe)+']'); + log(LOG_DEBUG,'- MODE_BL: EDIT ['+JSON.stringify(next_page)+']'); } mode = false; @@ -257,7 +353,7 @@ while(bbs.online) { } // Bookmark frame - if (cmd == '05') { + if (cmd === '05') { if (! user.number) { fo.cursorOff(); fo.sendBaseline('ERR_ROUTE',false); @@ -276,7 +372,7 @@ while(bbs.online) { } // Report Problem - if (cmd == '08') { + if (cmd === '08') { if (! user.number) { fo.cursorOff(); fo.sendBaseline('ERR_ROUTE',false); @@ -295,17 +391,17 @@ while(bbs.online) { } // Reload frame - if (cmd == '09') { + if (cmd === '09') { fo.cursorOff(); action = ACTION_GOTO; cmd = ''; - next_page = { frame: fo.frame, index: fo.index}; + next_page = {frame: fo.frame,index: fo.index}; break; } // Another star aborts the command - if (read == '*') { + if (read === '*') { fo.clearBaseline(false); fo.cursorOff(); mode = action = false; @@ -325,19 +421,19 @@ while(bbs.online) { } } - if ((viewdata && read=='_') || (! viewdata && read == '#') || read == '\r') { + if ((viewdata && read === '_') || (! viewdata && read === '#') || read === "\r") { // Nothing typed between * and # // *# means go back - if (cmd == '') { + if (cmd === '') { fo.clearBaseline(false); action = ACTION_BACKUP; - } else if (cmd == '0') { - next_page = { frame: user.number ? 1 : 98,index: 'a' }; // @todo specify home page in config + } else if (cmd === '0') { + next_page = user.number ? HOME_FRAME : LOGIN_FRAME; action = ACTION_GOTO; // Edit frame - } else if (cmd == '04') { + } else if (cmd === '04') { // If we are not a user if (! user.number) { fo.sendBaseline('ERR_ROUTE',false); @@ -348,7 +444,7 @@ while(bbs.online) { } } else { - next_page = { frame: cmd }; + next_page = {frame: parseInt(cmd),index: 'a'}; action = ACTION_GOTO; } @@ -362,7 +458,6 @@ while(bbs.online) { // Key presses during field input. case MODE_FIELD: - //$cmd = ''; action = false; switch (fo.type) { @@ -371,33 +466,35 @@ while(bbs.online) { switch (read) { case '_': if (! viewdata) break; + /* fallthrough */ case '#': - case '\r': + case "\r": log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_LOGIN: ['+read+'] A'); // If we are the main login screen, see if it is a new user - // @todo Need to make sure this is only actioned on user login - if (cf.ftype == 't' && cf.fvalue.toUpperCase() == 'NEW') { + if (cf.ftype === 't' && cf.fvalue.toUpperCase() === 'NEW') { action = ACTION_GOTO; - next_page = { frame: 981,index: 'a' }; // @todo This should be in the INI. + next_page = REGISTER_FRAME; break; } break; } + /* fallthrough */ // Response frame. case FRAME_TYPE_RESPONSE: // If we came from FRAME_TYPE_LOGIN and the user typed NEW to register - if (action == ACTION_GOTO) + if (action === ACTION_GOTO) break; switch (read) { // End of field entry. case '_': if (! viewdata) break; + /* fallthrough */ case '#': - case '\r': + case "\r": log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: # ['+read+']'); // Next Field fn++; @@ -424,13 +521,13 @@ while(bbs.online) { case '*': log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: ['+read+']'); - //$current['prevmode'] = MODE_FIELD; action = ACTION_STAR; break; // Delete Key pressed case CTRL_H: + case KEY_DEL: log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: DEL ['+read+']'+' cf:'+(cf ? cf.fvalue.length : '{}')+' ct:'+cf.ftype); if (cf.fvalue.length > 0) { @@ -523,7 +620,7 @@ while(bbs.online) { control[control.length-1].process(); - } else if (fo.key[1] == '*' || fo.key[1].match(/[0-9]/)) { + } else if (fo.key[1] === '*' || fo.key[1].match(/[0-9]/)) { fo.sendBaseline('NOACTION',false); mode = MODE_RFSENT; @@ -547,13 +644,13 @@ while(bbs.online) { log(LOG_DEBUG,' ! Login failed for User:'+JSON.stringify(fo.frame_fields[0].fvalue)); action = ACTION_GOTO; - next_page = { frame: 983,index: 'a' }; + next_page = LOGIN_FAILED_FRAME; break; default: // Its assumed that you get here after completing a form and you have pressed 1 to submit that form. log(LOG_DEBUG,' ! EVAL method:'+JSON.stringify(fo.key)); - x = cc.process(); + var x = cc.process(); log(LOG_DEBUG,' = EVAL method:'+JSON.stringify(x)); } /* @@ -580,7 +677,7 @@ while(bbs.online) { log(LOG_DEBUG,'- MODE_SUBMITRF: Key ['+read+'] ['+pageStr(fo)+']'); // @todo Check if HASH is a valid next destination - if (fo.type == 'l') { + if (fo.type === 'l') { action = ACTION_RELOAD; mode = false; @@ -658,7 +755,7 @@ while(bbs.online) { case MODE_RFERROR: fo.cursorOff(); - if ((viewdata && read == '_') || (! viewdata && read == '#')) { + if ((viewdata && read === '_') || (! viewdata && read === '#')) { /* if ($x = $this->fo->route(2) AND $x !== '*' AND is_numeric($x)) { $next_page = ['frame'=>$x]; @@ -677,7 +774,7 @@ while(bbs.online) { action = ACTION_GOTO; - } else if (read == '*') { + } else if (read === '*') { action = ACTION_STAR; break; @@ -716,16 +813,16 @@ while(bbs.online) { action = false; fo.cursorOff(); log(LOG_DEBUG,'- ACTION_SUBMITRF: ['+fo.type+']'); - fo.sendBaseline((fo.type == 'l' ? 'MSG_LOGON' : 'MSG_SENDORNOT'),true); + fo.sendBaseline((fo.type === 'l' ? 'MSG_LOGON' : 'MSG_SENDORNOT'),true); mode = MODE_SUBMITRF; break; // Edit a frame case ACTION_EDIT: - log(LOG_DEBUG,'- ACTION_EDIT: ['+JSON.stringify(fe)+']'); + log(LOG_DEBUG,'- ACTION_EDIT: ['+JSON.stringify(next_page)+']'); - if (! pageEditor(fe ? fe.frame : fo.frame)) { + if (! pageEditor(next_page ? next_page.frame : fo.frame)) { fo.cursorOff(); fo.sendBaseline('ACCESS_DENIED',false); action = false; @@ -735,21 +832,21 @@ while(bbs.online) { require('ansitex/load/edit.js','CONTROL_EDIT'); // If we are editing a specific frame, attempt to load it - if (fe) { - current = fo; + if (next_page) { + var current = fo; fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame(); - fo.load(pageStr(fe)); + fo.load(pageStr(next_page)); // If the frame doesnt exist, check that the parent frame exists in case we are creating a new one if (fo.page == null) { - log(LOG_DEBUG,'- ACTION_EDIT: check index: '+fe.index+' ('+String.fromCharCode(fe.index.charCodeAt(0)-1)+')'); + log(LOG_DEBUG,'- ACTION_EDIT: check index: '+next_page.index+' ('+String.fromCharCode(next_page.index.charCodeAt(0)-1)+')'); // We can always create an 'a' frame - if (fe.index !== 'a') { + if (next_page.index !== 'a') { fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame(); - fo.load(pageStr({frame: fe.frame, index: String.fromCharCode(fe.index.charCodeAt(0)-1)})); + fo.load(pageStr({frame: next_page.frame, index: String.fromCharCode(next_page.index.charCodeAt(0)-1)})); - log(LOG_DEBUG,'- ACTION_EDIT: check index: '+JSON.stringify(fo)+' ('+String.fromCharCode(fe.index.charCodeAt(0)-1)+')'); + log(LOG_DEBUG,'- ACTION_EDIT: check index: '+JSON.stringify(fo)+' ('+String.fromCharCode(next_page.index.charCodeAt(0)-1)+')'); if (fo.page == null) { fo = current; // sendbaseline ERR_PAGE @@ -761,10 +858,10 @@ while(bbs.online) { // New frame fo = viewdata ? new VIEWDATAFrame() : new ANSIFrame(); - fo.frame = fe.frame; - fo.index = fe.index; + fo.frame = next_page.frame; + fo.index = next_page.index; fo.cost = 0; - fo.owner = base64_decode(pageOwner(pageStr(fe)).logo); + fo.owner = base64_decode(pageOwner(pageStr(next_page)).logo); fo.content = base64_encode('Start your new page...'); } } @@ -796,6 +893,15 @@ while(bbs.online) { // Goto specific page case ACTION_GOTO: log(LOG_DEBUG,'- ACTION_GOTO: ['+(next_page ? pageStr(next_page) : '')+']'); + var current = null; + + // Check if this is a mail prefix. + // 1zzzzEEnnnn + if (user.number && /^1[0-9]{10}/.test(next_page.frame)) { + fo.sendBaseline('INVALID_EMAIL',false); + mode = action = false; + break; + } if (next_page !== null) { current = fo; @@ -818,7 +924,7 @@ while(bbs.online) { // If the user has access to the frame if (fo.accessible) { - if (fo.isMember && fo.type == FRAME_TYPE_LOGIN) { + if (fo.isMember && fo.type === FRAME_TYPE_LOGIN) { fo.sendBaseline('ALREADY_MEMBER',false); mode = action = false; break; @@ -833,13 +939,12 @@ while(bbs.online) { break; } - current = null; log(LOG_DEBUG,'- ACTION_GOTO: next_page ['+JSON.stringify(next_page)+'] last history ['+JSON.stringify(history[history.length-1])+']'); // Record our history - if (next_page && (! history.length || (pageStr(history[history.length-1]) != pageStr(next_page))) && (fo.type != FRAME_TYPE_LOGIN)) { + if (next_page && (! history.length || (pageStr(history[history.length-1]) !== pageStr(next_page))) && (fo.type !== FRAME_TYPE_LOGIN)) { // Ignore the login frames - if (NO_HISTORY_FRAMES.indexOf(pageStr(next_page)) == -1) { + if (NO_HISTORY_FRAMES.indexOf(pageStr(next_page)) === -1) { history.push(next_page); log(LOG_DEBUG,'- ACTION_GOTO: Added to history ['+(next_page ? pageStr(next_page) : '')+'] now ['+history.length+']'); } @@ -851,10 +956,7 @@ while(bbs.online) { case ACTION_RELOAD: log(LOG_DEBUG,'- ACTION_RELOAD: ['+(next_page ? pageStr(next_page) : '')+']'); - // Clear the baseline history - // $this->sendBaseline($client,''); - // $current['baseline'] = ''; - console.line_counter=0; // @todo fix to suppress a pause that is occurring before clear() + console.line_counter = 0; // @todo fix to suppress a pause that is occurring before clear() fo.cursorOff(); // Clear any controls @@ -887,7 +989,7 @@ while(bbs.online) { eval(content); // Check and see if our shell was changed - if (user.command_shell != 'ansitex') { + if (user.command_shell !== 'ansitex') { exit(); } @@ -906,6 +1008,7 @@ while(bbs.online) { case FRAME_TYPE_LOGIN: action = false; + /* fallthrough */ case FRAME_TYPE_RESPONSE: fn = 0; @@ -932,13 +1035,12 @@ while(bbs.online) { } // If this is the register page - // @todo this needs to be configurable - if (fo.page == '981a') { + if (fo.page === pageStr(REGISTER_FRAME)) { log(LOG_DEBUG,'Adding REGISTER to control stack'); require('ansitex/load/'+fo.key[1]+'.js','CONTROL_REGISTER'); control.push(eval("new "+fo.key[1]+'();')); - } else if (fo.page == '982a') { + } else if (fo.page === pageStr(SQRL_FRAME)) { log(LOG_DEBUG,'Adding SQRL to control stack'); require('ansitex/load/'+fo.key[1]+'.js','CONTROL_SQRL'); control.push(eval("new "+fo.key[1]+'();')); @@ -966,7 +1068,7 @@ while(bbs.online) { } log(LOG_DEBUG,'- FINISHED'); - if (action == ACTION_TERMINATE) { + if (action === ACTION_TERMINATE) { log(LOG_DEBUG,'! Hangup'); bbs.hangup(); }