diff --git a/frames_check.js b/frames_check.js index b34cf4f..0fdcec1 100644 --- a/frames_check.js +++ b/frames_check.js @@ -1,4 +1,10 @@ -log(LOG_DEBUG,'- INIT: ANSITEX'); +/** + * This will go through our videotex and ansitex frames and check for inconsistencies. + * + * We'll check for: + * + Mismatched metadata items + * + Out of sync content + */ // Load many SBBS definitions require('sbbsdefs.js','SS_USERON'); @@ -90,8 +96,8 @@ if (! ans.content) { if (x !== y) { // Check Content - writeln(' - Page Content :'+md5_calc(x)); - writeln(' - Source Content :'+md5_calc(y)); + writeln(' - Page Content :'+md5_calc(x,true)); + writeln(' - Source Content :'+md5_calc(y,true)); writeln('- ! WARNING: Content Differs.'+base64_decode(vtx.content)); errors = true; } diff --git a/frames_tag.js b/frames_tag.js new file mode 100644 index 0000000..c60c1b2 --- /dev/null +++ b/frames_tag.js @@ -0,0 +1,20 @@ +/** + * Go through our messages and tag a frame id for messages without one. + */ + +load('load/string.js'); +load('ansitex/load/msgbases.js'); + +ma = new MsgAreas() +for (var i=0;ib); + }); } this; diff --git a/load/msgbases.js b/load/msgbases.js new file mode 100644 index 0000000..7e2e0ab --- /dev/null +++ b/load/msgbases.js @@ -0,0 +1,233 @@ +// Our message bases +function MsgAreas() { + 'use strict'; + + this.areas = []; + this.areas_excluded = []; + var zone_id; + var zone_name; + var ma; + + for(var g in msg_area.grp_list) { + if (msg_area.grp_list[g].name.indexOf(':') !== -1) { + zone_id = msg_area.grp_list[g].name.split(':')[0]; + zone_name = msg_area.grp_list[g].name.split(':')[1]; + + for (var a in msg_area.grp_list[g].sub_list) { + if (msg_area.grp_list[g].sub_list[a].name.indexOf(':') !== -1) { + ma = new MsgArea(); + ma.zone_id = zone_id; + ma.zone_name = zone_name; + ma.area_id = msg_area.grp_list[g].sub_list[a].name.split(':')[0]; + ma.area_name = msg_area.grp_list[g].sub_list[a].name.split(':')[1]; + ma.code = msg_area.grp_list[g].sub_list[a].code; + + this.areas.push(ma); + } else { + this.areas_excluded.push(zone_name+':'+msg_area.grp_list[g].sub_list[a].name); + } + } + + } else { + zone_name = msg_area.grp_list[g].name; + + for (var a in msg_area.grp_list[g].sub_list) { + this.areas_excluded.push(zone_name+':'+msg_area.grp_list[g].sub_list[a].name); + } + } + } +} + +function MsgArea() { + this.zone_id = undefined; + this.zone_name = undefined; + this.area_id = undefined; + this.area_name = undefined; + this.msgbase = undefined; + this.headers = undefined; + this.tagged_list = undefined; + this.untagged_list = undefined; + + const PAGE_LENGTH = 4; // The size of our page tag. + const PAGE_LAST_KEY = 'last_page'; + + Object.defineProperty(this,'code',{ + set: function(code) { + this.msgbase = new MsgBase(code); + + if (! this.msgbase.open()) { + writeln(code+' cannot be opened:'+this.msgbase.error); + exit(2); + } + + this.headers = this.msgbase.get_all_msg_headers(false,false); + this.msgbase.close(); + } + }); + + // Get Area's full name + Object.defineProperty(this,'full_name',{ + get: function() { + return this.zone_name+':'+this.area_name; + } + }); + + // Total Messages + Object.defineProperty(this,'list',{ + get: function() { + return this.headers ? Object.keys(this.headers) : []; + } + }); + + // Total tagged messages + Object.defineProperty(this,'list_tagged',{ + get: function() { + if (this.tagged_list === undefined) { + this.tagged_list = []; + + if (! this.headers) + return this.tagged_list; + + for(var x in this.headers) { + if (this.headers[x].tags && (this.headers[x].tags.length === PAGE_LENGTH)) { + this.tagged_list.push(this.headers[x]); + write(); // @todo This is needed for this to work? + } + } + } + + return this.tagged_list; + } + }); + + // List untagged messages + Object.defineProperty(this,'list_untagged',{ + get: function() { + if (this.untagged_list === undefined) { + this.untagged_list = []; + + if (! this.headers) + return this.untagged_list; + + for(var x in this.headers) { + if ((! this.headers[x].tags) || (this.headers[x].tags.length !== PAGE_LENGTH)) { + this.untagged_list.push(this.headers[x]); + write(); // @todo This is needed for this to work? + } + + } + } + + return this.untagged_list.sort(function(x) { return x.when_written_time-(x.when_written_zone_offset*60); }); + } + }); + + // Get first untagged message + // Get specific tagged message + + // Get Next page number + Object.defineProperty(this,'page_next',{ + get: function() { + var f = new File(file_cfgname(system.mods_dir,'ansitex/ctrl/videotex.ini')); + if (! f.open('r')) { + writeln('Unable to open ini file'); + exit(2); + } + + var page = f.iniGetValue('zone:'+this.page_prefix,PAGE_LAST_KEY) + f.close(); + + return page ? page : '0'.repeat(PAGE_LENGTH); + }, + + set: function(page) { + var f = new File(file_cfgname(system.mods_dir,'ansitex/ctrl/videotex.ini')); + if (! f.open('r+')) { + writeln('Unable to open ini file'); + exit(2); + } + + f.iniSetValue('zone:'+this.page_prefix,PAGE_LAST_KEY,(''+page).padStart(4,'0')); + f.close(); + } + }); + + // Our page prefix for this msg area + Object.defineProperty(this,'page_prefix',{ + get: function() { + return ''+this.zone_id+this.area_id; + }, + }); +} + +/** + * Get a specific message with a tag + */ +MsgArea.prototype.getMessage = function(page) { + var msg = undefined; + + for(var x in this.headers) { + if (this.headers[x].tags === page) { + msg = this.headers[x]; + break; + } + write(); // @todo This is needed for this to work? + } + + if (! msg) + return undefined; + + this.msgbase.open(); + msg.content = this.msgbase.get_msg_body(false,msg.number,false,false,true,true); + this.msgbase.close(); + + return msg; +} + +/** + * Tag messages with a frame number + * + * @returns {boolean} + */ +MsgArea.prototype.tag_msgs = function() { + var msgs = this.list_untagged; + + // See if we need to something + if (! msgs.length) + return; + + if (! this.msgbase.open('r+')) { + writeln(ma.areas[i].code+' cannot be opened?'); + return false; + } + + var page_next = this.page_next; + for(var x in msgs) { + var msg = this.msgbase.get_msg_header(msgs[x].number, /* expand: */false) + writeln('Setting page:'+(''+(page_next)).padStart(4,'0')+', for:'+msg.number); + msg.tags = (''+(page_next)).padStart(4,'0'); + if(! this.msgbase.put_msg_header(msg.number,msg)) { + writeln('ERROR:'+this.msgbase.error); + + } else { + page_next++; + } + } + + this.msgbase.close(); + + this.page_next = page_next; + return true; +} + +MsgAreas.prototype.getMessage = function(page) { + var zone = page.substr(0,4); + var echo = page.substr(4,2); + var page = page.substr(6); + + area = this.areas.filter(function(x) { + return x.zone_id === zone && x.area_id === echo; + })[0] + + return area ? area.getMessage(page) : undefined; +} diff --git a/main.js b/main.js index 1b5f741..3c451e8 100644 --- a/main.js +++ b/main.js @@ -9,6 +9,7 @@ require('key_defs.js','KEY_ESC'); ansi = load({},'ansiterm_lib.js'); load('ansitex/load/funcs.js'); +load('ansitex/load/msgbases.js'); // Ansitex specific includes require('ansitex/load/defs.js','ACTION_EXIT'); @@ -895,11 +896,20 @@ while(bbs.online) { log(LOG_DEBUG,'- ACTION_GOTO: ['+(next_page ? pageStr(next_page) : '')+']'); var current = null; - // Check if this is a mail prefix. + // For logged in users, we'll see if this is a mail page. + // @todo consider how we do mail security. // 1zzzzEEnnnn if (user.number && /^1[0-9]{10}/.test(next_page.frame)) { - fo.sendBaseline('INVALID_EMAIL',false); - mode = action = false; + 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 { + fo.sendBaseline('ERR_ROUTE',false); + mode = action = false; + } break; } @@ -1045,7 +1055,10 @@ while(bbs.online) { require('ansitex/load/control-'+fo.key[1]+'.js','CONTROL_SQRL'); control.push(eval("new "+fo.key[1]+'();')); - break; + } 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]+'();')); } action = false;