Have some initial functionallity

This commit is contained in:
bwhitn 2018-11-23 23:43:06 -05:00
parent 189cf337d6
commit 9ef9dff832

View file

@ -21,12 +21,10 @@ import Utils from "../Utils";
* @constant * @constant
* @default * @default
*/ */
const IMF_FIELD_ITEM = { const FILE_TYPE_SUFFIX = {
FILENAME: [/filename=".*?([^~#%&*\][\\:<>?/|]+)"/, "content-disposition"], "text/plain": "txt",
CONTENT_TYPE: [/\s*([^;\s]+)/, "content-type"], "text/html": "htm",
BOUNDARY: [/boundary="(.+?)"/, "content-type"], "application/rtf": "rtf",
CHARSET: [/charset=([a-z0-9-]+)/, "content-type"],
TRANSER_ENCODING: [/\s*([A-Za-z0-9-]+)\s*/, "content-transfer-encoding"],
} }
class ParseIMF extends Operation { class ParseIMF extends Operation {
@ -64,22 +62,34 @@ class ParseIMF extends Operation {
* @returns {File[]} * @returns {File[]}
*/ */
run(input, args) { run(input, args) {
// TODO: need to add Non-Mime emails
// TODO: need to add header info to output
// TODO: no uuencode function. see if we can fix this
// TODO: Need to parse multipart headers better as they are key value pairs separated by a ";\s+".
if (!input) { if (!input) {
return []; return [];
} }
let headerBody = ParseIMF.splitHeaderFromBody(input); let headerBody = ParseIMF.splitHeaderFromBody(input);
let header = headerBody[0]; let headerArray = ParseIMF.parseHeader(headerBody[0]);
let headerArray = ParseIMF.parseHeader(header);
if (args[0] && headerBody.length > 0) { if (args[0] && headerBody.length > 0) {
headerBody[0] = ParseIMF.replaceDecodeWord(headerBody[0]); headerBody[0] = ParseIMF.replaceDecodeWord(headerBody[0]);
} }
let retfiles = ParseIMF.walkMime(headerBody[1], headerArray, input.indexOf("\r") >= 0); let retfiles = ParseIMF.walkMime(headerBody[1], headerArray, input.indexOf("\r") >= 0);
let retval = []; let retval = [];
let i = 0; retfiles.forEach(function(fileObj){
retfiles.forEach(function(file){ let file = null;
file = new File([file.data], "test"+String(i), {type: "text/plain"}); if (fileObj.name !== null) {
file = new File([fileObj.data], fileObj.name, {type: fileObj.type});
} else {
let name = ParseIMF.replaceDecodeWord(headerArray["subject"][0]).concat(".");
if (fileObj.type in FILE_TYPE_SUFFIX) {
name = name.concat(FILE_TYPE_SUFFIX[fileObj.type]);
} else {
name = name.concat("bin");
}
file = new File([fileObj.data], name, {type: fileObj.type});
}
retval.push(file); retval.push(file);
i++;
}); });
return retval; return retval;
} }
@ -115,21 +125,37 @@ class ParseIMF extends Operation {
} else { } else {
content_boundary = content_type_reg.exec(header["content-type"][0]); content_boundary = content_type_reg.exec(header["content-type"][0]);
} }
const boundary_str = "--".concat(content_boundary[idx]); let mime_parts = ParseIMF.splitMultipart(input, content_boundary[idx], new_line_length);
let start = input.indexOf(boundary_str) + boundary_str.length + new_line_length; mime_parts.forEach(function(mime_part){
let end = input.indexOf(boundary_str.concat("--")) - new_line_length; let headerBody = ParseIMF.splitHeaderFromBody(mime_part);
let output = input.substring(start, end); let headerArray = ParseIMF.parseHeader(headerBody[0]);
let headerBody = ParseIMF.splitHeaderFromBody(output); let parts = ParseIMF.walkMime(headerBody[1], headerArray, rn);
let headerArray = ParseIMF.parseHeader(headerBody[0]); parts.forEach(function(part){
let parts = ParseIMF.walkMime(headerBody[1], headerArray, rn); output_sections.push(part);
parts.forEach(function(part){ });
output_sections.push(part);
}); });
} else if (header.hasOwnProperty("content-type") && header.hasOwnProperty("content-transfer-encoding")) { } else if (header.hasOwnProperty("content-type") && header.hasOwnProperty("content-transfer-encoding")) {
const cont_type_data_reg = /^([^;]+);\s+charset\=(['"])(.+?)\2/g; let contType = null;
let cont_type = cont_type_data_reg.exec(header["content-type"][0]); let dataValue = null;
let val = ParseIMF.decodeMimeData(input, cont_type[3], header["content-transfer-encoding"][0]); let fileName = null;
return [{type:cont_type[1], data: val}]; let charEnc = null;
// TODO: if there is no content disposition filename try content type name.
if (header.hasOwnProperty("content-disposition")) {
const cont_disp = /^([^;]+);.*?filename\=(['"]?)(.+?)\2$/g;
let dispo = cont_disp.exec(header["content-disposition"][0]);
// TODO: Remove path if it contains it.
fileName = dispo[3];
const cont_type_file = /^([^;]+);\s+name\=(["']?)(.+?)\2$/g;
let content = cont_type_file.exec(header["content-type"][0]);
let contType = content[1];
} else {
const cont_type_data_reg = /^([^;]+);\s+charset\=(['"]?)(.+?)\2$/g;
let content = cont_type_data_reg.exec(header["content-type"][0]);
contType = content[1];
charEnc = content[3]
}
dataValue = ParseIMF.decodeMimeData(input, charEnc, header["content-transfer-encoding"][0]);
return [{type: contType, data: dataValue, name: fileName}];
} else { } else {
throw new OperationError("Invalid Mime section"); throw new OperationError("Invalid Mime section");
} }
@ -178,7 +204,7 @@ class ParseIMF extends Operation {
* @returns {object} * @returns {object}
*/ */
static parseHeader(input) { static parseHeader(input) {
const sectionRegex = /([A-Z-]+):\s+([\x20-\x7e\r\n\t]+?)(?=$|\r?\n\S)/gi; const sectionRegex = /([A-Za-z-]+):\s+([\x20-\xff\r\n\t]+?)(?=$|\r?\n\S)/g;
let header = {}, section; let header = {}, section;
while ((section = sectionRegex.exec(input))) { while ((section = sectionRegex.exec(input))) {
let fieldName = section[1].toLowerCase(); let fieldName = section[1].toLowerCase();
@ -220,22 +246,35 @@ class ParseIMF extends Operation {
} }
/** /**
* Returns a header item given a header object, itemName, and index number.
* *
* @param {object} header *
* @param {object} FIELD_ITEM *
* @param {integer} fieldNum *
* @returns {string}
*/ */
static getHeaderItem(header, fieldItem, fieldNum = 0){ static splitMultipart(input, boundary, new_line_length) {
if (fieldItem[1] in header && header[fieldItem[1]].length > fieldNum) { let output = [];
let field = header[fieldItem[1]][fieldNum], item; let newline = new_line_length === 2 ? "\r\n" : "\n";
if ((item = fieldItem[0].exec(field))) { const boundary_str = "--".concat(boundary, newline);
return item[1]; const last = input.indexOf("--".concat(boundary, "--", newline)) - new_line_length;
let start = 0;
while(true) {
let start = input.indexOf(boundary_str, start);
if (start >= 0) {
start = start + boundary_str.length;
} else {
break;
} }
let end = input.indexOf(boundary_str, start) - new_line_length;
if (end > start) {
output.push(input.substring(start, end));
} else {
output.push(input.substring(start, last));
break;
}
start = end;
} }
return output;
} }
} }
export default ParseIMF export default ParseIMF