enigma-bbs/core/descript_ion_file.js

83 lines
2.4 KiB
JavaScript

/* jslint node: true */
'use strict';
const { Errors } = require('./enig_error.js');
// deps
const fs = require('graceful-fs');
const iconv = require('iconv-lite');
const async = require('async');
module.exports = class DescriptIonFile {
constructor() {
this.entries = new Map();
}
get(fileName) {
return this.entries.get(fileName);
}
getDescription(fileName) {
const entry = this.get(fileName);
if (entry) {
return entry.desc;
}
}
static createFromFile(path, cb) {
fs.readFile(path, (err, descData) => {
if (err) {
return cb(err);
}
const descIonFile = new DescriptIonFile();
// DESCRIPT.ION entries are terminated with a CR and/or LF
const lines = iconv.decode(descData, 'cp437').split(/\r?\n/g);
async.each(
lines,
(entryData, nextLine) => {
//
// We allow quoted (long) filenames or non-quoted filenames.
// FILENAME<SPC>DESC<0x04><program data><CR/LF>
//
const parts = entryData.match(
/^(?:(?:"([^"]+)" )|(?:([^ ]+) ))([^\x04]+)\x04(.)[^\r\n]*$/
); // eslint-disable-line no-control-regex
if (!parts) {
return nextLine(null);
}
const fileName = parts[1] || parts[2];
//
// Un-escape CR/LF's
// - escapped \r and/or \n
// - BBBS style @n - See https://www.bbbs.net/sysop.html
//
const desc = parts[3].replace(/\\r\\n|\\n|[^@]@n/g, '\r\n');
descIonFile.entries.set(fileName, {
desc: desc,
programId: parts[4],
programData: parts[5],
});
return nextLine(null);
},
() => {
return cb(
descIonFile.entries.size > 0
? null
: Errors.Invalid(
'Invalid or unrecognized DESCRIPT.ION format'
),
descIonFile
);
}
);
});
}
};