From a1705c9697cc4e1c12b6590023ebf863a4cb6f34 Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 25 Feb 2015 17:14:10 +0200 Subject: [PATCH 01/67] Debug raw data also --- lib/Parser.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index d6d673e8..3535cade 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -95,13 +95,17 @@ Parser.prototype._parse = function(data) { this._literallen = 0; this._body = undefined; body._read = EMPTY_READCB; - if (datalen > litlen) - body.push(data.slice(0, litlen)); - else - body.push(data); + if (datalen > litlen) { + this.debug && this.debug('<= ' + inspect(data.slice(0, litlen).toString())); + body.push(data.slice(0, litlen)); + }else { + this.debug && this.debug('<= ' + inspect(data.toString())); + body.push(data); + } body.push(null); } else { this._literallen -= datalen; + this.debug && this.debug('<= ' + inspect(data.toString())); var r = body.push(data); if (!r) { body._read = this._cbReadable; @@ -129,7 +133,7 @@ Parser.prototype._parse = function(data) { this._buffer = this._buffer.trim(); i = idxlf + 1; - this.debug && this.debug('<= ' + inspect(this._buffer)); + !this._body && this.debug && this.debug('<= ' + inspect(this._buffer)); if (RE_PRECEDING.test(this._buffer)) { var firstChar = this._buffer[0]; From 03ee2a1946d903a6d228595730f59b1df6e9deb5 Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 28 May 2015 12:18:49 +0300 Subject: [PATCH 02/67] additional checks on lost _curReq --- lib/Connection.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/Connection.js b/lib/Connection.js index 57b83384..24e4fed3 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1389,6 +1389,7 @@ Connection.prototype._resUntagged = function(info) { } this._curReq.cbargs.push(box); } else if (type === 'fetch') { + if(this._fuckUp('_resUntagged')) return; if (/^(?:UID )?FETCH/.test(this._curReq.fullcmd)) { // FETCH response sent as result of FETCH request var msg = this._curReq.fetchCache[info.num], @@ -1469,7 +1470,19 @@ Connection.prototype._resUntagged = function(info) { } }; +Connection.prototype._fuckUp = function(place){ + if(!this._curReq){ + var err = new Error('no _curReq in connection '+ place); + err.source = 'imap-curreq'; + this.emit('error', err); + this._sock.end(); + return true; + } + return false; +} + Connection.prototype._resTagged = function(info) { + if(this._fuckUp('_resTagged')) return; var req = this._curReq, err; this._curReq = undefined; From 41082bd2684cc199d10cb215e2ece2876c8177c1 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sat, 30 May 2015 18:10:42 +0300 Subject: [PATCH 03/67] one more error hadling - simple quick way --- lib/Parser.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Parser.js b/lib/Parser.js index 3535cade..173e7b5c 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -612,6 +612,8 @@ function parseEnvelopeAddresses(list) { var inGroup = false, curGroup; for (var i = 0, len = list.length, addr; i < len; ++i) { addr = list[i]; + if(!Array.isArray(addr)) continue; + if (addr[2] === null) { // end of group addresses inGroup = false; if (curGroup) { From 64b5043a8a744a824f0891cb11830641d5d859b6 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 31 May 2015 09:09:19 +0300 Subject: [PATCH 04/67] one more fetch error failing --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 173e7b5c..27cfd39b 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -432,7 +432,7 @@ function parseFetch(text, literals, seqno) { var list = parseExpr(text, literals)[0], attrs = {}, m, body; // list is [KEY1, VAL1, KEY2, VAL2, .... KEYn, VALn] for (var i = 0, len = list.length, key, val; i < len; i += 2) { - key = list[i].toLowerCase(); + key = list[i].toString().toLowerCase(); val = list[i + 1]; if (key === 'envelope') val = parseFetchEnvelope(val); From b76591b17b507654cd5bacd942cc599a3571be35 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 31 May 2015 09:48:36 +0300 Subject: [PATCH 05/67] one more fetch error failing, null instead of string --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 27cfd39b..d8dbe068 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -432,7 +432,7 @@ function parseFetch(text, literals, seqno) { var list = parseExpr(text, literals)[0], attrs = {}, m, body; // list is [KEY1, VAL1, KEY2, VAL2, .... KEYn, VALn] for (var i = 0, len = list.length, key, val; i < len; i += 2) { - key = list[i].toString().toLowerCase(); + key = list[i] && list[i].toString().toLowerCase(); val = list[i + 1]; if (key === 'envelope') val = parseFetchEnvelope(val); From 55c8fa81c5ec6c225cf99469f15eedd8e1a60f13 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 31 May 2015 13:33:43 +0300 Subject: [PATCH 06/67] one more fix under siege --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 3535cade..d58af293 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -503,7 +503,7 @@ function parseBodyStructure(cur, literals, prefix, partID) { }; } else { // type information for malformed multipart body - part = { type: cur[0].toLowerCase(), params: null }; + part = { type: cur[0] && cur[0].toLowerCase() || '', params: null }; cur.splice(1, 0, null); ++partLen; next = 2; From 7f4b95dc04ffc2e35a53f22c815c929c91a8337a Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 31 May 2015 19:22:48 +0300 Subject: [PATCH 07/67] just marking the errors found --- lib/Parser.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 58b3a1ba..7bdb867e 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -432,6 +432,8 @@ function parseFetch(text, literals, seqno) { var list = parseExpr(text, literals)[0], attrs = {}, m, body; // list is [KEY1, VAL1, KEY2, VAL2, .... KEYn, VALn] for (var i = 0, len = list.length, key, val; i < len; i += 2) { + //SIEGE + //null.toString(); key = list[i] && list[i].toString().toLowerCase(); val = list[i + 1]; if (key === 'envelope') @@ -503,6 +505,8 @@ function parseBodyStructure(cur, literals, prefix, partID) { }; } else { // type information for malformed multipart body + //SIEGE + //null.toLowerCase(); part = { type: cur[0] && cur[0].toLowerCase() || '', params: null }; cur.splice(1, 0, null); ++partLen; @@ -612,8 +616,9 @@ function parseEnvelopeAddresses(list) { var inGroup = false, curGroup; for (var i = 0, len = list.length, addr; i < len; ++i) { addr = list[i]; + //SIEGE if(!Array.isArray(addr)) continue; - + //addr = undefined; if (addr[2] === null) { // end of group addresses inGroup = false; if (curGroup) { From b7efa5dafe574adc19f58e5b35cb81ee85687fdf Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 5 Jun 2015 01:03:31 +0300 Subject: [PATCH 08/67] one more bug in node-imap --- lib/Parser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 7bdb867e..e9c017a4 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -480,7 +480,7 @@ function parseBodyStructure(cur, literals, prefix, partID) { prefix + (prefix !== '' ? '.' : '') + (partID++).toString(), 1)); } - part = { type: cur[next++].toLowerCase() }; + part = { type: cur[next++].toString().toLowerCase() }; if (partLen > next) { if (Array.isArray(cur[next])) { part.params = {}; @@ -596,7 +596,7 @@ function parseStructExtra(part, partLen, cur, next) { function parseFetchEnvelope(list) { return { - date: new Date(list[0]), + date: new Date(list && list[0] || 0), subject: decodeWords(list[1]), from: parseEnvelopeAddresses(list[2]), sender: parseEnvelopeAddresses(list[3]), From 2aefa354ba880934b759d4c0d162d936a71876dc Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 5 Jun 2015 15:49:20 +0300 Subject: [PATCH 09/67] trying to create nice error event on parser --- lib/Parser.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index e9c017a4..48449731 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -3,6 +3,7 @@ var EventEmitter = require('events').EventEmitter, || require('readable-stream').Readable, inherits = require('util').inherits, inspect = require('util').inspect; + //domain = require('domain'); var utf7 = require('utf7').imap, jsencoding; // lazy-loaded @@ -77,10 +78,23 @@ Parser.prototype.setStream = function(stream) { }; Parser.prototype._tryread = function(n) { - if (this._stream.readable) { - var r = this._stream.read(n); - r && this._parse(r); - } + //we do not need odmains here - try/catch will be enough + //var dom = domain.create(); + //dom.run(function(){ + // try { + if (this._stream.readable) { + var r = this._stream.read(n); + r && this._parse(r); + } + //}catch(err){ + // console.error('Parsers try_read catched', err, new Date()); + //this.emit('error', err); + //} + //}.bind(this)); + //dom.on('error', function(err){ + // console.error('Parsers try_read error', err, new Date()); + //this.emit('error', err); + //}.bind(this)); }; Parser.prototype._parse = function(data) { @@ -480,6 +494,8 @@ function parseBodyStructure(cur, literals, prefix, partID) { prefix + (prefix !== '' ? '.' : '') + (partID++).toString(), 1)); } + //SIEGE 2 + //part=6;part = part.toLowerCase(); part = { type: cur[next++].toString().toLowerCase() }; if (partLen > next) { if (Array.isArray(cur[next])) { @@ -596,6 +612,8 @@ function parseStructExtra(part, partLen, cur, next) { function parseFetchEnvelope(list) { return { + //SIEGE 2 + //date: null[0], date: new Date(list && list[0] || 0), subject: decodeWords(list[1]), from: parseEnvelopeAddresses(list[2]), From 1540b0319a9949e468449bcc48ddf3256c5ad458 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 5 Jun 2015 21:35:13 +0300 Subject: [PATCH 10/67] error handling in parser --- lib/Parser.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 48449731..1af3092c 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -2,8 +2,8 @@ var EventEmitter = require('events').EventEmitter, ReadableStream = require('stream').Readable || require('readable-stream').Readable, inherits = require('util').inherits, - inspect = require('util').inspect; - //domain = require('domain'); + inspect = require('util').inspect, + domain = require('domain'); var utf7 = require('utf7').imap, jsencoding; // lazy-loaded @@ -77,24 +77,29 @@ Parser.prototype.setStream = function(stream) { this._stream.on('readable', this._cbReadable); }; +Parser.prototype.try_emit_error = function(err){ + if(this.$events && this.$events.error) + this.emit('error', err); +}; + Parser.prototype._tryread = function(n) { //we do not need odmains here - try/catch will be enough - //var dom = domain.create(); - //dom.run(function(){ - // try { + var dom = domain.create(); + dom.run(function(){ + try { if (this._stream.readable) { var r = this._stream.read(n); r && this._parse(r); } - //}catch(err){ - // console.error('Parsers try_read catched', err, new Date()); - //this.emit('error', err); - //} - //}.bind(this)); - //dom.on('error', function(err){ - // console.error('Parsers try_read error', err, new Date()); - //this.emit('error', err); - //}.bind(this)); + }catch(err){ + //console.error('Parsers try_read catched', err, new Date()); + this.try_emit_error(err); + } + }.bind(this)); + dom.on('error', function(err){ + //console.error('Parsers try_read error', err, new Date()); + this.try_emit_error(err); + }.bind(this)); }; Parser.prototype._parse = function(data) { From efeacfa9aeff9e35c8c1e224a8c03743bf8b69d1 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 7 Jun 2015 14:47:19 +0300 Subject: [PATCH 11/67] sieging --- lib/Parser.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 48449731..fffe8b5b 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -515,7 +515,8 @@ function parseBodyStructure(cur, literals, prefix, partID) { partID: (prefix !== '' ? prefix : '1'), // required fields as per RFC 3501 -- null or otherwise - type: cur[0].toLowerCase(), subtype: cur[1].toLowerCase(), + //SIEGE 3 + type: cur[0] && cur[0].toLowerCase() || '', subtype: cur[1].toLowerCase(), params: null, id: cur[3], description: cur[4], encoding: cur[5], size: cur[6] }; From e4dd73bdca8afa1cd00a7134b603fb2d82de4bc7 Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 30 Jun 2015 15:03:27 +0300 Subject: [PATCH 12/67] adding alive event --- lib/Connection.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 24e4fed3..86068d7d 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1565,25 +1565,33 @@ Connection.prototype._doKeepaliveTimer = function(immediate) { idleWait = this._config.keepalive.idleInterval || MAX_IDLE_WAIT, forceNoop = this._config.keepalive.forceNoop || false, timerfn = function() { + //console.log('ALIVE - _doKeepaliveTimer'); if (self._idle.enabled) { // unlike NOOP, IDLE is only a valid command after authenticating + //console.log('ALIVE - self._idle.enabled'); if (!self.serverSupports('IDLE') || self.state !== 'authenticated' - || forceNoop) + || forceNoop) { self._enqueue('NOOP', true); - else { + //console.log('ALIVE - self._enqueue(NOOP)'); + }else { if (self._idle.started === undefined) { + //console.log('ALIVE - self._enqueue(IDLE)'); self._idle.started = 0; self._enqueue('IDLE', true); } else if (self._idle.started > 0) { + //console.log('ALIVE - self._idle.started > 0'); var timeDiff = Date.now() - self._idle.started; if (timeDiff >= idleWait) { self._idle.enabled = false; self.debug && self.debug('=> DONE'); self._sock.write('DONE' + CRLF); + //console.log('ALIVE - DONE'); + self.emit('alive'); return; } } + //console.log('ALIVE - setTimeout(timerfn, interval)'); self._tmrKeepalive = setTimeout(timerfn, interval); } } From 947d4ce8ab531c0c083a93e26484973aceb89873 Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 30 Jun 2015 18:23:28 +0300 Subject: [PATCH 13/67] alive event for non-idle servers --- lib/Connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Connection.js b/lib/Connection.js index 86068d7d..73d7425f 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1573,6 +1573,7 @@ Connection.prototype._doKeepaliveTimer = function(immediate) { || self.state !== 'authenticated' || forceNoop) { self._enqueue('NOOP', true); + self.emit('alive'); //console.log('ALIVE - self._enqueue(NOOP)'); }else { if (self._idle.started === undefined) { From 347efb75ef336d4b9405675fab404f27160a8632 Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 30 Jun 2015 19:56:50 +0300 Subject: [PATCH 14/67] one more server type handling in alive --- lib/Connection.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 73d7425f..1125f0a6 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1580,15 +1580,16 @@ Connection.prototype._doKeepaliveTimer = function(immediate) { //console.log('ALIVE - self._enqueue(IDLE)'); self._idle.started = 0; self._enqueue('IDLE', true); + self.emit('alive'); } else if (self._idle.started > 0) { //console.log('ALIVE - self._idle.started > 0'); var timeDiff = Date.now() - self._idle.started; + self.emit('alive'); if (timeDiff >= idleWait) { self._idle.enabled = false; self.debug && self.debug('=> DONE'); self._sock.write('DONE' + CRLF); //console.log('ALIVE - DONE'); - self.emit('alive'); return; } } From b29c07c7a51a77a8b83b32307f2b642a97567d32 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 17 Jul 2015 12:43:03 +0300 Subject: [PATCH 15/67] fixing broken mails with multiline subject --- lib/Parser.js | 7 +++++-- test/test-parser.js | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 0f2efa8a..2444ac4e 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -156,9 +156,12 @@ Parser.prototype._parse = function(data) { if (RE_PRECEDING.test(this._buffer)) { var firstChar = this._buffer[0]; - if (firstChar === '*') + if (firstChar === '*') { + //here we become ready for broken first line + //needed for cases when the answer is the email body + if((i < data.length) && (data[i] == 32)) continue; this._resUntagged(); - else if (firstChar === 'A') + }else if (firstChar === 'A') this._resTagged(); else if (firstChar === '+') this._resContinue(); diff --git a/test/test-parser.js b/test/test-parser.js index 70d3883d..8338faf3 100644 --- a/test/test-parser.js +++ b/test/test-parser.js @@ -253,6 +253,29 @@ var CR = '\r', LF = '\n', CRLF = CR + LF; bodySHA1s: ['1f96faf50f6410f99237791f9e3b89454bf93fa7'], what: 'Untagged FETCH (body)' }, + { source: ['* 12 FETCH (BODY[HEADER]'+CRLF+' {344}', CRLF, + 'Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)', CRLF, + 'From: Terry Gray ', CRLF, + 'Subject: IMAP4rev1 WG mtg summary and minutes', CRLF, + 'To: imap@cac.washington.edu', CRLF, + 'cc: minutes@CNRI.Reston.VA.US, John Klensin ', CRLF, + 'Message-Id: ', CRLF, + 'MIME-Version: 1.0', CRLF, + 'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII', CRLF, CRLF, + ')', CRLF], + expected: [ { seqno: 12, + which: 'HEADER', + size: 344 + }, + { type: 'fetch', + num: 12, + textCode: undefined, + text: {} + } + ], + bodySHA1s: ['1f96faf50f6410f99237791f9e3b89454bf93fa7'], + what: 'Untagged FETCH (body) with broken first line' + }, { source: ['* 12 FETCH (BODY[TEXT] "IMAP is terrible")', CRLF], expected: [ { seqno: 12, which: 'TEXT', From c2892e7385749405a86c6c7adc6fc774d6c557ac Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 19 Jul 2015 09:50:15 +0300 Subject: [PATCH 16/67] rolling back --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 2444ac4e..ebfd649b 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -159,7 +159,7 @@ Parser.prototype._parse = function(data) { if (firstChar === '*') { //here we become ready for broken first line //needed for cases when the answer is the email body - if((i < data.length) && (data[i] == 32)) continue; + //if((i < data.length) && (data[i] == 32)) continue; this._resUntagged(); }else if (firstChar === 'A') this._resTagged(); From fac7283986f714bee59a74702b36d52c279f6e8a Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 19 Jul 2015 10:03:58 +0300 Subject: [PATCH 17/67] forward --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index ebfd649b..2444ac4e 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -159,7 +159,7 @@ Parser.prototype._parse = function(data) { if (firstChar === '*') { //here we become ready for broken first line //needed for cases when the answer is the email body - //if((i < data.length) && (data[i] == 32)) continue; + if((i < data.length) && (data[i] == 32)) continue; this._resUntagged(); }else if (firstChar === 'A') this._resTagged(); From 25fbc52e7442aa0030bee890d4f8fa0c710c7b5f Mon Sep 17 00:00:00 2001 From: phgrey Date: Sun, 19 Jul 2015 17:06:46 +0300 Subject: [PATCH 18/67] rolling back --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 2444ac4e..ebfd649b 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -159,7 +159,7 @@ Parser.prototype._parse = function(data) { if (firstChar === '*') { //here we become ready for broken first line //needed for cases when the answer is the email body - if((i < data.length) && (data[i] == 32)) continue; + //if((i < data.length) && (data[i] == 32)) continue; this._resUntagged(); }else if (firstChar === 'A') this._resTagged(); From 8ef5b307fe3c6dc48c7036e68986bf8955d3f634 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 24 Jul 2015 17:12:42 +0300 Subject: [PATCH 19/67] gitignore itself --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..bb5c8c1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/node_modules +.idea \ No newline at end of file From 4ffb3cde0040cd81d791c7a0ebbca7b400439f72 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 7 Aug 2015 14:53:50 +0300 Subject: [PATCH 20/67] error logging --- lib/Parser.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index ebfd649b..7dee8011 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -77,14 +77,28 @@ Parser.prototype.setStream = function(stream) { this._stream.on('readable', this._cbReadable); }; -Parser.prototype.try_emit_error = function(err){ - if(this.$events && this.$events.error) - this.emit('error', err); +Parser.prototype.log_error = function(err, source){ + //return console.log('Fuck it up'); + var path = err && err.stack && err.stack.split && err.stack.split('\n')[1]; + console.error('json '+JSON.stringify({ + error:{ + message: err.message, + name: err.name, + stack: path ? path.trim() : err.stack + }, + source: source, + message: 'Email fault' + })); }; Parser.prototype._tryread = function(n) { //we do not need odmains here - try/catch will be enough var dom = domain.create(); + + dom.on('error', function(err){ + this.log_error(err, 'parser_domain'); + }.bind(this)); + dom.run(function(){ try { if (this._stream.readable) { @@ -92,14 +106,9 @@ Parser.prototype._tryread = function(n) { r && this._parse(r); } }catch(err){ - //console.error('Parsers try_read catched', err, new Date()); - this.try_emit_error(err); + this.log_error(err, 'parser_catch'); } }.bind(this)); - dom.on('error', function(err){ - //console.error('Parsers try_read error', err, new Date()); - this.try_emit_error(err); - }.bind(this)); }; Parser.prototype._parse = function(data) { From 8832db9518e81d9f716aa91a02ecf130f58f3cc7 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 7 Aug 2015 17:56:01 +0300 Subject: [PATCH 21/67] alive moving --- lib/Connection.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 1125f0a6..b772e340 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -187,12 +187,15 @@ Connection.prototype.connect = function() { this._parser = parser = new Parser(this._sock, this.debug); parser.on('untagged', function(info) { + self.emit('alive'); self._resUntagged(info); }); parser.on('tagged', function(info) { + self.emit('alive'); self._resTagged(info); }); parser.on('body', function(stream, info) { + self.emit('alive'); var msg = self._curReq.fetchCache[info.seqno], toget; if (msg === undefined) { @@ -223,6 +226,7 @@ Connection.prototype.connect = function() { stream.resume(); // a body we didn't ask for? }); parser.on('continue', function(info) { + self.emit('alive'); var type = self._curReq.type; if (type === 'IDLE') { if (self._queue.length @@ -251,6 +255,7 @@ Connection.prototype.connect = function() { } }); parser.on('other', function(line) { + self.emit('alive'); var m; if (m = RE_IDLENOOPRES.exec(line)) { // no longer idling @@ -1573,18 +1578,18 @@ Connection.prototype._doKeepaliveTimer = function(immediate) { || self.state !== 'authenticated' || forceNoop) { self._enqueue('NOOP', true); - self.emit('alive'); + //self.emit('alive'); //console.log('ALIVE - self._enqueue(NOOP)'); }else { if (self._idle.started === undefined) { //console.log('ALIVE - self._enqueue(IDLE)'); self._idle.started = 0; self._enqueue('IDLE', true); - self.emit('alive'); + //self.emit('alive'); } else if (self._idle.started > 0) { //console.log('ALIVE - self._idle.started > 0'); var timeDiff = Date.now() - self._idle.started; - self.emit('alive'); + //self.emit('alive'); if (timeDiff >= idleWait) { self._idle.enabled = false; self.debug && self.debug('=> DONE'); From f663768dc01bc93423ac91429ae7eac34bcc5866 Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 10 Aug 2015 16:55:11 +0300 Subject: [PATCH 22/67] a few major bugfixes --- lib/Connection.js | 3 ++- lib/Parser.js | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index b772e340..7678abf0 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -424,6 +424,7 @@ Connection.prototype.openBox = function(name, readOnly, cb) { self._box = undefined; cb(err); } else { + if(!self._box) self._createCurrentBox(); self._box.name = name; cb(err, self._box); } @@ -1265,7 +1266,7 @@ Connection.prototype._resUntagged = function(info) { this._sock.end(); } } else if (type === 'exists') { - if (!this._box && RE_OPENBOX.test(this._curReq.type)) + if (!this._box && this._curReq && RE_OPENBOX.test(this._curReq.type)) this._createCurrentBox(); if (this._box) { var prev = this._box.messages.total, diff --git a/lib/Parser.js b/lib/Parser.js index 7dee8011..5cc09c23 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -629,6 +629,18 @@ function parseStructExtra(part, partLen, cur, next) { } function parseFetchEnvelope(list) { + if(!list) return { + date: new Date( 0), + subject: '', + from: [], + sender: [], + replyTo: [], + to: [], + cc: [], + bcc: [], + inReplyTo: '', + messageId: '' + }; return { //SIEGE 2 //date: null[0], From ff5afd45ae44fa017ae97039b3d083c7de9ba1d2 Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 11 Aug 2015 14:54:55 +0300 Subject: [PATCH 23/67] one more imap module fix --- lib/Connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 7678abf0..3a509e54 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1247,7 +1247,7 @@ Connection.prototype._resUntagged = function(info) { cbargs.push([]); cbargs[0].push(info.text); } else if (type === 'recent') { - if (!this._box && RE_OPENBOX.test(this._curReq.type)) + if (!this._box && this._curReq && RE_OPENBOX.test(this._curReq.type)) this._createCurrentBox(); if (this._box) this._box.messages.new = info.num; From 5ffcc44a4db7d27b5b64b084e0d4b49d18a60631 Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 25 Aug 2015 13:45:03 +0300 Subject: [PATCH 24/67] 2 more verid errors are gone --- lib/Parser.js | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 5cc09c23..ff5246af 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -513,16 +513,18 @@ function parseBodyStructure(cur, literals, prefix, partID) { } //SIEGE 2 //part=6;part = part.toLowerCase(); - part = { type: cur[next++].toString().toLowerCase() }; - if (partLen > next) { - if (Array.isArray(cur[next])) { - part.params = {}; - for (i = 0, len = cur[next].length; i < len; i += 2) - part.params[cur[next][i].toLowerCase()] = cur[next][i + 1]; - } else - part.params = cur[next]; - ++next; - } + if(typeof(cur[next]) !== 'undefined'){ + part = { type: cur[next++].toString().toLowerCase() }; + if (partLen > next) { + if (Array.isArray(cur[next])) { + part.params = {}; + for (i = 0, len = cur[next].length; i < len; i += 2) + part.params[cur[next][i].toLowerCase()] = cur[next][i + 1]; + } else + part.params = cur[next]; + ++next; + } + }else part = false; } else { // single part next = 7; if (typeof cur[1] === 'string') { @@ -575,9 +577,11 @@ function parseBodyStructure(cur, literals, prefix, partID) { if (typeof cur[1] === 'string' && partLen > next) part.md5 = cur[next++]; } - // add any extra fields that may or may not be omitted entirely - parseStructExtra(part, partLen, cur, next); - ret.unshift(part); + if(part){ + // add any extra fields that may or may not be omitted entirely + parseStructExtra(part, partLen, cur, next); + ret.unshift(part); + } } return ret; } @@ -713,6 +717,10 @@ function parseExpr(o, literals, result, start, useBrackets) { useBrackets = true; if (!result) result = []; + + //LATE SIEGE. + //Cannot read property 'str' of null + if(o === null) o = ''; if (typeof o === 'string') { o = { str: o }; isTop = true; From 89e11983b9d5082682b5e4c28262076626afb29a Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 25 Aug 2015 15:52:47 +0300 Subject: [PATCH 25/67] cb on method end --- lib/Connection.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 3a509e54..e29c2da0 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -300,12 +300,13 @@ Connection.prototype.destroy = function() { this._sock && this._sock.destroy(); }; -Connection.prototype.end = function() { +Connection.prototype.end = function(cb) { var self = this; this._enqueue('LOGOUT', function() { self._queue = []; self._curReq = undefined; self._sock.end(); + cb && cb(); }); }; From a38f9557d3f4e9a8f0ecc26efd1c4768d1c61be5 Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 26 Aug 2015 14:46:13 +0300 Subject: [PATCH 26/67] all error handlings are removed --- lib/Parser.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index ff5246af..f73d1cc6 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -2,8 +2,8 @@ var EventEmitter = require('events').EventEmitter, ReadableStream = require('stream').Readable || require('readable-stream').Readable, inherits = require('util').inherits, - inspect = require('util').inspect, - domain = require('domain'); + inspect = require('util').inspect; +//var domain = require('domain'); var utf7 = require('utf7').imap, jsencoding; // lazy-loaded @@ -93,22 +93,22 @@ Parser.prototype.log_error = function(err, source){ Parser.prototype._tryread = function(n) { //we do not need odmains here - try/catch will be enough - var dom = domain.create(); - - dom.on('error', function(err){ - this.log_error(err, 'parser_domain'); - }.bind(this)); - - dom.run(function(){ - try { + //var dom = domain.create(); + + //dom.on('error', function(err){ + // this.log_error(err, 'parser_domain'); + //}.bind(this)); + // + //dom.run(function(){ + // try { if (this._stream.readable) { var r = this._stream.read(n); r && this._parse(r); } - }catch(err){ - this.log_error(err, 'parser_catch'); - } - }.bind(this)); + //}catch(err){ + // this.log_error(err, 'parser_catch'); + //} + //}.bind(this)); }; Parser.prototype._parse = function(data) { From 99f1d1a3382f8cd0778b263a32038c9a6b9aa059 Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 26 Aug 2015 16:41:49 +0300 Subject: [PATCH 27/67] reverting LATE SIEGE --- lib/Parser.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index f73d1cc6..a03f9c64 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -511,9 +511,10 @@ function parseBodyStructure(cur, literals, prefix, partID) { prefix + (prefix !== '' ? '.' : '') + (partID++).toString(), 1)); } - //SIEGE 2 - //part=6;part = part.toLowerCase(); - if(typeof(cur[next]) !== 'undefined'){ + ///LATE CANCELED SIEGE. + //if(typeof(cur[next]) !== 'undefined'){ + //SIEGE 2 + //part=6;part = part.toLowerCase(); part = { type: cur[next++].toString().toLowerCase() }; if (partLen > next) { if (Array.isArray(cur[next])) { @@ -524,7 +525,7 @@ function parseBodyStructure(cur, literals, prefix, partID) { part.params = cur[next]; ++next; } - }else part = false; + //}else part = false; } else { // single part next = 7; if (typeof cur[1] === 'string') { @@ -577,11 +578,11 @@ function parseBodyStructure(cur, literals, prefix, partID) { if (typeof cur[1] === 'string' && partLen > next) part.md5 = cur[next++]; } - if(part){ + //if(part){ // add any extra fields that may or may not be omitted entirely parseStructExtra(part, partLen, cur, next); ret.unshift(part); - } + //} } return ret; } @@ -718,9 +719,9 @@ function parseExpr(o, literals, result, start, useBrackets) { if (!result) result = []; - //LATE SIEGE. + //LATE CANCELED SIEGE. //Cannot read property 'str' of null - if(o === null) o = ''; + //if(o === null) o = ''; if (typeof o === 'string') { o = { str: o }; isTop = true; From fa91a67e81a80c624928844636f30f2b3118c056 Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 26 Aug 2015 18:47:50 +0300 Subject: [PATCH 28/67] getting back late siege --- lib/Parser.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index a03f9c64..458a1531 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -512,7 +512,7 @@ function parseBodyStructure(cur, literals, prefix, partID) { + (partID++).toString(), 1)); } ///LATE CANCELED SIEGE. - //if(typeof(cur[next]) !== 'undefined'){ + if(typeof(cur[next]) !== 'undefined'){ //SIEGE 2 //part=6;part = part.toLowerCase(); part = { type: cur[next++].toString().toLowerCase() }; @@ -525,7 +525,7 @@ function parseBodyStructure(cur, literals, prefix, partID) { part.params = cur[next]; ++next; } - //}else part = false; + }else part = false; } else { // single part next = 7; if (typeof cur[1] === 'string') { @@ -578,11 +578,11 @@ function parseBodyStructure(cur, literals, prefix, partID) { if (typeof cur[1] === 'string' && partLen > next) part.md5 = cur[next++]; } - //if(part){ + if(part){ // add any extra fields that may or may not be omitted entirely parseStructExtra(part, partLen, cur, next); ret.unshift(part); - //} + } } return ret; } @@ -721,7 +721,7 @@ function parseExpr(o, literals, result, start, useBrackets) { //LATE CANCELED SIEGE. //Cannot read property 'str' of null - //if(o === null) o = ''; + if(o === null) o = ''; if (typeof o === 'string') { o = { str: o }; isTop = true; From f8000f1eca1722ab8de6cff0ae7d60b777a6822c Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 28 Aug 2015 16:28:48 +0300 Subject: [PATCH 29/67] node 0.12 error handling on tls connect --- lib/Connection.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index e29c2da0..cae10c61 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -107,7 +107,7 @@ Connection.prototype.connect = function() { this._tmrAuth = undefined; this._queue = []; this._box = undefined; - this._idle = { started: undefined, enabled: false }; + this._idle = {started: undefined, enabled: false}; this._parser = undefined; this._curReq = undefined; this.delimiter = undefined; @@ -123,9 +123,9 @@ Connection.prototype.connect = function() { tlsOptions.socket = socket; } - if (config.tls) + if (config.tls){ this._sock = tls.connect(tlsOptions, onconnect); - else { + }else { socket.once('connect', onconnect); this._sock = socket; } @@ -150,6 +150,9 @@ Connection.prototype.connect = function() { self.emit('error', err); }; this._sock.on('error', this._onError); + if(config.tls) + socket.on('error', this._onError); + this._onSocketTimeout = function() { clearTimeout(self._tmrConn); From f97808389348a726c6f754fa3add0df22c5966db Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 3 Sep 2015 12:39:13 +0300 Subject: [PATCH 30/67] one more err fixing in imap --- lib/Connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Connection.js b/lib/Connection.js index cae10c61..933016e9 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -230,6 +230,7 @@ Connection.prototype.connect = function() { }); parser.on('continue', function(info) { self.emit('alive'); + if(!self._curReq) return; var type = self._curReq.type; if (type === 'IDLE') { if (self._queue.length From ce4901c6193005cf06ac498a358b0d5ee66fdeb3 Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 10 Sep 2015 23:55:32 +0300 Subject: [PATCH 31/67] one more fix --- lib/Connection.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 3a509e54..7d91e0f5 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1811,7 +1811,9 @@ module.exports = Connection; // utilities ------------------------------------------------------------------- function escape(str) { - return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"'); + return typeof(str.replace) == 'function' + ? str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"') + : ''; } function validateUIDList(uids, noThrow) { From 6ca7fbf77ffca556180e2b9bb33e3caba9c6216f Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 11 Sep 2015 08:56:54 +0300 Subject: [PATCH 32/67] rollback --- lib/Connection.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Connection.js b/lib/Connection.js index 1b37a890..aeea1c79 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -150,6 +150,7 @@ Connection.prototype.connect = function() { self.emit('error', err); }; this._sock.on('error', this._onError); + //SIEGE 31 if(config.tls) socket.on('error', this._onError); @@ -230,6 +231,7 @@ Connection.prototype.connect = function() { }); parser.on('continue', function(info) { self.emit('alive'); + //SIEGE 31 if(!self._curReq) return; var type = self._curReq.type; if (type === 'IDLE') { @@ -310,6 +312,7 @@ Connection.prototype.end = function(cb) { self._queue = []; self._curReq = undefined; self._sock.end(); + //SIEGE 31 cb && cb(); }); }; @@ -1816,6 +1819,8 @@ module.exports = Connection; // utilities ------------------------------------------------------------------- function escape(str) { + //SIEGE 31 + return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"'); return typeof(str.replace) == 'function' ? str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"') : ''; From 992840a443b09cc591fdcdf3870f96ea2f9b08bf Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 11 Sep 2015 13:43:18 +0300 Subject: [PATCH 33/67] some additional comment --- lib/Connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index aeea1c79..4aecd70c 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1819,7 +1819,7 @@ module.exports = Connection; // utilities ------------------------------------------------------------------- function escape(str) { - //SIEGE 31 + //SIEGE 31 - bad place to protect, take a look deeper return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"'); return typeof(str.replace) == 'function' ? str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"') From 70a896c4a64e247f249ac3756c60ccc85b22adfa Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 11 Sep 2015 22:18:23 +0300 Subject: [PATCH 34/67] trying to fix sleeping by refix late siege --- lib/Parser.js | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 458a1531..f47404ff 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -511,21 +511,20 @@ function parseBodyStructure(cur, literals, prefix, partID) { prefix + (prefix !== '' ? '.' : '') + (partID++).toString(), 1)); } - ///LATE CANCELED SIEGE. - if(typeof(cur[next]) !== 'undefined'){ - //SIEGE 2 - //part=6;part = part.toLowerCase(); - part = { type: cur[next++].toString().toLowerCase() }; - if (partLen > next) { - if (Array.isArray(cur[next])) { - part.params = {}; - for (i = 0, len = cur[next].length; i < len; i += 2) - part.params[cur[next][i].toLowerCase()] = cur[next][i + 1]; - } else - part.params = cur[next]; - ++next; - } - }else part = false; + //SIEGE 2 + //part=6;part = part.toLowerCase(); + //LATE SIEGE too: + //undefined.toString() + part = { type: (cur[next++] || '').toString().toLowerCase() }; + if (partLen > next) { + if (Array.isArray(cur[next])) { + part.params = {}; + for (i = 0, len = cur[next].length; i < len; i += 2) + part.params[cur[next][i].toLowerCase()] = cur[next][i + 1]; + } else + part.params = cur[next]; + ++next; + } } else { // single part next = 7; if (typeof cur[1] === 'string') { @@ -578,11 +577,9 @@ function parseBodyStructure(cur, literals, prefix, partID) { if (typeof cur[1] === 'string' && partLen > next) part.md5 = cur[next++]; } - if(part){ - // add any extra fields that may or may not be omitted entirely - parseStructExtra(part, partLen, cur, next); - ret.unshift(part); - } + // add any extra fields that may or may not be omitted entirely + parseStructExtra(part, partLen, cur, next); + ret.unshift(part); } return ret; } From a75bcaa778b821bf0d2b771ed92f30fe0304554b Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 14 Sep 2015 14:50:50 +0300 Subject: [PATCH 35/67] one more comment --- lib/Connection.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 4aecd70c..3eb0de4f 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1819,11 +1819,8 @@ module.exports = Connection; // utilities ------------------------------------------------------------------- function escape(str) { - //SIEGE 31 - bad place to protect, take a look deeper + //SIEGE 31 - REALY CANCELED - bad place to protect, take a look deeper return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"'); - return typeof(str.replace) == 'function' - ? str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"') - : ''; } function validateUIDList(uids, noThrow) { From e81e1d3db885fbfb7d03aacd205792ab0b8760ec Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 24 Sep 2015 19:10:19 +0300 Subject: [PATCH 36/67] 'close' event rising --- lib/Connection.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index aeea1c79..214c1182 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -170,14 +170,19 @@ Connection.prototype.connect = function() { this._sock.on('timeout', this._onSocketTimeout); socket.setTimeout(config.socketTimeout); - socket.once('close', function(had_err) { + var socket_on_close = function (had_err) { clearTimeout(self._tmrConn); clearTimeout(self._tmrAuth); clearTimeout(self._tmrKeepalive); self.state = 'disconnected'; self.debug && self.debug('[connection] Closed'); self.emit('close', had_err); - }); + }; + socket.once('close', socket_on_close); + + //SIEGE 31.late + if(config.tls) + this._sock.once('close', socket_on_close); socket.once('end', function() { clearTimeout(self._tmrConn); From 0f467f3c67c617e41d36dbd54f52db7b141fcf6d Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 28 Sep 2015 17:42:17 +0300 Subject: [PATCH 37/67] one more siege --- lib/Parser.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index f47404ff..6d6ba3c5 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -550,8 +550,12 @@ function parseBodyStructure(cur, literals, prefix, partID) { } if (Array.isArray(cur[2])) { part.params = {}; - for (i = 0, len = cur[2].length; i < len; i += 2) - part.params[cur[2][i].toLowerCase()] = cur[2][i + 1]; + for (i = 0, len = cur[2].length; i < len; i += 2){ + //Cannot read property toLowerCase of NULL + if(cur[2][i]) + part.params[cur[2][i].toLowerCase()] = cur[2][i + 1]; + } + if (cur[1] === null) ++next; } From 49bb573d0cce89a172d51e783c24ef76f04ebed8 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 6 Nov 2015 19:42:46 +0200 Subject: [PATCH 38/67] tls quickfix --- lib/Connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 8401a6e7..8a5827cc 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1734,7 +1734,7 @@ Connection.prototype._starttls = function() { self._sock.on('error', self._onError); self._sock.on('timeout', this._onSocketTimeout); - self._sock.setTimeout(config.socketTimeout); + self._sock.setTimeout(this._config.socketTimeout); self._parser.setStream(self._sock); }); From df0e973d16094c46e465183a056f92b6632e4793 Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 9 Nov 2015 15:17:26 +0200 Subject: [PATCH 39/67] startls sub-socket error thrown repair --- lib/Connection.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 8a5827cc..cfea89aa 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1726,6 +1726,10 @@ Connection.prototype._starttls = function() { // Host name may be overridden the tlsOptions for (var k in this._config.tlsOptions) tlsOptions[k] = this._config.tlsOptions[k]; + + self._sock.on('error', self._onError); + //self._sock.on('timeout', self._onSocketTimeout); + tlsOptions.socket = self._sock; self._sock = tls.connect(tlsOptions, function() { @@ -1733,7 +1737,8 @@ Connection.prototype._starttls = function() { }); self._sock.on('error', self._onError); - self._sock.on('timeout', this._onSocketTimeout); + self._sock.on('timeout', self._onSocketTimeout); + self._sock.setTimeout(this._config.socketTimeout); self._parser.setStream(self._sock); From 4bf584f6d7a30c0bea5ee4f82792a27844038260 Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 9 Nov 2015 16:14:19 +0200 Subject: [PATCH 40/67] one more event through 2-level tls socket --- lib/Connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index cfea89aa..5c6a7543 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1728,7 +1728,7 @@ Connection.prototype._starttls = function() { tlsOptions[k] = this._config.tlsOptions[k]; self._sock.on('error', self._onError); - //self._sock.on('timeout', self._onSocketTimeout); + self._sock.on('timeout', self._onSocketTimeout); tlsOptions.socket = self._sock; From 3dba2b48791b90087c806ce61a925cf7f24d8332 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 13 Nov 2015 21:19:34 +0200 Subject: [PATCH 41/67] starttls fixed, 163.com marked, email in error --- lib/Connection.js | 30 +++++++++++++++++------------- lib/Parser.js | 5 +++++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 5c6a7543..4c79b334 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -64,6 +64,7 @@ function Connection(config) { tlsOptions: config.tlsOptions, autotls: config.autotls, user: config.user, + email: config.email, password: config.password, xoauth: config.xoauth, xoauth2: config.xoauth2, @@ -135,7 +136,7 @@ Connection.prototype.connect = function() { self.state = 'connected'; self.debug && self.debug('[connection] Connected to host'); self._tmrAuth = setTimeout(function() { - var err = new Error('Timed out while authenticating with server'); + var err = new Error('Timed out while authenticating with server for ' + config.email); err.source = 'timeout-auth'; self.emit('error', err); socket.destroy(); @@ -1624,7 +1625,7 @@ Connection.prototype._doKeepaliveTimer = function(immediate) { this._tmrKeepalive = setTimeout(timerfn, interval); }; -Connection.prototype._login = function() { +Connection.prototype._login = function(without_starttls) { var self = this, checkedNS = false; var reentry = function(err) { @@ -1665,19 +1666,20 @@ Connection.prototype._login = function() { } else reentry(); }; - - if (self.serverSupports('STARTTLS') - && (self._config.autotls === 'always' - || (self._config.autotls === 'required' - && self.serverSupports('LOGINDISABLED')))) { + if(!without_starttls){ + if (self.serverSupports('STARTTLS') + && (self._config.autotls === 'always' + || (self._config.autotls === 'required' + && self.serverSupports('LOGINDISABLED')))) { self._starttls(); return; - } + } - if (self.serverSupports('LOGINDISABLED')) { - err = new Error('Logging in is disabled on this server'); - err.source = 'authentication'; - return reentry(err); + if (self.serverSupports('LOGINDISABLED')) { + err = new Error('Logging in is disabled on this server'); + err.source = 'authentication'; + return reentry(err); + } } var cmd; @@ -1733,7 +1735,7 @@ Connection.prototype._starttls = function() { tlsOptions.socket = self._sock; self._sock = tls.connect(tlsOptions, function() { - self._login(); + self._login(true); }); self._sock.on('error', self._onError); @@ -1760,6 +1762,8 @@ Connection.prototype._processQueue = function() { prefix = this._curReq.type; else prefix = 'A' + (this._tagcount++); + //163.com fix + //prefix = 'C' + (this._tagcount++); var out = prefix + ' ' + this._curReq.fullcmd; this.debug && this.debug('=> ' + inspect(out)); diff --git a/lib/Parser.js b/lib/Parser.js index 6d6ba3c5..1651d9ac 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -13,6 +13,8 @@ var CH_LF = 10, EMPTY_READCB = function(n) {}, RE_INTEGER = /^\d+$/, RE_PRECEDING = /^(?:(?:\*|A\d+) )|\+ ?/, + //163.com fix + //RE_PRECEDING = /^(?:(?:\*|C\d+) )|\+ ?/, RE_BODYLITERAL = /BODY\[(.*)\] \{(\d+)\}$/i, RE_BODYINLINEKEY = /^BODY\[(.*)\]$/i, RE_SEQNO = /^\* (\d+)/, @@ -20,6 +22,8 @@ var CH_LF = 10, RE_LITERAL = /\{(\d+)\}$/, RE_UNTAGGED = /^\* (?:(OK|NO|BAD|BYE|FLAGS|ID|LIST|LSUB|SEARCH|STATUS|CAPABILITY|NAMESPACE|PREAUTH|SORT|THREAD|ESEARCH|QUOTA|QUOTAROOT)|(\d+) (EXPUNGE|FETCH|RECENT|EXISTS))(?:(?: \[([^\]]+)\])?(?: (.+))?)?$/i, RE_TAGGED = /^A(\d+) (OK|NO|BAD) (?:\[([^\]]+)\] )?(.+)$/i, + //163.com fix + //RE_TAGGED = /^C(\d+) (OK|NO|BAD) (?:\[([^\]]+)\] )?(.+)$/i, RE_CONTINUE = /^\+(?: (?:\[([^\]]+)\] )?(.+))?$/i, RE_CRLF = /\r\n/g, RE_HDR = /^([^:]+):[ \t]?(.+)?$/, @@ -171,6 +175,7 @@ Parser.prototype._parse = function(data) { //if((i < data.length) && (data[i] == 32)) continue; this._resUntagged(); }else if (firstChar === 'A') + //}else if (firstChar === 'C')//163.com this._resTagged(); else if (firstChar === '+') this._resContinue(); From ca4600198b76e9a7bf1b6decb6ca2b3f03e85348 Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 18 Nov 2015 05:08:34 +0200 Subject: [PATCH 42/67] workersdeath marked --- lib/Connection.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 4c79b334..10488985 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -135,6 +135,7 @@ Connection.prototype.connect = function() { clearTimeout(self._tmrConn); self.state = 'connected'; self.debug && self.debug('[connection] Connected to host'); + //WORKERDEATH#2 self._tmrAuth = setTimeout(function() { var err = new Error('Timed out while authenticating with server for ' + config.email); err.source = 'timeout-auth'; @@ -291,7 +292,7 @@ Connection.prototype.connect = function() { self._processQueue(); } }); - + //WORKERDEATH#1 this._tmrConn = setTimeout(function() { var err = new Error('Timed out while connecting to server'); err.source = 'timeout'; From d1dfbcff00b4b6c1e3095573e579ae9ef4e7edb8 Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 18 Nov 2015 11:00:01 +0200 Subject: [PATCH 43/67] several major fixes --- lib/Connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Connection.js b/lib/Connection.js index 10488985..4f28d556 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -103,6 +103,7 @@ Connection.prototype.connect = function() { socket.setKeepAlive(true); this._sock = undefined; this._tagcount = 0; + //TODO: why? no clearTimeout. no checks. do not re-connect, initialize new instance. this._tmrConn = undefined; this._tmrKeepalive = undefined; this._tmrAuth = undefined; From be890a073d4590218c16b428af3eeb28dfbd872f Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 19 Nov 2015 13:35:50 +0200 Subject: [PATCH 44/67] end event throwing through the sockets --- lib/Connection.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 4c79b334..520d0dd8 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -172,6 +172,7 @@ Connection.prototype.connect = function() { socket.setTimeout(config.socketTimeout); var socket_on_close = function (had_err) { + //socket_on_close = function(){}; clearTimeout(self._tmrConn); clearTimeout(self._tmrAuth); clearTimeout(self._tmrKeepalive); @@ -179,20 +180,27 @@ Connection.prototype.connect = function() { self.debug && self.debug('[connection] Closed'); self.emit('close', had_err); }; - socket.once('close', socket_on_close); + socket.on('close', socket_on_close); //SIEGE 31.late if(config.tls) - this._sock.once('close', socket_on_close); + this._sock.on('close', socket_on_close); - socket.once('end', function() { - clearTimeout(self._tmrConn); - clearTimeout(self._tmrAuth); - clearTimeout(self._tmrKeepalive); - self.state = 'disconnected'; - self.debug && self.debug('[connection] Ended'); - self.emit('end'); - }); + + var socket_on_end = function() { + socket_on_end = function(){}; + clearTimeout(self._tmrConn); + clearTimeout(self._tmrAuth); + clearTimeout(self._tmrKeepalive); + self.state = 'disconnected'; + self.debug && self.debug('[connection] Ended'); + self.emit('end'); + }; + socket.once('end', socket_on_end); + + //SIEGE 31.very.very.late + if(config.tls) + this._sock.once('end', socket_on_end); this._parser = parser = new Parser(this._sock, this.debug); From 4dd0c9d55638acf6690b474afa31d04949083b53 Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 19 Nov 2015 14:49:40 +0200 Subject: [PATCH 45/67] end event throwing through the startls sockets --- lib/Connection.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index d1504810..0d835990 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -189,8 +189,7 @@ Connection.prototype.connect = function() { this._sock.on('close', socket_on_close); - var socket_on_end = function() { - socket_on_end = function(){}; + this._onSocketEnd = function() { clearTimeout(self._tmrConn); clearTimeout(self._tmrAuth); clearTimeout(self._tmrKeepalive); @@ -198,11 +197,11 @@ Connection.prototype.connect = function() { self.debug && self.debug('[connection] Ended'); self.emit('end'); }; - socket.once('end', socket_on_end); + socket.once('end', this._onSocketEnd); //SIEGE 31.very.very.late if(config.tls) - this._sock.once('end', socket_on_end); + this._sock.once('end', this._onSocketEnd); this._parser = parser = new Parser(this._sock, this.debug); @@ -1741,6 +1740,7 @@ Connection.prototype._starttls = function() { self._sock.on('error', self._onError); self._sock.on('timeout', self._onSocketTimeout); + self._sock.once('end', self._onSocketEnd); tlsOptions.socket = self._sock; @@ -1750,6 +1750,7 @@ Connection.prototype._starttls = function() { self._sock.on('error', self._onError); self._sock.on('timeout', self._onSocketTimeout); + self._sock.once('end', self._onSocketEnd); self._sock.setTimeout(this._config.socketTimeout); From 801e812935bcfe3cacf5ce987a07bf18eb959c18 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 20 Nov 2015 14:09:50 +0200 Subject: [PATCH 46/67] and no matter if we forgot about timers --- lib/Connection.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 0d835990..0a9f46ec 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -138,10 +138,12 @@ Connection.prototype.connect = function() { self.debug && self.debug('[connection] Connected to host'); //WORKERDEATH#2 self._tmrAuth = setTimeout(function() { - var err = new Error('Timed out while authenticating with server for ' + config.email); - err.source = 'timeout-auth'; - self.emit('error', err); - socket.destroy(); + if(self){ + var err = new Error('Timed out while authenticating with server for ' + config.email); + err.source = 'timeout-auth'; + self.emit('error', err); + } + socket && socket.destroy(); }, config.authTimeout); } @@ -302,10 +304,12 @@ Connection.prototype.connect = function() { }); //WORKERDEATH#1 this._tmrConn = setTimeout(function() { - var err = new Error('Timed out while connecting to server'); - err.source = 'timeout'; - self.emit('error', err); - socket.destroy(); + if(self){ + var err = new Error('Timed out while connecting to server'); + err.source = 'timeout'; + self.emit('error', err); + } + socket && socket.destroy(); }, config.connTimeout); socket.connect(config.port, config.host); From 26032f88cb74a6a3fe054ea2b0505b9039d382b7 Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 14 Dec 2015 18:43:25 +0200 Subject: [PATCH 47/67] and do not call me, timers! ever! --- lib/Connection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 0a9f46ec..ebf65882 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -138,7 +138,7 @@ Connection.prototype.connect = function() { self.debug && self.debug('[connection] Connected to host'); //WORKERDEATH#2 self._tmrAuth = setTimeout(function() { - if(self){ + if(self && self.listeners && self.listeners('error') && self.listeners('error').length > 0){ var err = new Error('Timed out while authenticating with server for ' + config.email); err.source = 'timeout-auth'; self.emit('error', err); @@ -304,7 +304,7 @@ Connection.prototype.connect = function() { }); //WORKERDEATH#1 this._tmrConn = setTimeout(function() { - if(self){ + if(self && self.listeners && self.listeners('error') && self.listeners('error').length > 0){ var err = new Error('Timed out while connecting to server'); err.source = 'timeout'; self.emit('error', err); From fca2f062d6b21226fbd4ddd419a7761c5ee8f585 Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 15 Feb 2016 13:45:50 +0200 Subject: [PATCH 48/67] still under siege --- lib/Parser.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 1651d9ac..2c2c2a39 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -725,13 +725,14 @@ function parseExpr(o, literals, result, start, useBrackets) { if (!result) result = []; - //LATE CANCELED SIEGE. - //Cannot read property 'str' of null - if(o === null) o = ''; if (typeof o === 'string') { o = { str: o }; isTop = true; } + //instead of UNCANCELLED SIEGE + //Cannot read property 'str' of null|undefined + if(!o) o = {}; + if(!o.str) o.str = ''; for (var i = start, len = o.str.length; i < len; ++i) { if (!inQuote) { if (isBody) { From a87f20b0a69fa3e3315a01daddf6f23e5acf1cff Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 16 Feb 2016 12:24:50 +0200 Subject: [PATCH 49/67] Merge branch 'master' into prod # Conflicts: # app/lib/ews/runner.js # package.json --- lib/Connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index ebf65882..b440998e 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1301,7 +1301,7 @@ Connection.prototype._resUntagged = function(info) { this._box.messages.total = now; if (now > prev && this.state === 'authenticated') { this._box.messages.new = now - prev; - this.emit('mail', this._box.messages.new); + this.emit('mail', now); } } } else if (type === 'expunge') { From bdfd9d8b0a0a662d4a69b0dd0a7abecdb29d486c Mon Sep 17 00:00:00 2001 From: phgrey Date: Mon, 7 Mar 2016 17:33:42 +0200 Subject: [PATCH 50/67] one obsolette check removing --- lib/Connection.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index b440998e..d67e8ed5 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -547,8 +547,7 @@ Connection.prototype.getSubscribedBoxes = function(namespace, cb) { }; Connection.prototype.status = function(boxName, cb) { - if (this._box && this._box.name === boxName) - throw new Error('Cannot call status on currently selected mailbox'); + boxName = boxName || (this._box && this._box.name) || ''; boxName = escape(utf7.encode(''+boxName)); From 222f8b611a0c481c2c049273e1201f32cb512ffb Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 9 Mar 2016 13:41:31 +0200 Subject: [PATCH 51/67] folder default value for status request --- lib/Connection.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/Connection.js b/lib/Connection.js index d67e8ed5..4f74c333 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -547,6 +547,11 @@ Connection.prototype.getSubscribedBoxes = function(namespace, cb) { }; Connection.prototype.status = function(boxName, cb) { + if(typeof(boxName) == 'function'){ + cb = boxName; + boxName = null; + } + boxName = boxName || (this._box && this._box.name) || ''; boxName = escape(utf7.encode(''+boxName)); From e945dbc6f20eacb0fb17f1afa830cb81169ef2e5 Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 10 Mar 2016 22:53:39 +0200 Subject: [PATCH 52/67] minor fix to do not lose connections --- lib/Connection.js | 84 ++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 4f74c333..c4776564 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1516,56 +1516,58 @@ Connection.prototype._fuckUp = function(place){ return true; } return false; -} +}; Connection.prototype._resTagged = function(info) { - if(this._fuckUp('_resTagged')) return; - var req = this._curReq, err; + if(this._curReq){ + var req = this._curReq, err; - this._curReq = undefined; + this._curReq = undefined; - if (info.type === 'no' || info.type === 'bad') { - var errtext; - if (info.text) - errtext = info.text; - else - errtext = req.oauthError; - err = new Error(errtext); - err.type = info.type; - err.textCode = info.textCode; - err.source = 'protocol'; - } else if (this._box) { - if (req.type === 'EXAMINE' || req.type === 'SELECT') { - this._box.readOnly = (typeof info.textCode === 'string' - && info.textCode.toUpperCase() === 'READ-ONLY'); - } + if (info.type === 'no' || info.type === 'bad') { + var errtext; + if (info.text) + errtext = info.text; + else + errtext = req.oauthError; + err = new Error(errtext); + err.type = info.type; + err.textCode = info.textCode; + err.source = 'protocol'; + } else if (this._box) { + if (req.type === 'EXAMINE' || req.type === 'SELECT') { + this._box.readOnly = (typeof info.textCode === 'string' + && info.textCode.toUpperCase() === 'READ-ONLY'); + } - // According to RFC 3501, UID commands do not give errors for - // non-existant user-supplied UIDs, so give the callback empty results - // if we unexpectedly received no untagged responses. - if (RE_UIDCMD_HASRESULTS.test(req.fullcmd) && req.cbargs.length === 0) - req.cbargs.push([]); - } + // According to RFC 3501, UID commands do not give errors for + // non-existant user-supplied UIDs, so give the callback empty results + // if we unexpectedly received no untagged responses. + if (RE_UIDCMD_HASRESULTS.test(req.fullcmd) && req.cbargs.length === 0) + req.cbargs.push([]); + } - if (req.bodyEmitter) { - var bodyEmitter = req.bodyEmitter; - if (err) - bodyEmitter.emit('error', err); - process.nextTick(function() { - bodyEmitter.emit('end'); - }); - } else { - req.cbargs.unshift(err); - if (info.textCode && info.textCode.key) { - var key = info.textCode.key.toUpperCase(); - if (key === 'APPENDUID') // [uidvalidity, newUID] - req.cbargs.push(info.textCode.val[1]); - else if (key === 'COPYUID') // [uidvalidity, sourceUIDs, destUIDs] - req.cbargs.push(info.textCode.val[2]); + if (req.bodyEmitter) { + var bodyEmitter = req.bodyEmitter; + if (err) + bodyEmitter.emit('error', err); + process.nextTick(function() { + bodyEmitter.emit('end'); + }); + } else { + req.cbargs.unshift(err); + if (info.textCode && info.textCode.key) { + var key = info.textCode.key.toUpperCase(); + if (key === 'APPENDUID') // [uidvalidity, newUID] + req.cbargs.push(info.textCode.val[1]); + else if (key === 'COPYUID') // [uidvalidity, sourceUIDs, destUIDs] + req.cbargs.push(info.textCode.val[2]); + } + req.cb && req.cb.apply(this, req.cbargs); } - req.cb && req.cb.apply(this, req.cbargs); } + if (this._queue.length === 0 && this._config.keepalive && this.state === 'authenticated' From 85bce98baea0a699a40c376a48cc656ed21eb996 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sat, 12 Mar 2016 02:31:08 +0200 Subject: [PATCH 53/67] Revert "minor fix to do not lose connections" This reverts commit e945dbc6f20eacb0fb17f1afa830cb81169ef2e5. --- lib/Connection.js | 84 +++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index c4776564..4f74c333 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1516,57 +1516,55 @@ Connection.prototype._fuckUp = function(place){ return true; } return false; -}; +} Connection.prototype._resTagged = function(info) { - if(this._curReq){ - var req = this._curReq, err; - - this._curReq = undefined; + if(this._fuckUp('_resTagged')) return; + var req = this._curReq, err; - if (info.type === 'no' || info.type === 'bad') { - var errtext; - if (info.text) - errtext = info.text; - else - errtext = req.oauthError; - err = new Error(errtext); - err.type = info.type; - err.textCode = info.textCode; - err.source = 'protocol'; - } else if (this._box) { - if (req.type === 'EXAMINE' || req.type === 'SELECT') { - this._box.readOnly = (typeof info.textCode === 'string' - && info.textCode.toUpperCase() === 'READ-ONLY'); - } + this._curReq = undefined; - // According to RFC 3501, UID commands do not give errors for - // non-existant user-supplied UIDs, so give the callback empty results - // if we unexpectedly received no untagged responses. - if (RE_UIDCMD_HASRESULTS.test(req.fullcmd) && req.cbargs.length === 0) - req.cbargs.push([]); + if (info.type === 'no' || info.type === 'bad') { + var errtext; + if (info.text) + errtext = info.text; + else + errtext = req.oauthError; + err = new Error(errtext); + err.type = info.type; + err.textCode = info.textCode; + err.source = 'protocol'; + } else if (this._box) { + if (req.type === 'EXAMINE' || req.type === 'SELECT') { + this._box.readOnly = (typeof info.textCode === 'string' + && info.textCode.toUpperCase() === 'READ-ONLY'); } - if (req.bodyEmitter) { - var bodyEmitter = req.bodyEmitter; - if (err) - bodyEmitter.emit('error', err); - process.nextTick(function() { - bodyEmitter.emit('end'); - }); - } else { - req.cbargs.unshift(err); - if (info.textCode && info.textCode.key) { - var key = info.textCode.key.toUpperCase(); - if (key === 'APPENDUID') // [uidvalidity, newUID] - req.cbargs.push(info.textCode.val[1]); - else if (key === 'COPYUID') // [uidvalidity, sourceUIDs, destUIDs] - req.cbargs.push(info.textCode.val[2]); - } - req.cb && req.cb.apply(this, req.cbargs); - } + // According to RFC 3501, UID commands do not give errors for + // non-existant user-supplied UIDs, so give the callback empty results + // if we unexpectedly received no untagged responses. + if (RE_UIDCMD_HASRESULTS.test(req.fullcmd) && req.cbargs.length === 0) + req.cbargs.push([]); } + if (req.bodyEmitter) { + var bodyEmitter = req.bodyEmitter; + if (err) + bodyEmitter.emit('error', err); + process.nextTick(function() { + bodyEmitter.emit('end'); + }); + } else { + req.cbargs.unshift(err); + if (info.textCode && info.textCode.key) { + var key = info.textCode.key.toUpperCase(); + if (key === 'APPENDUID') // [uidvalidity, newUID] + req.cbargs.push(info.textCode.val[1]); + else if (key === 'COPYUID') // [uidvalidity, sourceUIDs, destUIDs] + req.cbargs.push(info.textCode.val[2]); + } + req.cb && req.cb.apply(this, req.cbargs); + } if (this._queue.length === 0 && this._config.keepalive From e87f660a4628d47ed4dc451e80f87e2190d81fe7 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sat, 12 Mar 2016 19:20:27 +0200 Subject: [PATCH 54/67] one more siege --- lib/Parser.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Parser.js b/lib/Parser.js index 2c2c2a39..aa83d105 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -1015,19 +1015,22 @@ function decodeWords(str, state) { decodeBytes(bytes, m.charset, m.index, m.length, m.pendoffset, state, next && next.buf); } - +//VERY LATE SIEGE + str = str.toString(); // perform the actual replacements for (i = state.replaces.length - 1; i >= 0; --i) { seq = state.replaces[i]; if (Array.isArray(seq)) { for (j = 0, lenj = seq.length; j < lenj; ++j) { str = str.substring(0, seq[j].fromOffset) - + seq[j].val + + seq[j].val.toString() + str.substring(seq[j].toOffset); } } else { + //VERY LATE SIEGE + //Parser.js:1029 str = str.substring(0, seq.fromOffset) ^ TypeError: undefined is not a function str = str.substring(0, seq.fromOffset) - + seq.val + + seq.val.toString() + str.substring(seq.toOffset); } } From 054d06417c1355ff79236151932ebb0d698b1735 Mon Sep 17 00:00:00 2001 From: phgrey Date: Sat, 12 Mar 2016 19:41:13 +0200 Subject: [PATCH 55/67] one more siege - fix --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index aa83d105..13b882b1 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -1016,7 +1016,7 @@ function decodeWords(str, state) { next && next.buf); } //VERY LATE SIEGE - str = str.toString(); + str = str ? str.toString() : ''; // perform the actual replacements for (i = state.replaces.length - 1; i >= 0; --i) { seq = state.replaces[i]; From ecd91a8b0497cf916e7473f35de79a9ef65ddb70 Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 15 Mar 2016 19:38:46 +0200 Subject: [PATCH 56/67] one more siege is logged --- lib/Connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 4f74c333..1e97a5ed 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -249,7 +249,7 @@ Connection.prototype.connect = function() { parser.on('continue', function(info) { self.emit('alive'); //SIEGE 31 - if(!self._curReq) return; + if(self._fuckUp('parseContinue')) return; var type = self._curReq.type; if (type === 'IDLE') { if (self._queue.length From da518f91bb37f95b0951b0b3b9eacadd1e78e1f7 Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 18 Mar 2016 17:44:15 +0200 Subject: [PATCH 57/67] one more siege --- lib/Parser.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index 13b882b1..a7ef3586 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -558,7 +558,8 @@ function parseBodyStructure(cur, literals, prefix, partID) { for (i = 0, len = cur[2].length; i < len; i += 2){ //Cannot read property toLowerCase of NULL if(cur[2][i]) - part.params[cur[2][i].toLowerCase()] = cur[2][i + 1]; + //SIEGE - undefined is not a function + part.params[cur[2][i].toString().toLowerCase()] = cur[2][i + 1]; } if (cur[1] === null) From 75c8a5111bb7357e98c7d5384480c273195db8da Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 22 Mar 2016 22:54:49 +0200 Subject: [PATCH 58/67] some more logs and a timeout --- lib/Connection.js | 27 +++++++++++++-------------- lib/Parser.js | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 1e97a5ed..c08be4a5 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -170,13 +170,17 @@ Connection.prototype.connect = function() { var err = new Error('Socket timed out while talking to server'); err.source = 'socket-timeout'; self.emit('error', err); + self.emit('close'); socket.destroy(); }; - this._sock.on('timeout', this._onSocketTimeout); + + socket.on('timeout', this._onSocketTimeout); + if(config.tls) + this._sock.on('timeout', this._onSocketTimeout); + socket.setTimeout(config.socketTimeout); var socket_on_close = function (had_err) { - //socket_on_close = function(){}; clearTimeout(self._tmrConn); clearTimeout(self._tmrAuth); clearTimeout(self._tmrKeepalive); @@ -184,11 +188,11 @@ Connection.prototype.connect = function() { self.debug && self.debug('[connection] Closed'); self.emit('close', had_err); }; - socket.on('close', socket_on_close); + socket.once('close', socket_on_close); //SIEGE 31.late if(config.tls) - this._sock.on('close', socket_on_close); + this._sock.once('close', socket_on_close); this._onSocketEnd = function() { @@ -207,14 +211,8 @@ Connection.prototype.connect = function() { this._parser = parser = new Parser(this._sock, this.debug); - parser.on('untagged', function(info) { - self.emit('alive'); - self._resUntagged(info); - }); - parser.on('tagged', function(info) { - self.emit('alive'); - self._resTagged(info); - }); + parser.on('untagged', self._resUntagged.bind(self)); + parser.on('tagged', self._resTagged.bind(self)); parser.on('body', function(stream, info) { self.emit('alive'); var msg = self._curReq.fetchCache[info.seqno], toget; @@ -247,9 +245,9 @@ Connection.prototype.connect = function() { stream.resume(); // a body we didn't ask for? }); parser.on('continue', function(info) { - self.emit('alive'); //SIEGE 31 if(self._fuckUp('parseContinue')) return; + self.emit('alive'); var type = self._curReq.type; if (type === 'IDLE') { if (self._queue.length @@ -278,7 +276,6 @@ Connection.prototype.connect = function() { } }); parser.on('other', function(line) { - self.emit('alive'); var m; if (m = RE_IDLENOOPRES.exec(line)) { // no longer idling @@ -1252,6 +1249,7 @@ Connection.prototype.__defineGetter__('seq', function() { Connection.prototype._resUntagged = function(info) { var type = info.type, i, len, box, attrs, key; + if(this._curReq) this.emit('alive'); if (type === 'bye') this._sock.end(); @@ -1520,6 +1518,7 @@ Connection.prototype._fuckUp = function(place){ Connection.prototype._resTagged = function(info) { if(this._fuckUp('_resTagged')) return; + this.emit('alive'); var req = this._curReq, err; this._curReq = undefined; diff --git a/lib/Parser.js b/lib/Parser.js index a7ef3586..bfaea9b8 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -116,6 +116,7 @@ Parser.prototype._tryread = function(n) { }; Parser.prototype._parse = function(data) { + this.debug && this.debug('<> ' + data.toString()); var i = 0, datalen = data.length, idxlf; if (this._literallen > 0) { From e578f195dbca3a97f21a0d840094da64e19719f6 Mon Sep 17 00:00:00 2001 From: phgrey Date: Wed, 23 Mar 2016 19:35:32 +0200 Subject: [PATCH 59/67] again aliving on parser's other --- lib/Connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Connection.js b/lib/Connection.js index c08be4a5..39874c77 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -278,6 +278,7 @@ Connection.prototype.connect = function() { parser.on('other', function(line) { var m; if (m = RE_IDLENOOPRES.exec(line)) { + self.emit('alive'); // no longer idling self._idle.enabled = false; self._idle.started = undefined; From ed7107c64a548de02199415cf98d99b7c338ce0e Mon Sep 17 00:00:00 2001 From: phgrey Date: Thu, 24 Mar 2016 16:24:23 +0200 Subject: [PATCH 60/67] timeout to work correct --- lib/Connection.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 39874c77..b61b193f 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -175,10 +175,12 @@ Connection.prototype.connect = function() { }; socket.on('timeout', this._onSocketTimeout); - if(config.tls) + socket.setTimeout(config.socketTimeout); + if(config.tls){ this._sock.on('timeout', this._onSocketTimeout); + this._sock.setTimeout(config.socketTimeout); + } - socket.setTimeout(config.socketTimeout); var socket_on_close = function (had_err) { clearTimeout(self._tmrConn); From 1281d1420b52b4a69cd5b148571e0abbceaafc1f Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 25 Mar 2016 17:09:24 +0200 Subject: [PATCH 61/67] post-done enhancements --- lib/Connection.js | 35 ++++++++++++----------------------- lib/Parser.js | 26 ++++++-------------------- 2 files changed, 18 insertions(+), 43 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index b61b193f..743cfaab 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -182,7 +182,7 @@ Connection.prototype.connect = function() { } - var socket_on_close = function (had_err) { + this._onSocketClose = function (had_err) { clearTimeout(self._tmrConn); clearTimeout(self._tmrAuth); clearTimeout(self._tmrKeepalive); @@ -190,11 +190,11 @@ Connection.prototype.connect = function() { self.debug && self.debug('[connection] Closed'); self.emit('close', had_err); }; - socket.once('close', socket_on_close); + socket.once('close', this._onSocketClose); //SIEGE 31.late if(config.tls) - this._sock.once('close', socket_on_close); + this._sock.once('close', this._onSocketClose); this._onSocketEnd = function() { @@ -304,11 +304,11 @@ Connection.prototype.connect = function() { }); //WORKERDEATH#1 this._tmrConn = setTimeout(function() { - if(self && self.listeners && self.listeners('error') && self.listeners('error').length > 0){ + // if(self && self.listeners && self.listeners('error') && self.listeners('error').length > 0){ var err = new Error('Timed out while connecting to server'); err.source = 'timeout'; self.emit('error', err); - } + // } socket && socket.destroy(); }, config.connTimeout); @@ -451,7 +451,10 @@ Connection.prototype.openBox = function(name, readOnly, cb) { self._box = undefined; cb(err); } else { - if(!self._box) self._createCurrentBox(); + if(!self._box){ + self._createCurrentBox(); + self.notifyEdited('openBox'); + } self._box.name = name; cb(err, self._box); } @@ -1604,35 +1607,25 @@ Connection.prototype._doKeepaliveTimer = function(immediate) { idleWait = this._config.keepalive.idleInterval || MAX_IDLE_WAIT, forceNoop = this._config.keepalive.forceNoop || false, timerfn = function() { - //console.log('ALIVE - _doKeepaliveTimer'); if (self._idle.enabled) { // unlike NOOP, IDLE is only a valid command after authenticating - //console.log('ALIVE - self._idle.enabled'); if (!self.serverSupports('IDLE') || self.state !== 'authenticated' - || forceNoop) { + || forceNoop) self._enqueue('NOOP', true); - //self.emit('alive'); - //console.log('ALIVE - self._enqueue(NOOP)'); - }else { + else { if (self._idle.started === undefined) { - //console.log('ALIVE - self._enqueue(IDLE)'); self._idle.started = 0; self._enqueue('IDLE', true); - //self.emit('alive'); } else if (self._idle.started > 0) { - //console.log('ALIVE - self._idle.started > 0'); var timeDiff = Date.now() - self._idle.started; - //self.emit('alive'); if (timeDiff >= idleWait) { self._idle.enabled = false; self.debug && self.debug('=> DONE'); self._sock.write('DONE' + CRLF); - //console.log('ALIVE - DONE'); return; } } - //console.log('ALIVE - setTimeout(timerfn, interval)'); self._tmrKeepalive = setTimeout(timerfn, interval); } } @@ -1747,11 +1740,6 @@ Connection.prototype._starttls = function() { // Host name may be overridden the tlsOptions for (var k in this._config.tlsOptions) tlsOptions[k] = this._config.tlsOptions[k]; - - self._sock.on('error', self._onError); - self._sock.on('timeout', self._onSocketTimeout); - self._sock.once('end', self._onSocketEnd); - tlsOptions.socket = self._sock; self._sock = tls.connect(tlsOptions, function() { @@ -1760,6 +1748,7 @@ Connection.prototype._starttls = function() { self._sock.on('error', self._onError); self._sock.on('timeout', self._onSocketTimeout); + self._sock.once('close', self._onSocketClose); self._sock.once('end', self._onSocketEnd); self._sock.setTimeout(this._config.socketTimeout); diff --git a/lib/Parser.js b/lib/Parser.js index bfaea9b8..ffaedbdb 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -21,7 +21,7 @@ var CH_LF = 10, RE_LISTCONTENT = /^\((.*)\)$/, RE_LITERAL = /\{(\d+)\}$/, RE_UNTAGGED = /^\* (?:(OK|NO|BAD|BYE|FLAGS|ID|LIST|LSUB|SEARCH|STATUS|CAPABILITY|NAMESPACE|PREAUTH|SORT|THREAD|ESEARCH|QUOTA|QUOTAROOT)|(\d+) (EXPUNGE|FETCH|RECENT|EXISTS))(?:(?: \[([^\]]+)\])?(?: (.+))?)?$/i, - RE_TAGGED = /^A(\d+) (OK|NO|BAD) (?:\[([^\]]+)\] )?(.+)$/i, + RE_TAGGED = /^A(\d+) (OK|NO|BAD) ?(?:\[([^\]]+)\] )?(.*)$/i, //163.com fix //RE_TAGGED = /^C(\d+) (OK|NO|BAD) (?:\[([^\]]+)\] )?(.+)$/i, RE_CONTINUE = /^\+(?: (?:\[([^\]]+)\] )?(.+))?$/i, @@ -96,23 +96,10 @@ Parser.prototype.log_error = function(err, source){ }; Parser.prototype._tryread = function(n) { - //we do not need odmains here - try/catch will be enough - //var dom = domain.create(); - - //dom.on('error', function(err){ - // this.log_error(err, 'parser_domain'); - //}.bind(this)); - // - //dom.run(function(){ - // try { - if (this._stream.readable) { - var r = this._stream.read(n); - r && this._parse(r); - } - //}catch(err){ - // this.log_error(err, 'parser_catch'); - //} - //}.bind(this)); + if (this._stream.readable) { + var r = this._stream.read(n); + r && this._parse(r); + } }; Parser.prototype._parse = function(data) { @@ -726,7 +713,6 @@ function parseExpr(o, literals, result, start, useBrackets) { useBrackets = true; if (!result) result = []; - if (typeof o === 'string') { o = { str: o }; isTop = true; @@ -966,7 +952,7 @@ function decodeWords(str, state) { state.replaces = []; var bytes, m, next, i, j, leni, lenj, seq, replaces = [], lastReplace = {}; - + // join consecutive q-encoded words that have the same charset first while (m = RE_ENCWORD.exec(str)) { seq = { From 5d3820e74f4eff1f579faf940fa4a8633213211c Mon Sep 17 00:00:00 2001 From: phgrey Date: Fri, 25 Mar 2016 17:36:03 +0200 Subject: [PATCH 62/67] all new mails are sent in case of exists response --- lib/Connection.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Connection.js b/lib/Connection.js index 743cfaab..6f8145c2 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1309,7 +1309,8 @@ Connection.prototype._resUntagged = function(info) { this._box.messages.total = now; if (now > prev && this.state === 'authenticated') { this._box.messages.new = now - prev; - this.emit('mail', now); + for(var x = now, seqs = []; x > prev; seqs.push(x--)); + this.emit('mail', seqs); } } } else if (type === 'expunge') { From 62838ec218b80ac8587c099711864b7b46aca2e4 Mon Sep 17 00:00:00 2001 From: phgrey Date: Tue, 12 Apr 2016 17:07:09 +0300 Subject: [PATCH 63/67] one more event propagating to be sure we do react on exists/fetch/expunge events from server --- lib/Connection.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Connection.js b/lib/Connection.js index 6f8145c2..0dff66c7 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1311,6 +1311,8 @@ Connection.prototype._resUntagged = function(info) { this._box.messages.new = now - prev; for(var x = now, seqs = []; x > prev; seqs.push(x--)); this.emit('mail', seqs); + }else{ + this.emit('exists', now); } } } else if (type === 'expunge') { From b117766691308e9e303c86aef69b922eac54b885 Mon Sep 17 00:00:00 2001 From: destel Date: Wed, 13 Apr 2016 17:44:09 +0300 Subject: [PATCH 64/67] made all fields except the UID optional when fetching --- lib/Connection.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index 0dff66c7..d27d94f2 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -831,17 +831,23 @@ Connection.prototype._fetch = function(which, uids, options) { fetching = [], i, len, key; - if (this.serverSupports('X-GM-EXT-1')) { + if (this.serverSupports('X-GM-EXT-1') && options.gmail !== false) { fetching.push('X-GM-THRID'); fetching.push('X-GM-MSGID'); fetching.push('X-GM-LABELS'); } - if (this.serverSupports('CONDSTORE') && !this._box.nomodseq) + if (this.serverSupports('CONDSTORE') && !this._box.nomodseq && options.modseq !== false) fetching.push('MODSEQ'); fetching.push('UID'); - fetching.push('FLAGS'); - fetching.push('INTERNALDATE'); + + if (options.flags !== false) { + fetching.push('FLAGS'); + } + + if (options.date !== false) { + fetching.push('INTERNALDATE'); + } var modifiers; From 4d0f4186d064603e7c0e04ae6a1e2607a93d84ef Mon Sep 17 00:00:00 2001 From: destel Date: Tue, 19 Apr 2016 13:42:56 +0300 Subject: [PATCH 65/67] Workaround for untagged status updates w/o UID field --- lib/Connection.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/Connection.js b/lib/Connection.js index d27d94f2..b344c3c4 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1496,6 +1496,13 @@ Connection.prototype._resUntagged = function(info) { } } } + + //destel: workaround, if we didn't get attributes from list below... then let's pretend we we're not going to fetch them + //otherwise condition below is not matched and 'attributes' and 'end' events are not emitted + var ignored = ['UID'] + toget = toget.filter(function(v) { + return !v || !v.toUpperCase || ignored.indexOf(v.toUpperCase()) == -1 + }) if (toget.length === 0) { if (msg) From ec3658e22b068a9ee60e2ecb46272697e38dda53 Mon Sep 17 00:00:00 2001 From: destel Date: Tue, 19 Apr 2016 20:07:11 +0300 Subject: [PATCH 66/67] fix of previous workaround --- lib/Connection.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/Connection.js b/lib/Connection.js index b344c3c4..24750f4a 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1496,13 +1496,6 @@ Connection.prototype._resUntagged = function(info) { } } } - - //destel: workaround, if we didn't get attributes from list below... then let's pretend we we're not going to fetch them - //otherwise condition below is not matched and 'attributes' and 'end' events are not emitted - var ignored = ['UID'] - toget = toget.filter(function(v) { - return !v || !v.toUpperCase || ignored.indexOf(v.toUpperCase()) == -1 - }) if (toget.length === 0) { if (msg) @@ -1573,6 +1566,20 @@ Connection.prototype._resTagged = function(info) { if (err) bodyEmitter.emit('error', err); process.nextTick(function() { + + //destel: emit 'attributes' and 'end' events for messages which are not yet ended + for (var sn in req.fetchCache) { + if (req.fetchCache.hasOwnProperty(sn)) { + var item = req.fetchCache[sn] + if (!item.ended) { + item.ended = true + item.msgEmitter.emit('attributes', item.attrs); + item.msgEmitter.emit('end'); + } + } + } + //end + bodyEmitter.emit('end'); }); } else { From 79f9bb93a7c3407a27fcea89476636b78bb82e15 Mon Sep 17 00:00:00 2001 From: destel Date: Fri, 22 Apr 2016 12:35:37 +0300 Subject: [PATCH 67/67] Removed extra debug --- lib/Parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parser.js b/lib/Parser.js index ffaedbdb..1cc201bf 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -103,7 +103,7 @@ Parser.prototype._tryread = function(n) { }; Parser.prototype._parse = function(data) { - this.debug && this.debug('<> ' + data.toString()); + //this.debug && this.debug('<> ' + data.toString()); var i = 0, datalen = data.length, idxlf; if (this._literallen > 0) {