New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

rfc2047

Package Overview
Dependencies
Maintainers
3
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rfc2047 - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

.editorconfig

386

lib/rfc2047.js

@@ -1,17 +0,17 @@

/*jshint regexp:false*/
/*global unescape*/
/* jshint regexp:false */
/* global unescape */
var isUtf8RegExp = /^utf-?8$/i,
isLatin1RegExp = /^(?:iso-8859-1|latin1)$/i,
iconvLite = require('iconv-lite'),
rfc2047 = module.exports = {};
var isUtf8RegExp = /^utf-?8$/i;
var isLatin1RegExp = /^(?:iso-8859-1|latin1)$/i;
var iconvLite = require('iconv-lite');
var rfc2047 = (module.exports = {});
function stringify(obj) {
if (typeof obj === 'string') {
return obj;
} else if (obj === null || typeof obj === 'undefined') {
return '';
} else {
return String(obj);
}
if (typeof obj === 'string') {
return obj;
} else if (obj === null || typeof obj === 'undefined') {
return '';
} else {
return String(obj);
}
}

@@ -21,35 +21,38 @@

try {
iconv = require('' + 'iconv'); // Prevent browserify from detecting iconv and failing
iconv = require('' + 'iconv'); // Prevent browserify from detecting iconv and failing
} catch (e) {}
function decodeBuffer(encodedText, encoding) {
if (encoding === 'q') {
encodedText = encodedText.replace(/_/g, ' ');
var numValidlyEncodedBytes = 0,
i;
for (i = 0 ; i < encodedText.length ; i += 1) {
if (encodedText[i] === '=' && /^[0-9a-f]{2}$/i.test(encodedText.slice(i + 1, i + 3))) {
numValidlyEncodedBytes += 1;
}
if (encoding === 'q') {
encodedText = encodedText.replace(/_/g, ' ');
var numValidlyEncodedBytes = 0;
var i;
for (i = 0; i < encodedText.length; i += 1) {
if (
encodedText[i] === '=' &&
/^[0-9a-f]{2}$/i.test(encodedText.slice(i + 1, i + 3))
) {
numValidlyEncodedBytes += 1;
}
}
var buffer = Buffer.alloc(encodedText.length - numValidlyEncodedBytes * 2);
var j = 0;
for (i = 0; i < encodedText.length; i += 1) {
if (encodedText[i] === '=') {
var hexChars = encodedText.slice(i + 1, i + 3);
if (/^[0-9a-f]{2}$/i.test(hexChars)) {
buffer[j] = parseInt(encodedText.substr(i + 1, 2), 16);
i += 2;
} else {
buffer[j] = encodedText.charCodeAt(i);
}
var buffer = new Buffer(encodedText.length - numValidlyEncodedBytes * 2),
j = 0;
for (i = 0 ; i < encodedText.length ; i += 1) {
if (encodedText[i] === '=') {
var hexChars = encodedText.slice(i + 1, i + 3);
if (/^[0-9a-f]{2}$/i.test(hexChars)) {
buffer[j] = parseInt(encodedText.substr(i + 1, 2), 16);
i += 2;
} else {
buffer[j] = encodedText.charCodeAt(i);
}
} else {
buffer[j] = encodedText.charCodeAt(i);
}
j += 1;
}
return buffer;
} else {
return new Buffer(encodedText, 'base64');
} else {
buffer[j] = encodedText.charCodeAt(i);
}
j += 1;
}
return buffer;
} else {
return Buffer.from(encodedText, 'base64');
}
}

@@ -59,77 +62,91 @@

function decodeEncodedWord(encodedText, encoding, charset) {
if (encoding === 'q' && isLatin1RegExp.test(charset)) {
return unescape(encodedText.replace(/_/g, ' ').replace(/%/g, '%25').replace(/\=(?=[0-9a-f]{2})/gi, '%'));
} else {
var buffer;
try {
buffer = decodeBuffer(encodedText, encoding);
} catch (e) {
return;
}
if (/^ks_c_5601/i.test(charset)) {
charset = 'CP949';
}
var decoded;
if (iconv) {
var converter;
try {
converter = new iconv.Iconv(charset, 'utf-8//TRANSLIT');
} catch (e1) {
// Assume EINVAL (unsupported charset) and fall back to assuming iso-8859-1:
converter = new iconv.Iconv('iso-8859-1', 'utf-8//TRANSLIT');
}
try {
return converter.convert(buffer).toString('utf-8');
} catch (e2) {
return;
}
} else if (isUtf8RegExp.test(charset)) {
decoded = buffer.toString('utf-8');
if (!/\ufffd/.test(decoded)) {
return decoded;
}
} else if (/^(?:us-)?ascii$/i.test(charset)) {
return buffer.toString('ascii');
} else if (iconvLite.encodingExists(charset)) {
decoded = iconvLite.decode(buffer, charset);
if (!/\ufffd/.test(decoded)) {
return decoded;
}
}
if (encoding === 'q' && isLatin1RegExp.test(charset)) {
return unescape(
encodedText
.replace(/_/g, ' ')
.replace(/%/g, '%25')
.replace(/=(?=[0-9a-f]{2})/gi, '%')
);
} else {
var buffer;
try {
buffer = decodeBuffer(encodedText, encoding);
} catch (e) {
return;
}
if (/^ks_c_5601/i.test(charset)) {
charset = 'CP949';
}
var decoded;
if (iconv) {
var converter;
try {
converter = new iconv.Iconv(charset, 'utf-8//TRANSLIT');
} catch (e1) {
// Assume EINVAL (unsupported charset) and fall back to assuming iso-8859-1:
converter = new iconv.Iconv('iso-8859-1', 'utf-8//TRANSLIT');
}
try {
return converter.convert(buffer).toString('utf-8');
} catch (e2) {}
} else if (isUtf8RegExp.test(charset)) {
decoded = buffer.toString('utf-8');
if (!/\ufffd/.test(decoded)) {
return decoded;
}
} else if (/^(?:us-)?ascii$/i.test(charset)) {
return buffer.toString('ascii');
} else if (iconvLite.encodingExists(charset)) {
decoded = iconvLite.decode(buffer, charset);
if (!/\ufffd/.test(decoded)) {
return decoded;
}
}
}
}
var encodedWordRegExp = /\=\?([^\?]+)\?([QB])\?([^\?]*)\?=/gi;
var encodedWordRegExp = /=\?([^?]+)\?([QB])\?([^?]*)\?=/gi;
rfc2047.decode = function (text) {
text = stringify(text).replace(/\?\=\s+\=\?/g, '?==?'); // Strip whitespace between neighbouring encoded words
text = stringify(text).replace(/\?=\s+=\?/g, '?==?'); // Strip whitespace between neighbouring encoded words
var numEncodedWordsToIgnore = 0;
var numEncodedWordsToIgnore = 0;
return text.replace(encodedWordRegExp, function (encodedWord, charset, encoding, encodedText, index) {
if (numEncodedWordsToIgnore > 0) {
numEncodedWordsToIgnore -= 1;
return '';
}
encoding = encoding.toLowerCase();
var decodedTextOrBuffer = decodeEncodedWord(encodedText, encoding, charset);
while (typeof decodedTextOrBuffer !== 'string') {
// The encoded word couldn't be decoded because it contained a partial character in a multibyte charset.
// Keep trying to look ahead and consume an additional encoded word right after this one, and if its
// encoding and charsets match, try to decode the concatenation.
return text.replace(encodedWordRegExp, function (
encodedWord,
charset,
encoding,
encodedText,
index
) {
if (numEncodedWordsToIgnore > 0) {
numEncodedWordsToIgnore -= 1;
return '';
}
encoding = encoding.toLowerCase();
var decodedTextOrBuffer = decodeEncodedWord(encodedText, encoding, charset);
while (typeof decodedTextOrBuffer !== 'string') {
// The encoded word couldn't be decoded because it contained a partial character in a multibyte charset.
// Keep trying to look ahead and consume an additional encoded word right after this one, and if its
// encoding and charsets match, try to decode the concatenation.
// The ongoing replace call is unaffected by this trick, so we don't need to reset .lastIndex afterwards:
encodedWordRegExp.lastIndex = index + encodedWord.length;
var matchNextEncodedWord = encodedWordRegExp.exec(text);
if (matchNextEncodedWord && matchNextEncodedWord.index === index + encodedWord.length && matchNextEncodedWord[1] === charset && matchNextEncodedWord[2].toLowerCase() === encoding) {
numEncodedWordsToIgnore += 1;
encodedWord += matchNextEncodedWord[0];
encodedText += matchNextEncodedWord[3];
decodedTextOrBuffer = decodeEncodedWord(encodedText, encoding, charset);
} else {
return encodedWord;
}
}
return decodedTextOrBuffer;
});
// The ongoing replace call is unaffected by this trick, so we don't need to reset .lastIndex afterwards:
encodedWordRegExp.lastIndex = index + encodedWord.length;
var matchNextEncodedWord = encodedWordRegExp.exec(text);
if (
matchNextEncodedWord &&
matchNextEncodedWord.index === index + encodedWord.length &&
matchNextEncodedWord[1] === charset &&
matchNextEncodedWord[2].toLowerCase() === encoding
) {
numEncodedWordsToIgnore += 1;
encodedWord += matchNextEncodedWord[0];
encodedText += matchNextEncodedWord[3];
decodedTextOrBuffer = decodeEncodedWord(encodedText, encoding, charset);
} else {
return encodedWord;
}
}
return decodedTextOrBuffer;
});
};

@@ -143,21 +160,25 @@

// Initialize array used as lookup table (int (octet) => string)
var qpTokenByOctet = new Array(256),
i;
var qpTokenByOctet = new Array(256);
var i;
for (i = 0 ; i < 256 ; i += 1) {
qpTokenByOctet[i] = "=" + (i < 16 ? "0" : "") + i.toString(16).toUpperCase();
for (i = 0; i < 256; i += 1) {
qpTokenByOctet[i] = `=${i < 16 ? '0' : ''}${i.toString(16).toUpperCase()}`;
}
"!#$%&'*+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz{|}~".split(/(?:)/).forEach(function (encodedWordSafeAsciiChar) {
qpTokenByOctet[encodedWordSafeAsciiChar.charCodeAt(0)] = encodedWordSafeAsciiChar;
});
"!#$%&'*+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^`abcdefghijklmnopqrstuvwxyz{|}~"
.split(/(?:)/)
.forEach(function (encodedWordSafeAsciiChar) {
qpTokenByOctet[
encodedWordSafeAsciiChar.charCodeAt(0)
] = encodedWordSafeAsciiChar;
});
qpTokenByOctet[32] = "_";
qpTokenByOctet[32] = '_';
function bufferToQuotedPrintableString(buffer) {
var result = '';
for (var i = 0 ; i < buffer.length ; i += 1) {
result += qpTokenByOctet[buffer[i]];
}
return result;
var result = '';
for (var i = 0; i < buffer.length; i += 1) {
result += qpTokenByOctet[buffer[i]];
}
return result;
}

@@ -167,73 +188,82 @@

var headerSafeAsciiChars = " !\"#$%&'()*+-,-./0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",
headerUnsafeAsciiChars = "";
var headerSafeAsciiChars =
' !"#$%&\'()*+-,-./0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
var headerUnsafeAsciiChars = '';
for (i = 0 ; i < 128 ; i += 1) {
var ch = String.fromCharCode(i);
if (headerSafeAsciiChars.indexOf(ch) === -1) { // O(n^2) but only happens at startup
headerUnsafeAsciiChars += ch;
}
for (i = 0; i < 128; i += 1) {
var ch = String.fromCharCode(i);
if (headerSafeAsciiChars.indexOf(ch) === -1) {
// O(n^2) but only happens at startup
headerUnsafeAsciiChars += ch;
}
}
function quoteCharacterClass(chars) {
return chars.replace(/[\\\|\^\*\+\?\[\]\(\)\-\.]/g, "\\$&");
return chars.replace(/[\\|^*+?[\]().-]/g, '\\$&');
}
var unsafeTokenRegExp = new RegExp("[\u0080-\uffff" + quoteCharacterClass(headerUnsafeAsciiChars) + "]"),
maxNumCharsPerEncodedWord = 8; // Very conservative limit to prevent creating an encoded word of more than 72 ascii chars
var unsafeTokenRegExp = new RegExp(
`[\u0080-\uffff${quoteCharacterClass(headerUnsafeAsciiChars)}]`
);
var maxNumCharsPerEncodedWord = 8; // Very conservative limit to prevent creating an encoded word of more than 72 ascii chars
rfc2047.encode = function (text) {
text = stringify(text)
.replace(/\s/g, ' '); // Normalize whitespace
var tokens = text.match(/([^\s]*\s*)/g), // Split at space, but keep trailing space as part of each token
previousTokenWasEncodedWord = false, // Consecutive encoded words must have a space between them, so this state must be kept
previousTokenWasWhitespaceFollowingEncodedWord = false,
result = '';
if (tokens) {
for (var i = 0 ; i < tokens.length ; i += 1) {
var token = tokens[i];
if (unsafeTokenRegExp.test(token)) {
var matchQuotesAtBeginning = token.match(/^"+/);
if (matchQuotesAtBeginning) {
previousTokenWasEncodedWord = false;
result += matchQuotesAtBeginning[0];
tokens[i] = token = token.substr(matchQuotesAtBeginning[0].length);
tokens.splice(i, 0, matchQuotesAtBeginning[0]);
i += 1;
}
text = stringify(text).replace(/\s/g, ' '); // Normalize whitespace
var tokens = text.match(/([^\s]*\s*)/g); // Split at space, but keep trailing space as part of each token
var previousTokenWasEncodedWord = false; // Consecutive encoded words must have a space between them, so this state must be kept
var previousTokenWasWhitespaceFollowingEncodedWord = false;
var result = '';
if (tokens) {
for (var i = 0; i < tokens.length; i += 1) {
var token = tokens[i];
if (unsafeTokenRegExp.test(token)) {
var matchQuotesAtBeginning = token.match(/^"+/);
if (matchQuotesAtBeginning) {
previousTokenWasEncodedWord = false;
result += matchQuotesAtBeginning[0];
tokens[i] = token = token.substr(matchQuotesAtBeginning[0].length);
tokens.splice(i, 0, matchQuotesAtBeginning[0]);
i += 1;
}
var matchWhitespaceOrQuotesAtEnd = token.match(/\\?[\s"]+$/);
if (matchWhitespaceOrQuotesAtEnd) {
tokens.splice(i + 1, 0, matchWhitespaceOrQuotesAtEnd[0]);
token = token.substr(0, token.length - matchWhitespaceOrQuotesAtEnd[0].length);
}
var matchWhitespaceOrQuotesAtEnd = token.match(/\\?[\s"]+$/);
if (matchWhitespaceOrQuotesAtEnd) {
tokens.splice(i + 1, 0, matchWhitespaceOrQuotesAtEnd[0]);
token = token.substr(
0,
token.length - matchWhitespaceOrQuotesAtEnd[0].length
);
}
// Word contains at least one header unsafe char, an encoded word must be created.
if (token.length > maxNumCharsPerEncodedWord) {
tokens.splice(i + 1, 0, token.substr(maxNumCharsPerEncodedWord));
token = token.substr(0, maxNumCharsPerEncodedWord);
}
// Word contains at least one header unsafe char, an encoded word must be created.
if (token.length > maxNumCharsPerEncodedWord) {
tokens.splice(i + 1, 0, token.substr(maxNumCharsPerEncodedWord));
token = token.substr(0, maxNumCharsPerEncodedWord);
}
if (previousTokenWasWhitespaceFollowingEncodedWord) {
token = " " + token;
}
if (previousTokenWasWhitespaceFollowingEncodedWord) {
token = ` ${token}`;
}
var charset = 'utf-8';
// Around 25% faster than encodeURIComponent(token.replace(/ /g, "_")).replace(/%/g, "="):
var encodedWordBody = bufferToQuotedPrintableString(new Buffer(token, 'utf-8'));
if (previousTokenWasEncodedWord) {
result += ' ';
}
result += "=?" + charset + "?Q?" + encodedWordBody + "?=";
previousTokenWasWhitespaceFollowingEncodedWord = false;
previousTokenWasEncodedWord = true;
} else {
// Word only contains header safe chars, no need to encode:
result += token;
previousTokenWasWhitespaceFollowingEncodedWord = /^\s*$/.test(token) && previousTokenWasEncodedWord;
previousTokenWasEncodedWord = false;
}
var charset = 'utf-8';
// Around 25% faster than encodeURIComponent(token.replace(/ /g, "_")).replace(/%/g, "="):
var encodedWordBody = bufferToQuotedPrintableString(
Buffer.from(token, 'utf-8')
);
if (previousTokenWasEncodedWord) {
result += ' ';
}
result += `=?${charset}?Q?${encodedWordBody}?=`;
previousTokenWasWhitespaceFollowingEncodedWord = false;
previousTokenWasEncodedWord = true;
} else {
// Word only contains header safe chars, no need to encode:
result += token;
previousTokenWasWhitespaceFollowingEncodedWord =
/^\s*$/.test(token) && previousTokenWasEncodedWord;
previousTokenWasEncodedWord = false;
}
}
return result;
}
return result;
};
{
"name": "rfc2047",
"version": "2.0.1",
"version": "3.0.0",
"description": "Encode and decode rfc2047 (MIME encoded words)",

@@ -10,6 +10,6 @@ "main": "lib/rfc2047.js",

"scripts": {
"lint": "jshint .",
"test": "mocha && npm run lint",
"travis": "npm test && npm run coverage && <coverage/lcov.info coveralls",
"coverage": "NODE_ENV=development istanbul cover _mocha -- --reporter dot && echo google-chrome coverage/lcov-report/index.html"
"lint": "eslint . && prettier --check '**/*.{js,md,json}'",
"test": "mocha",
"test:ci": "npm run coverage",
"coverage": "nyc --reporter=lcov --reporter=text --all -- npm test && echo google-chrome coverage/lcov-report/index.html"
},

@@ -30,3 +30,3 @@ "repository": {

],
"author": "Andreas Lind <andreas@one.com>",
"author": "Andreas Lind <andreaslindpetersen@gmail.com>",
"license": "BSD",

@@ -38,7 +38,15 @@ "bugs": {

"devDependencies": {
"coveralls": "2.11.2",
"iconv": "2.2.1",
"istanbul": "0.3.5",
"jshint": "2.5.11",
"coveralls": "^2.11.2",
"eslint": "^7.10.0",
"eslint-config-prettier": "^6.12.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-mocha": "^8.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"iconv": "^3.0.0",
"mocha": "2.1.0",
"nyc": "^15.1.0",
"prettier": "^2.1.2",
"unexpected": "10.20.0"

@@ -48,3 +56,8 @@ },

"iconv-lite": "0.4.5"
},
"nyc": {
"include": [
"lib/**"
]
}
}

@@ -1,3 +0,2 @@

rfc2047
=======
# rfc2047

@@ -12,3 +11,5 @@ Encode and decode [rfc2047](https://www.ietf.org/rfc/rfc2047.txt) (MIME encoded words).

console.log(rfc2047.decode('=?iso-8859-1?Q?=A1?=Hola, se=?iso-8859-1?Q?=F1?=or!'));
console.log(
rfc2047.decode('=?iso-8859-1?Q?=A1?=Hola, se=?iso-8859-1?Q?=F1?=or!')
);
// ¡Hola, señor!

@@ -15,0 +16,0 @@ ```

@@ -1,212 +0,344 @@

/*global describe, it*/
var unexpected = require('unexpected'),
rfc2047 = require('../lib/rfc2047');
/* global describe, it */
var unexpected = require('unexpected');
var rfc2047 = require('../lib/rfc2047');
describe('rfc2047', function () {
var expect = unexpected.clone().addAssertion('to encode to', function (expect, subject, value) {
expect(rfc2047.encode(subject), 'to equal', value);
}).addAssertion('to decode to', function (expect, subject, value) {
expect(rfc2047.decode(subject), 'to equal', value);
}).addAssertion('to encode back and forth to', function (expect, subject, value) {
expect(subject, 'to encode to', value);
expect(value, 'to decode to', subject);
var expect = unexpected
.clone()
.addAssertion('to encode to', function (expect, subject, value) {
expect(rfc2047.encode(subject), 'to equal', value);
})
.addAssertion('to decode to', function (expect, subject, value) {
expect(rfc2047.decode(subject), 'to equal', value);
})
.addAssertion('to encode back and forth to', function (
expect,
subject,
value
) {
expect(subject, 'to encode to', value);
expect(value, 'to decode to', subject);
});
describe('#encode() and #decode()', function () {
it('should handle the empty string', function () {
expect('', 'to encode back and forth to', '');
});
describe('#encode() and #decode()', function () {
it('should handle the empty string', function () {
expect('', 'to encode back and forth to', '');
});
it('should handle a string only containing a space', function () {
expect(' ', 'to encode back and forth to', ' ');
});
it('should handle a string only containing a space', function () {
expect(' ', 'to encode back and forth to', ' ');
});
it('should not encode an equals sign', function () {
expect('=', 'to encode back and forth to', '=');
});
it('should not encode an equals sign', function () {
expect('=', 'to encode back and forth to', '=');
});
it('should handle a string that does not need to be encoded', function () {
expect('Andreas Lind <andreas@one.com>', 'to encode back and forth to', 'Andreas Lind <andreas@one.com>');
});
it('should handle a string that does not need to be encoded', function () {
expect(
'Andreas Lind <andreas@one.com>',
'to encode back and forth to',
'Andreas Lind <andreas@one.com>'
);
});
it('should handle a multi-word string where the middle word has to be encoded', function () {
expect('Andreas Lindø <andreas@one.com>', 'to encode back and forth to', 'Andreas =?utf-8?Q?Lind=C3=B8?= <andreas@one.com>');
});
it('should handle a multi-word string where the middle word has to be encoded', function () {
expect(
'Andreas Lindø <andreas@one.com>',
'to encode back and forth to',
'Andreas =?utf-8?Q?Lind=C3=B8?= <andreas@one.com>'
);
});
it('should use an UTF-8 encoded word when a character is not in iso-8859-1', function () {
expect('Mr. Smiley face aka ☺ <smiley@face.dk>', 'to encode back and forth to', 'Mr. Smiley face aka =?utf-8?Q?=E2=98=BA?= <smiley@face.dk>');
});
it('should use an UTF-8 encoded word when a character is not in iso-8859-1', function () {
expect(
'Mr. Smiley face aka ☺ <smiley@face.dk>',
'to encode back and forth to',
'Mr. Smiley face aka =?utf-8?Q?=E2=98=BA?= <smiley@face.dk>'
);
});
it('should handle two neighbouring words that have to be encoded', function () {
expect('¡Hola, señor!', 'to encode back and forth to', '=?utf-8?Q?=C2=A1Hola=2C?= =?utf-8?Q?_se=C3=B1or!?=');
expect('På lördag', 'to encode back and forth to', '=?utf-8?Q?P=C3=A5?= =?utf-8?Q?_l=C3=B6rdag?=');
});
it('should handle two neighbouring words that have to be encoded', function () {
expect(
'¡Hola, señor!',
'to encode back and forth to',
'=?utf-8?Q?=C2=A1Hola=2C?= =?utf-8?Q?_se=C3=B1or!?='
);
expect(
'På lördag',
'to encode back and forth to',
'=?utf-8?Q?P=C3=A5?= =?utf-8?Q?_l=C3=B6rdag?='
);
});
it('should not rely on the space between neighbouring encoded words to be preserved', function () {
expect('☺ ☺', 'to encode back and forth to', '=?utf-8?Q?=E2=98=BA?= =?utf-8?Q?_=E2=98=BA?=');
});
it('should not rely on the space between neighbouring encoded words to be preserved', function () {
expect(
'☺ ☺',
'to encode back and forth to',
'=?utf-8?Q?=E2=98=BA?= =?utf-8?Q?_=E2=98=BA?='
);
});
it('should handle some dreamed up edge cases', function () {
expect('lördag', 'to encode back and forth to', '=?utf-8?Q?l=C3=B6rdag?=');
});
it('should handle some dreamed up edge cases', function () {
expect(
'lördag',
'to encode back and forth to',
'=?utf-8?Q?l=C3=B6rdag?='
);
});
it('should handle a multi-word string where the middle word has to be left unencoded', function () {
expect('Så er fødselen i gang', 'to encode back and forth to', '=?utf-8?Q?S=C3=A5?= er =?utf-8?Q?f=C3=B8dselen?= i gang');
});
it('should handle a multi-word string where the middle word has to be left unencoded', function () {
expect(
'Så er fødselen i gang',
'to encode back and forth to',
'=?utf-8?Q?S=C3=A5?= er =?utf-8?Q?f=C3=B8dselen?= i gang'
);
});
it('should place leading quotes correctly', function () {
expect('"ÅÄÖ" <sss@example.com>', 'to encode back and forth to', '"=?utf-8?Q?=C3=85=C3=84=C3=96?=" <sss@example.com>');
});
it('should place leading quotes correctly', function () {
expect(
'"ÅÄÖ" <sss@example.com>',
'to encode back and forth to',
'"=?utf-8?Q?=C3=85=C3=84=C3=96?=" <sss@example.com>'
);
});
it('should place trailing quotes correctly', function () {
expect('"TEST ÅÄÖ" <sss@example.com>', 'to encode back and forth to', '"TEST =?utf-8?Q?=C3=85=C3=84=C3=96?=" <sss@example.com>');
});
it('should place trailing quotes correctly', function () {
expect(
'"TEST ÅÄÖ" <sss@example.com>',
'to encode back and forth to',
'"TEST =?utf-8?Q?=C3=85=C3=84=C3=96?=" <sss@example.com>'
);
});
// Regression test for #2:
it('should handle an emoji test case', function () {
expect('{"tags":"","fullName":"😬"}', 'to encode back and forth to', '=?utf-8?Q?{=22tags=22=3A?=""=?utf-8?Q?=2C=22fullNa?= =?utf-8?Q?me=22=3A=22=F0=9F=98=AC=22?=}');
});
// Regression test for #2:
it('should handle an emoji test case', function () {
expect(
'{"tags":"","fullName":"😬"}',
'to encode back and forth to',
'=?utf-8?Q?{=22tags=22=3A?=""=?utf-8?Q?=2C=22fullNa?= =?utf-8?Q?me=22=3A=22=F0=9F=98=AC=22?=}'
);
});
describe('#encode()', function () {
it('should handle non-string values correctly', function () {
expect(-1, 'to encode to', '-1');
expect(Infinity, 'to encode to', 'Infinity');
expect(false, 'to encode to', 'false');
expect(true, 'to encode to', 'true');
expect(/bla/, 'to encode to', '/bla/');
expect(undefined, 'to encode to', '');
expect(null, 'to encode to', '');
});
it('should handle the replacement character', function () {
expect(
'test_�.docx',
'to encode back and forth to',
'=?utf-8?Q?test=5F=EF=BF=BD=2Ed?=ocx'
);
});
});
it('should handle a tab character at the beginning of a word', function () {
expect('\tfoo', 'to encode to', ' foo');
});
describe('#encode()', function () {
it('should handle non-string values correctly', function () {
expect(-1, 'to encode to', '-1');
expect(Infinity, 'to encode to', 'Infinity');
expect(false, 'to encode to', 'false');
expect(true, 'to encode to', 'true');
expect(/bla/, 'to encode to', '/bla/');
expect(undefined, 'to encode to', '');
expect(null, 'to encode to', '');
});
it('should handle control chars', function () {
expect(
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f',
'to encode to',
'=?utf-8?Q?=00=01=02=03=04=05=06=07?= =?utf-8?Q?=08?= =?utf-8?Q?_=0E=0F=10=11=12=13=14=15?= =?utf-8?Q?=16=17=18=19=1A=1B=1C=1D?= =?utf-8?Q?=1E=1F?='
);
});
it('should handle a tab character at the beginning of a word', function () {
expect('\tfoo', 'to encode to', ' foo');
});
it('should handle a tab character at the end of a word', function () {
expect('foo\t', 'to encode to', 'foo ');
});
it('should handle control chars', function () {
expect(
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f',
'to encode to',
'=?utf-8?Q?=00=01=02=03=04=05=06=07?= =?utf-8?Q?=08?= =?utf-8?Q?_=0E=0F=10=11=12=13=14=15?= =?utf-8?Q?=16=17=18=19=1A=1B=1C=1D?= =?utf-8?Q?=1E=1F?='
);
});
it('should handle a tab character with spaces around it', function () {
expect('bar \t foo', 'to encode to', 'bar foo');
});
it('should handle a tab character at the end of a word', function () {
expect('foo\t', 'to encode to', 'foo ');
});
it('should not split a backslash from the doublequote it is escaping', function () {
expect('"Öland\\""', 'to encode to', '"=?utf-8?Q?=C3=96land?=\\""');
});
it('should handle a tab character with spaces around it', function () {
expect('bar \t foo', 'to encode to', 'bar foo');
});
describe('#decode()', function () {
it('should handle non-string values correctly', function () {
expect(-1, 'to decode to', '-1');
expect(Infinity, 'to decode to', 'Infinity');
expect(false, 'to decode to', 'false');
expect(true, 'to decode to', 'true');
expect(/bla/, 'to decode to', '/bla/');
expect(undefined, 'to decode to', '');
expect(null, 'to decode to', '');
});
it('should not split a backslash from the doublequote it is escaping', function () {
expect('"Öland\\""', 'to encode to', '"=?utf-8?Q?=C3=96land?=\\""');
});
});
it('should decode encoded word with invalid quoted-printable, decodeURIComponent case', function () {
expect('=?UTF-8?Q?=xxfoo?=', 'to decode to', '=xxfoo');
});
describe('#decode()', function () {
it('should handle non-string values correctly', function () {
expect(-1, 'to decode to', '-1');
expect(Infinity, 'to decode to', 'Infinity');
expect(false, 'to decode to', 'false');
expect(true, 'to decode to', 'true');
expect(/bla/, 'to decode to', '/bla/');
expect(undefined, 'to decode to', '');
expect(null, 'to decode to', '');
});
it('should decode encoded word with invalid quoted-printable, unescape case', function () {
expect('=?iso-8859-1?Q?=xxfoo?=', 'to decode to', '=xxfoo');
});
it('should decode encoded word with invalid quoted-printable, decodeURIComponent case', function () {
expect('=?UTF-8?Q?=xxfoo?=', 'to decode to', '=xxfoo');
});
it('should decode encoded word with invalid base64', function () {
expect('=?iso-8859-1?B?\u0000``?=', 'to decode to', '');
});
it('should decode encoded word with invalid quoted-printable, unescape case', function () {
expect('=?iso-8859-1?Q?=xxfoo?=', 'to decode to', '=xxfoo');
});
it('should decode separated encoded words', function () {
expect(
'=?utf-8?Q?One.com=E2=80?= =?utf-8?Q?=99s_=E2=80=9CDon=E2=80=99t_screw_it_up=E2=80=9D_?= =?utf-8?Q?code?=',
'to decode to',
'One.com’s “Don’t screw it up” code'
);
});
it('should decode encoded word with invalid base64', function () {
expect('=?iso-8859-1?B?\u0000``?=', 'to decode to', '');
});
it('should handle the test cases listed in RFC 2047', function () {
expect('=?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>', 'to decode to', 'Olle Järnefors <ojarnef@admin.kth.se>');
expect('=?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>', 'to decode to', 'Patrik Fältström <paf@nada.kth.se>');
expect('Nathaniel Borenstein <nsb@thumper.bellcore.com> (=?iso-8859-8?b?7eXs+SDv4SDp7Oj08A==?=)', 'to decode to', 'Nathaniel Borenstein <nsb@thumper.bellcore.com> (םולש ןב ילטפנ)');
expect('(=?ISO-8859-1?Q?a?=)', 'to decode to', '(a)');
expect('(=?ISO-8859-1?Q?a?= b)', 'to decode to', '(a b)');
expect('(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)', 'to decode to', '(ab)');
expect('(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)', 'to decode to', '(ab)');
expect('(=?ISO-8859-1?Q?a_b?=)', 'to decode to', '(a b)');
expect('(=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=)', 'to decode to', '(a b)');
});
it('should decode separated encoded words', function () {
expect(
'=?utf-8?Q?One.com=E2=80?= =?utf-8?Q?=99s_=E2=80=9CDon=E2=80=99t_screw_it_up=E2=80=9D_?= =?utf-8?Q?code?=',
'to decode to',
'One.com’s “Don’t screw it up” code'
);
});
it('should handle subject found in mail with X-Mailer: MailChimp Mailer', function () {
expect('=?utf-8?Q?Spar=2020=20%=20p=C3=A5=20de=20bedste=20businessb=C3=B8ger=20fra=20Gyldendal=21?=', 'to decode to', 'Spar 20 % på de bedste businessbøger fra Gyldendal!');
expect('=?iso-8859-1?Q?Spar 20 %...?=', 'to decode to', 'Spar 20 %...');
});
it('should handle the test cases listed in RFC 2047', function () {
expect(
'=?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>',
'to decode to',
'Olle Järnefors <ojarnef@admin.kth.se>'
);
expect(
'=?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>',
'to decode to',
'Patrik Fältström <paf@nada.kth.se>'
);
expect(
'Nathaniel Borenstein <nsb@thumper.bellcore.com> (=?iso-8859-8?b?7eXs+SDv4SDp7Oj08A==?=)',
'to decode to',
'Nathaniel Borenstein <nsb@thumper.bellcore.com> (םולש ןב ילטפנ)'
);
expect('(=?ISO-8859-1?Q?a?=)', 'to decode to', '(a)');
expect('(=?ISO-8859-1?Q?a?= b)', 'to decode to', '(a b)');
expect('(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)', 'to decode to', '(ab)');
expect(
'(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)',
'to decode to',
'(ab)'
);
expect('(=?ISO-8859-1?Q?a_b?=)', 'to decode to', '(a b)');
expect(
'(=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=)',
'to decode to',
'(a b)'
);
});
it('should handle multiple base64 encoded words issued by Thunderbird', function () {
expect(
'=?UTF-8?B?Rm9vw6YsIEZvbyDDpiwgw6bDuMOmw7jDpsO4w6bDuMOmw7jDpsO4LCA=?==?UTF-8?B?4pi6IE1y4pi6IOKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYug==?= =?UTF-8?B?4pi64pi64pi64pi64pi64pi64pi6?=',
'to decode to',
'Fooæ, Foo æ, æøæøæøæøæøæø, ☺ Mr☺ ☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺'
);
});
it('should handle subject found in mail with X-Mailer: MailChimp Mailer', function () {
expect(
'=?utf-8?Q?Spar=2020=20%=20p=C3=A5=20de=20bedste=20businessb=C3=B8ger=20fra=20Gyldendal=21?=',
'to decode to',
'Spar 20 % på de bedste businessbøger fra Gyldendal!'
);
expect('=?iso-8859-1?Q?Spar 20 %...?=', 'to decode to', 'Spar 20 %...');
});
it('should handle two back-to-back UTF-8 encoded words from the subject in a raygun mail', function () {
expect('=?utf-8?B?d2VibWFpbCBwcm9kdWN0aW9uIC0gbmV3IGVycm9yIC0gR2XD?==?utf-8?B?p2Vyc2l6IGRlxJ9pxZ9rZW4u?=', 'to decode to', 'webmail production - new error - Geçersiz değişken.');
});
it('should handle multiple base64 encoded words issued by Thunderbird', function () {
expect(
'=?UTF-8?B?Rm9vw6YsIEZvbyDDpiwgw6bDuMOmw7jDpsO4w6bDuMOmw7jDpsO4LCA=?==?UTF-8?B?4pi6IE1y4pi6IOKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYuuKYug==?= =?UTF-8?B?4pi64pi64pi64pi64pi64pi64pi6?=',
'to decode to',
'Fooæ, Foo æ, æøæøæøæøæøæø, ☺ Mr☺ ☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺'
);
});
it('should keep encoded words with partial sequences separate if there is text between them', function () {
expect('=?utf-8?B?d2VibWFpbCBwcm9kdWN0aW9uIC0gbmV3IGVycm9yIC0gR2XD?=foo=?utf-8?B?p2Vyc2l6IGRlxJ9pxZ9rZW4u?=', 'to decode to', '=?utf-8?B?d2VibWFpbCBwcm9kdWN0aW9uIC0gbmV3IGVycm9yIC0gR2XD?=foo=?utf-8?B?p2Vyc2l6IGRlxJ9pxZ9rZW4u?=');
});
it('should handle two back-to-back UTF-8 encoded words from the subject in a raygun mail', function () {
expect(
'=?utf-8?B?d2VibWFpbCBwcm9kdWN0aW9uIC0gbmV3IGVycm9yIC0gR2XD?==?utf-8?B?p2Vyc2l6IGRlxJ9pxZ9rZW4u?=',
'to decode to',
'webmail production - new error - Geçersiz değişken.'
);
});
it('should decode a UTF-8 smiley (illegally) split up into 2 encoded words', function () {
expect('=?utf-8?Q?=E2=98?= =?utf-8?Q?=BA?=', 'to decode to', '☺');
});
it('should keep encoded words with partial sequences separate if there is text between them', function () {
expect(
'=?utf-8?B?d2VibWFpbCBwcm9kdWN0aW9uIC0gbmV3IGVycm9yIC0gR2XD?=foo=?utf-8?B?p2Vyc2l6IGRlxJ9pxZ9rZW4u?=',
'to decode to',
'=?utf-8?B?d2VibWFpbCBwcm9kdWN0aW9uIC0gbmV3IGVycm9yIC0gR2XD?=foo=?utf-8?B?p2Vyc2l6IGRlxJ9pxZ9rZW4u?='
);
});
it('should decode a UTF-8 smiley (illegally) split up into 3 encoded words', function () {
expect('=?utf-8?Q?=E2?= =?utf-8?Q?=98?= =?utf-8?Q?=BA?=', 'to decode to', '☺');
});
it('should decode a UTF-8 smiley (illegally) split up into 2 encoded words', function () {
expect('=?utf-8?Q?=E2=98?= =?utf-8?Q?=BA?=', 'to decode to', '☺');
});
it('should give up decoding a UTF-8 smiley (illegally) split up into 3 encoded words if there is regular text between the encoded words', function () {
expect('=?utf-8?Q?=E2?= =?utf-8?Q?=98?=a=?utf-8?Q?=BA?==?utf-8?Q?=BA?=a', 'to decode to', '=?utf-8?Q?=E2?==?utf-8?Q?=98?=a=?utf-8?Q?=BA?==?utf-8?Q?=BA?=a');
});
it('should decode a UTF-8 smiley (illegally) split up into 3 encoded words', function () {
expect(
'=?utf-8?Q?=E2?= =?utf-8?Q?=98?= =?utf-8?Q?=BA?=',
'to decode to',
'☺'
);
});
it('should decode an encoded word following a undecodable sequence of encoded words', function () {
expect('=?utf-8?Q?=E2?= =?utf-8?Q?=98?= =?iso-8859-1?Q?=A1?=Hola, se=?iso-8859-1?Q?=F1?=or!', 'to decode to', '=?utf-8?Q?=E2?==?utf-8?Q?=98?=¡Hola, señor!');
});
it('should give up decoding a UTF-8 smiley (illegally) split up into 3 encoded words if there is regular text between the encoded words', function () {
expect(
'=?utf-8?Q?=E2?= =?utf-8?Q?=98?=a=?utf-8?Q?=BA?==?utf-8?Q?=BA?=a',
'to decode to',
'=?utf-8?Q?=E2?==?utf-8?Q?=98?=a=?utf-8?Q?=BA?==?utf-8?Q?=BA?=a'
);
});
it('should handle test cases from the MIME tools package', function () {
// From http://search.cpan.org/~dskoll/MIME-tools-5.502/lib/MIME/Words.pm:
expect('=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>', 'to decode to', 'Keld Jørn Simonsen <keld@dkuug.dk>');
expect('=?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>', 'to decode to', 'Keith Moore <moore@cs.utk.edu>');
expect('=?ISO-8859-1?Q?Andr=E9_?= Pirard <PIRARD@vm1.ulg.ac.be>', 'to decode to', 'André Pirard <PIRARD@vm1.ulg.ac.be>');
expect('=?iso-8859-1?Q?J=F8rgen_Nellemose?=', 'to decode to', 'Jørgen Nellemose');
expect(
'=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?==?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?==?US-ASCII?Q?.._cool!?=',
'to decode to',
'If you can read this you understand the example... cool!'
);
});
it('should decode an encoded word following a undecodable sequence of encoded words', function () {
expect(
'=?utf-8?Q?=E2?= =?utf-8?Q?=98?= =?iso-8859-1?Q?=A1?=Hola, se=?iso-8859-1?Q?=F1?=or!',
'to decode to',
'=?utf-8?Q?=E2?==?utf-8?Q?=98?=¡Hola, señor!'
);
});
it('should handle a file name found in a Korean mail', function () {
expect('=?ks_c_5601-1987?B?MTMwMTE3X8HWwvfA5V+1tcDlX7jetLq+8y5wZGY=?=', 'to decode to', '130117_주차장_도장_메뉴얼.pdf');
});
it('should handle test cases from the MIME tools package', function () {
// From http://search.cpan.org/~dskoll/MIME-tools-5.502/lib/MIME/Words.pm:
expect(
'=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>',
'to decode to',
'Keld Jørn Simonsen <keld@dkuug.dk>'
);
expect(
'=?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>',
'to decode to',
'Keith Moore <moore@cs.utk.edu>'
);
expect(
'=?ISO-8859-1?Q?Andr=E9_?= Pirard <PIRARD@vm1.ulg.ac.be>',
'to decode to',
'André Pirard <PIRARD@vm1.ulg.ac.be>'
);
expect(
'=?iso-8859-1?Q?J=F8rgen_Nellemose?=',
'to decode to',
'Jørgen Nellemose'
);
expect(
'=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?==?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?==?US-ASCII?Q?.._cool!?=',
'to decode to',
'If you can read this you understand the example... cool!'
);
});
it('should handle bogus encoded words (spotted in the wild)', function () {
expect('=?utf-8?Q??= <andreas@one.com>', 'to decode to', ' <andreas@one.com>');
});
it('should handle a file name found in a Korean mail', function () {
expect(
'=?ks_c_5601-1987?B?MTMwMTE3X8HWwvfA5V+1tcDlX7jetLq+8y5wZGY=?=',
'to decode to',
'130117_주차장_도장_메뉴얼.pdf'
);
});
it('should decode a character set not in iconv-lite', function () {
expect('=?iso-2022-jp?B?GyRCRnxLXDhsJE4lNSVWJTglJyUvJUghXRsoQnRlc3Q=?=', 'to decode to', '日本語のサブジェクト−test');
});
it('should handle bogus encoded words (spotted in the wild)', function () {
expect(
'=?utf-8?Q??= <andreas@one.com>',
'to decode to',
' <andreas@one.com>'
);
});
it('should decode a character set not in iconv-lite', function () {
expect(
'=?iso-2022-jp?B?GyRCRnxLXDhsJE4lNSVWJTglJyUvJUghXRsoQnRlc3Q=?=',
'to decode to',
'日本語のサブジェクト−test'
);
});
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc