fixed some lint errors

This commit is contained in:
Brian Whitney 2018-12-01 23:09:50 -05:00
parent 78ba4d4fd3
commit a980462d71
5 changed files with 84 additions and 68 deletions

View file

@ -11,7 +11,7 @@ import {decodeQuotedPrintable} from "../lib/QuotedPrintable";
import {MIME_FORMAT} from "../lib/ChrEnc"; import {MIME_FORMAT} from "../lib/ChrEnc";
import Utils from "../Utils"; import Utils from "../Utils";
// FIXME: files are a bit off on size.
/** /**
* NOTE: Liberties taken include: * NOTE: Liberties taken include:
* No checks are made to verify quoted words are valid encodings e.g. underscore vs escape * No checks are made to verify quoted words are valid encodings e.g. underscore vs escape
@ -37,21 +37,22 @@ class Mime {
* @returns {File[]} * @returns {File[]}
*/ */
decodeMime(decodeWords) { decodeMime(decodeWords) {
// TODO: content-type can be omitted and would mean us-ascii charset and text/plain.
if (!this.input) { if (!this.input) {
return []; return [];
} }
let emlObj = Mime._splitParseHead(this.input); const emlObj = Mime._splitParseHead(this.input);
if (!emlObj.body) { throw new OperationError("No body was found");} if (!emlObj.body) {
throw new OperationError("No body was found");
}
if (decodeWords) { if (decodeWords) {
emlObj.rawHeader = Mime.replaceEncodedWord(emlObj.rawHeader); emlObj.rawHeader = Mime.replaceEncodedWord(emlObj.rawHeader);
} }
let retval = [new File([emlObj.rawHeader], "Header", {type: "text/plain"})]; const retval = [new File([emlObj.rawHeader], "Header", {type: "text/plain"})];
this._walkMime(emlObj).forEach(function(fileObj){ this._walkMime(emlObj).forEach(function(fileObj){
let name = fileObj.name; let name = fileObj.name;
if (fileObj.name === null) { if (fileObj.name === null) {
if ("subject" in emlObj.header) { if (emlObj.header.hasOwnProperty("subject")) {
name = emlObj.header["subject"][0]; name = emlObj.header.subject[0];
} else { } else {
name = "Undefined"; name = "Undefined";
} }
@ -62,6 +63,12 @@ class Mime {
return retval; return retval;
} }
/**
* Simple function to add a common file extention based on mime type string.
*
* @param {string} mimetype
* @returns {string}
*/
static getFileExt(mimetype) { static getFileExt(mimetype) {
switch (mimetype) { switch (mimetype) {
case "text/plain": case "text/plain":
@ -75,24 +82,23 @@ class Mime {
} }
/** /**
* Walks a MIME document and returns an array of Mime data and header objects. * Walks a MIME document and returns an array of Mime data.
* *
* @param {string} input * @param {object} parentObj
* @param {object} header
* @returns {object[]} * @returns {object[]}
*/ */
_walkMime(parentObj) { _walkMime(parentObj) {
let new_line_length = this.rn ? 2 : 1; const newLineLength = this.rn ? 2 : 1;
let contType = null, let contType = "text/plain",
fileName = null, fileName = null,
charEnc = null, charEnc = "us-ascii",
contDispoObj = null, contDispoObj = null,
contTypeObj = null; contTypeObj = null;
if (parentObj.header.hasOwnProperty("content-type")) { if (parentObj.header.hasOwnProperty("content-type")) {
contTypeObj = Mime._decodeComplexField(parentObj.header["content-type"][0]); contTypeObj = Mime._decodeComplexField(parentObj.header["content-type"][0]);
} }
if (parentObj.header.hasOwnProperty("content-disposition")) { if (parentObj.header.hasOwnProperty("content-disposition")) {
contDispoObj = Mime._decodeComplexField(parentObj.header["content-disposition"][0]) contDispoObj = Mime._decodeComplexField(parentObj.header["content-disposition"][0]);
if (contDispoObj != null && contDispoObj.hasOwnProperty("filename")) { if (contDispoObj != null && contDispoObj.hasOwnProperty("filename")) {
fileName = contDispoObj.filename; fileName = contDispoObj.filename;
} }
@ -107,29 +113,23 @@ class Mime {
if (fileName == null && contTypeObj.hasOwnProperty("name")) { if (fileName == null && contTypeObj.hasOwnProperty("name")) {
fileName = contTypeObj.name; fileName = contTypeObj.name;
} }
} else {
contType = "text/plain";
charEnc = "us-ascii";
} }
if (contType.startsWith("multipart/")) { if (contType.startsWith("multipart/")) {
let output_sections = []; const sections = [];
if (!contTypeObj.hasOwnProperty("boundary")) { if (!contTypeObj.hasOwnProperty("boundary")) {
throw new OperationError("Invalid mulitpart section no boundary"); throw new OperationError("Invalid mulitpart section no boundary");
} }
let mime_parts = this._splitMultipart(parentObj.body, contTypeObj.boundary, new_line_length); const mimeParts = this._splitMultipart(parentObj.body, contTypeObj.boundary, newLineLength);
mime_parts.forEach(function(mime_part){ mimeParts.forEach(function(mimePart){
let mimeObj = Mime._splitParseHead(mime_part); const mimeObj = Mime._splitParseHead(mimePart);
if (!mimeObj.body) { if (mimeObj) {
return []; this._walkMime(mimeObj).forEach(part => sections.push(part));
} }
this._walkMime(mimeObj).forEach(function(part){
output_sections.push(part);
}, this);
}, this); }, this);
return output_sections; return sections;
} }
if (parentObj.header.hasOwnProperty("content-transfer-encoding")) { if (parentObj.header.hasOwnProperty("content-transfer-encoding")) {
let contEncObj = Mime._decodeComplexField(parentObj.header["content-transfer-encoding"][0]); const contEncObj = Mime._decodeComplexField(parentObj.header["content-transfer-encoding"][0]);
if (contEncObj != null && contEncObj.hasOwnProperty("value")) { if (contEncObj != null && contEncObj.hasOwnProperty("value")) {
parentObj.body = Mime._decodeMimeData(parentObj.body, charEnc, contEncObj.value[0]); parentObj.body = Mime._decodeMimeData(parentObj.body, charEnc, contEncObj.value[0]);
} }
@ -165,21 +165,22 @@ class Mime {
*/ */
static _splitParseHead(input) { static _splitParseHead(input) {
const emlRegex = /(?:\r?\n){2}/g; const emlRegex = /(?:\r?\n){2}/g;
let matchobj = emlRegex.exec(input); const matchObj = emlRegex.exec(input);
if (matchobj) { if (matchObj) {
let splitEmail = [input.substring(0,matchobj.index), input.substring(emlRegex.lastIndex)]; const splitEmail = [input.substring(0, matchObj.index), input.substring(emlRegex.lastIndex)];
const sectionRegex = /([A-Za-z-]+):\s+([\x00-\xff]+?)(?=$|\r?\n\S)/g; const sectionRegex = /([A-Za-z-]+):\s+([\x00-\xff]+?)(?=$|\r?\n\S)/g;
let headerObj = {}, section; const headerObj = {};
let section;
while ((section = sectionRegex.exec(splitEmail[0]))) { while ((section = sectionRegex.exec(splitEmail[0]))) {
let fieldName = section[1].toLowerCase(); const fieldName = section[1].toLowerCase();
let fieldValue = Mime.replaceEncodedWord(section[2].replace(/\n|\r/g, " ")); const fieldValue = Mime.replaceEncodedWord(section[2].replace(/\n|\r/g, " "));
if (fieldName in headerObj) { if (fieldName in headerObj) {
headerObj[fieldName].push(fieldValue); headerObj[fieldName].push(fieldValue);
} else { } else {
headerObj[fieldName] = [fieldValue]; headerObj[fieldName] = [fieldValue];
} }
} }
return {rawHeader:splitEmail[0], body: splitEmail[1], header: headerObj}; return {rawHeader: splitEmail[0], body: splitEmail[1], header: headerObj};
} }
return null; return null;
} }
@ -215,30 +216,29 @@ class Mime {
* @returns {object} * @returns {object}
*/ */
static _decodeComplexField(field) { static _decodeComplexField(field) {
let fieldSplit = field.split(/;\s+/g); const fieldSplit = field.split(/;\s+/g);
let retVal = {}; const retVal = {};
fieldSplit.forEach(function(item){ fieldSplit.forEach(function(item){
let eq = item.indexOf("="); const eq = item.indexOf("=");
if (eq >= 0) { if (eq >= 0) {
if (item.length > eq) { if (item.length > eq) {
let kv = [item.substring(0, eq), item.substring(eq + 1).trim()]; const kv = [item.substring(0, eq), item.substring(eq + 1).trim()];
if ((kv[1].startsWith("\'") && kv[1].endsWith("\'")) if ((kv[1].startsWith("'") && kv[1].endsWith("'")) || (kv[1].startsWith("\"") && kv[1].endsWith("\""))) {
|| (kv[1].startsWith("\"") && kv[1].endsWith("\""))) {
kv[1] = (/(['"])(.+)\1/.exec(kv[1]))[2]; kv[1] = (/(['"])(.+)\1/.exec(kv[1]))[2];
} }
retVal[kv[0].toLowerCase()] = kv[1]; this[kv[0].toLowerCase()] = kv[1];
} else { } else {
throw OperationError("Not a valid header entry"); throw OperationError("Not a valid header entry");
} }
} else { } else {
item = item.trim().toLowerCase(); item = item.trim().toLowerCase();
if (retVal.hasOwnProperty("value")) { if (this.hasOwnProperty("value")) {
retVal.value.push(item); this.value.push(item);
} else { } else {
retVal.value = [item]; this.value = [item];
} }
} }
}); }, retVal);
return retVal; return retVal;
} }
@ -248,25 +248,27 @@ class Mime {
* *
* @param {string} input * @param {string} input
* @param {string} boundary * @param {string} boundary
* @param {string} new_line_length * @param {string} newLineLength
* @return {string[]} * @return {string[]}
*/ */
_splitMultipart(input, boundary, new_line_length) { _splitMultipart(input, boundary, newLineLength) {
let output = []; const output = [];
const boundary_str = "--".concat(boundary, this.rn ? "\r\n" : "\n"); const boundaryStr = "--".concat(boundary, this.rn ? "\r\n" : "\n");
let last = input.indexOf("--".concat(boundary, "--")) - new_line_length; const last = input.indexOf("--".concat(boundary, "--")) - newLineLength;
let start = 0; for (;;) {
while(true) { let start = input.indexOf(boundaryStr, start);
let start = input.indexOf(boundary_str, start);
if (start < 0) { if (start < 0) {
break; break;
} }
start = start + boundary_str.length; start += boundaryStr.length;
let end = input.indexOf(boundary_str, start) - new_line_length; const end = input.indexOf(boundaryStr, start) - newLineLength;
if (end <= start) { if (end <= start) {
break; break;
} }
output.push(input.substring(start, end)); output.push(input.substring(start, end));
if (end === last) {
break;
}
start = end; start = end;
} }
return output; return output;

View file

@ -8,8 +8,6 @@
* @license Apache-2.0 * @license Apache-2.0
*/ */
import Operation from "../Operation";
/** /**
* @param {string} input * @param {string} input
* @returns {byteArray} * @returns {byteArray}

View file

@ -5,10 +5,11 @@
*/ */
import Operation from "../Operation"; import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Mime from "../lib/Mime"; import Mime from "../lib/Mime";
import Utils from "../Utils";
/**
* Operation for Finding and replacing Mime encoded words.
*/
class DecodeMimeEncodedWords extends Operation { class DecodeMimeEncodedWords extends Operation {
/** /**
@ -19,8 +20,7 @@ class DecodeMimeEncodedWords extends Operation {
this.name = "Decode Mime Encoded Words"; this.name = "Decode Mime Encoded Words";
this.module = "Default"; this.module = "Default";
this.description = ["Parser an IMF formatted messages following RFC5322.", this.description = ["Parser an IMF formatted messages following RFC5322.",
"<br><br>", "<br><br>", "Parses an IMF formated message. These often have the file extention &quot;.eml&quote; and contain the email headers and body. The output will be a file list of the headers and mime parts.",
"Parses an IMF formated message. These often have the file extention &quot;.eml&quote; and contain the email headers and body. The output will be a file list of the headers and mime parts.",
].join("\n"); ].join("\n");
this.infoURL = "https://tools.ietf.org/html/rfc2047"; this.infoURL = "https://tools.ietf.org/html/rfc2047";
this.inputType = "string"; this.inputType = "string";
@ -28,6 +28,13 @@ class DecodeMimeEncodedWords extends Operation {
this.args = []; this.args = [];
} }
/**
*
*
*
*
*
*/
run(input, args) { run(input, args) {
return Mime.replaceEncodedWord(input); return Mime.replaceEncodedWord(input);
} }

View file

@ -9,7 +9,7 @@
*/ */
import Operation from "../Operation"; import Operation from "../Operation";
import {decodeQuotedPrintable} from "../lib/QuotedPrintable" import {decodeQuotedPrintable} from "../lib/QuotedPrintable";
/** /**
* From Quoted Printable operation * From Quoted Printable operation

View file

@ -5,10 +5,12 @@
*/ */
import Operation from "../Operation"; import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Mime from "../lib/Mime"; import Mime from "../lib/Mime";
import Utils from "../Utils"; import Utils from "../Utils";
/**
*
*/
class ParseIMF extends Operation { class ParseIMF extends Operation {
/** /**
@ -19,8 +21,8 @@ class ParseIMF extends Operation {
this.name = "Parse Internet Message Format"; this.name = "Parse Internet Message Format";
this.module = "Default"; this.module = "Default";
this.description = ["Parse an IMF formatted messages following RFC5322.", this.description = ["Parse an IMF formatted messages following RFC5322.",
"<br><br>", "<br><br>",
"Parses an IMF formated message. These often have the file extention &quot;.eml&quote; and contain the email headers and body. The output will be a file list of the root header and decoded mime parts.", "Parses an IMF formated message. These often have the file extention &quot;.eml&quote; and contain the email headers and body. The output will be a file list of the root header and decoded mime parts.",
].join("\n"); ].join("\n");
this.infoURL = "https://tools.ietf.org/html/rfc5322"; this.infoURL = "https://tools.ietf.org/html/rfc5322";
this.inputType = "string"; this.inputType = "string";
@ -35,9 +37,16 @@ class ParseIMF extends Operation {
]; ];
} }
/**
*
*
*
*
*
*/
run(input, args) { run(input, args) {
let mimeObj = new Mime(input); //let mimeObj = new Mime(input);
return mimeObj.decodeMime(args[0]); return new Mime(input).decodeMime(args[0]);
} }
/** /**