diff --git a/load/control-echomail.js b/load/control-echomail.js new file mode 100644 index 0000000..cec0ceb --- /dev/null +++ b/load/control-echomail.js @@ -0,0 +1,86 @@ +/** + * This control renders echomail + * + * The system echomail prefix is *1, with echomail pages built from the following page number: + * zzzzEEpppp, where: + * + zzzz is the zone, zero padded, the zone identifies the message groups + * + EE is the echomail area, ie: the message areas + * + pppp is the message number, identified by the tag attached to the message header + * + * (Tags are added to the messages via an external process.) + */ + +var CONTROL_ECHOMAIL = '1'; + +load('frame.js'); +load('graphic.js'); + +log(LOG_DEBUG,'+ Control ECHOMAIL loaded'); + +function echomail(page) { + var complete = false; + var pageframe = undefined; + + log(LOG_DEBUG,'Loading echomail page:'+page); + + // Setup our frame + fo = viewdata ? new FrameViewdata() : new FrameAnsi(); + fo.loadMessage(page); + + if (fo.content) + pageframe = fo.render(); + + // Called before processing for a field + Object.defineProperty(this, 'getName', { + get: function () { + return 'ECHOMAIL'; + } + }); + + Object.defineProperty(this, 'isComplete', { + get: function () { + return complete; + } + }); + + // Handle the keyboard responses as we receive them. + this.handle=function(read) { + log(LOG_DEBUG,'Control ECHOMAIL handle() start. ('+read+')'); + + switch(read) { + case KEY_DOWN: + log(LOG_DEBUG,' - Control TEST scroll 0,1'); + pageframe.scroll(0,1); + read = ''; + break; + + case KEY_UP: + log(LOG_DEBUG,' - Control TEST scroll 0,-1'); + pageframe.scroll(0,-1); + read = ''; + break; + + case '*': + break; + } + + pageframe.cycle(); + + return read; + } + + // @todo Does this need to be defined? + this.prefield=function() {}; + + this.ready=function() { + //log(LOG_DEBUG,' - pageframe:'+pageframe+',typeof:'+(typeof pageframe)); + if ((typeof pageframe) === 'undefined') + log(LOG_DEBUG,'+ Control ECHOMAIL page doesnt exist ['+page+']'); + else + log(LOG_DEBUG,'+ Control ECHOMAIL ready'); + + return (typeof pageframe) !== 'undefined'; + } +} + +this; diff --git a/load/frame-ansi.js b/load/frame-ansi.js index 7129ff0..2b4dbd5 100644 --- a/load/frame-ansi.js +++ b/load/frame-ansi.js @@ -75,16 +75,15 @@ function FrameAnsi() { } // Render the frame to the user - this.render=function(withHeader) { + this.render=function(withoutHeader) { log(LOG_DEBUG,'- ANSI FRAME'); owner = base64_decode(this.owner); - header = '\n\r'; - - //log(LOG_DEBUG,' - FRAME User: ['+JSON.stringify(user)+']'); + const frame = new Frame(1,1,this.settings.FRAME_WIDTH,this.settings.FRAME_LENGTH+2,LIGHTGRAY); + frame.open(); // Dont show the page number on system login page - if (user.number || (this.type !== FRAME_TYPE_LOGIN && NO_HISTORY_FRAMES.indexOf(this.page) === -1)) { + if ((! withoutHeader) && (user.number || (this.type !== FRAME_TYPE_LOGIN && NO_HISTORY_FRAMES.indexOf(this.page) === -1))) { log(LOG_DEBUG,' - Owner: ['+this.pageowner+']'); cost = (this.isAccessible ? this.cost+FRAME_COSTUNIT : ' -'); @@ -93,14 +92,27 @@ function FrameAnsi() { (this.isAccessible ? '\1W' : '\1R')+'\1H'+this.page+' '.repeat(this.settings.FRAME_PAGENUM-this.page.length)+' '+ '\1G\1H'+' '.repeat(this.settings.FRAME_COST-cost.toString().length+1)+cost+'\1n'+ (console.screen_columns > 80 ? '\n\r' : ''); + + frame.putmsg(header); } - console.clear(LIGHTGRAY); + contentgraphic = new Graphic(this.settings.FRAME_WIDTH); + contentgraphic.auto_extend = true; + contentgraphic.ANSI = this.parse(base64_decode(this.content)); - return console.putmsg(header+this.parse(base64_decode(this.content))); + var contentframe = new Frame(1,2,this.settings.FRAME_WIDTH,this.settings.FRAME_LENGTH,LIGHTGRAY,frame); + contentframe.open(); + contentframe.lf_strict = false; + contentframe.atcodes = true; + contentframe.putmsg(contentgraphic.MSG) + contentframe.scrollTo(0,0); + + frame.cycle(); + + return contentframe; }; - this.qrcode = function(qr,subframe) { + this.qrcode=function(qr,subframe) { // SMALL Image var full = ascii(0xdb); var top = ascii(0xdf); diff --git a/load/frame-page.js b/load/frame-page.js index 902bfd2..6f612da 100644 --- a/load/frame-page.js +++ b/load/frame-page.js @@ -1,3 +1,5 @@ +var MAIL_TEMPLATE_FRAME = '199a'; + // Our frame object function PageFrame() { 'use strict'; @@ -115,6 +117,24 @@ function PageFrame() { }) } +/** + * Enable pulling out submitted value by its name + * + * @param key + * @returns {null|string|*} + */ +PageFrame.prototype.fieldValue = function(key) { + for each (var k in this.frame_fields) { + log(LOG_DEBUG,' - k:'+JSON.stringify(k)); + + if (k.fname === key) { + return k.fvalue; + } + } + + return null; +} + /** * Return the message for a index * @@ -160,21 +180,58 @@ PageFrame.prototype.load = function(filename) { }; /** - * Enable pulling out submitted value by its name + * Load a message frame * - * @param key - * @returns {null|string|*} + * @param page */ -PageFrame.prototype.fieldValue = function(key) { - for each (var k in this.frame_fields) { - log(LOG_DEBUG,' - k:'+JSON.stringify(k)); +PageFrame.prototype.loadMessage = function(page) { + this.frame = '1'+page; + this.index = 'a'; + this.owner = 1; + this.isPublic = true; + this.isAccessible = true; + this.key = [0,null,null,null,null,null,null,null,null,918]; - if (k.fname === key) { - return k.fvalue; - } + // Load our message + var ma = new MsgAreas() + var msg = ma.getMessage(page); + var msg_header; + + if (! msg) + return undefined; + + // @todo Search 1zzzzEE..., 1zzzz... + var to = viewdata ? new FrameViewdata() : new FrameAnsi(); + to.load(MAIL_TEMPLATE_FRAME); + // @todo Check that this is a frame of type "m" and report error if not + // @todo Take the cost from the template + this.cost = 5; + + if (! to) { + log(LOG_ERROR,'Echomail template missing :['+MAIL_TEMPLATE_FRAME+'] ?'); + msg_header = 'TO: '+msg.to.substr(0,72)+"\n\r"; + msg_header += 'FROM: '+msg.from.substr(0,72)+"\n\r"; + msg_header += 'DATE: '+msg.date.substr(0,72)+"\n\r"; + msg_header += 'SUBJECT: '+msg.subject.substr(0,72)+"\n\r"; + + } else { + msg_header = base64_decode(to.content).replace(/@(.*)@/g, + function (str, code, offset, s) { + var length = code.split(':')[1]; + switch(code.split(':')[0]) { + case 'DATE': return msg.date.substr(0,length); + case 'TO': return msg.to.substr(0,length); + case 'FROM': return msg.from.substr(0,length); + case 'SUBJECT': return msg.subject.substr(0,length); + } + } + ); } - return null; + log(LOG_DEBUG,'Loaded message: '+msg_header+msg.content); + this.content = base64_encode(msg_header+msg.content); + + log(LOG_DEBUG,'Loaded frame: ['+this.frame+']['+this.index+'] ('+this.page+')'); } /** diff --git a/main.js b/main.js index 3c451e8..5b5200b 100644 --- a/main.js +++ b/main.js @@ -222,6 +222,7 @@ while(bbs.online) { 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 IS: ['+typeof cc+']'); 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); @@ -900,13 +901,15 @@ while(bbs.online) { // @todo consider how we do mail security. // 1zzzzEEnnnn if (user.number && /^1[0-9]{10}/.test(next_page.frame)) { - var ma = new MsgAreas(); - if (x=ma.getMessage((''+next_page.frame).substr(1))) { - current = fo; - fo = viewdata ? new FrameViewdata() : new FrameAnsi(); - fo.loadMessage(x); - writeln(x.content); - } else { + log(LOG_DEBUG,'- ACTION_GOTO - load message: ['+next_page.frame+']'); + + require('ansitex/load/control-echomail.js','CONTROL_ECHOMAIL'); + control.push(new echomail((''+next_page.frame).substr(1))); + action = false; + log(LOG_DEBUG,'- ACTION_GOTO - control message: ['+JSON.stringify(control[control.length-1])+'] ('+control.length+')'); + + if (! control[control.length-1].ready()) { + control.pop(); fo.sendBaseline('ERR_ROUTE',false); mode = action = false; } @@ -1048,17 +1051,17 @@ while(bbs.online) { if (fo.page === pageStr(REGISTER_FRAME)) { log(LOG_DEBUG,'Adding REGISTER to control stack'); require('ansitex/load/control-'+fo.key[1]+'.js','CONTROL_REGISTER'); - control.push(eval("new "+fo.key[1]+'();')); + control.push(eval('new '+fo.key[1]+'();')); } else if (fo.page === pageStr(SQRL_FRAME)) { log(LOG_DEBUG,'Adding SQRL to control stack'); require('ansitex/load/control-'+fo.key[1]+'.js','CONTROL_SQRL'); - control.push(eval("new "+fo.key[1]+'();')); + control.push(eval('new '+fo.key[1]+'();')); } else if (fo.key[1] && (fo.type === FRAME_TYPE_RESPONSE) && (typeof(fo.key[1]) !== 'number')) { log(LOG_DEBUG,'Adding METHOD to control stack: '+fo.key[1]); require('ansitex/load/control-'+fo.key[1]+'.js','CONTROL_'+fo.key[1].toUpperCase()); - control.push(eval("new "+fo.key[1]+'();')); + control.push(eval('new '+fo.key[1]+'();')); } action = false; diff --git a/text/199a.tex b/text/199a.tex new file mode 100644 index 0000000..5c83536 --- /dev/null +++ b/text/199a.tex @@ -0,0 +1 @@ +{"version":1,"frame":199,"index":"a","owner":1,"cost":0,"content":"DQogG1sxOzM2bURhdGU6IBtbMzdtQERBVEU6NjBADQogICAbWzE7MzZtVG86IBtbMzdtQFRPOjYwQA0KIBtbMTszNm1Gcm9tOiAbWzM3bUBGUk9NOjYwQA0KIBtbMTszNm1TdWJqOiAbWzM3bUBTVUJKRUNUOjYwQA0KIBtbMTszMG3ExMTExMQbWzBtxMTExMTEG1sxOzMwbcTExMTExBtbMG3ExMTExMQbWzE7MzBtxMTExMTEG1swbcTExMTExBtbMTszMG3ExMTExMQbWzBtxMTExMTEG1sxOzMwbcTExMTExBtbMG3ExMTExMQbWzE7MzBtxMTExMTEG1swbQ0K","isPublic":0,"isAccessible":1,"type":"m","key":[null,null,null,null,null,null,null,null,null,null],"date":"2022-04-29T00:00:00.000Z"}