* 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 */
|
||||
'use strict';
|
||||
|
||||
var Config = require('./config.js').config;
|
||||
var MailPacket = require('./mail_packet.js');
|
||||
var ftn = require('./ftn_util.js');
|
||||
var Message = require('./message.js');
|
||||
|
||||
var _ = require('lodash');
|
||||
var assert = require('assert');
|
||||
|
@ -21,16 +22,9 @@ var async = require('async');
|
|||
//
|
||||
function FTNMailPacket(options) {
|
||||
|
||||
//
|
||||
// Map of networkName -> { zone, net, node, point, ... }
|
||||
//
|
||||
//
|
||||
// :TODO: ...
|
||||
// options.nodeAddresses
|
||||
MailPacket.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.nodeAddresses = options.nodeAddresses || {};
|
||||
|
||||
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) {
|
||||
// :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 msgBody = {
|
||||
|
@ -183,6 +184,56 @@ function FTNMailPacket(options) {
|
|||
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) {
|
||||
var nullTermBuf = new Buffer( [ 0 ] );
|
||||
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) {
|
||||
async.waterfall(
|
||||
[
|
||||
|
@ -253,9 +331,10 @@ function FTNMailPacket(options) {
|
|||
}
|
||||
);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
require('util').inherits(FTNMailPacket, MailPacket);
|
||||
|
||||
FTNMailPacket.prototype.parse = function(path, cb) {
|
||||
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(
|
||||
{
|
||||
|
@ -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) {
|
||||
console.log(err)
|
||||
});
|
||||
});
|
||||
*/
|
|
@ -12,10 +12,11 @@ var util = require('util');
|
|||
|
||||
exports.stringFromFTN = stringFromFTN;
|
||||
exports.getFormattedFTNAddress = getFormattedFTNAddress;
|
||||
exports.getDateFromFtnDateTime = getDateFromFtnDateTime;
|
||||
|
||||
// See list here: https://github.com/Mithgol/node-fidonet-jam
|
||||
|
||||
|
||||
// :TODO: proably move this elsewhere as a general method
|
||||
function stringFromFTN(buf, encoding) {
|
||||
var nullPos = buf.length;
|
||||
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');
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 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) {
|
||||
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,10 +8,10 @@ var async = require('async');
|
|||
var _ = require('lodash');
|
||||
var assert = require('assert');
|
||||
|
||||
exports.Message = Message;
|
||||
module.exports = Message;
|
||||
|
||||
function Message(options) {
|
||||
|
||||
|
||||
this.messageId = options.messageId || 0; // always generated @ persist
|
||||
this.areaId = options.areaId || Message.WellKnownAreaIds.Invalid; // 0 = invalid; 1 = private; Everything else is user defined
|
||||
this.uuid = uuid.v1();
|
||||
|
|
|
@ -6,7 +6,7 @@ var ViewController = require('../core/view_controller.js').ViewController;
|
|||
var ansi = require('../core/ansi_term.js');
|
||||
var theme = require('../core/theme.js');
|
||||
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 assert = require('assert');
|
||||
|
@ -36,6 +36,8 @@ function FullScreenEditorModule(options) {
|
|||
|
||||
// :TODO: This needs to be passed in via args:
|
||||
this.editorMode = 'edit'; // view | edit | editMenu |
|
||||
|
||||
// netMail/crashMail | echoMail
|
||||
this.messageAreaId = 'netMail' === this.editorType ? Message.WellKnownAreaIds.Private : options.messageAreaId;
|
||||
|
||||
this.getFooterName = function(editorMode) {
|
||||
|
|
Loading…
Reference in New Issue