Added Ansitex Data transport
This commit is contained in:
parent
a5231cb7ff
commit
31bf9b9dd7
241
mods/ansitex_export.js
Normal file
241
mods/ansitex_export.js
Normal file
@ -0,0 +1,241 @@
|
||||
load('texdefs.js');
|
||||
load('texfuncs.js');
|
||||
load('smbdefs.js');
|
||||
|
||||
/**
|
||||
* Work out which key should be used for a page, or validate if a key used is valid
|
||||
*
|
||||
* @param page
|
||||
* @param signed
|
||||
* @returns {*}
|
||||
*/
|
||||
function getKey(page,signed) {
|
||||
log(LOG_DEBUG,'+ CHECKING key:'+signed+' for page: '+page);
|
||||
|
||||
var f = new File(file_cfgname(system.ctrl_dir,'videotex.ini'));
|
||||
var match = '';
|
||||
|
||||
if (f.open("r")) {
|
||||
var BreakException = {};
|
||||
|
||||
// Default Key
|
||||
var key = f.iniGetValue('prefix','key');
|
||||
|
||||
try {
|
||||
f.iniGetSections("prefix:").forEach(function (prefix) {
|
||||
var p = prefix.substr(7);
|
||||
var pk = f.iniGetValue(prefix, 'Key', '');
|
||||
var re = new RegExp('^' + p, 'g');
|
||||
|
||||
// If it was signed, is the key a value one
|
||||
if (signed && signed.length) {
|
||||
if (pk == signed) {
|
||||
//print('SIGNED key is valid:' + signed);
|
||||
key = signed;
|
||||
throw BreakException;
|
||||
}
|
||||
|
||||
// Which key should sign this page
|
||||
} else if (page.toString().match(re) && (p.length > match.length)) {
|
||||
match = p;
|
||||
key = pk;
|
||||
}
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
if (e !== BreakException) throw e;
|
||||
}
|
||||
}
|
||||
|
||||
f.close();
|
||||
|
||||
log(LOG_DEBUG,'- key:'+key);
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export message from message base
|
||||
*
|
||||
* @param msgbase
|
||||
*/
|
||||
function msgBaseExport(msgbase) {
|
||||
var ini = new File(msgbase.file+'.ini');
|
||||
var i=0;
|
||||
|
||||
if (ini.open("r")) {
|
||||
export_ptr=ini.iniGetValue('videotex','export_ptr',0);
|
||||
ini.close();
|
||||
|
||||
} else {
|
||||
log(LOG_ERROR,'! ERROR: Unable to open INI for ['+msgbase.file+']');
|
||||
}
|
||||
|
||||
// If pointer doesnt exist, reset it from the message base.
|
||||
if (export_ptr == undefined) {
|
||||
var f = new File(file_getcase(msgbase.file+'.sbl'));
|
||||
|
||||
if (f.open('rb')) {
|
||||
export_ptr = f.readBin(4);
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
highest = export_ptr;
|
||||
var total_msgs = msgbase.total_msgs;
|
||||
|
||||
log(LOG_DEBUG,'| msgBaseExport: export_ptr='+export_ptr+'|last_msg='+msgbase.last_msg+'|total_msgs='+total_msgs);
|
||||
|
||||
if (msgbase.last_msg >= export_ptr)
|
||||
i = total_msgs-(msgbase.last_msg-export_ptr);
|
||||
|
||||
for (; i<total_msgs; i++) {
|
||||
if (js.terminated)
|
||||
break;
|
||||
|
||||
var idx = msgbase.get_msg_index(true,i);
|
||||
if (! idx) {
|
||||
log(LOG_ERROR,'! ERROR: Reading index of msg offset ['+i+'] : ['+msgbase.error+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip message until we get to our last one read.
|
||||
if (idx.number <= export_ptr)
|
||||
continue;
|
||||
|
||||
if (idx.number > highest)
|
||||
highest = idx.number;
|
||||
|
||||
// Only check messages from Videotex
|
||||
if (idx.from != crc16_calc('videotex')) {
|
||||
log(LOG_DEBUG,'! IGNORING: Message offset ['+i+'] in ['+msgbase.file+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the message header
|
||||
var hdr = msgbase.get_msg_header(true,i);
|
||||
|
||||
// Ignore deleted messages
|
||||
if (hdr.attr&MSG_DELETE) {
|
||||
log(LOG_DEBUG,'! IGNORING: Deleted message offset ['+i+'] in ['+msgbase.file+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore locally posted messages
|
||||
if (! hdr.from_net_type) {
|
||||
log(LOG_DEBUG,'! IGNORING: Local message offset ['+i+'] in ['+msgbase.file+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
log(LOG_DEBUG,'+ PROCESSING: Message offset ['+i+'] in ['+msgbase.file+'] from ['+hdr.from_net_addr+'] ('+hdr.subject+')');
|
||||
|
||||
var body = msgbase.get_msg_body(
|
||||
/* by_offset: */true,
|
||||
i,
|
||||
/* strip Ctrl-A */true,
|
||||
/* rfc822-encoded: */false,
|
||||
/* include tails: */false);
|
||||
|
||||
t = new File(system.temp_dir+'videotex.gpg');
|
||||
if (! t.open('w+')) {
|
||||
log(LOG_ERROR,'! ERROR: Unable to open temp file ['+system.temp_dir+'videotex.gpg'+']');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
t.write(base64_decode(body));
|
||||
t.close();
|
||||
|
||||
} catch (error) {
|
||||
log(LOG_ERROR,error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Check if the signature is good
|
||||
result = system.exec('gpgv --keyring /opt/sbbs/mods/keys/pubring.kbx '+system.temp_dir+'videotex.gpg');
|
||||
|
||||
if (result !== 0 ) {
|
||||
log(LOG_ERROR,'! ERROR: Invalid Signature for message offset ['+i+'] in ['+msgbase.file+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file_exists(system.temp_dir+'videotex.tex'))
|
||||
file_remove(system.temp_dir+'videotex.tex')
|
||||
|
||||
// Check that the signature is allowed to author the frames
|
||||
result = system.exec('gpg --homedir /opt/sbbs/mods/keys --batch --status-fd 3 -o '+system.temp_dir+'videotex.tex '+system.temp_dir+'videotex.gpg 3>'+system.temp_dir+'videotex.log');
|
||||
|
||||
if (result !== 0 ) {
|
||||
log(LOG_ERROR,'! ERROR: Failed to extract message offset ['+i+'] in ['+msgbase.file+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Put frame in place.
|
||||
f = new File(system.temp_dir+'videotex.tex');
|
||||
if (! f.exists || ! f.open('r')) {
|
||||
log(LOG_ERROR,'! ERROR: Failed to open frame for message offset ['+i+'] in ['+msgbase.file+']');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
frame = JSON.parse(f.read());
|
||||
x = new Frame(0);
|
||||
frame.render = x.render;
|
||||
|
||||
// @todo Figure out how to delete this duplicate code
|
||||
Object.defineProperty(frame,'page', {
|
||||
get: function() {return this.frame+this.index}
|
||||
});
|
||||
|
||||
x = null;
|
||||
|
||||
} catch (error) {
|
||||
log(LOG_ERROR,error);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the key that signed the message
|
||||
f = new File(system.temp_dir+'videotex.log');
|
||||
if (! f.exists || ! f.open('r')) {
|
||||
log(LOG_ERROR,'! ERROR: Failed to open gpg log for message offset ['+i+'] in ['+msgbase.file+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
var signed = '';
|
||||
while (string = f.readln()) {
|
||||
var matches = string.match(/\s+GOODSIG\s+.*\<(.*)\>/);
|
||||
|
||||
if (matches) {
|
||||
signed = matches[1];
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
|
||||
if (signed != getKey(frame.frame,signed)) {
|
||||
log(LOG_ERROR,'! ERROR: Key ['+signed+' is not authorised for message offset ['+i+'] in ['+msgbase.file+']');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Save the frame.
|
||||
log(LOG_INFO,'Updating page ['+frame.page+'] from ['+hdr.from_net_addr+'] signed with ['+signed+']');
|
||||
saveFrame(frame);
|
||||
}
|
||||
|
||||
if (ini.open(file_exists(ini.name) ? 'r+':'w+')) {
|
||||
ini.iniSetValue('videotex','export_ptr',highest);
|
||||
ini.close();
|
||||
|
||||
} else {
|
||||
log(LOG_ERROR,'! ERROR: Unable to save to INI for ['+msgbase.file+']');
|
||||
}
|
||||
}
|
||||
|
||||
var msgbase = new MsgBase(findMsgBase(null));
|
||||
log(LOG_DEBUG,'+ ANSITEX_EXPORT: Open message base in ['+msgbase.file+']');
|
||||
|
||||
if (! msgbase.open()) {
|
||||
log(LOG_ERROR,'! ERROR: Unable to open ['+msgbase.file+']');
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
msgBaseExport(msgbase);
|
||||
msgbase.close();
|
@ -80,17 +80,7 @@ if (! send || ! frame || file) {
|
||||
}
|
||||
|
||||
// Store the frame in file
|
||||
file = system.text_dir+'ansitex/'+frame.page+'.tex';
|
||||
w = new File(file);
|
||||
if (! w.open('w')) {
|
||||
log(LOG_ERROR,'! ERROR: Unable to create TEX file for '+frame.page);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
w.write(JSON.stringify(frame));
|
||||
w.close();
|
||||
|
||||
printf('Saved file: %s.tex',frame.page);
|
||||
saveFrame(frame);
|
||||
}
|
||||
|
||||
// @NOTE: We need to use a binary signature then base64 encode it, as mailers may strip 0x0a while messages are in transit.
|
||||
|
@ -108,6 +108,8 @@ function getFrame(page) {
|
||||
get: function() {return this.frame+this.index}
|
||||
});
|
||||
|
||||
x = null;
|
||||
|
||||
} catch (error) {
|
||||
log(LOG_ERROR,error);
|
||||
return null;
|
||||
@ -155,6 +157,25 @@ function pageStr(page) {
|
||||
return page.frame+page.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the frame
|
||||
*
|
||||
* @param frame
|
||||
*/
|
||||
function saveFrame(frame) {
|
||||
file = system.text_dir+'ansitex/'+frame.page+'.tex';
|
||||
w = new File(file);
|
||||
if (! w.open('w')) {
|
||||
log(LOG_ERROR,'! ERROR: Unable to create TEX file for '+frame.page);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
w.write(JSON.stringify(frame));
|
||||
w.close();
|
||||
|
||||
log(LOG_DEBUG,'Saved file: '+frame.page+'.tex');
|
||||
}
|
||||
|
||||
function sendBaseline(text,reposition) {
|
||||
console.pushxy();
|
||||
console.gotoxy(0,24);
|
||||
|
Loading…
Reference in New Issue
Block a user