Skip to content

Commit

Permalink
fix(data-uri): Moved all data-uri regexes to use the non-regex parseD…
Browse files Browse the repository at this point in the history
…ataUri method
  • Loading branch information
andris9 committed Feb 22, 2024
1 parent db77249 commit edd5dfe
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 53 deletions.
52 changes: 2 additions & 50 deletions lib/mail-composer/index.js
Expand Up @@ -4,6 +4,7 @@

const MimeNode = require('../mime-node');
const mimeFuncs = require('../mime-funcs');
const parseDataURI = require('../shared').parseDataURI;

/**
* Creates the object for composing a MimeNode instance out from the mail options
Expand Down Expand Up @@ -539,7 +540,7 @@ class MailComposer {
_processDataUrl(element) {
let parsedDataUri;
if ((element.path || element.href).match(/^data:/)) {
parsedDataUri = this.parseDataURI(element.path || element.href);
parsedDataUri = parseDataURI(element.path || element.href);
}

if (!parsedDataUri) {
Expand All @@ -559,55 +560,6 @@ class MailComposer {

return element;
}

parseDataURI(uri) {
let input = uri;
let commaPos = input.indexOf(',');
if (!commaPos) {
return uri;
}

let data = input.substring(commaPos + 1);
let metaStr = input.substring('data:'.length, commaPos);

let encoding;

let metaEntries = metaStr.split(';');
let lastMetaEntry = metaEntries.length > 1 ? metaEntries[metaEntries.length - 1] : false;
if (lastMetaEntry && lastMetaEntry.indexOf('=') < 0) {
encoding = lastMetaEntry.toLowerCase();
metaEntries.pop();
}

let contentType = metaEntries.shift() || 'application/octet-stream';
let params = {};
for (let entry of metaEntries) {
let sep = entry.indexOf('=');
if (sep >= 0) {
let key = entry.substring(0, sep);
let value = entry.substring(sep + 1);
params[key] = value;
}
}

switch (encoding) {
case 'base64':
data = Buffer.from(data, 'base64');
break;
case 'utf8':
data = Buffer.from(data);
break;
default:
try {
data = Buffer.from(decodeURIComponent(data));
} catch (err) {
data = Buffer.from(data);
}
data = Buffer.from(data);
}

return { data, encoding, contentType, params };
}
}

module.exports = MailComposer;
56 changes: 53 additions & 3 deletions lib/shared/index.js
Expand Up @@ -418,6 +418,55 @@ module.exports.callbackPromise = (resolve, reject) =>
}
};

module.exports.parseDataURI = uri => {
let input = uri;
let commaPos = input.indexOf(',');
if (!commaPos) {
return uri;
}

let data = input.substring(commaPos + 1);
let metaStr = input.substring('data:'.length, commaPos);

let encoding;

let metaEntries = metaStr.split(';');
let lastMetaEntry = metaEntries.length > 1 ? metaEntries[metaEntries.length - 1] : false;
if (lastMetaEntry && lastMetaEntry.indexOf('=') < 0) {
encoding = lastMetaEntry.toLowerCase();
metaEntries.pop();
}

let contentType = metaEntries.shift() || 'application/octet-stream';
let params = {};
for (let entry of metaEntries) {
let sep = entry.indexOf('=');
if (sep >= 0) {
let key = entry.substring(0, sep);
let value = entry.substring(sep + 1);
params[key] = value;
}
}

switch (encoding) {
case 'base64':
data = Buffer.from(data, 'base64');
break;
case 'utf8':
data = Buffer.from(data);
break;
default:
try {
data = Buffer.from(decodeURIComponent(data));
} catch (err) {
data = Buffer.from(data);
}
data = Buffer.from(data);
}

return { data, encoding, contentType, params };
};

/**
* Resolves a String or a Buffer value for content value. Useful if the value
* is a Stream or a file or an URL. If the value is a Stream, overwrites
Expand Down Expand Up @@ -470,11 +519,12 @@ module.exports.resolveContent = (data, key, callback) => {
contentStream = nmfetch(content.path || content.href);
return resolveStream(contentStream, callback);
} else if (/^data:/i.test(content.path || content.href)) {
let parts = (content.path || content.href).match(/^data:((?:[^;]*;)*(?:[^,]*)),(.*)$/i);
if (!parts) {
let parsedDataUri = module.exports.parseDataURI(content.path || content.href);

if (!parsedDataUri || !parsedDataUri.data) {
return callback(null, Buffer.from(0));
}
return callback(null, /\bbase64$/i.test(parts[1]) ? Buffer.from(parts[2], 'base64') : Buffer.from(decodeURIComponent(parts[2])));
return callback(null, parsedDataUri.data);
} else if (content.path) {
return resolveStream(fs.createReadStream(content.path), callback);
}
Expand Down

0 comments on commit edd5dfe

Please sign in to comment.