more fetch() fixes

fork
Brian White 12 years ago
parent ee89662679
commit 70251b00c3

@ -208,16 +208,43 @@ ImapConnection.prototype.connect = function(loginCb) {
} }
} }
function emitLitData(key, data) {
var fetches = requests[0].fetchers[key];
for (var i=0, len=fetches.length; i<len; ++i)
fetches[i]._msg.emit('data', data);
}
function emitLitMsg(key, msg) {
var fetches = requests[0].fetchers[key];
for (var i=0, len=fetches.length; i<len; ++i) {
if (!fetches[i]._msg) {
fetches[i]._msg = msg;
fetches[i].emit('message', msg);
}
}
}
function emitMsgEnd(key) {
var fetches = requests[0].fetchers[key];
for (var i=0, len=fetches.length; i<len; ++i) {
if (fetches[i]._msg._ended)
continue;
fetches[i]._msg.emit('end');
fetches[i]._msg._ended = true;
}
}
function ondata(b) { function ondata(b) {
b.p || (b.p = 0); b.p || (b.p = 0);
if (b.length === 0 || b.p >= b.length) return; if (b.length === 0 || b.p >= b.length) return;
self.debug&&self.debug('\n<== ' + inspect(b.toString('binary', b.p)) + '\n'); self.debug&&self.debug('\n<== ' + inspect(b.toString('binary', b.p)) + '\n');
var r, m, litType, i, len, msg, fetches; var r, m, litType, i, len, msg, fetches, f, lenf;
if (indata.expect > 0) { if (indata.expect > 0) {
r = read(b); r = read(b);
if (indata.streaming) { if (indata.streaming) {
requests[0].msg.emit('data', r); //requests[0].fetchers[requests[0].key].msg.emit('data', r);
emitLitData(requests[0].key, r);
if (indata.expect === 0) if (indata.expect === 0)
indata.streaming = false; indata.streaming = false;
} else { } else {
@ -248,16 +275,22 @@ ImapConnection.prototype.connect = function(loginCb) {
if (indata.expect > -1) { if (indata.expect > -1) {
if ((m = /\* (\d+) FETCH/i.exec(indata.line)) if ((m = /\* (\d+) FETCH/i.exec(indata.line))
&& /^BODY\[/i.test(litType)) { && /^BODY\[/i.test(litType)) {
if (!requests[0].msg) { /*if (!requests[0].fetchers[litType].msg) {
msg = new ImapMessage(); msg = new ImapMessage();
msg.seqno = parseInt(m[1], 10); msg.seqno = parseInt(m[1], 10);
requests[0].msg = msg;
var fetches = requests[0].fetchers[litType]; var fetches = requests[0].fetchers[litType];
for (var f = 0, lenf = fetches.length; f < lenf; ++f) fetches.msg = msg;
for (f = 0, lenf = fetches.length; f < lenf; ++f)
fetches[f].emit('message', msg); fetches[f].emit('message', msg);
} }*/
msg = new ImapMessage();
msg.seqno = parseInt(m[1], 10);
fetches = requests[0].fetchers[litType];
emitLitMsg(litType, msg);
requests[0].key = litType; requests[0].key = litType;
indata.streaming = (!RE_ISHEADER.test(litType)); indata.streaming = !RE_ISHEADER.test(litType);
if (indata.streaming) if (indata.streaming)
indata.literals.push(indata.expect); indata.literals.push(indata.expect);
} else if (indata.expect === 0) } else if (indata.expect === 0)
@ -278,61 +311,71 @@ ImapConnection.prototype.connect = function(loginCb) {
switch (m.type) { switch (m.type) {
case 'FETCH': case 'FETCH':
// m.info = message details // m.info = message details
var data, parsed, headers, f, lenf; var data, parsed, headers, f, lenf, body, lenb, msg, bodies,
msg = (requests[0] && requests[0].msg details, val;
? requests[0].msg bodies = parsers.parseFetchBodies(m.info, indata.literals);
: new ImapMessage()); details = new ImapMessage();
parsers.parseFetch(m.info, indata.literals, msg); parsers.parseFetch(m.info, indata.literals, details);
details.seqno = parseInt(m.num, 10);
if (typeof msg.body === 'number') {
// we streamed a body, e.g. {3}\r\nfoo if (requests[0].fetchers[''] !== undefined) {
delete msg.body; // account for non-body fetches
msg.emit('end'); if (bodies) {
} else { bodies.push('');
// no body was streamed bodies.push(null);
msg.seqno = parseInt(m.num, 10); } else
if (isUnsolicited) bodies = ['', null];
self.emit('msgupdate', msg); }
else {
if (typeof msg.body === 'string') { for (body = 0, lenb = bodies.length; body < lenb; body += 2) {
// a body was given as a non-literal string, e.g. "foo" fetches = requests[0].fetchers[bodies[body]];
fetches = requests[0].fetchers[requests[0].key]; val = bodies[body + 1];
if (RE_ISHEADER.test(requests[0].key)) {
var parsed, data, headers; for (var i=0, len=fetches.length; i<len; ++i) {
for (f = 0, lenf = fetches.length; f < lenf; ++f) { if (!fetches[i]._msg)
if (fetches[f]._parse) { fetches[i]._msg = new ImapMessage();
if (parsed === undefined)
parsed = parsers.parseHeaders(msg.body); // copy message properties (uid, date, flags, etc)
headers = parsed; for (var k = 0, keys = Object.keys(details), lenk = keys.length;
} else { k < lenk; ++k)
if (data === undefined) fetches[i]._msg[keys[k]] = details[keys[k]];
data = new Buffer(msg.body, 'binary');
headers = data; if (typeof val === 'number') {
} // we streamed a body, e.g. {3}\r\nfoo
delete msg.body;
msg.emit('headers', headers);
msg.emit('end');
}
} else {
var data = new Buffer(msg.body, 'binary');
delete msg.body;
for (f = 0, lenf = fetches.length; f < lenf; ++f) {
msg.emit('data', data);
msg.emit('end');
}
}
} else { } else {
// non-body fetch // no body was streamed
if ('body' in msg) if (isUnsolicited)
delete msg.body; self.emit('msgupdate', details);
fetches = requests[0].fetchers['']; else if (typeof val === 'string') {
for (f = 0, lenf = fetches.length; f < lenf; ++f) { // a body was given as a non-literal string, e.g. "foo"
fetches[f].emit('message', msg); if (RE_ISHEADER.test(bodies[body])) {
msg.emit('end'); var parsed, data, headers;
//for (f = 0, lenf = fetches.length; f < lenf; ++f) {
if (fetches[i]._parse) {
if (parsed === undefined)
parsed = parsers.parseHeaders(val);
headers = parsed;
} else {
if (data === undefined)
data = new Buffer(val, 'binary');
headers = data;
}
fetches[i]._msg.emit('headers', headers);
//}
} else {
var data = new Buffer(val, 'binary');
//for (f = 0, lenf = fetches.length; f < lenf; ++f)
fetches[i]._msg.emit('data', data);
}
} else if (val === null) {
//for (f = 0, lenf = fetches.length; f < lenf; ++f)
fetches[i].emit('message', fetches[i]._msg);
} }
} }
} }
} }
for (body = 0, lenb = bodies.length; body < lenb; body += 2)
emitMsgEnd(bodies[body]);
break; break;
case 'EXISTS': case 'EXISTS':
// mailbox total message count // mailbox total message count
@ -1015,7 +1058,7 @@ ImapConnection.prototype._fetch = function(which, uids, options, what, cb) {
toFetch += ' '; toFetch += ' ';
toFetch += key; toFetch += key;
} else } else
fetchers.push(stream); fetchers[key].push(stream);
if (typeof wp.cb === 'function') if (typeof wp.cb === 'function')
wp.cb(stream); wp.cb(stream);
key = undefined; key = undefined;

@ -74,14 +74,30 @@ exports.parseNamespaces = function(str, literals) {
return vals; return vals;
}; };
exports.parseFetchBodies = function(str, literals) {
literals.lp = 0;
var result = exports.parseExpr(str, literals),
bodies;
for (var i=0,len=result.length; i<len; i+=2) {
if (Array.isArray(result[i])) {
if (bodies === undefined)
bodies = ['BODY[' + result[i][0] + ']', result[i+1]];
else {
bodies.push('BODY[' + result[i][0] + ']');
bodies.push(result[i+1]);
}
}
}
return bodies;
};
exports.parseFetch = function(str, literals, fetchData) { exports.parseFetch = function(str, literals, fetchData) {
literals.lp = 0; literals.lp = 0;
var result = exports.parseExpr(str, literals); var result = exports.parseExpr(str, literals);
for (var i=0,len=result.length; i<len; i+=2) { for (var i=0,len=result.length; i<len; i+=2) {
if (Array.isArray(result[i])) if (Array.isArray(result[i]))
result[i] = 'BODY'; continue;
else result[i] = result[i].toUpperCase();
result[i] = result[i].toUpperCase();
if (result[i] === 'UID') if (result[i] === 'UID')
fetchData.uid = parseInt(result[i+1], 10); fetchData.uid = parseInt(result[i+1], 10);
else if (result[i] === 'INTERNALDATE') else if (result[i] === 'INTERNALDATE')

Loading…
Cancel
Save