dockerized_openAger/nodered/rootfs/data/node_modules/mailsplit/lib/headers.js
2020-10-17 18:42:50 +02:00

207 lines
5.4 KiB
JavaScript

'use strict';
const libmime = require('libmime');
/**
* Class Headers to parse and handle message headers. Headers instance allows to
* check existing, delete or add new headers
*/
class Headers {
constructor(headers, config) {
config = config || {};
if (Array.isArray(headers)) {
// already using parsed headers
this.changed = true;
this.headers = false;
this.parsed = true;
this.lines = headers;
} else {
// using original string/buffer headers
this.changed = false;
this.headers = headers;
this.parsed = false;
this.lines = false;
}
this.mbox = false;
this.http = false;
this.libmime = new libmime.Libmime({ Iconv: config.Iconv });
}
get(key) {
if (!this.parsed) {
this._parseHeaders();
}
key = this._normalizeHeader(key);
let lines = this.lines.filter(line => line.key === key).map(line => line.line);
return lines;
}
getDecoded(key) {
return this.get(key)
.map(line => this.libmime.decodeHeader(line))
.filter(line => line && line.value);
}
getFirst(key) {
if (!this.parsed) {
this._parseHeaders();
}
key = this._normalizeHeader(key);
let header = this.lines.find(line => line.key === key);
if (!header) {
return '';
}
return ((this.libmime.decodeHeader(header.line) || {}).value || '').toString().trim();
}
getList() {
if (!this.parsed) {
this._parseHeaders();
}
return this.lines;
}
add(key, value, index) {
if (typeof value === 'undefined') {
return;
}
if (typeof value === 'number') {
value = value.toString();
}
if (typeof value === 'string') {
value = Buffer.from(value);
}
value = value.toString('binary');
this.addFormatted(key, this.libmime.foldLines(key + ': ' + value.replace(/\r?\n/g, ''), 76, false), index);
}
addFormatted(key, line, index) {
if (!this.parsed) {
this._parseHeaders();
}
index = index || 0;
this.changed = true;
let header = {
key: this._normalizeHeader(key),
line
};
if (index < 1) {
this.lines.unshift(header);
} else if (index >= this.lines.length) {
this.lines.push(header);
} else {
this.lines.splice(index, 0, header);
}
}
remove(key) {
if (!this.parsed) {
this._parseHeaders();
}
key = this._normalizeHeader(key);
for (let i = this.lines.length - 1; i >= 0; i--) {
if (this.lines[i].key === key) {
this.changed = true;
this.lines.splice(i, 1);
}
}
}
update(key, value) {
if (!this.parsed) {
this._parseHeaders();
}
let keyName = key;
let index = 0;
key = this._normalizeHeader(key);
for (let i = this.lines.length - 1; i >= 0; i--) {
if (this.lines[i].key === key) {
index = i;
this.changed = true;
this.lines.splice(i, 1);
}
}
this.add(keyName, value, index);
}
build(lineEnd) {
if (!this.changed && !lineEnd) {
return typeof this.headers === 'string' ? Buffer.from(this.headers, 'binary') : this.headers;
}
if (!this.parsed) {
this._parseHeaders();
}
lineEnd = lineEnd || '\r\n';
let headers = this.lines.map(line => line.line.replace(/\r?\n/g, lineEnd)).join(lineEnd) + `${lineEnd}${lineEnd}`;
if (this.mbox) {
headers = this.mbox + lineEnd + headers;
}
if (this.http) {
headers = this.http + lineEnd + headers;
}
return Buffer.from(headers, 'binary');
}
_normalizeHeader(key) {
return (key || '').toLowerCase().trim();
}
_parseHeaders() {
if (!this.headers) {
this.lines = [];
this.parsed = true;
return;
}
let lines = this.headers
.toString('binary')
.replace(/[\r\n]+$/, '')
.split(/\r?\n/);
for (let i = lines.length - 1; i >= 0; i--) {
let chr = lines[i].charAt(0);
if (i && (chr === ' ' || chr === '\t')) {
lines[i - 1] += '\r\n' + lines[i];
lines.splice(i, 1);
} else {
let line = lines[i];
if (!i && /^From /i.test(line)) {
// mbox file
this.mbox = line;
lines.splice(i, 1);
continue;
} else if (!i && /^POST /i.test(line)) {
// HTTP POST request
this.http = line;
lines.splice(i, 1);
continue;
}
let key = this._normalizeHeader(line.substr(0, line.indexOf(':')));
lines[i] = {
key,
line
};
}
}
this.lines = lines;
this.parsed = true;
}
}
// expose to the world
module.exports = Headers;