libmime 4.1.3 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +3 -2
- package/.github/FUNDING.yml +4 -0
- package/.prettierrc.js +4 -1
- package/CHANGELOG.md +19 -0
- package/lib/charset.js +22 -7
- package/lib/libmime.js +17 -31
- package/package.json +8 -8
package/.eslintrc
CHANGED
package/.prettierrc.js
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v5.0.0 2020-07-22
|
|
4
|
+
|
|
5
|
+
- Removed optional node-iconv support
|
|
6
|
+
- Bumped dependencies
|
|
7
|
+
- Updated Travis test matrix, dropped Node 8
|
|
8
|
+
|
|
9
|
+
## v4.2.1 2019-10-28
|
|
10
|
+
|
|
11
|
+
- Replace jconv with more recent encoding-japanese
|
|
12
|
+
|
|
13
|
+
## v4.2.0 2019-10-28
|
|
14
|
+
|
|
15
|
+
- Use jconv module to parse ISO-2022-JP by default
|
|
16
|
+
|
|
17
|
+
## v4.1.4 2019-10-28
|
|
18
|
+
|
|
19
|
+
- decodeWords should also decode empty content part [WeiAnAn](9bbcfd2)
|
|
20
|
+
- fix decode base64 ending with = [WeiAnAn](6e656e2)
|
|
21
|
+
|
|
3
22
|
## v4.1.0 2019-05-01
|
|
4
23
|
|
|
5
24
|
- Experimental support for node-iconv
|
package/lib/charset.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const iconv = require('iconv-lite');
|
|
4
|
+
const encodingJapanese = require('encoding-japanese');
|
|
4
5
|
const charsets = require('./charsets');
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -25,10 +26,9 @@ const charset = (module.exports = {
|
|
|
25
26
|
*
|
|
26
27
|
* @param {Buffer} buf Binary data to be decoded
|
|
27
28
|
* @param {String} [fromCharset='UTF-8'] Binary data is decoded into string using this charset
|
|
28
|
-
* @param {Function} [Iconv] node-iconv function
|
|
29
29
|
* @return {String} Decded string
|
|
30
30
|
*/
|
|
31
|
-
decode(buf, fromCharset
|
|
31
|
+
decode(buf, fromCharset) {
|
|
32
32
|
fromCharset = charset.normalizeCharset(fromCharset || 'UTF-8');
|
|
33
33
|
|
|
34
34
|
if (/^(us-)?ascii|utf-8|7bit$/i.test(fromCharset)) {
|
|
@@ -36,10 +36,25 @@ const charset = (module.exports = {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
try {
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
if (/^jis|^iso-?2022-?jp|^EUCJP/i.test(fromCharset)) {
|
|
40
|
+
if (typeof buf === 'string') {
|
|
41
|
+
buf = Buffer.from(buf);
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
let output = encodingJapanese.convert(buf, {
|
|
45
|
+
to: 'UNICODE',
|
|
46
|
+
from: fromCharset,
|
|
47
|
+
type: 'string'
|
|
48
|
+
});
|
|
49
|
+
if (typeof output === 'string') {
|
|
50
|
+
output = Buffer.from(output);
|
|
51
|
+
}
|
|
52
|
+
return output;
|
|
53
|
+
} catch (err) {
|
|
54
|
+
// ignore, defaults to iconv-lite on error
|
|
55
|
+
}
|
|
42
56
|
}
|
|
57
|
+
|
|
43
58
|
return iconv.decode(buf, fromCharset);
|
|
44
59
|
} catch (err) {
|
|
45
60
|
// enforce utf-8, data loss might occur
|
|
@@ -54,7 +69,7 @@ const charset = (module.exports = {
|
|
|
54
69
|
* @param {String} [fromCharset='UTF-8'] Source encoding for the string
|
|
55
70
|
* @return {Buffer} UTF-8 encoded typed array
|
|
56
71
|
*/
|
|
57
|
-
convert(data, fromCharset
|
|
72
|
+
convert(data, fromCharset) {
|
|
58
73
|
fromCharset = charset.normalizeCharset(fromCharset || 'UTF-8');
|
|
59
74
|
|
|
60
75
|
let bufString;
|
|
@@ -64,7 +79,7 @@ const charset = (module.exports = {
|
|
|
64
79
|
return data;
|
|
65
80
|
}
|
|
66
81
|
|
|
67
|
-
bufString = charset.decode(data, fromCharset
|
|
82
|
+
bufString = charset.decode(data, fromCharset);
|
|
68
83
|
return charset.encode(bufString);
|
|
69
84
|
}
|
|
70
85
|
return charset.encode(data);
|
package/lib/libmime.js
CHANGED
|
@@ -112,11 +112,7 @@ class Libmime {
|
|
|
112
112
|
* @return {String} Single or several mime words joined together
|
|
113
113
|
*/
|
|
114
114
|
encodeWord(data, mimeWordEncoding, maxLength) {
|
|
115
|
-
mimeWordEncoding = (mimeWordEncoding || 'Q')
|
|
116
|
-
.toString()
|
|
117
|
-
.toUpperCase()
|
|
118
|
-
.trim()
|
|
119
|
-
.charAt(0);
|
|
115
|
+
mimeWordEncoding = (mimeWordEncoding || 'Q').toString().toUpperCase().trim().charAt(0);
|
|
120
116
|
maxLength = maxLength || 0;
|
|
121
117
|
|
|
122
118
|
let encodedStr;
|
|
@@ -129,10 +125,7 @@ class Libmime {
|
|
|
129
125
|
if (mimeWordEncoding === 'Q') {
|
|
130
126
|
// https://tools.ietf.org/html/rfc2047#section-5 rule (3)
|
|
131
127
|
encodedStr = libqp.encode(data).replace(/[^a-z0-9!*+\-/=]/gi, chr => {
|
|
132
|
-
let ord = chr
|
|
133
|
-
.charCodeAt(0)
|
|
134
|
-
.toString(16)
|
|
135
|
-
.toUpperCase();
|
|
128
|
+
let ord = chr.charCodeAt(0).toString(16).toUpperCase();
|
|
136
129
|
if (chr === ' ') {
|
|
137
130
|
return '_';
|
|
138
131
|
} else {
|
|
@@ -223,13 +216,18 @@ class Libmime {
|
|
|
223
216
|
}
|
|
224
217
|
str = Buffer.from(bytes);
|
|
225
218
|
} else if (encoding === 'B') {
|
|
226
|
-
str = Buffer.
|
|
219
|
+
str = Buffer.concat(
|
|
220
|
+
str
|
|
221
|
+
.split('=')
|
|
222
|
+
.filter(s => s !== '') // filter empty string
|
|
223
|
+
.map(str => Buffer.from(str, 'base64'))
|
|
224
|
+
);
|
|
227
225
|
} else {
|
|
228
226
|
// keep as is, convert Buffer to unicode string, assume utf8
|
|
229
227
|
str = Buffer.from(str);
|
|
230
228
|
}
|
|
231
229
|
|
|
232
|
-
return libcharset.decode(str, charset
|
|
230
|
+
return libcharset.decode(str, charset);
|
|
233
231
|
}
|
|
234
232
|
|
|
235
233
|
/**
|
|
@@ -249,7 +247,7 @@ class Libmime {
|
|
|
249
247
|
|
|
250
248
|
maxLength = maxLength || 0;
|
|
251
249
|
|
|
252
|
-
let decodedValue = libcharset.decode(libcharset.convert(data || '', fromCharset
|
|
250
|
+
let decodedValue = libcharset.decode(libcharset.convert(data || '', fromCharset));
|
|
253
251
|
let encodedValue;
|
|
254
252
|
|
|
255
253
|
let firstMatch = decodedValue.match(/(?:^|\s)([^\s]*[\u0080-\uFFFF])/);
|
|
@@ -289,7 +287,7 @@ class Libmime {
|
|
|
289
287
|
(str || '')
|
|
290
288
|
.toString()
|
|
291
289
|
// find base64 words that can be joined
|
|
292
|
-
.replace(/(=\?([^?]+)\?[Bb]\?[^?]
|
|
290
|
+
.replace(/(=\?([^?]+)\?[Bb]\?[^?]*\?=)\s*(?==\?([^?]+)\?[Bb]\?[^?]*\?=)/g, (match, left, chLeft, chRight) => {
|
|
293
291
|
// only mark b64 chunks to be joined if charsets match
|
|
294
292
|
if (libcharset.normalizeCharset(chLeft || '') === libcharset.normalizeCharset(chRight || '')) {
|
|
295
293
|
// set a joiner marker
|
|
@@ -298,7 +296,7 @@ class Libmime {
|
|
|
298
296
|
return match;
|
|
299
297
|
})
|
|
300
298
|
// find QP words that can be joined
|
|
301
|
-
.replace(/(=\?([^?]+)\?[Qq]\?[^?]
|
|
299
|
+
.replace(/(=\?([^?]+)\?[Qq]\?[^?]*\?=)\s*(?==\?([^?]+)\?[Qq]\?[^?]*\?=)/g, (match, left, chLeft, chRight) => {
|
|
302
300
|
// only mark QP chunks to be joined if charsets match
|
|
303
301
|
if (libcharset.normalizeCharset(chLeft || '') === libcharset.normalizeCharset(chRight || '')) {
|
|
304
302
|
// set a joiner marker
|
|
@@ -309,9 +307,9 @@ class Libmime {
|
|
|
309
307
|
// join base64 encoded words
|
|
310
308
|
.replace(/(\?=)?__\x00JOIN\x00__(=\?([^?]+)\?[QqBb]\?)?/g, '')
|
|
311
309
|
// remove spaces between mime encoded words
|
|
312
|
-
.replace(/(=\?[^?]+\?[QqBb]\?[^?]
|
|
310
|
+
.replace(/(=\?[^?]+\?[QqBb]\?[^?]*\?=)\s+(?==\?[^?]+\?[QqBb]\?[^?]*\?=)/g, '$1')
|
|
313
311
|
// decode words
|
|
314
|
-
.replace(/=\?([\w_\-*]+)\?([QqBb])\?([^?]
|
|
312
|
+
.replace(/=\?([\w_\-*]+)\?([QqBb])\?([^?]*)\?=/g, (m, charset, encoding, text) => this.decodeWord(charset, encoding, text))
|
|
315
313
|
);
|
|
316
314
|
}
|
|
317
315
|
|
|
@@ -718,10 +716,7 @@ class Libmime {
|
|
|
718
716
|
* @return {String} File extension
|
|
719
717
|
*/
|
|
720
718
|
detectExtension(mimeType) {
|
|
721
|
-
mimeType = (mimeType || '')
|
|
722
|
-
.toString()
|
|
723
|
-
.toLowerCase()
|
|
724
|
-
.replace(/\s/g, '');
|
|
719
|
+
mimeType = (mimeType || '').toString().toLowerCase().replace(/\s/g, '');
|
|
725
720
|
if (!(mimeType in mimetypes.list)) {
|
|
726
721
|
return 'bin';
|
|
727
722
|
}
|
|
@@ -751,13 +746,7 @@ class Libmime {
|
|
|
751
746
|
* @return {String} File extension
|
|
752
747
|
*/
|
|
753
748
|
detectMimeType(extension) {
|
|
754
|
-
extension = (extension || '')
|
|
755
|
-
.toString()
|
|
756
|
-
.toLowerCase()
|
|
757
|
-
.replace(/\s/g, '')
|
|
758
|
-
.replace(/^\./g, '')
|
|
759
|
-
.split('.')
|
|
760
|
-
.pop();
|
|
749
|
+
extension = (extension || '').toString().toLowerCase().replace(/\s/g, '').replace(/^\./g, '').split('.').pop();
|
|
761
750
|
|
|
762
751
|
if (!(extension in mimetypes.extensions)) {
|
|
763
752
|
return 'application/octet-stream';
|
|
@@ -877,10 +866,7 @@ class Libmime {
|
|
|
877
866
|
|
|
878
867
|
encodeURICharComponent(chr) {
|
|
879
868
|
let res = '';
|
|
880
|
-
let ord = chr
|
|
881
|
-
.charCodeAt(0)
|
|
882
|
-
.toString(16)
|
|
883
|
-
.toUpperCase();
|
|
869
|
+
let ord = chr.charCodeAt(0).toString(16).toUpperCase();
|
|
884
870
|
|
|
885
871
|
if (ord.length % 2) {
|
|
886
872
|
ord = '0' + ord;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libmime",
|
|
3
3
|
"description": "Encode and decode quoted printable and base64 strings",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "5.0.0",
|
|
5
5
|
"main": "lib/libmime",
|
|
6
6
|
"homepage": "https://github.com/andris9/libmime",
|
|
7
7
|
"repository": {
|
|
@@ -19,19 +19,19 @@
|
|
|
19
19
|
"test": "grunt"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"
|
|
23
|
-
"
|
|
22
|
+
"encoding-japanese": "1.0.30",
|
|
23
|
+
"iconv-lite": "0.6.2",
|
|
24
|
+
"libbase64": "1.2.1",
|
|
24
25
|
"libqp": "1.1.0"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"chai": "4.2.0",
|
|
28
29
|
"eslint-config-nodemailer": "1.2.0",
|
|
29
|
-
"eslint-config-prettier": "
|
|
30
|
-
"grunt": "1.
|
|
30
|
+
"eslint-config-prettier": "6.11.0",
|
|
31
|
+
"grunt": "1.2.1",
|
|
31
32
|
"grunt-cli": "1.3.2",
|
|
32
|
-
"grunt-eslint": "
|
|
33
|
+
"grunt-eslint": "23.0.0",
|
|
33
34
|
"grunt-mocha-test": "0.13.3",
|
|
34
|
-
"
|
|
35
|
-
"mocha": "6.1.4"
|
|
35
|
+
"mocha": "8.0.1"
|
|
36
36
|
}
|
|
37
37
|
}
|