Add CONTROL.DAT parsing
This commit is contained in:
parent
6edfe95dfe
commit
d8f0601914
|
@ -31,12 +31,17 @@ const SMBTZToUTCOffset = (smbTZ) => {
|
||||||
'4294' : '-11:00', // Bering
|
'4294' : '-11:00', // Bering
|
||||||
|
|
||||||
// US Daylight
|
// US Daylight
|
||||||
|
// :TODO: FINISH ME!
|
||||||
|
|
||||||
}[smbTZ];
|
}[smbTZ];
|
||||||
};
|
};
|
||||||
|
|
||||||
const QWKMessageBlockSize = 128;
|
const QWKMessageBlockSize = 128;
|
||||||
|
|
||||||
|
// See the following:
|
||||||
|
// - http://fileformats.archiveteam.org/wiki/QWK
|
||||||
|
// - http://wiki.synchro.net/ref:qwk
|
||||||
|
//
|
||||||
const MessageHeaderParser = new Parser()
|
const MessageHeaderParser = new Parser()
|
||||||
.endianess('little')
|
.endianess('little')
|
||||||
.string('status', {
|
.string('status', {
|
||||||
|
@ -272,6 +277,9 @@ class QWKPacketReader extends EventEmitter {
|
||||||
processPacketFiles(cb) {
|
processPacketFiles(cb) {
|
||||||
async.series(
|
async.series(
|
||||||
[
|
[
|
||||||
|
(callback) => {
|
||||||
|
return this.readControl(callback);
|
||||||
|
},
|
||||||
(callback) => {
|
(callback) => {
|
||||||
return this.readHeadersExtension(callback);
|
return this.readHeadersExtension(callback);
|
||||||
},
|
},
|
||||||
|
@ -285,6 +293,91 @@ class QWKPacketReader extends EventEmitter {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readControl(cb) {
|
||||||
|
//
|
||||||
|
// CONTROL.DAT is a CRLF text file containing information about
|
||||||
|
// the originating BBS, conf number <> name mapping, etc.
|
||||||
|
//
|
||||||
|
// References:
|
||||||
|
// - http://fileformats.archiveteam.org/wiki/QWK
|
||||||
|
//
|
||||||
|
if (!this.packetInfo.control) {
|
||||||
|
return cb(Errors.DoesNotExist('No control file found within QWK packet'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = paths.join(this.packetInfo.tempDir, this.packetInfo.control.filename);
|
||||||
|
|
||||||
|
// note that we read as UTF-8. Legacy says it should be CP437/ASCII
|
||||||
|
// but this seems safer for now so conference names and the like
|
||||||
|
// can be non-English for example.
|
||||||
|
fs.readFile(path, { encoding : 'utf8' }, (err, controlLines) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
controlLines = splitTextAtTerms(controlLines);
|
||||||
|
|
||||||
|
let state = 'header';
|
||||||
|
const control = { confMap : {} };
|
||||||
|
let currConfNumber;
|
||||||
|
for (let lineNumber = 0; lineNumber < controlLines.length; ++lineNumber) {
|
||||||
|
const line = controlLines[lineNumber].trim();
|
||||||
|
switch (lineNumber) {
|
||||||
|
// first set of lines is header info
|
||||||
|
case 0 : control.bbsName = line; break;
|
||||||
|
case 1 : control.bbsLocation = line; break;
|
||||||
|
case 2 : control.bbsPhone = line; break;
|
||||||
|
case 3 : control.bbsSysOp = line; break;
|
||||||
|
case 4 : control.doorRegAndBoardID = line; break;
|
||||||
|
case 5 : control.packetCreationTime = line; break;
|
||||||
|
case 6 : control.toUser = line; break;
|
||||||
|
case 7 : break; // Qmail menu
|
||||||
|
case 8 : break; // unknown, always 0?
|
||||||
|
case 9 : break; // total messages in packet (often set to 0)
|
||||||
|
case 10 :
|
||||||
|
control.totalMessages = (parseInt(line) + 1);
|
||||||
|
state = 'confNumber';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
switch (state) {
|
||||||
|
case 'confNumber' :
|
||||||
|
currConfNumber = parseInt(line);
|
||||||
|
if (isNaN(currConfNumber)) {
|
||||||
|
state = 'news';
|
||||||
|
|
||||||
|
control.welcomeFile = line;
|
||||||
|
} else {
|
||||||
|
state = 'confName';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'confName' :
|
||||||
|
control.confMap[currConfNumber] = line;
|
||||||
|
state = 'confNumber';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'news' :
|
||||||
|
control.newsFile = line;
|
||||||
|
state = 'logoff';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'logoff' :
|
||||||
|
control.logoffFile = line;
|
||||||
|
state = 'footer';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'footer' :
|
||||||
|
// some systems append additional info; we don't care.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
readHeadersExtension(cb) {
|
readHeadersExtension(cb) {
|
||||||
if (!this.packetInfo.headers) {
|
if (!this.packetInfo.headers) {
|
||||||
return cb(null); // nothing to do
|
return cb(null); // nothing to do
|
||||||
|
|
Loading…
Reference in New Issue