imapflow 1.0.96 → 1.0.97
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/CHANGELOG.md
CHANGED
|
@@ -60,16 +60,16 @@ class ParserInstance {
|
|
|
60
60
|
let match, element, errPos;
|
|
61
61
|
|
|
62
62
|
if (this.remainder.match(/^\s/)) {
|
|
63
|
-
throw new Error(
|
|
63
|
+
throw new Error(`Unexpected whitespace at position ${this.pos} [E1]`);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
if ((match = this.remainder.match(/^\s*[^\s]+(?=\s|$)/))) {
|
|
67
67
|
element = match[0];
|
|
68
68
|
if ((errPos = imapFormalSyntax.verify(element, syntax)) >= 0) {
|
|
69
|
-
throw new Error(
|
|
69
|
+
throw new Error(`Unexpected char at position ${this.pos + errPos} [E2: ${JSON.stringify(element.charAt(errPos))}]`);
|
|
70
70
|
}
|
|
71
71
|
} else {
|
|
72
|
-
throw new Error(
|
|
72
|
+
throw new Error(`Unexpected end of input at position ${this.pos} [E3]`);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
this.pos += match[0].length;
|
|
@@ -80,11 +80,11 @@ class ParserInstance {
|
|
|
80
80
|
|
|
81
81
|
async getSpace() {
|
|
82
82
|
if (!this.remainder.length) {
|
|
83
|
-
throw new Error(
|
|
83
|
+
throw new Error(`Unexpected end of input at position ${this.pos} [E4]`);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
if (imapFormalSyntax.verify(this.remainder.charAt(0), imapFormalSyntax.SP()) >= 0) {
|
|
87
|
-
throw new Error(
|
|
87
|
+
throw new Error(`Unexpected char at position ${this.pos} [E5: ${JSON.stringify(this.remainder.charAt(0))}]`);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
this.pos++;
|
|
@@ -93,11 +93,11 @@ class ParserInstance {
|
|
|
93
93
|
|
|
94
94
|
async getAttributes() {
|
|
95
95
|
if (!this.remainder.length) {
|
|
96
|
-
throw new Error(
|
|
96
|
+
throw new Error(`Unexpected end of input at position ${this.pos} [E6]`);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
if (this.remainder.match(/^\s/)) {
|
|
100
|
-
throw new Error(
|
|
100
|
+
throw new Error(`Unexpected whitespace at position ${this.pos} [E7]`);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
const tokenParser = new TokenParser(this, this.pos, this.remainder, this.options);
|
|
@@ -36,7 +36,7 @@ class TokenParser {
|
|
|
36
36
|
|
|
37
37
|
// If the node was never closed, throw it
|
|
38
38
|
if (!node.isClosed) {
|
|
39
|
-
throw new Error(
|
|
39
|
+
throw new Error(`Unexpected end of input at position ${this.pos + this.str.length - 1} [E6]`);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
let type = (node.type || '').toString().toUpperCase();
|
|
@@ -149,7 +149,7 @@ class TokenParser {
|
|
|
149
149
|
// ) closes a list
|
|
150
150
|
case ')':
|
|
151
151
|
if (this.currentNode.type !== 'LIST') {
|
|
152
|
-
throw new Error(
|
|
152
|
+
throw new Error(`Unexpected list terminator ) at position ${this.pos + i} [E7]`);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
this.currentNode.isClosed = true;
|
|
@@ -162,7 +162,7 @@ class TokenParser {
|
|
|
162
162
|
// ] closes section group
|
|
163
163
|
case ']':
|
|
164
164
|
if (this.currentNode.type !== 'SECTION') {
|
|
165
|
-
throw new Error(
|
|
165
|
+
throw new Error(`Unexpected section terminator ] at position ${this.pos + i} [E8]`);
|
|
166
166
|
}
|
|
167
167
|
this.currentNode.isClosed = true;
|
|
168
168
|
this.currentNode.endPos = this.pos + i;
|
|
@@ -189,7 +189,7 @@ class TokenParser {
|
|
|
189
189
|
case '~': {
|
|
190
190
|
let nextChr = this.str.charAt(i + 1);
|
|
191
191
|
if (nextChr !== '{') {
|
|
192
|
-
throw new Error(
|
|
192
|
+
throw new Error(`Unexpected literal8 marker at position ${this.pos + i} [E9]`);
|
|
193
193
|
}
|
|
194
194
|
this.expectedLiteralType = 'literal8';
|
|
195
195
|
break;
|
|
@@ -270,7 +270,7 @@ class TokenParser {
|
|
|
270
270
|
// Allow \ as the first char for atom to support system flags
|
|
271
271
|
// Allow % to support LIST '' %
|
|
272
272
|
if (imapFormalSyntax['ATOM-CHAR']().indexOf(chr) < 0 && chr !== '\\' && chr !== '%') {
|
|
273
|
-
throw new Error(
|
|
273
|
+
throw new Error(`Unexpected char at position ${this.pos + i} [E10: ${JSON.stringify(chr)}]`);
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
this.currentNode = this.createNode(this.currentNode, this.pos + i);
|
|
@@ -317,7 +317,7 @@ class TokenParser {
|
|
|
317
317
|
if (chr === '[') {
|
|
318
318
|
// allowed only for selected elements
|
|
319
319
|
if (['BODY', 'BODY.PEEK', 'BINARY', 'BINARY.PEEK'].indexOf(this.currentNode.value.toUpperCase()) < 0) {
|
|
320
|
-
throw new Error(
|
|
320
|
+
throw new Error(`Unexpected section start char [ at position ${this.pos} [E11]`);
|
|
321
321
|
}
|
|
322
322
|
this.currentNode.endPos = this.pos + i;
|
|
323
323
|
this.currentNode = this.createNode(this.currentNode.parentNode, this.pos + i);
|
|
@@ -328,7 +328,7 @@ class TokenParser {
|
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
if (chr === '<') {
|
|
331
|
-
throw new Error(
|
|
331
|
+
throw new Error(`Unexpected start of partial at position ${this.pos} [E12]`);
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
// if the char is not ATOM compatible, throw. Allow \* as an exception
|
|
@@ -338,9 +338,9 @@ class TokenParser {
|
|
|
338
338
|
!(chr === '*' && this.currentNode.value === '\\') &&
|
|
339
339
|
(!this.parent || !this.parent.command || !['NO', 'BAD', 'OK'].includes(this.parent.command))
|
|
340
340
|
) {
|
|
341
|
-
throw new Error(
|
|
341
|
+
throw new Error(`Unexpected char at position ${this.pos + i} [E13: ${JSON.stringify(chr)}]`);
|
|
342
342
|
} else if (this.currentNode.value === '\\*') {
|
|
343
|
-
throw new Error(
|
|
343
|
+
throw new Error(`Unexpected char at position ${this.pos + i} [E14: ${JSON.stringify(chr)}]`);
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
this.currentNode.value += chr;
|
|
@@ -362,7 +362,7 @@ class TokenParser {
|
|
|
362
362
|
if (chr === '\\') {
|
|
363
363
|
i++;
|
|
364
364
|
if (i >= len) {
|
|
365
|
-
throw new Error(
|
|
365
|
+
throw new Error(`Unexpected end of input at position ${this.pos + i} [E15]`);
|
|
366
366
|
}
|
|
367
367
|
chr = this.str.charAt(i);
|
|
368
368
|
}
|
|
@@ -373,7 +373,7 @@ class TokenParser {
|
|
|
373
373
|
case 'PARTIAL':
|
|
374
374
|
if (chr === '>') {
|
|
375
375
|
if (this.currentNode.value.substr(-1) === '.') {
|
|
376
|
-
throw new Error(
|
|
376
|
+
throw new Error(`Unexpected end of partial at position ${this.pos} [E16]`);
|
|
377
377
|
}
|
|
378
378
|
this.currentNode.endPos = this.pos + i;
|
|
379
379
|
this.currentNode.isClosed = true;
|
|
@@ -384,15 +384,15 @@ class TokenParser {
|
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
if (chr === '.' && (!this.currentNode.value.length || this.currentNode.value.match(/\./))) {
|
|
387
|
-
throw new Error(
|
|
387
|
+
throw new Error(`Unexpected partial separator . at position ${this.pos} [E17]`);
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
if (imapFormalSyntax.DIGIT().indexOf(chr) < 0 && chr !== '.') {
|
|
391
|
-
throw new Error(
|
|
391
|
+
throw new Error(`Unexpected char at position ${this.pos + i} [E18: ${JSON.stringify(chr)}]`);
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
if (this.currentNode.value.match(/^0$|\.0$/) && chr !== '.') {
|
|
395
|
-
throw new Error(
|
|
395
|
+
throw new Error(`Invalid partial at position ${this.pos + i} [E19: ${JSON.stringify(chr)}]`);
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
this.currentNode.value += chr;
|
|
@@ -431,14 +431,14 @@ class TokenParser {
|
|
|
431
431
|
|
|
432
432
|
if (chr === '}') {
|
|
433
433
|
if (!('literalLength' in this.currentNode)) {
|
|
434
|
-
throw new Error(
|
|
434
|
+
throw new Error(`Unexpected literal prefix end char } at position ${this.pos + i} [E20]`);
|
|
435
435
|
}
|
|
436
436
|
if (this.str.charAt(i + 1) === '\n') {
|
|
437
437
|
i++;
|
|
438
438
|
} else if (this.str.charAt(i + 1) === '\r' && this.str.charAt(i + 2) === '\n') {
|
|
439
439
|
i += 2;
|
|
440
440
|
} else {
|
|
441
|
-
throw new Error(
|
|
441
|
+
throw new Error(`Unexpected char at position ${this.pos + i} [E21: ${JSON.stringify(chr)}]`);
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
this.currentNode.literalLength = Number(this.currentNode.literalLength);
|
|
@@ -479,10 +479,10 @@ class TokenParser {
|
|
|
479
479
|
break;
|
|
480
480
|
}
|
|
481
481
|
if (imapFormalSyntax.DIGIT().indexOf(chr) < 0) {
|
|
482
|
-
throw new Error(
|
|
482
|
+
throw new Error(`Unexpected char at position ${this.pos + i} [E22: ${JSON.stringify(chr)}]`);
|
|
483
483
|
}
|
|
484
484
|
if (this.currentNode.literalLength === '0') {
|
|
485
|
-
throw new Error(
|
|
485
|
+
throw new Error(`Invalid literal at position ${this.pos + i} [E23]`);
|
|
486
486
|
}
|
|
487
487
|
this.currentNode.literalLength = (this.currentNode.literalLength || '') + chr;
|
|
488
488
|
break;
|
|
@@ -491,11 +491,11 @@ class TokenParser {
|
|
|
491
491
|
// space finishes the sequence set
|
|
492
492
|
if (chr === ' ') {
|
|
493
493
|
if (!this.currentNode.value.substr(-1).match(/\d/) && this.currentNode.value.substr(-1) !== '*') {
|
|
494
|
-
throw new Error(
|
|
494
|
+
throw new Error(`Unexpected whitespace at position ${this.pos + i} [E24]`);
|
|
495
495
|
}
|
|
496
496
|
|
|
497
497
|
if (this.currentNode.value !== '*' && this.currentNode.value.substr(-1) === '*' && this.currentNode.value.substr(-2, 1) !== ':') {
|
|
498
|
-
throw new Error(
|
|
498
|
+
throw new Error(`Unexpected whitespace at position ${this.pos + i} [E25]`);
|
|
499
499
|
}
|
|
500
500
|
|
|
501
501
|
this.currentNode.isClosed = true;
|
|
@@ -518,25 +518,25 @@ class TokenParser {
|
|
|
518
518
|
|
|
519
519
|
if (chr === ':') {
|
|
520
520
|
if (!this.currentNode.value.substr(-1).match(/\d/) && this.currentNode.value.substr(-1) !== '*') {
|
|
521
|
-
throw new Error(
|
|
521
|
+
throw new Error(`Unexpected range separator : at position ${this.pos + i} [E26]`);
|
|
522
522
|
}
|
|
523
523
|
} else if (chr === '*') {
|
|
524
524
|
if ([',', ':'].indexOf(this.currentNode.value.substr(-1)) < 0) {
|
|
525
|
-
throw new Error(
|
|
525
|
+
throw new Error(`Unexpected range wildcard at position ${this.pos + i} [E27]`);
|
|
526
526
|
}
|
|
527
527
|
} else if (chr === ',') {
|
|
528
528
|
if (!this.currentNode.value.substr(-1).match(/\d/) && this.currentNode.value.substr(-1) !== '*') {
|
|
529
|
-
throw new Error(
|
|
529
|
+
throw new Error(`Unexpected sequence separator , at position ${this.pos + i} [E28]`);
|
|
530
530
|
}
|
|
531
531
|
if (this.currentNode.value.substr(-1) === '*' && this.currentNode.value.substr(-2, 1) !== ':') {
|
|
532
|
-
throw new Error(
|
|
532
|
+
throw new Error(`Unexpected sequence separator , at position ${this.pos + i} [E29]`);
|
|
533
533
|
}
|
|
534
534
|
} else if (!chr.match(/\d/)) {
|
|
535
|
-
throw new Error(
|
|
535
|
+
throw new Error(`Unexpected char at position ${this.pos + i} [E30: ${JSON.stringify(chr)}]`);
|
|
536
536
|
}
|
|
537
537
|
|
|
538
538
|
if (chr.match(/\d/) && this.currentNode.value.substr(-1) === '*') {
|
|
539
|
-
throw new Error(
|
|
539
|
+
throw new Error(`Unexpected number at position ${this.pos + i} [E31: ${JSON.stringify(chr)}]`);
|
|
540
540
|
}
|
|
541
541
|
|
|
542
542
|
this.currentNode.value += chr;
|
package/package.json
CHANGED
package/test/imap-parser-test.js
CHANGED
|
@@ -921,3 +921,15 @@ module.exports['IMAP Parser, unicode select'] = test =>
|
|
|
921
921
|
{ type: 'ATOM', value: '[THROTTLED]' }
|
|
922
922
|
])
|
|
923
923
|
);
|
|
924
|
+
|
|
925
|
+
module.exports['IMAP Parser, single quote in atom'] = test =>
|
|
926
|
+
asyncWrapper(test, async test =>
|
|
927
|
+
test.deepEqual((await parser('* LIST (HasNoChildren UnMarked) "/" \'a')).attributes, [
|
|
928
|
+
[
|
|
929
|
+
{ type: 'ATOM', value: 'HasNoChildren' },
|
|
930
|
+
{ type: 'ATOM', value: 'UnMarked' }
|
|
931
|
+
],
|
|
932
|
+
{ type: 'STRING', value: '/' },
|
|
933
|
+
{ type: 'ATOM', value: "'a" }
|
|
934
|
+
])
|
|
935
|
+
);
|