From 09b2fe0968bd0cad1fa662d3bae2909da20b10cd Mon Sep 17 00:00:00 2001 From: Brian White Date: Fri, 19 Nov 2010 01:25:26 -0500 Subject: [PATCH] Swap out regex used for parsing FETCH responses for a real parser. Not all IMAP servers respond with the requested FETCH data in the same order. --- imap.js | 99 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/imap.js b/imap.js index 03d6208..b496c11 100644 --- a/imap.js +++ b/imap.js @@ -84,17 +84,16 @@ ImapConnection.prototype.connect = function(loginCb) { // Don't mess with incoming data if it's part of a literal if (/\{(\d+)\}$/.test(data.substr(0, data.indexOf(CRLF)))) { - var result = /\{(\d+)\}$/.exec(data.substr(0, data.indexOf(CRLF))), - total = parseInt(result[1]); - self._state.fetchData._total = total; + var result = /\{(\d+)\}$/.exec(data.substr(0, data.indexOf(CRLF))); + self._state.fetchData._total = parseInt(result[1]); } if (self._state.fetchData._total > 0) { if (data.length - (data.indexOf(CRLF)+2) <= self._state.fetchData._total) { self._state.curData = data; return; } - literalData = data.substr(data.indexOf(CRLF)+2, total); - data = data.substr(0, data.indexOf(CRLF)) + data.substr(data.indexOf(CRLF) + 3 + total); + literalData = data.substr(data.indexOf(CRLF) + 2, self._state.fetchData._total); + data = data.substr(0, data.indexOf(CRLF)) + data.substr(data.indexOf(CRLF) + 2 + self._state.fetchData._total); self._state.fetchData._total = 0; } @@ -176,28 +175,8 @@ ImapConnection.prototype.connect = function(loginCb) { break; default: // Check for FETCH result - if (/^FETCH /i.test(data[2])) { - var regex = "\\(UID ([\\d]+) INTERNALDATE \"(.*?)\" FLAGS \\((.*?)\\)", result; - if ((result = new RegExp(regex + " BODYSTRUCTURE \\((.*\\))(?=\\)|[\\s])").exec(data[2]))) - self._state.fetchData.structure = parseBodyStructure(result[4]); - result = new RegExp(regex).exec(data[2]); - self._state.fetchData.date = result[2]; - self._state.fetchData.flags = result[3].split(' ').filter(isNotEmpty); - if (literalData.length > 0) { - result = /BODY\[(.*)\](?:\<[\d]+\>)? \{[\d]+\}$/.exec(data[2]); - if (result[1].indexOf('HEADER') === 0) { // either full or selective headers - var headers = literalData.split(/\r\n(?=[\w])/), header; - self._state.fetchData.headers = {}; - for (var i=0,len=headers.length; i 0) { + key = str.substring(0, str.indexOf(' ')); + str = str.substring(str.indexOf(' ')+1); + isNil = (str.substr(0, 3) === 'NIL'); + if (isNil) + idxNext = 3; + else { + switch (key) { + case 'UID': + idxNext = str.indexOf(' ')+1; + break; + case 'INTERNALDATE': + idxNext = str.indexOf('"', 1)+1; + fetchData.date = str.substring(1, idxNext-1); + break; + case 'FLAGS': + idxNext = str.indexOf(')')+1; + fetchData.flags = str.substring(1, idxNext-1).split(' ').filter(isNotEmpty); + break; + case 'BODYSTRUCTURE': + var inQuote = false, + countParen = 0, + lastIndex = -1; + for (var i=1,len=str.length; i)?$/.exec(key); + idxNext = str.indexOf("}")+1; + if (result[1].indexOf('HEADER') === 0) { // either full or selective headers + var headers = literalData.split(/\r\n(?=[\w])/), header; + fetchData.headers = {}; + for (var i=0,len=headers.length; i