Enabled login and shell

This commit is contained in:
Deon George 2020-05-27 21:56:12 +10:00
parent 8e2b715829
commit 0febc9ff38
3 changed files with 471 additions and 99 deletions

View File

@ -2,6 +2,7 @@
* ANSItex definitions * ANSItex definitions
*/ */
var ACTION_EXIT =99; /* Exit the script */
var ACTION_RELOAD =1; /* Reload the current frame */ var ACTION_RELOAD =1; /* Reload the current frame */
var ACTION_GOTO =2; /* Goto a specific frame */ var ACTION_GOTO =2; /* Goto a specific frame */
var ACTION_BACKUP =3; /* Goto previous frame */ var ACTION_BACKUP =3; /* Goto previous frame */
@ -11,6 +12,11 @@ var ACTION_SUBMITRF =6; /* Submit form contents */
var ACTION_STAR =7; /* Star command entry */ var ACTION_STAR =7; /* Star command entry */
var MODE_BL =1; /* Typing * command on baseline */ 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 */
var FRAME_LENGTH =22; /* Length of a frame */ var FRAME_LENGTH =22; /* Length of a frame */
var FRAME_WIDTH =80; /* Width of a frame */ var FRAME_WIDTH =80; /* Width of a frame */
@ -19,52 +25,71 @@ var FRAME_PAGENUM =12; /* Size of page number (length with a-z) */
var FRAME_COST = 9; /* Size of cost (length without unit) */ var FRAME_COST = 9; /* Size of cost (length without unit) */
var FRAME_COSTUNIT ='c'; /* Unit of cost */ var FRAME_COSTUNIT ='c'; /* Unit of cost */
var FRAME_TYPE_INFO ='i'; var FRAME_TYPE_INFO ='i'; // Information Frame, requires no response after viewed
var FRAME_TYPE_TERMINATE ='t'; var FRAME_TYPE_TERMINATE ='t'; // Terminate Frame, contents displayed and then carrier dropped
var FRAME_TYPE_EXTERNAL ='x'; var FRAME_TYPE_EXTERNAL ='x'; // Frame the calls an External Method
var FRAME_TYPE_RESPONSE ='r'; // Contents indicate the method to be called with arguments
var FRAME_TYPE_LOGIN ='l'; 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
var ERR_NOT_IMPLEMENTED ='\1RNOT IMPLEMENTED YET?'; var MSG_SENDORNOT ='\1n\1h\1GKEY 1 TO SEND, 2 NOT TO SEND';
var MSG_LOGON ='\1n\1h\1GKEY 1 TO LOGON, 2 TO RETURN';
var MSG_SENT ='\1n\1h\1GMESSAGE SENT - KEY # TO CONTINUE';
var MSG_NOTSENT ='\1n\1h\1GMESSAGE NOT SENT - KEY # TO CONTINUE';
var ERR_NOT_IMPLEMENTED ='\1n\1h\1RNOT IMPLEMENTED YET?';
var ERR_ROUTE ='\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08'; var ERR_ROUTE ='\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
var ERR_METHOD_NOT_EXIST ='\1n\1h\1WMISTAKE? \1GTRY AGAIN OR TELL US ON *08';
var ACCESS_DENIED ='\1n\1h\1RACCESS DENIED. \1RMISTAKE? TRY AGAIN OR TELL US *08';
var NO_HISTORY_FRAMES =['98b']; var NO_HISTORY_FRAMES =['98b'];
var SYSTEM_FRAMES =['AWgBUkEBR04BQlMBWUkBbgE3AWt0ZXgBbg=='];
// Our frame object // Our frame object
function Frame() { function Frame() {
this.version=1; this.version=1; // The version of this frame - in case we update functionality and we need to be
this.frame=null; // backwards compatible
this.index=null; this.frame=null; // Frame Number [0-9]+
this.owner=''; // @todo this.index=null; // Frame Index [a-z]
this.cost=0; // @todo this.owner=''; // The Service Provider owning the frame.
this.content=''; this.cost=0; // The cost to view the frame @TODO
this.isPublic=false; // @todo this.content=''; // The frame content
this.isAccessible=false; // @todo
this.type = FRAME_TYPE_INFO;
this.key=[ null,null,null,null,null,null,null,null,null,null ];
// Initialise frame array // Frame's owned by the system where:
/* // isPublic is FALSE - the user must be logged in to view it
this.frame_data = {}; // isPublic is TRUE - can be viewed by non-logged in users
this.frame_content = {};
for(x=0;x<FRAME_LENGTH;x++)
{
this.frame_data[x] = {};
this.frame_content[x] = {};
}
*/
this.frame_fields = [];
// 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)
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
this.isAccessible=false; // Is this frame available to be accessed
// If FALSE, only the SP can view/edit the frame
this.type = FRAME_TYPE_INFO; // The frame type - see FRAME_TYPES above
this.key=[ null,null,null,null,null,null,null,null,null,null ]; // Key actions [0-9]
this.frame_fields = []; // If a response frame, the embedded fields in the frame
// The RAW frame content
this.raw=function() { this.raw=function() {
return base64_decode(this.content).replace(/(\r\n|\n|\r)/gm,''); return base64_decode(this.content).replace(/(\r\n|\n|\r)/gm,'');
}; };
// Render the frame to the user
this.render=function(withHeader) { this.render=function(withHeader) {
owner = base64_decode(this.owner); owner = base64_decode(this.owner);
header = '\n\r'; header = '\n\r';
if (this.type != FRAME_TYPE_LOGIN) { log(LOG_DEBUG,'- FRAME User: ['+JSON.stringify(user)+']');
// Dont show the page number on system login page
if (user.number || this.type != FRAME_TYPE_LOGIN) {
header = '\1n'+owner+' '.repeat(FRAME_HEADER-console.strlen(owner))+'\1n '+ header = '\1n'+owner+' '.repeat(FRAME_HEADER-console.strlen(owner))+'\1n '+
'\1W\1H'+this.page+' '.repeat(FRAME_PAGENUM-this.page.length)+' '+ '\1W\1H'+this.page+' '.repeat(FRAME_PAGENUM-this.page.length)+' '+
'\1G\1H'+' '.repeat(FRAME_COST-this.cost.toString().length)+this.cost+FRAME_COSTUNIT+ '\1G\1H'+' '.repeat(FRAME_COST-this.cost.toString().length)+this.cost+FRAME_COSTUNIT+
@ -90,6 +115,28 @@ function Frame() {
return this.frame_fields; return this.frame_fields;
} }
}); });
Object.defineProperty(this,'accessible',{
get: function() {
log(LOG_DEBUG,'- Checking if user can access frame: '+this.page);
log(LOG_DEBUG,' - User: '+JSON.stringify(user.number));
log(LOG_DEBUG,' - Frame Owner: '+JSON.stringify(this.owner)+', System Frame: '+(SYSTEM_FRAMES.indexOf(this.owner)>-1));
system_frame = (SYSTEM_FRAMES.indexOf(this.owner)>-1);
// user.number 0 is unidentified user.
if (user.number) {
return (
(this.isAccessible && this.isPublic) ||
(this.isAccessible && ! this.isPublic && user.isMember) ||
(user.isOwner)
);
} else {
return (system_frame && this.isPublic && this.isAccessible);
}
}
});
} }
// Load a frame from disk (.tex file) // Load a frame from disk (.tex file)
@ -102,7 +149,7 @@ Frame.prototype.load = function(filename) {
} }
try { try {
load = JSON.parse(f.read()); var load = JSON.parse(f.read());
for (property in load) { for (property in load) {
this[property] = load[property]; this[property] = load[property];
@ -134,8 +181,9 @@ Frame.prototype.load = function(filename) {
*/ */
Frame.prototype.parse = function(text) { Frame.prototype.parse = function(text) {
var c = 1; // column var c = 1; // column
var r = 1; // row var r = 2; // row (row 1 is the header)
var output = ''; var output = '';
this.frame_fields = [];
// Default Attributes // Default Attributes
f = 39; f = 39;
@ -146,11 +194,11 @@ Frame.prototype.parse = function(text) {
// Look for a special character until the end of the frame width // Look for a special character until the end of the frame width
cte = (r*FRAME_WIDTH - ((r-1)*FRAME_WIDTH+c)); cte = (r*FRAME_WIDTH - ((r-1)*FRAME_WIDTH+c));
match = text.substr(p,cte).match(/[\r\n\x1b]/); match = text.substr(p,cte).match(/[\r\n\x1b]/);
log(LOG_DEBUG,'SPECIAL CHAR ['+r+'x'+c+'] ['+p+'-'+cte+'] for: '+match); //log(LOG_DEBUG,'SPECIAL CHAR ['+r+'x'+c+'] ['+p+'-'+cte+'] for: '+match);
if (match == null || match.index) { if (match == null || match.index) {
advance = match ? match.index : cte; advance = match ? match.index : cte;
log(LOG_DEBUG,'INCLUDE: '+text.substr(p,advance)); //log(LOG_DEBUG,'INCLUDE: '+text.substr(p,advance));
output += text.substr(p,advance); output += text.substr(p,advance);
p += advance; p += advance;
@ -165,13 +213,13 @@ Frame.prototype.parse = function(text) {
switch (byte) { switch (byte) {
// Carriage Return // Carriage Return
case '\r': case '\r':
log(LOG_DEBUG,'CR'); // log(LOG_DEBUG,'CR');
c=1; c=1;
break; break;
// New line // New line
case '\n': case '\n':
log(LOG_DEBUG,'LF'); // log(LOG_DEBUG,'LF');
r++; r++;
break; break;
@ -180,7 +228,7 @@ Frame.prototype.parse = function(text) {
advance = 1; advance = 1;
// Is the next byte something we know about // Is the next byte something we know about
nextbyte = text.charAt(p+advance); nextbyte = text.charAt(p+advance);
log(LOG_DEBUG,'ESC ['+r+'x'+c+'] NEXT: '+nextbyte); //log(LOG_DEBUG,'ESC ['+r+'x'+c+'] NEXT: '+nextbyte);
switch (nextbyte) { switch (nextbyte) {
// CSI // CSI
@ -190,7 +238,7 @@ Frame.prototype.parse = function(text) {
// Find our end CSI param in the next 50 chars // Find our end CSI param in the next 50 chars
matches = text.substr(p+advance,50).match(/([0-9]+[;]?)+([a-zA-Z])/); matches = text.substr(p+advance,50).match(/([0-9]+[;]?)+([a-zA-Z])/);
log(LOG_DEBUG,'CSI ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+matches+', STRING: '+text.substr(p+advance,50)); //log(LOG_DEBUG,'CSI ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+matches+', STRING: '+text.substr(p+advance,50));
if (! matches) { if (! matches) {
chars += nextbyte; chars += nextbyte;
@ -200,17 +248,17 @@ Frame.prototype.parse = function(text) {
advance += matches[0].length-1; advance += matches[0].length-1;
chars += nextbyte+matches[0]; chars += nextbyte+matches[0];
log(LOG_DEBUG,'CSI ['+r+'x'+c+'] ADVANCE: '+advance+', CHARS: '+chars+', CHARSLEN: '+chars.length); //log(LOG_DEBUG,'CSI ['+r+'x'+c+'] ADVANCE: '+advance+', CHARS: '+chars+', CHARSLEN: '+chars.length);
switch (matches[2]) { switch (matches[2]) {
// Color CSIs // Color CSIs
case 'm': case 'm':
log(LOG_DEBUG,'CSI m ['+r+'x'+c+'] MATCHES: '+matches[0]+', LENGTH : '+matches[0].length); //log(LOG_DEBUG,'CSI m ['+r+'x'+c+'] MATCHES: '+matches[0]+', LENGTH : '+matches[0].length);
csi = matches[0].substr(0,matches[0].length-1).split(';'); csi = matches[0].substr(0,matches[0].length-1).split(';');
var num = null; var num = null;
for (num in csi) { for (num in csi) {
log(LOG_DEBUG,'CSI m ['+r+'x'+c+'] NUM: '+num+', CSI: '+csi[num]); //log(LOG_DEBUG,'CSI m ['+r+'x'+c+'] NUM: '+num+', CSI: '+csi[num]);
// Intensity // Intensity
if (csi[num] >= 0 && csi[num] <= 8) { if (csi[num] >= 0 && csi[num] <= 8) {
i = csi[num]; i = csi[num];
@ -230,12 +278,12 @@ Frame.prototype.parse = function(text) {
// Advance characters // Advance characters
case 'C': case 'C':
log(LOG_DEBUG,'CSI C ['+r+'x'+c+'] CHARS: '+matches[1]); //log(LOG_DEBUG,'CSI C ['+r+'x'+c+'] CHARS: '+matches[1]);
c += parseInt(matches[1]); // Advance our position c += parseInt(matches[1]); // Advance our position
break; break;
default: default:
dump('? CSI: '.matches[2]); log(LOG_DEBUG,'? CSI: '.matches[2]);
} }
break; break;
@ -247,12 +295,12 @@ Frame.prototype.parse = function(text) {
// SOS // SOS
case '_': case '_':
log(LOG_DEBUG,'SOS ['+r+'x'+c+'] '+advance); //log(LOG_DEBUG,'SOS ['+r+'x'+c+'] '+advance);
advance++; advance++;
// Find our end ST param in the next 50 chars // Find our end ST param in the next 50 chars
matches = text.substr(p+advance,50).match(/(([A-Z]+;[0-9a-z]+)([;]?.+)?)\x1b\\/); matches = text.substr(p+advance,50).match(/(([A-Z]+;[0-9a-z]+)([;]?.+)?)\x1b\\/);
log(LOG_DEBUG,'SOS ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+matches+', LENGTH: '+matches[0].length+', STRING: '+text.substr(p+advance,50)); //log(LOG_DEBUG,'SOS ['+r+'x'+c+'] ADVANCE: '+advance+', MATCHES: '+matches+', LENGTH: '+matches[0].length+', STRING: '+text.substr(p+advance,50));
if (! matches) { if (! matches) {
chars += nextbyte; chars += nextbyte;
@ -264,12 +312,12 @@ Frame.prototype.parse = function(text) {
// The last 2 chars of matches[0] are the ESC \ // The last 2 chars of matches[0] are the ESC \
sos = matches[0].substr(0,matches[0].length-2).split(';'); sos = matches[0].substr(0,matches[0].length-2).split(';');
log(LOG_DEBUG,'SOS ['+r+'x'+c+'] ADVANCE: '+advance+', SOS: '+sos); //log(LOG_DEBUG,'SOS ['+r+'x'+c+'] ADVANCE: '+advance+', SOS: '+sos);
var num = null; var num = null;
var fieldlen = null; var fieldlen = null;
for (num in sos) { for (num in sos) {
log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM: '+num+', SOS: '+sos[num]); //log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM: '+num+', SOS: '+sos[num]);
switch (num) { switch (num) {
// First value is the field name // First value is the field name
@ -285,7 +333,7 @@ Frame.prototype.parse = function(text) {
break; break;
} }
log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM CHARS: '+x[1]+', TYPE: '+x[2]); //log(LOG_DEBUG,'SOS ['+r+'x'+c+'] NUM CHARS: '+x[1]+', TYPE: '+x[2]);
fieldlen = x[1]; fieldlen = x[1];
fieldtype = x[2]; fieldtype = x[2];
break; break;
@ -296,7 +344,7 @@ Frame.prototype.parse = function(text) {
break; break;
default: default:
log(LOG_ERROR,'IGNORING ADITIONAL SOS FIELDS. ['+r+'x'+c+'] '+sos[num]); log(LOG_ERROR,'IGNORING ADDITIONAL SOS FIELDS. ['+r+'x'+c+'] '+sos[num]);
} }
} }
@ -307,11 +355,12 @@ Frame.prototype.parse = function(text) {
byte = ''; byte = '';
this.frame_fields.push({ this.frame_fields.push({
type: fieldtype, ftype: fieldtype,
length: fieldlen, flength: fieldlen,
r: r, r: r,
c: c, c: c,
attribute: {i:i,f:f,b:b}, attribute: {i:i,f:f,b:b},
fvalue: '',
}); });
log(LOG_DEBUG,'SOS Field found at ['+r+'x'+(c-1)+'], Type: '+fieldtype+', Length: '+fieldlen+', Attrs: '+JSON.stringify({i:i,f:f,b:b})); log(LOG_DEBUG,'SOS Field found at ['+r+'x'+(c-1)+'], Type: '+fieldtype+', Length: '+fieldlen+', Attrs: '+JSON.stringify({i:i,f:f,b:b}));
@ -325,16 +374,13 @@ Frame.prototype.parse = function(text) {
break; break;
default: default:
//this.frame_data[r][c] = {i:i,f:f,b:b};
//this.frame_content[r][c] = byte;
log(LOG_DEBUG,'ADD OUTPUT ['+r+'x'+c+'] for: '+byte);
c++; c++;
} }
output += byte; output += byte;
if (advance) { if (advance) {
log(LOG_DEBUG,'ADVANCE P ['+r+'x'+c+'] '+advance+', NEXT CHAR: '+text.charAt(p+advance)+' ('+text.charCodeAt(p+advance)+')'); //log(LOG_DEBUG,'ADVANCE P ['+r+'x'+c+'] '+advance+', NEXT CHAR: '+text.charAt(p+advance)+' ('+text.charCodeAt(p+advance)+')');
output += chars; output += chars;
p += advance; p += advance;
} }
@ -344,19 +390,15 @@ Frame.prototype.parse = function(text) {
r++; r++;
} }
/*
// @todo - If we are longer than FRAME_LENGTH, move the output into the next frame. // @todo - If we are longer than FRAME_LENGTH, move the output into the next frame.
if (r>FRAME_LENGTH) { if (r>FRAME_LENGTH) {
break; break;
} }
*/
// Debugging
if (false && r > 3) {
console.write(output);
bbs.hangup();
exit(1);
}
} }
return output; return output;
}; };
this;

View File

@ -41,6 +41,9 @@ if (!String.prototype.repeat) {
}; };
} }
/**
* Turn off the cursor
*/
function cursorOff() { function cursorOff() {
ansi.send('ext_mode','clear','cursor'); ansi.send('ext_mode','clear','cursor');
console.gotoxy(0,24); console.gotoxy(0,24);
@ -148,6 +151,12 @@ function saveFrame(frame) {
log(LOG_DEBUG,'Saved file: '+frame.page+'.tex'); log(LOG_DEBUG,'Saved file: '+frame.page+'.tex');
} }
/**
* Send a message to the baseline.
*
* @param text
* @param reposition
*/
function sendBaseline(text,reposition) { function sendBaseline(text,reposition) {
console.pushxy(); console.pushxy();
console.gotoxy(0,24); console.gotoxy(0,24);
@ -157,4 +166,6 @@ function sendBaseline(text,reposition) {
if (! reposition) { if (! reposition) {
console.popxy(); console.popxy();
} }
} }
this;

391
main.js
View File

@ -1,34 +1,46 @@
log(LOG_DEBUG,'- INIT: ANSITEX');
// Load many SBBS definitions // Load many SBBS definitions
load('sbbsdefs.js'); require('sbbsdefs.js','SS_UNUSED');
// Load text.dat defintions // Load text.dat definitions
load('text.js'); require('text.js','TOTAL_TEXT');
// Key definitions // Key definitions
load('key_defs.js'); require('key_defs.js','KEY_ESC');
// Enable to manipulate the ANSI terminal
ansi = load({},'ansiterm_lib.js'); ansi = load({},'ansiterm_lib.js');
load('ansitex/load/funcs.js');
// Ansitex specific includes // Ansitex specific includes
load('ansitex/load/defs.js'); require('ansitex/load/defs.js','ACTION_EXIT');
load('ansitex/load/funcs.js');
while(bbs.online) { while(bbs.online) {
var mode = false; // Initial mode var mode = false; // Initial mode
var next_page = { frame: 98,index: 'b' }; // Start Frame
// If the user is already on, our start page is 98b
var next_page = { frame: 98,index: user.number ? 'b' : 'a' }; // Start Frame
var action = ACTION_GOTO; // Initial action var action = ACTION_GOTO; // Initial action
var inkey_timeout = 600000; // Timeout waiting for input @todo required? check if idle timetout occurs var inkey_timeout = 10000; // Timeout waiting for input @todo required? check if idle timeout occurs
var fo = null; // Current Frame var fo = null; // Current Frame
var fn = null; // Current Field Number for an Input Frame
var history = []; // Page history var history = []; // Page history
var control = []; // Methods that need to process input
ansi.send('ext_mode','clear','cursor'); ansi.send('ext_mode','clear','cursor');
while (action != ACTION_TERMINATE) { while (action != ACTION_TERMINATE && action !=ACTION_EXIT) {
bbs.nodesync(false); // @todo Stop the display of telegrams bbs.nodesync(false); // @todo Stop the display of telegrams
read = ''; read = '';
// If we have no action, read from the terminal
if (action == false) { if (action == false) {
read = console.inkey(K_NONE,inkey_timeout); read = console.inkey(K_NONE,inkey_timeout);
} }
system.node_list[bbs.node_num-1].action=0xff; // to ensure our node status is updated correctly
inkey_timeout = 60000; // Set our key timeout to 60s
log(LOG_DEBUG,'READ: ['+read+']'); log(LOG_DEBUG,'READ: ['+read+']');
inkey_timeout = 60000; // Set our key timeout to 60s
system.node_list[bbs.node_num-1].action=0xff; // to ensure our node status is updated correctly
log(LOG_DEBUG,'MODE START: ['+read+']'); log(LOG_DEBUG,'MODE START: ['+read+']');
switch (mode) { switch (mode) {
@ -177,10 +189,272 @@ while(bbs.online) {
break; break;
// @todo MODE_CONTROL // Key presses during field input.
case MODE_FIELD:
//$cmd = '';
action = false;
switch (fo.type) {
// Login frame.
case FRAME_TYPE_LOGIN:
switch (read) {
case '#':
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
//if ($this->fo->isCUG(0)) {
if (fo.frame_fields[fn].ftype == 't' && fo.frame_fields[fn].fvalue == 'NEW') {
action = ACTION_GOTO;
next_page = { frame: 981,index: 'a' }; // @todo This should be in the INI.
break;
}
//}
break;
}
// Response frame.
case FRAME_TYPE_RESPONSE:
// If we came from FRAME_TYPE_LOGIN and the user typed NEW to register
if (action == ACTION_GOTO)
break;
switch (read) {
// End of field entry.
case '#':
case '\r':
log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: ['+read+'] A');
// Next Field
fn++;
cf = fo.frame_fields[fn];
log(LOG_DEBUG,'fn:'+fn+', cf'+JSON.stringify(cf));
if (cf) {
mode = MODE_FIELD;
console.gotoxy(cf.c,cf.r);
console.write(KEY_ESC+'['+cf.attribute.i+';'+cf.attribute.f+';'+cf.attribute.b+'m');
// Finished all editable fields.
} else {
action = ACTION_SUBMITRF;
}
break;
case '*':
log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: ['+read+'] B');
//$current['prevmode'] = MODE_FIELD;
action = ACTION_STAR;
break;
case KEY_DEL:
log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: ['+read+'] C');
/*
if ($this->fo->setFieldCurrentInputDelete())
$client->send(LEFT.$this->fo::$if_filler.LEFT);
*/
break;
case KEY_ESC:
log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: ['+read+'] D');
break;
// Record Data Entry
default:
log(LOG_DEBUG,'- MODE_FIELD:FRAME_TYPE_RESPONSE: ['+read+'] E:'+read.charCodeAt(0)+' cf:'+(cf ? cf.flength : '{}'));
if (read.charCodeAt(0) > 31 && cf.fvalue.length < cf.flength) {
cf.fvalue += read;
console.write((cf.ftype == 't') ? read : 'x');
}
}
break;
// Other Frame Types - Shouldnt get here.
default:
log(LOG_DEBUG,'- SHOULDNT GET HERE: ['+read+']');
action = ACTION_TERMINATE;
}
break;
// Form submission: 1 to send, 2 not to send.
case MODE_SUBMITRF:
switch (read) {
case '1':
log(LOG_DEBUG,'- MODE_SUBMITRF: Key ['+read+'] ['+pageStr(fo)+']');
log(LOG_DEBUG,' - Frame fields: '+JSON.stringify(fo.frame_fields));
log(LOG_DEBUG,' - Key 1 is:'+JSON.stringify(fo.key[1]));
// If we are in a control method, complete it
if (control.count) {
log(LOG_DEBUG,'Last control method is:'+JSON.stringify(control[control.length-1]));
control[control.length-1].process();
} else if (fo.key[1] == '*' || fo.key[1].match(/[0-9]/)) {
sendBaseline('\1n\1h\1RNO ACTION PERFORMED',false);
mode = MODE_RFSENT;
} else {
log(LOG_DEBUG,' - Key 1 is a METHOD check it exists:'+JSON.stringify(fo.key[1]));
switch(fo.key[1]) {
// User is logging in to system or CUG
case 'login':
log(LOG_DEBUG,' - User:'+JSON.stringify(fo.frame_fields[0].fvalue));
// If login is successful, we'll exit here
if (bbs.login(fo.frame_fields[0].fvalue,null,fo.frame_fields[1].fvalue)) {
log(LOG_DEBUG,' - User:'+JSON.stringify(user.number));
bbs.logon();
log(LOG_DEBUG,' - SEND TO EXIT:');
action = ACTION_EXIT;
break;
}
log(LOG_DEBUG,' ! Login failed for User:'+JSON.stringify(fo.frame_fields[0].fvalue));
break;
}
/*
} elseif ($ao = FrameClass\Action::factory($this->fo->route(1),$this,$user,$action,$mode)) {
$ao->handle();
$mode = $ao->mode;
$action = $ao->action;
if ($ao->page)
$next_page = $ao->page;
} else {
sendBaseline(ERR_METHOD_NOT_EXIST,false);
mode = MODE_RFSENT;
}
*/
}
break;
case '2':
log(LOG_DEBUG,'- MODE_SUBMITRF: Key ['+read+'] ['+pageStr(fo)+']');
// @todo Check if HASH is a valid next destination
if (fo.type == 'l') {
action = ACTION_RELOAD;
mode = false;
} else {
sendBaseline(MSG_NOTSENT,false);
mode = MODE_RFNOTSENT;
}
/*
// If a Control method was rejected, we can clear it
if ($control AND $method->count()) {
$save = $method->pop();
if ($method->count()) {
$control = $method->last()->state['control'];
} else {
$mode = $save->state['mode'];
$action = $save->state['action'];
$control = FALSE;
}
}
*/
break;
case '*':
action = ACTION_STAR;
break;
}
break;
// Response form after Sent processing
case MODE_RFSENT:
ansi.send('ext_mode','clear','cursor');
switch (read) {
case '*':
action = ACTION_STAR;
break;
}
/*
if ($read == HASH) {
if ($x = $this->fo->route(2) AND $x !== '*' AND is_numeric($x)) {
$next_page = ['frame'=>$x];
} elseif (FrameModel::where('frame',$this->fo->frame())->where('index',$this->fo->index_next())->exists()) {
$next_page = ['frame'=>$this->fo->frame(),'index'=>$this->fo->index_next()];
} elseif ($x = $this->fo->route(0) AND $x !== '*' AND is_numeric($x)) {
$next_page = ['frame'=>$x];
// No further routes defined, go home.
} else {
$next_page = ['frame'=>0];
}
$action = ACTION_GOTO;
}
*/
break;
// Response form after NOT sending
case MODE_RFNOTSENT:
// Response form ERROR
case MODE_RFERROR:
cursorOff();
if (read == '#') {
/*
if ($x = $this->fo->route(2) AND $x !== '*' AND is_numeric($x)) {
$next_page = ['frame'=>$x];
} elseif (FrameModel::where('frame',$this->fo->frame())->where('index',$this->fo->index_next())->exists()) {
$next_page = ['frame'=>$this->fo->frame(),'index'=>$this->fo->index_next()];
} elseif ($x = $this->fo->route(0) AND $x !== '*' AND is_numeric($x)) {
$next_page = ['frame'=>$x];
// No further routes defined, go home.
} else {
$next_page = ['frame'=>0];
}
*/
action = ACTION_GOTO;
} else if (read == '*') {
action = ACTION_STAR;
break;
}
break;
// @todo MODE_CONTROL
default: default:
log(LOG_DEBUG,'- SHOULDNT GET HERE: ['+read+']'); log(LOG_DEBUG,'- SHOULDNT GET HERE: ['+read+']');
action = ACTION_TERMINATE;
} }
log(LOG_DEBUG,'MODE END: ['+read+']'); log(LOG_DEBUG,'MODE END: ['+read+']');
@ -202,6 +476,16 @@ while(bbs.online) {
break; break;
// Submitting forms
case ACTION_SUBMITRF:
action = false;
cursorOff();
log(LOG_DEBUG,'- ACTION_SUBMITRF: ['+fo.type+']');
sendBaseline((fo.type == 'l' ? MSG_LOGON : MSG_SENDORNOT),true);
mode = MODE_SUBMITRF;
break;
// GO Backwards // GO Backwards
case ACTION_BACKUP: case ACTION_BACKUP:
// Do we have anywhere to go, drop the current page from the history. // Do we have anywhere to go, drop the current page from the history.
@ -239,28 +523,19 @@ while(bbs.online) {
current = null; current = null;
} }
if (fo.isPublic && fo.isAccessible) { // If the user has access to the frame
if (fo.accessible) {
// @todo if its a login frame and the user is already member of CUG, display error // @todo if its a login frame and the user is already member of CUG, display error
if (false) { if (false) {
// baseline USER_ALREADY_MEMBER // baseline USER_ALREADY_MEMBER
break; break;
} }
// Check if the frame exists, and the user is the Service Provider
} else { } else {
// @todo if user is not the owner sendBaseline(ACCESS_DENIED,false);
if (false) { mode = action = false;
// @todo if frame is not accessible break;
if (false) {
// baseline ACCESS_DENIED
break;
}
// @todo if user not a member
if (false) {
// baseline ACCESS_DENIED_NOT_IN_CUG
break;
}
}
} }
log(LOG_DEBUG,'- ACTION_GOTO: next_page ['+JSON.stringify(next_page)+'] last history ['+JSON.stringify(history[history.length-1])+']'); log(LOG_DEBUG,'- ACTION_GOTO: next_page ['+JSON.stringify(next_page)+'] last history ['+JSON.stringify(history[history.length-1])+']');
@ -276,6 +551,7 @@ while(bbs.online) {
next_page = null; next_page = null;
// Load frame
case ACTION_RELOAD: case ACTION_RELOAD:
log(LOG_DEBUG,'- ACTION_RELOAD: ['+(next_page ? pageStr(next_page) : '')+']'); log(LOG_DEBUG,'- ACTION_RELOAD: ['+(next_page ? pageStr(next_page) : '')+']');
@ -292,8 +568,10 @@ while(bbs.online) {
// Terminate frame // Terminate frame
case FRAME_TYPE_TERMINATE: case FRAME_TYPE_TERMINATE:
console.putmsg(fo.render()); console.putmsg(fo.render());
bbs.hangup(); mode = false;
exit(); action = ACTION_TERMINATE;
break;
// External Frame // External Frame
// @todo returning from the frame, go to the 0 key if it is set // @todo returning from the frame, go to the 0 key if it is set
@ -327,13 +605,46 @@ while(bbs.online) {
break; break;
case FRAME_TYPE_LOGIN: case FRAME_TYPE_LOGIN:
action = false;
/*
// If this is the registration page
// @todo Should be evaluated out of the DB
if ($this->fo->page() == '981a') {
$control = CONTROL_METHOD;
$method->push(Control::factory('register',$this));
$method->last()->state['control'] = $control;
$method->last()->state['action'] = FALSE;
$method->last()->state['mode'] = MODE_FIELD;
}
*/
case FRAME_TYPE_RESPONSE: case FRAME_TYPE_RESPONSE:
log(LOG_DEBUG,'response frame :'+fo.page); //log(LOG_DEBUG,'FRAME_TYPE_RESPONSE :'+fo.page+', FIELDS: '+fo.frame_fields.count);
fn = 0;
cf = null;
console.putmsg(fo.render()); console.putmsg(fo.render());
mode = action = false;
//fo.fields; if (fo.frame_fields.length) {
//bbs.hangup(); cf = fo.frame_fields[fn];
//exit(); log(LOG_DEBUG,'cf'+JSON.stringify(cf));
if (cf) {
mode = MODE_FIELD;
ansi.send('ext_mode','set','cursor');
console.gotoxy(cf.c,cf.r);
console.write(KEY_ESC+'['+cf.attribute.i+';'+cf.attribute.f+';'+cf.attribute.b+'m');
// There were no editable fields.
} else {
mode = MODE_COMPLETE;
cursorOff();
}
} else {
mode = false;
}
break; break;
// Standard Frame // Standard Frame
@ -350,4 +661,12 @@ while(bbs.online) {
} }
log(LOG_DEBUG,'ACTION END: ['+read+']'); log(LOG_DEBUG,'ACTION END: ['+read+']');
} }
}
log(LOG_DEBUG,'- FINISHED');
if (action == ACTION_TERMINATE) {
log(LOG_DEBUG,'! Hangup');
bbs.hangup();
}
exit();
}