Some fixes to NNTP POSTs, logging, etc.

This commit is contained in:
Bryan Ashby 2022-09-23 11:06:33 -06:00
parent 2cb0970a31
commit 5f6d70e460
No known key found for this signature in database
GPG Key ID: C2C1B501E4EFD994
1 changed files with 35 additions and 13 deletions

View File

@ -980,6 +980,17 @@ class NNTPServer extends NNTPServerBase {
} }
static _importMessage(session, articleLines, cb) { static _importMessage(session, articleLines, cb) {
const tidyFrom = f => {
if (f) {
// remove quotes around name, if present
let m = /^"([^"]+)" <([^>]+)>$/.exec(f);
if (m && m[1] && m[2]) {
f = `${m[1]} <${m[2]}>`;
}
}
return f;
};
asyncWaterfall( asyncWaterfall(
[ [
callback => { callback => {
@ -989,8 +1000,10 @@ class NNTPServer extends NNTPServerBase {
// gather some initially important bits // gather some initially important bits
const subject = parsed.header.get('subject'); const subject = parsed.header.get('subject');
const to = parsed.header.get('to'); // non-standard, may be missing const to = parsed.header.get('to'); // non-standard, may be missing
const from = parsed.header.get('from'); const from = tidyFrom(
const date = parsed.header.get('date'); parsed.header.get('from') || parsed.header.get('sender')
);
const date = parsed.header.get('date'); // if not present we'll use 'now'
const newsgroups = parsed.header const newsgroups = parsed.header
.get('newsgroups') .get('newsgroups')
.split(',') .split(',')
@ -1029,7 +1042,6 @@ class NNTPServer extends NNTPServerBase {
if ( if (
!_.isString(subject) || !_.isString(subject) ||
!_.isString(from) || !_.isString(from) ||
!_.isString(date) ||
!Array.isArray(newsgroups) !Array.isArray(newsgroups)
) { ) {
return callback( return callback(
@ -1111,7 +1123,7 @@ class NNTPServer extends NNTPServerBase {
replyToMsgId: msgData.replyToMsgId || 0, replyToMsgId: msgData.replyToMsgId || 0,
modTimestamp: msgData.date, // moment can generally parse these modTimestamp: msgData.date, // moment can generally parse these
// :TODO: inspect Content-Type 'charset' if present & attempt to properly decode if not UTF-8 // :TODO: inspect Content-Type 'charset' if present & attempt to properly decode if not UTF-8
message: msgData.parsed.body.slice(0, -1).join('\n'), // remove trailing blank message: msgData.parsed.body.join('\n'),
areaTag: msgData.newsgroups[0].areaTag, areaTag: msgData.newsgroups[0].areaTag,
}); });
@ -1121,6 +1133,11 @@ class NNTPServer extends NNTPServerBase {
// :TODO: investigate JAMNTTP clients/etc. // :TODO: investigate JAMNTTP clients/etc.
persistMessage(message, err => { persistMessage(message, err => {
if (!err) {
Log.info(
`NNTP post to "${message.areaTag}" by "${session.authUser.username}": "${message.subject}"`
);
}
return callback(err); return callback(err);
}); });
}, },
@ -1181,8 +1198,12 @@ class NNTPServer extends NNTPServerBase {
// body // body
if (line !== '.') { if (line !== '.') {
// :TODO: de-escape lines that start with ".." -> "." // lines consisting of a single '.' are escaped to '..'
body.push(line); if (line.startsWith('..')) {
body.push(line.slice(1));
} else {
body.push(line);
}
} }
return nextLine(null); return nextLine(null);
}, },
@ -1193,8 +1214,6 @@ class NNTPServer extends NNTPServerBase {
} }
} }
const EndOfPostMarker = ['', '.'];
exports.getModule = class NNTPServerModule extends ServerModule { exports.getModule = class NNTPServerModule extends ServerModule {
constructor() { constructor() {
super(); super();
@ -1277,10 +1296,7 @@ exports.getModule = class NNTPServerModule extends ServerModule {
receivePostArticleData(data) { receivePostArticleData(data) {
this.articleLinesBuffer.push(...data.split(/r?\n/)); this.articleLinesBuffer.push(...data.split(/r?\n/));
const endOfPost = _.isEqual( const endOfPost = data.length === 1 && data[0] === '.';
this.articleLinesBuffer.slice(-2),
EndOfPostMarker
);
if (endOfPost) { if (endOfPost) {
this.receivingPostArticle = false; this.receivingPostArticle = false;
@ -1311,8 +1327,14 @@ exports.getModule = class NNTPServerModule extends ServerModule {
return new Promise(resolve => { return new Promise(resolve => {
NNTPServer._importMessage(this.session, this.articleLines, err => { NNTPServer._importMessage(this.session, this.articleLines, err => {
if (err) { if (err) {
this.rejected_value = Responses.ArticlePostFailed; this.rejected_value = err; // will be serialized and 403 sent back currently; not really ideal as we want ArticlePostFailed
// :TODO: tick() needs updated in session.js such that we can write back a proper code
this.state = 3; // CMD_REJECTED this.state = 3; // CMD_REJECTED
Log.error(
{ error: err.message },
`NNTP post failed: ${err.message}`
);
} else { } else {
this.resolved_value = Responses.ArticlePostedOk; this.resolved_value = Responses.ArticlePostedOk;
this.state = 2; // CMD_RESOLVED this.state = 2; // CMD_RESOLVED