diff --git a/lib/imap.js b/lib/imap.js index 372317d..323d9d5 100644 --- a/lib/imap.js +++ b/lib/imap.js @@ -23,6 +23,7 @@ var CRLF = '\r\n', }, RE_LITHEADER = /(?:((?:BODY\[.*\](?:<\d+>)?)?|[^ ]+) )?\{(\d+)\}$/i, RE_UNRESP = /^\* (OK|PREAUTH|NO|BAD) (?:\[(.+)\] )?(.+)$/i, + //RE_ISPARTIAL = /<(\d+)>$/, RE_CMD = /^([^ ]+)(?: |$)/, RE_ISHEADER = /HEADER/, REX_UNRESPDATA = XRegExp('^\\* (?:(?:(?NAMESPACE) (?(?:NIL|\\((?:\\(.+\\))+\\))) (?(?:NIL|\\((?:\\(.+\\))+\\))) (?(?:NIL|\\((?:\\(.+\\))+\\))))|(?:(?FLAGS) \\((?.*)\\))|(?:(?LIST|LSUB|XLIST) \\((?.*)\\) (?".+"|NIL) (?.+))|(?:(?(SEARCH|SORT))(?: (?.*))?)|(?:(?STATUS) (?.+) \\((?.*)\\))|(?:(?CAPABILITY) (?.+))|(?:(?BYE) (?:\\[(?.+)\\] )?(?.+)))$', 'i'), @@ -273,17 +274,10 @@ ImapConnection.prototype.connect = function(loginCb) { litType = m[1]; indata.expect = (m ? parseInt(m[2], 10) : -1); if (indata.expect > -1) { + /*if (RE_ISPARTIAL.test(litType)) + litType = litType.replace(RE_ISPARTIAL, '<$1.' + indata.expect + '>');*/ if ((m = /\* (\d+) FETCH/i.exec(indata.line)) && /^BODY\[/i.test(litType)) { - /*if (!requests[0].fetchers[litType].msg) { - msg = new ImapMessage(); - msg.seqno = parseInt(m[1], 10); - var fetches = requests[0].fetchers[litType]; - fetches.msg = msg; - for (f = 0, lenf = fetches.length; f < lenf; ++f) - fetches[f].emit('message', msg); - }*/ - msg = new ImapMessage(); msg.seqno = parseInt(m[1], 10); fetches = requests[0].fetchers[litType]; @@ -935,7 +929,7 @@ ImapConnection.prototype._fetch = function(which, uids, options, what, cb) { var toFetch = '', prefix, extensions, self = this, parse = true, headers, key, stream, opts = { markSeen: false, struct: true, size: false }, - fetchers = {}, part; + fetchers = {}; if (typeof what === 'function') { cb = what; @@ -1073,23 +1067,20 @@ ImapConnection.prototype._fetch = function(which, uids, options, what, cb) { } if (wp.body) { key = pprefix; - if (wp.body === true) { + if (wp.body === true) key += 'TEXT]'; - part = key; - } else if (typeof wp.body.start === 'number' - && wp.body.length === 'number') { + /*else if (typeof wp.body.start === 'number' + && typeof wp.body.length === 'number') { if (wp.body.start < 0) throw new Error('Invalid `start` value: ' + wp.body.start); else if (wp.body.length <= 0) throw new Error('Invalid `length` value: ' + wp.body.length); key += 'TEXT]<'; key += wp.body.start; - part = key; - part += '.'; - part += wp.body.length; + key += '.'; + key += wp.body.length; key += '>'; - part += '>'; - } else + }*/ else throw new Error('Invalid `body` value: ' + wp.body); key = key.trim(); @@ -1097,13 +1088,12 @@ ImapConnection.prototype._fetch = function(which, uids, options, what, cb) { stream = new ImapFetch(); if (!fetchers[key]) { fetchers[key] = [stream]; - toFetch += part; + toFetch += ' ' + key; } else fetchers[key].push(stream); if (!wp.headers && !wp.headersNot && typeof wp.cb === 'function') wp.cb(stream); stream = undefined; - part = undefined; key = undefined; } } else { diff --git a/lib/imap.parsers.js b/lib/imap.parsers.js index 42d14b8..32d8d9c 100644 --- a/lib/imap.parsers.js +++ b/lib/imap.parsers.js @@ -53,7 +53,7 @@ exports.parseNamespaces = function(str, literals) { else { result = exports.parseExpr(str, literals); vals = []; - for (var i=0,len=result.length; i 2) { // extension data val.extensions = []; - for (var j=2,len2=result[i].length; j 1) { + //else if (result[i].length === 2 && typeof result[i][1] === 'number') { + // OK, so ordinarily this is where we'd transform a partial fetch + // key so that it matches up with a key in our request's fetchers object + // but since IMAP sucks, we have no way to match up a partial fetch + // response if less than the number of octets we requested were returned. + // + // Example: We request BODY[TEXT]<0.32>, but BODY[TEXT] is only 16 bytes, + // then we get back: BODY[TEXT]<0> {16} + // This leaves us with no way to find out what the original + // length request was. ARGH!!!^%&#^@#$%&$! + // Because of this and the fact that the server can return requested + // values in any order, I am disabling partial fetches entirely. + + // BODY[TEXT]<0.32> + /*result[i][0] += '<'; + result[i][0] += result[i][1]; // starting octet + result[i][0] += '.'; + if (typeof result[i + 1] === 'number') + result[i][0] += result[i + 1]; + else if (typeof + result[i][0] += '>';*/ + } else if (result[i].length > 1) { // HEADER.FIELDS (foo) result[i][0] += ' ('; result[i][0] += result[i].slice(1).join(' '); result[i][0] += ')'; } if (bodies === undefined) - bodies = ['BODY[' + result[i][0] + ']', result[i+1]]; + bodies = ['BODY[' + result[i][0] + ']', result[i + 1]]; else { bodies.push('BODY[' + result[i][0] + ']'); - bodies.push(result[i+1]); + bodies.push(result[i + 1]); } } } @@ -102,22 +123,22 @@ exports.parseFetchBodies = function(str, literals) { exports.parseFetch = function(str, literals, fetchData) { literals.lp = 0; var result = exports.parseExpr(str, literals); - for (var i=0,len=result.length; i next) { if (Array.isArray(cur[next])) { part.params = {}; - for (i=0,len=cur[next].length; i next && Array.isArray(cur[next])) { part.envelope = {}; - for (i=0,len=cur[next].length; i 0) - result.push(exports.convStr(o.str.substring(lastPos+1, i), literals)); + if (i - (lastPos + 1) > 0) { + val = exports.convStr(o.str.substring(lastPos + 1, i), literals); + result.push(val); + } if ((o.str[i] === ')' || o.str[i] === ']') && !isTop) return i; lastPos = i; - } else if ((o.str[i] === '(' || o.str[i] === '[') - /*&& (i === 0 || !isAlpha(o.str.charCodeAt(i-1)))*/) { + } else if ((o.str[i] === '(' || o.str[i] === '[')) { var innerResult = []; - i = exports.parseExpr(o, literals, innerResult, i+1); + i = exports.parseExpr(o, literals, innerResult, i + 1); lastPos = i; result.push(innerResult); - } + }/* else if (i > 0 && o.str[i] === '<' && o.str[i - 1] === ']') { + lastPos = i; + inLitStart = true; + } else if (o.str[i] === '>' && inLitStart) { + val = exports.convStr(o.str.substring(lastPos + 1, i), literals); + result[result.length - 1].push(val); + inLitStart = false; + }*/ } else if (o.str[i] === '"' && - (o.str[i-1] && - (o.str[i-1] !== '\\' || (o.str[i-2] && o.str[i-2] === '\\')))) + (o.str[i - 1] && + (o.str[i - 1] !== '\\' + || (o.str[i - 2] && o.str[i - 2] === '\\') + ))) inQuote = false; - if (i+1 === len && len - (lastPos+1) > 0) - result.push(exports.convStr(o.str.substring(lastPos+1), literals)); + if (i + 1 === len && len - (lastPos + 1) > 0) + result.push(exports.convStr(o.str.substring(lastPos + 1), literals)); } return (isTop ? result : start); };