diff --git a/core/message_area.js b/core/message_area.js index ff01f1e1..30ad14ed 100644 --- a/core/message_area.js +++ b/core/message_area.js @@ -24,6 +24,7 @@ exports.getAvailableMessageConferences = getAvailableMessageConferences; exports.getSortedAvailMessageConferences = getSortedAvailMessageConferences; exports.getAvailableMessageAreasByConfTag = getAvailableMessageAreasByConfTag; exports.getSortedAvailMessageAreasByConfTag = getSortedAvailMessageAreasByConfTag; +exports.getAllAvailableMessageAreaTags = getAllAvailableMessageAreaTags; exports.getDefaultMessageConferenceTag = getDefaultMessageConferenceTag; exports.getDefaultMessageAreaTagByConfTag = getDefaultMessageAreaTagByConfTag; exports.getSuitableMessageConfAndAreaTags = getSuitableMessageConfAndAreaTags; @@ -140,6 +141,20 @@ function getSortedAvailMessageAreasByConfTag(confTag, options) { return areas; } +function getAllAvailableMessageAreaTags(client, options) { + const areaTags = []; + + // mask over older messy APIs for now + const confOpts = Object.assign({}, options, { noClient : client ? false : true }); + const areaOpts = Object.assign({}, options, { client }); + + Object.keys(getAvailableMessageConferences(client, confOpts)).forEach(confTag => { + areaTags.push(...Object.keys(getAvailableMessageAreasByConfTag(confTag, areaOpts))); + }); + + return areaTags; +} + function getDefaultMessageConferenceTag(client, disableAcsCheck) { // // Find the first conference marked 'default'. If found, diff --git a/core/oputil/oputil_message_base.js b/core/oputil/oputil_message_base.js index e29a30dc..ea996c6c 100644 --- a/core/oputil/oputil_message_base.js +++ b/core/oputil/oputil_message_base.js @@ -546,14 +546,10 @@ function exportQWKPacket() { // if they were not explicitly supplied if (!areaTags.length) { const { - getAvailableMessageConferences, - getAvailableMessageAreasByConfTag + getAllAvailableMessageAreaTags } = require('../../core/message_area'); - const confTags = Object.keys(getAvailableMessageConferences(null, { noClient : true })); - confTags.forEach( confTag => { - areaTags = areaTags.concat(Object.keys(getAvailableMessageAreasByConfTag(confTag))); - }); + areaTags = getAllAvailableMessageAreaTags(); } return callback(null, user); }, diff --git a/core/qwk_mail_packet.js b/core/qwk_mail_packet.js index 5aa5deac..be524422 100644 --- a/core/qwk_mail_packet.js +++ b/core/qwk_mail_packet.js @@ -5,6 +5,7 @@ const { splitTextAtTerms } = require('./string_util'); const { getMessageConfTagByAreaTag, getMessageAreaByTag, + getAllAvailableMessageAreaTags, } = require('./message_area'); const StatLog = require('./stat_log'); const Config = require('./config').get; @@ -822,6 +823,7 @@ class QWKPacketReader extends EventEmitter { class QWKPacketWriter extends EventEmitter { constructor( { + mode = QWKPacketWriter.Modes.User, enableQWKE = true, enableHeadersExtension = true, enableAtKludges = true, @@ -835,6 +837,7 @@ class QWKPacketWriter extends EventEmitter { super(); this.options = { + mode, enableQWKE, enableHeadersExtension, enableAtKludges, @@ -846,10 +849,13 @@ class QWKPacketWriter extends EventEmitter { }; this.temptmp = temptmp.createTrackedSession('qwkpacketwriter'); + + this.areaTagConfMap = {}; } static get DefaultOptions() { return { + mode : QWKPacketWriter.Modes.User, enableQWKE : true, enableHeadersExtension : true, enableAtKludges : true, @@ -861,6 +867,13 @@ class QWKPacketWriter extends EventEmitter { }; } + static get Modes() { + return { + User : 'user', // creation of a packet for a user (non-network); non-mapped confs allowed + Network : 'network', // creation of a packet for QWK network + }; + } + init() { async.series( [ @@ -873,6 +886,48 @@ class QWKPacketWriter extends EventEmitter { return callback(err); }); }, + (callback) => { + // + // Prepare areaTag -> conference number mapping: + // - In User mode, areaTags's that are not explicitly configured + // will have their conference number auto-generated. + // - In Network mode areaTags's missing a configuration will not + // be mapped, and thus skipped. + // + const configuredAreas = _.get(Config(), 'messageNetworks.qwk.areas'); + if (configuredAreas) { + Object.keys(configuredAreas).forEach(areaTag => { + const confNumber = configuredAreas[areaTag].conference; + if (confNumber) { + this.areaTagConfMap[areaTag] = confNumber; + } + }); + } + + if (this.options.mode === QWKPacketWriter.Modes.User) { + // All the rest + let confNumber = 1; + const usedConfNumbers = new Set(Object.values(this.areaTagConfMap)); + getAllAvailableMessageAreaTags().forEach(areaTag => { + if (this.areaTagConfMap[areaTag]) { + return; + } + + while (confNumber < 65537 && usedConfNumbers.has(confNumber)) { + ++confNumber; + } + + if (confNumber === 65536) { // sanity... + this.emit('warning', Errors.General(`To many conferences`)); + } else { + this.areaTagConfMap[areaTag] = confNumber; + ++confNumber; + } + }); + } + + return callback(null); + }, (callback) => { this.messagesStream = fs.createWriteStream(paths.join(this.workDir, 'messages.dat')); @@ -1241,8 +1296,8 @@ class QWKPacketWriter extends EventEmitter { if (Message.isPrivateAreaTag(areaTag)) { return 0; } - const areaConfig = _.get(Config(), [ 'messageNetworks', 'qwk', 'areas', areaTag ]); - return areaConfig && areaConfig.conference; + + return this.areaTagConfMap[areaTag]; } _getExportForUsername() {