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

@ -74,14 +74,30 @@ exports.parseNamespaces = function(str, literals) {
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) {
literals.lp = 0;
var result = exports.parseExpr(str, literals);
for (var i=0,len=result.length; i<len; i+=2) {
if (Array.isArray(result[i]))
result[i] = 'BODY';
else
result[i] = result[i].toUpperCase();
continue;
result[i] = result[i].toUpperCase();
if (result[i] === 'UID')
fetchData.uid = parseInt(result[i+1], 10);
else if (result[i] === 'INTERNALDATE')

Loading…
Cancel
Save