UNPKG

libas2

Version:

Implementation of the AS2 protocol as presented in RFC 4130 and related RFCs

107 lines (106 loc) 4.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AS2Parser = void 0; const stream_1 = require("stream"); const AS2MimeNode_1 = require("../AS2MimeNode"); // @ts-ignore const emailjs_mime_parser_1 = require("@nhs-llc/emailjs-mime-parser"); /** Options for parsing a MIME document; useful if there is no access to the underlying raw response. * @typedef {object} ParseOptions * @property {string[]|object} headers - Either an object like Node.js `IncomingMessage.headers` or like `IncomingMessage.rawHeaders`. * @property {Buffer|Stream|string} content - The raw body of the MIME document. */ /** Class for parsing a MIME document to an AS2MimeNode tree. */ class AS2Parser { static isStream(stream) { return stream instanceof stream_1.Stream || typeof stream.on === 'function'; } static async streamToBuffer(stream) { return new Promise((resolve, reject) => { try { const chunks = []; stream.on('data', chunk => chunks.push(chunk)); stream.on('error', error => reject(error)); stream.on('end', () => resolve(Buffer.concat(chunks))); } catch (error) { reject(error); } }); } static transformParsedHeaders(headerObj) { const headers = []; for (const [key, value] of Object.entries(headerObj)) { for (const obj of value) { headers.push({ key: key, value: obj.initial }); } } return headers; } static transformNodeLike(nodeLike, rootNode, parentNode) { const currentNode = new AS2MimeNode_1.AS2MimeNode({ filename: nodeLike.headers['content-disposition'] !== undefined ? nodeLike.headers['content-disposition'][0].params.filename : undefined, contentType: nodeLike.contentType.initial, headers: this.transformParsedHeaders(nodeLike.headers), content: nodeLike.content === undefined || this.isStream(nodeLike.content) ? nodeLike.content : Buffer.from(nodeLike.content), boundary: nodeLike._multipartBoundary === false ? undefined : nodeLike._multipartBoundary, boundaryPrefix: false }); if (!rootNode) rootNode = currentNode; currentNode.rootNode = rootNode; currentNode.parentNode = parentNode; currentNode.nodeCounter = typeof nodeLike.nodeCounter === 'object' ? nodeLike.nodeCounter.count : nodeLike.nodeCounter; currentNode.parsed = true; currentNode.raw = nodeLike.raw; if (Array.isArray(nodeLike.childNodes)) { for (const childNode of nodeLike.childNodes) { const as2Node = this.transformNodeLike(childNode, rootNode, currentNode); currentNode.childNodes.push(as2Node); } } return currentNode; } /** Parse a raw MIME document into an AS2MimeNode. * @param {Buffer|Stream|string|ParseOptions} content - A raw MIME message or ParseOptions object. * @returns {Promise<AS2MimeNode>} The MIME document as an AS2MimeNode. */ static async parse(content) { const options = content; if (typeof options.headers !== 'undefined' && typeof options.content !== 'undefined') { if (this.isStream(options.content)) { options.content = await this.streamToBuffer(options.content); } if (Buffer.isBuffer(options.content)) { options.content = options.content.toString('utf8'); } let headers = ''; if (Array.isArray(options.headers)) { for (let i = 0; i < options.headers.length; i += 2) { headers += options.headers[i] + ': ' + options.headers[i + 1] + '\r\n'; } } else { for (const [key, val] of Object.entries(options.headers)) { headers += key + ': ' + val + '\r\n'; } } content = headers + '\r\n' + options.content.trimLeft(); } else if (this.isStream(content)) { content = await this.streamToBuffer(content); } const result = emailjs_mime_parser_1.default(content); const as2node = this.transformNodeLike(result); return as2node; } } exports.AS2Parser = AS2Parser;