* MailPacket class: read() and write() with event emits
* FTNMailPacket WIP derived from MailPacket
This commit is contained in:
parent
7fa27e46a5
commit
aebf494ae7
|
@ -1,8 +1,9 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Config = require('./config.js').config;
|
var MailPacket = require('./mail_packet.js');
|
||||||
var ftn = require('./ftn_util.js');
|
var ftn = require('./ftn_util.js');
|
||||||
|
var Message = require('./message.js');
|
||||||
|
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -21,16 +22,9 @@ var async = require('async');
|
||||||
//
|
//
|
||||||
function FTNMailPacket(options) {
|
function FTNMailPacket(options) {
|
||||||
|
|
||||||
//
|
MailPacket.call(this, options);
|
||||||
// Map of networkName -> { zone, net, node, point, ... }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// :TODO: ...
|
|
||||||
// options.nodeAddresses
|
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.nodeAddresses = options.nodeAddresses || {};
|
|
||||||
|
|
||||||
self.KLUDGE_PREFIX = '\x01';
|
self.KLUDGE_PREFIX = '\x01';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -123,9 +117,16 @@ function FTNMailPacket(options) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.getMessageMeta = function(msgData) {
|
||||||
|
return {}; // :TODO: convert msgData kludges/etc. -> Message meta
|
||||||
|
};
|
||||||
|
|
||||||
this.parseFtnMessageBody = function(msgBodyBuffer, cb) {
|
this.parseFtnMessageBody = function(msgBodyBuffer, cb) {
|
||||||
// :TODO: Look at spec about line endings/etc. Prob \r\n|[\r\n]|<someOlderAndAmigaStuff>
|
// :TODO: Look at spec about line endings/etc. Prob \r\n|[\r\n]|<someOlderAndAmigaStuff>
|
||||||
|
|
||||||
|
// :TODO: Use the proper encoding here. There appear to be multiple specs and/or
|
||||||
|
// stuff people do with this... some specs kludge lines, which is kinda durpy since
|
||||||
|
// to get to that point, one must read the file (and decode) to find said kludge...
|
||||||
var msgLines = msgBodyBuffer.toString().split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
|
var msgLines = msgBodyBuffer.toString().split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
|
||||||
|
|
||||||
var msgBody = {
|
var msgBody = {
|
||||||
|
@ -183,6 +184,56 @@ function FTNMailPacket(options) {
|
||||||
cb(null, msgBody);
|
cb(null, msgBody);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.extractMessages = function(buffer, cb) {
|
||||||
|
var nullTermBuf = new Buffer( [ 0 ] );
|
||||||
|
|
||||||
|
binary.stream(buffer).loop(function looper(end, vars) {
|
||||||
|
this
|
||||||
|
.word16lu('messageType')
|
||||||
|
.word16lu('originNode')
|
||||||
|
.word16lu('destNode')
|
||||||
|
.word16lu('originNet')
|
||||||
|
.word16lu('destNet')
|
||||||
|
.word8('attrFlags1')
|
||||||
|
.word8('attrFlags2')
|
||||||
|
.word16lu('cost')
|
||||||
|
.scan('modDateTime', nullTermBuf)
|
||||||
|
.scan('toUserName', nullTermBuf)
|
||||||
|
.scan('fromUserName', nullTermBuf)
|
||||||
|
.scan('subject', nullTermBuf)
|
||||||
|
.scan('message', nullTermBuf)
|
||||||
|
.tap(function tapped(msgData) {
|
||||||
|
if(!msgData.originNode) {
|
||||||
|
end();
|
||||||
|
cb(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// buffer to string conversion
|
||||||
|
// :TODO: What is the real encoding here?
|
||||||
|
[ 'modDateTime', 'toUserName', 'fromUserName', 'subject', ].forEach(function field(f) {
|
||||||
|
msgData[f] = msgData[f].toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.parseFtnMessageBody(msgData.message, function msgBodyParsed(err, msgBody) {
|
||||||
|
//
|
||||||
|
// Now, create a Message object
|
||||||
|
//
|
||||||
|
var msg = new Message( {
|
||||||
|
toUserName : msgData.toUserName,
|
||||||
|
fromUserName : msgData.fromUserName,
|
||||||
|
subject : msgData.subject,
|
||||||
|
message : msgBody.message.join('\n'), // :TODO: \r\n is better?
|
||||||
|
modTimestamp : ftn.getDateFromFtnDateTime(msgData.modDateTime),
|
||||||
|
meta : self.getMessageMeta(msgData),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.emit('message', msg); // :TODO: Placeholder
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.parseFtnMessages = function(buffer, cb) {
|
this.parseFtnMessages = function(buffer, cb) {
|
||||||
var nullTermBuf = new Buffer( [ 0 ] );
|
var nullTermBuf = new Buffer( [ 0 ] );
|
||||||
var fidoMessages = [];
|
var fidoMessages = [];
|
||||||
|
@ -223,6 +274,33 @@ function FTNMailPacket(options) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.extractMesssagesFromPacketBuffer = function(packetBuffer, cb) {
|
||||||
|
async.waterfall(
|
||||||
|
[
|
||||||
|
function parseHeader(callback) {
|
||||||
|
self.parseFtnPacketHeader(packetBuffer, function headerParsed(err, packetHeader) {
|
||||||
|
self.packetHeader = packetHeader;
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function validateDesinationAddress(callback) {
|
||||||
|
self.localNetworkName = self.getNetworkNameForAddress(self.getPacketHeaderAddress());
|
||||||
|
self.localNetworkName = 'AllowAnyNetworkForDebugging';
|
||||||
|
callback(self.localNetworkName ? null : new Error('Packet not addressed do this system'));
|
||||||
|
},
|
||||||
|
function extractEmbeddedMessages(callback) {
|
||||||
|
// note: packet header is 58 bytes in length
|
||||||
|
self.extractMessages(packetBuffer.slice(58), function extracted(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
],
|
||||||
|
function complete(err) {
|
||||||
|
cb(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
this.loadMessagesFromPacketBuffer = function(packetBuffer, cb) {
|
this.loadMessagesFromPacketBuffer = function(packetBuffer, cb) {
|
||||||
async.waterfall(
|
async.waterfall(
|
||||||
[
|
[
|
||||||
|
@ -253,9 +331,10 @@ function FTNMailPacket(options) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require('util').inherits(FTNMailPacket, MailPacket);
|
||||||
|
|
||||||
FTNMailPacket.prototype.parse = function(path, cb) {
|
FTNMailPacket.prototype.parse = function(path, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -278,6 +357,40 @@ FTNMailPacket.prototype.parse = function(path, cb) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FTNMailPacket.prototype.read = function(options) {
|
||||||
|
FTNMailPacket.super_.prototype.read.call(this, options);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if(_.isString(options.packetPath)) {
|
||||||
|
async.waterfall(
|
||||||
|
[
|
||||||
|
function readPacketFile(callback) {
|
||||||
|
fs.readFile(options.packetPath, function packetData(err, data) {
|
||||||
|
callback(err, data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function extractMessages(data, callback) {
|
||||||
|
self.extractMesssagesFromPacketBuffer(data, function extracted(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
],
|
||||||
|
function complete(err) {
|
||||||
|
if(err) {
|
||||||
|
self.emit('error', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else if(Buffer.isBuffer(options.packetBuffer)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FTNMailPacket.prototype.write = function(options) {
|
||||||
|
FTNMailPacket.super_.prototype.write.call(this, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var mailPacket = new FTNMailPacket(
|
var mailPacket = new FTNMailPacket(
|
||||||
{
|
{
|
||||||
|
@ -293,6 +406,14 @@ var mailPacket = new FTNMailPacket(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
mailPacket.on('message', function msgParsed(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
mailPacket.read( { packetPath : '/home/nuskooler/ownCloud/Projects/ENiGMA½ BBS/FTNPackets/BAD_BNDL.007' } );
|
||||||
|
|
||||||
|
/*
|
||||||
mailPacket.parse('/home/nuskooler/ownCloud/Projects/ENiGMA½ BBS/FTNPackets/BAD_BNDL.007', function parsed(err, messages) {
|
mailPacket.parse('/home/nuskooler/ownCloud/Projects/ENiGMA½ BBS/FTNPackets/BAD_BNDL.007', function parsed(err, messages) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
});
|
});
|
||||||
|
*/
|
|
@ -12,10 +12,11 @@ var util = require('util');
|
||||||
|
|
||||||
exports.stringFromFTN = stringFromFTN;
|
exports.stringFromFTN = stringFromFTN;
|
||||||
exports.getFormattedFTNAddress = getFormattedFTNAddress;
|
exports.getFormattedFTNAddress = getFormattedFTNAddress;
|
||||||
|
exports.getDateFromFtnDateTime = getDateFromFtnDateTime;
|
||||||
|
|
||||||
// See list here: https://github.com/Mithgol/node-fidonet-jam
|
// See list here: https://github.com/Mithgol/node-fidonet-jam
|
||||||
|
|
||||||
|
// :TODO: proably move this elsewhere as a general method
|
||||||
function stringFromFTN(buf, encoding) {
|
function stringFromFTN(buf, encoding) {
|
||||||
var nullPos = buf.length;
|
var nullPos = buf.length;
|
||||||
for(var i = 0; i < buf.length; ++i) {
|
for(var i = 0; i < buf.length; ++i) {
|
||||||
|
@ -28,6 +29,20 @@ function stringFromFTN(buf, encoding) {
|
||||||
return buf.slice(0, nullPos).toString(encoding || 'utf-8');
|
return buf.slice(0, nullPos).toString(encoding || 'utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert a FTN style DateTime string to a Date object
|
||||||
|
//
|
||||||
|
function getDateFromFtnDateTime(dateTime) {
|
||||||
|
//
|
||||||
|
// Examples seen in the wild (Working):
|
||||||
|
// "12 Sep 88 18:17:59"
|
||||||
|
// "Tue 01 Jan 80 00:00"
|
||||||
|
// "27 Feb 15 00:00:03"
|
||||||
|
//
|
||||||
|
return (new Date(Date.parse(dateTime))).toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
function getFormattedFTNAddress3D(zone, net, node) {
|
function getFormattedFTNAddress3D(zone, net, node) {
|
||||||
return util.format('%d:%d/%d', zone, net, node);
|
return util.format('%d:%d/%d', zone, net, node);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* jslint node: true */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var events = require('events');
|
||||||
|
var assert = require('assert');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
|
module.exports = MailPacket;
|
||||||
|
|
||||||
|
function MailPacket(options) {
|
||||||
|
events.EventEmitter.call(this);
|
||||||
|
|
||||||
|
// map of network name -> address obj ( { zone, net, node, point, domain } )
|
||||||
|
this.nodeAddresses = options.nodeAddresses || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
require('util').inherits(MailPacket, events.EventEmitter);
|
||||||
|
|
||||||
|
MailPacket.prototype.read = function(options) {
|
||||||
|
//
|
||||||
|
// options.packetPath | opts.packetBuffer: supplies a path-to-file
|
||||||
|
// or a buffer containing packet data
|
||||||
|
//
|
||||||
|
// emits 'message' event per message read
|
||||||
|
//
|
||||||
|
assert(_.isString(options.packetPath) || Buffer.isBuffer(options.packetBuffer));
|
||||||
|
};
|
||||||
|
|
||||||
|
MailPacket.prototype.write = function(options) {
|
||||||
|
//
|
||||||
|
// options.messages[]: array of message(s) to create packets from
|
||||||
|
//
|
||||||
|
// emits 'packet' event per packet constructed
|
||||||
|
//
|
||||||
|
assert(_.isArray(options.messages));
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ var async = require('async');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
exports.Message = Message;
|
module.exports = Message;
|
||||||
|
|
||||||
function Message(options) {
|
function Message(options) {
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ var ViewController = require('../core/view_controller.js').ViewController;
|
||||||
var ansi = require('../core/ansi_term.js');
|
var ansi = require('../core/ansi_term.js');
|
||||||
var theme = require('../core/theme.js');
|
var theme = require('../core/theme.js');
|
||||||
var MultiLineEditTextView = require('../core/multi_line_edit_text_view.js').MultiLineEditTextView;
|
var MultiLineEditTextView = require('../core/multi_line_edit_text_view.js').MultiLineEditTextView;
|
||||||
var Message = require('../core/message.js').Message;
|
var Message = require('../core/message.js');
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -36,6 +36,8 @@ function FullScreenEditorModule(options) {
|
||||||
|
|
||||||
// :TODO: This needs to be passed in via args:
|
// :TODO: This needs to be passed in via args:
|
||||||
this.editorMode = 'edit'; // view | edit | editMenu |
|
this.editorMode = 'edit'; // view | edit | editMenu |
|
||||||
|
|
||||||
|
// netMail/crashMail | echoMail
|
||||||
this.messageAreaId = 'netMail' === this.editorType ? Message.WellKnownAreaIds.Private : options.messageAreaId;
|
this.messageAreaId = 'netMail' === this.editorType ? Message.WellKnownAreaIds.Private : options.messageAreaId;
|
||||||
|
|
||||||
this.getFooterName = function(editorMode) {
|
this.getFooterName = function(editorMode) {
|
||||||
|
|
Loading…
Reference in New Issue