Merge branch 'upstream' into fix-empty-boxname

Conflicts:
	lib/imap.js
fork
Chotiwat Chawannakul 11 years ago
commit 73c7d4cea9

@ -22,19 +22,26 @@ var CRLF = '\r\n',
BOXSELECTING: 3,
BOXSELECTED: 4
},
RE_LITHEADER = /(?:((?:BODY\[.*\](?:<\d+>)?)?|[^ ]+) )?\{(\d+)\}$/i,
RE_UNRESP = /^\* (OK|PREAUTH|NO|BAD) (?:\[(.+)\] )?(.+)$/i,
RE_LITHEADER = /(?:((?:BODY\[.*\](?:<\d+>)?)?|[^ ]+) )?\{(\d+)\}(?:$|\r\n)/i,
RE_UNRESP = /^\* (OK|PREAUTH|NO|BAD)(?:\r\n|(?: \[(.+?)\])?(?: (.+))?)(?:$|\r\n)/i,
RE_TAGGED_RESP = /^A\d+ (OK|NO|BAD) (?:\[(.+?)\] )?(.+)(?:$|\r\n)/i,
RE_TEXT_CODE = /([^ ]+)(?: (.*))?$/,
RE_RES_IDLE = /^IDLE /i,
RE_RES_NOOP = /^NOOP /i,
RE_CMD_FETCH = /^(?:UID )?FETCH/i,
RE_PARTID = /^(?:[\d]+[\.]{0,1})*[\d]+$/,
RE_ESCAPE = /\\\\/g,
//RE_ISPARTIAL = /<(\d+)>$/,
RE_DBLQ = /"/g,
RE_CMD = /^([^ ]+)(?: |$)/,
RE_ISHEADER = /HEADER/,
REX_UNRESPDATA = XRegExp('^\\* (?:(?:(?<type>NAMESPACE) (?<personal>(?:NIL|\\((?:\\(.+\\))+\\))) (?<other>(?:NIL|\\((?:\\(.+\\))+\\))) (?<shared>(?:NIL|\\((?:\\(.+\\))+\\))))|(?:(?<type>FLAGS) \\((?<flags>.*)\\))|(?:(?<type>LIST|LSUB|XLIST) \\((?<flags>.*)\\) (?<delimiter>"[^"]+"|NIL) (?<mailbox>.+))|(?:(?<type>(SEARCH|SORT))(?: (?<results>.*))?)|(?:(?<type>STATUS) (?<mailbox>.+) \\((?<attributes>.*)\\))|(?:(?<type>CAPABILITY) (?<capabilities>.+))|(?:(?<type>BYE) (?:\\[(?<code>.+)\\] )?(?<message>.+)))[ \t]*(?:\r\n|$)', 'i'),
REX_UNRESPNUM = XRegExp('^\\* (?<num>\\d+) (?:(?<type>EXISTS)|(?<type>RECENT)|(?<type>EXPUNGE)|(?:(?<type>FETCH) \\((?<info>.*)\\)))[ \t]*(?:\r\n|$)', 'i');
REX_UNRESPDATA = XRegExp('^\\* (?:(?:(?<type>NAMESPACE) (?<personal>(?:NIL|\\((?:\\(.+\\))+\\))) (?<other>(?:NIL|\\((?:\\(.+\\))+\\))) (?<shared>(?:NIL|\\((?:\\(.+\\))+\\))))|(?:(?<type>FLAGS) \\((?<flags>.*)\\))|(?:(?<type>LIST|LSUB|XLIST) \\((?<flags>.*)\\) (?<delimiter>"[^"]+"|NIL) (?<mailbox>.+))|(?:(?<type>(SEARCH|SORT))(?: (?<results>.*))?)|(?:(?<type>STATUS) (?<mailbox>.+) \\((?<attributes>.*)\\))|(?:(?<type>CAPABILITY) (?<capabilities>.+))|(?:(?<type>BYE) (?:\\[(?<code>.+)\\] )?(?<message>.+)))[ \t]*(?:$|\r\n)', 'i'),
REX_UNRESPNUM = XRegExp('^\\* (?<num>\\d+) (?:(?<type>EXISTS)|(?<type>RECENT)|(?<type>EXPUNGE)|(?:(?<type>FETCH) \\((?<info>.*)\\)))[ \t]*(?:$|\r\n)', 'i');
// extension constants
var IDLE_NONE = 1,
IDLE_WAIT = 2,
IDLE_READY = 3,
IDLE_IDLING = 3,
IDLE_DONE = 4;
function ImapConnection(options) {
@ -47,7 +54,9 @@ function ImapConnection(options) {
password: options.password || '',
host: options.host || 'localhost',
port: options.port || 143,
secure: options.secure || false,
secure: options.secure === true ? { // secure = true means default behavior
rejectUnauthorized: false // Force pre-node-0.9.2 behavior
} : (options.secure || false),
connTimeout: options.connTimeout || 10000, // connection timeout in msecs
xoauth: options.xoauth,
xoauth2: options.xoauth2
@ -87,9 +96,8 @@ function ImapConnection(options) {
ext: {
// Capability-specific state info
idle: {
MAX_WAIT: 1740000, // 29 mins in ms
MAX_WAIT: 300000, // 5 mins in ms
state: IDLE_NONE,
reIDLE: false,
timeStarted: undefined
}
}
@ -124,10 +132,14 @@ ImapConnection.prototype.connect = function(loginCb) {
socket.setTimeout(0);
if (this._options.secure) {
var tlsOptions = {};
for (var k in this._options.secure)
tlsOptions[k] = this._options.secure[k];
tlsOptions.socket = state.conn;
if (process.version.indexOf('v0.6.') > -1)
socket = tls.connect(null, { socket: state.conn }, onconnect);
socket = tls.connect(null, tlsOptions, onconnect);
else
socket = tls.connect({ socket: state.conn }, onconnect);
socket = tls.connect(tlsOptions, onconnect);
} else
state.conn.once('connect', onconnect);
@ -156,7 +168,7 @@ ImapConnection.prototype.connect = function(loginCb) {
self.emit('close', had_error);
});
state.conn.on('error', function(err) {
socket.on('error', function(err) {
clearTimeout(state.tmrConn);
err.level = 'socket';
if (state.status === STATES.NOCONNECT)
@ -174,7 +186,7 @@ ImapConnection.prototype.connect = function(loginCb) {
return loginCb(err);
}
// Next, get the list of available namespaces if supported (RFC2342)
if (!checkedNS && self._serverSupports('NAMESPACE')) {
if (!checkedNS && self.serverSupports('NAMESPACE')) {
// Re-enter this function after we've obtained the available
// namespaces
checkedNS = true;
@ -299,9 +311,9 @@ ImapConnection.prototype.connect = function(loginCb) {
}
if (indata.line[0] === '*') { // Untagged server response
var isUnsolicited =
(requests[0] && requests[0].cmd === 'NOOP')
|| (state.isIdle && state.ext.idle.state === IDLE_READY);
var isUnsolicited = (requests[0] && requests[0].cmd === 'NOOP')
|| (state.isIdle && state.ext.idle.state !== IDLE_NONE)
|| !requests.length;
if (m = XRegExp.exec(indata.line, REX_UNRESPNUM)) {
// m.type = response type (numeric-based)
m.type = m.type.toUpperCase();
@ -311,12 +323,24 @@ ImapConnection.prototype.connect = function(loginCb) {
// m.info = message details
var data, parsed, headers, f, lenf, body, lenb, msg, bodies,
details, val;
isUnsolicited = isUnsolicited
|| (requests[0]
&& !RE_CMD_FETCH.test(requests[0].cmdstr));
if (!isUnsolicited)
bodies = parsers.parseFetchBodies(m.info, indata.literals);
details = new ImapMessage();
parsers.parseFetch(m.info, indata.literals, details);
details.seqno = parseInt(m.num, 10);
if (typeof details['x-gm-labels'] !== undefined) {
var labels = details['x-gm-labels'];
for (var i=0, len=labels.length; i<len; ++i)
labels[i] = labels[i].replace(RE_ESCAPE, '\\');
}
if (isUnsolicited)
self.emit('msgupdate', details);
else {
@ -531,23 +555,31 @@ ImapConnection.prototype.connect = function(loginCb) {
self.debug&&self.debug('[parsing incoming] saw untagged ' + m[1]);
switch (m[1]) {
case 'OK':
var code = m[2];
if (m[2] === undefined && m[3] === undefined)
break;
var code, codeval;
if (m[2]) {
code = RE_TEXT_CODE.exec(m[2]);
codeval = code[2];
code = code[1].toUpperCase();
}
if (state.status === STATES.NOAUTH) {
if (!state.isReady) {
clearTimeout(state.tmrConn);
state.isReady = true;
state.conn.emit('ready');
}
} else if (/^ALERT$/i.test(code))
} else if (code === 'ALERT')
self.emit('alert', m[3]);
else if (state.status === STATES.BOXSELECTING) {
if (m = /^UIDVALIDITY (\d+)/i.exec(code))
state.box.uidvalidity = parseInt(m[1], 10);
else if (m = /^UIDNEXT (\d+)/i.exec(code))
state.box.uidnext = parseInt(m[1], 10);
else if (m = /^PERMANENTFLAGS \((.*)\)/i.exec(code)) {
if (code === 'UIDVALIDITY')
state.box.uidvalidity = parseInt(codeval, 10);
else if (code === 'UIDNEXT')
state.box.uidnext = parseInt(codeval, 10);
else if (code === 'PERMANENTFLAGS') {
var idx, permFlags, keywords;
state.box.permFlags = permFlags = m[1].split(' ');
codeval = codeval.substr(1, codeval.length - 2);
state.box.permFlags = permFlags = codeval.split(' ');
if ((idx = state.box.permFlags.indexOf('\\*')) > -1) {
state.box.newKeywords = true;
permFlags.splice(idx, 1);
@ -562,8 +594,8 @@ ImapConnection.prototype.connect = function(loginCb) {
});
}
} else if (state.status === STATES.BOXSELECTED) {
if (m = /^UIDVALIDITY (\d+)/i.exec(code)) {
state.box.uidvalidity = parseInt(m[1], 10);
if (code === 'UIDVALIDITY') {
state.box.uidvalidity = parseInt(codeval, 10);
self.emit('uidvalidity', state.box.uidvalidity);
}
}
@ -608,18 +640,21 @@ ImapConnection.prototype.connect = function(loginCb) {
indata.temp = undefined;
indata.streaming = false;
indata.expect = -1;
self.debug&&self.debug(line[0] === 'A'
? '[parsing incoming] saw tagged response'
: '[parsing incoming] saw continuation response');
clearTimeout(state.tmrKeepalive);
if (line[0] === '+' && state.ext.idle.state === IDLE_WAIT) {
state.ext.idle.state = IDLE_READY;
state.ext.idle.state = IDLE_IDLING;
state.ext.idle.timeStarted = Date.now();
doKeepaliveTimer();
return process.nextTick(function() { self._send(); });
}
var sendBox = false;
clearTimeout(state.tmrKeepalive);
if (state.status === STATES.BOXSELECTING) {
if (/^A\d+ OK/i.test(line)) {
sendBox = true;
@ -630,7 +665,6 @@ ImapConnection.prototype.connect = function(loginCb) {
self._resetBox();
}
}
if (requests[0].cmd === 'RENAME') {
if (state.box._newName) {
state.box.name = state.box._newName;
@ -640,18 +674,24 @@ ImapConnection.prototype.connect = function(loginCb) {
}
if (typeof requests[0].callback === 'function') {
m = RE_TAGGED_RESP.exec(line);
var err = null;
var args = requests[0].cbargs,
cmdstr = requests[0].cmdstr;
if (line[0] === '+') {
if (requests[0].cmd !== 'APPEND') {
err = new Error('Unexpected continuation');
if (!m) {
if (requests[0].cmd === 'APPEND')
return requests[0].callback();
else {
var isXOAuth2 = (cmdstr.indexOf('AUTHENTICATE XOAUTH2') === 0),
msg = (isXOAuth2
? new Buffer(line.substr(2), 'base64').toString('utf8')
: 'Unexpected continuation');
err = new Error(msg);
err.level = 'protocol';
err.type = 'continuation';
err.type = (isXOAuth2 ? 'failure' : 'continuation');
err.request = cmdstr;
} else
return requests[0].callback();
} else if (m = /^A\d+ (NO|BAD) (?:\[(.+?)\] )?(.+)$/i.exec(line)) {
}
} else if (m[1] !== 'OK') {
// m[1]: error type
// m[2]: resp-text-code
// m[3]: message
@ -672,45 +712,50 @@ ImapConnection.prototype.connect = function(loginCb) {
) && args.length === 0)
args.unshift([]);
}
if (m) {
var msg = m[3], info;
if (m[2]) {
m = RE_TEXT_CODE.exec(m[2]);
info = {
code: m[1].toUpperCase(),
codeval: m[2],
message: msg
};
} else
info = { message: msg };
args.push(info);
}
args.unshift(err);
requests[0].callback.apply(self, args);
}
var recentCmd = requests[0].cmdstr;
var recentCmd = requests[0].cmd;
requests.shift();
if (requests.length === 0 && recentCmd !== 'LOGOUT') {
if (state.status >= STATES.AUTH && self._serverSupports('IDLE')) {
// According to RFC 2177, we should re-IDLE at least every 29
// minutes to avoid disconnection by the server
self._send('IDLE', undefined, true);
}
state.tmrKeepalive = setTimeout(function idleHandler() {
if (state.isIdle) {
if (state.ext.idle.state === IDLE_READY) {
state.tmrKeepalive = setTimeout(idleHandler, state.tmoKeepalive);
var timeDiff = Date.now() - state.ext.idle.timeStarted;
if (timeDiff >= state.ext.idle.MAX_WAIT)
self._send('IDLE', undefined, true); // restart IDLE
} else if (!self._serverSupports('IDLE'))
self._noop();
}
}, state.tmoKeepalive);
} else
if (!requests.length && recentCmd !== 'LOGOUT')
doKeepalive();
else
process.nextTick(function() { self._send(); });
state.isIdle = true;
} else if (/^IDLE /i.test(indata.line)) {
} else if (RE_RES_IDLE.test(indata.line)) {
self.debug&&self.debug('[parsing incoming] saw IDLE');
if (requests.length)
process.nextTick(function() { self._send(); });
state.isIdle = false;
state.ext.idle.state = IDLE_NONE;
state.ext.idle.timeStated = undefined;
requests.shift(); // remove IDLE request
indata.line = undefined;
if (state.ext.idle.reIDLE) {
state.ext.idle.reIDLE = false;
self._send('IDLE', undefined, true);
}
state.ext.idle.state = IDLE_NONE;
state.ext.idle.timeStarted = undefined;
if (requests.length) {
state.isIdle = false;
self._send();
} else
doKeepalive();
} else if (RE_RES_NOOP.test(indata.line)) {
self.debug&&self.debug('[parsing incoming] saw NOOP');
requests.shift(); // remove NOOP request
if (!requests.length)
doKeepaliveTimer();
else
self._send();
} else {
// unknown response
self.debug&&self.debug('[parsing incoming] saw unexpected response: '
@ -719,6 +764,31 @@ ImapConnection.prototype.connect = function(loginCb) {
}
}
function doKeepalive() {
if (state.status >= STATES.AUTH) {
if (self.serverSupports('IDLE'))
self._send('IDLE');
else
self._noop();
}
}
function doKeepaliveTimer() {
state.tmrKeepalive = setTimeout(function idleHandler() {
if (state.isIdle) {
if (state.ext.idle.state === IDLE_IDLING) {
var timeDiff = Date.now() - state.ext.idle.timeStarted;
if (timeDiff >= state.ext.idle.MAX_WAIT) {
state.ext.idle.state = IDLE_DONE;
self._send('DONE');
} else
state.tmrKeepalive = setTimeout(idleHandler, state.tmoKeepalive);
} else if (!self.serverSupports('IDLE'))
doKeepalive();
}
}, state.tmoKeepalive);
}
state.conn.connect(this._options.port, this._options.host);
state.tmrConn = setTimeout(function() {
@ -796,7 +866,7 @@ ImapConnection.prototype.getBoxes = function(namespace, cb) {
cb = namespace;
namespace = '';
}
this._send((!this._serverSupports('XLIST') ? 'LIST' : 'XLIST')
this._send((!this.serverSupports('XLIST') ? 'LIST' : 'XLIST')
+ ' "' + utils.escape(utf7.encode(''+namespace)) + '" "*"', cb);
};
@ -837,7 +907,8 @@ ImapConnection.prototype.append = function(data, options, cb) {
if (options.flags) {
if (!Array.isArray(options.flags))
options.flags = [options.flags];
cmd += " (\\" + options.flags.join(' \\') + ")";
if (options.flags.length > 0)
cmd += " (\\" + options.flags.join(' \\') + ")";
}
if (options.date) {
if (!isDate(options.date))
@ -863,9 +934,9 @@ ImapConnection.prototype.append = function(data, options, cb) {
cmd += (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data));
cmd += '}';
var self = this, step = 1;
this._send(cmd, function(err) {
this._send(cmd, function(err, info) {
if (err || step++ === 2)
return cb(err);
return cb(err, info);
self._state.conn.write(data);
self._state.conn.write(CRLF);
self.debug&&self.debug('\n==> ' + inspect(data.toString()) + '\n');
@ -896,7 +967,7 @@ ImapConnection.prototype._sort = function(which, sorts, options, cb) {
throw new Error('Expected array with at least one sort criteria');
if (!Array.isArray(options))
throw new Error('Expected array for search options');
if (!this._serverSupports('SORT'))
if (!this.serverSupports('SORT'))
return cb(new Error('Sorting is not supported on the server'));
var criteria = sorts.map(function(criterion) {
@ -991,9 +1062,9 @@ ImapConnection.prototype._fetch = function(which, uids, options, what, cb) {
for (var i = 0, wp, pprefix, len = what.length; i < len; ++i) {
wp = what[i];
parse = true;
if (wp.id !== undefined && !/^(?:[\d]+[\.]{0,1})*[\d]+$/.test(''+wp.id))
if (wp.id !== undefined && !RE_PARTID.test(''+wp.id))
throw new Error('Invalid part id: ' + wp.id);
if (( (wp.headers
if (( (typeof wp.headers === 'object'
&& (!wp.headers.fields
|| (Array.isArray(wp.headers.fields)
&& wp.headers.fields.length === 0)
@ -1001,7 +1072,7 @@ ImapConnection.prototype._fetch = function(which, uids, options, what, cb) {
&& wp.headers.parse === false
)
||
(wp.headersNot
(typeof wp.headersNot === 'object'
&& (!wp.headersNot.fields
|| (Array.isArray(wp.headersNot.fields)
&& wp.headersNot.fields.length === 0)
@ -1155,7 +1226,7 @@ ImapConnection.prototype._fetch = function(which, uids, options, what, cb) {
}
// always fetch GMail-specific bits of information when on GMail
if (this._serverSupports('X-GM-EXT-1'))
if (this.serverSupports('X-GM-EXT-1'))
extensions = 'X-GM-THRID X-GM-MSGID X-GM-LABELS ';
var cmd = which;
@ -1233,7 +1304,7 @@ ImapConnection.prototype.delLabels = function(uids, labels, cb) {
};
ImapConnection.prototype._storeLabels = function(which, uids, labels, mode, cb) {
if (!this._serverSupports('X-GM-EXT-1'))
if (!this.serverSupports('X-GM-EXT-1'))
throw new Error('Server must support X-GM-EXT-1 capability');
if (this._state.status !== STATES.BOXSELECTED)
throw new Error('No mailbox is currently selected');
@ -1284,46 +1355,47 @@ ImapConnection.prototype._move = function(which, uids, boxTo, cb) {
throw new Error('Cannot move message: '
+ 'server does not allow deletion of messages');
} else {
this._copy(which, uids, boxTo, function ccb(err, reentryCount, deletedUIDs,
counter) {
if (err)
return cb(err);
counter = counter || 0;
// Make sure we don't expunge any messages marked as Deleted except the
// one we are moving
if (reentryCount === undefined) {
self.search(['DELETED'], function(e, result) {
ccb(e, 1, result);
});
} else if (reentryCount === 1) {
if (counter < deletedUIDs.length) {
self.delFlags(deletedUIDs[counter], 'Deleted', function(e) {
process.nextTick(function() {
ccb(e, reentryCount, deletedUIDs, counter + 1);
});
this._copy(which, uids, boxTo,
function ccb(err, info, reentryCount, deletedUIDs, counter) {
if (err)
return cb(err, info);
counter = counter || 0;
// Make sure we don't expunge any messages marked as Deleted except the
// one we are moving
if (reentryCount === undefined) {
self.search(['DELETED'], function(e, result) {
ccb(e, info, 1, result);
});
} else
ccb(err, reentryCount + 1, deletedUIDs);
} else if (reentryCount === 2) {
self.addFlags(uids, 'Deleted', function(e) {
ccb(e, reentryCount + 1, deletedUIDs);
});
} else if (reentryCount === 3) {
self.removeDeleted(function(e) {
ccb(e, reentryCount + 1, deletedUIDs);
});
} else if (reentryCount === 4) {
if (counter < deletedUIDs.length) {
self.addFlags(deletedUIDs[counter], 'Deleted', function(e) {
process.nextTick(function() {
ccb(e, reentryCount, deletedUIDs, counter + 1);
} else if (reentryCount === 1) {
if (counter < deletedUIDs.length) {
self.delFlags(deletedUIDs[counter], 'Deleted', function(e) {
process.nextTick(function() {
ccb(e, info, reentryCount, deletedUIDs, counter + 1);
});
});
} else
ccb(err, info, reentryCount + 1, deletedUIDs);
} else if (reentryCount === 2) {
self.addFlags(uids, 'Deleted', function(e) {
ccb(e, info, reentryCount + 1, deletedUIDs);
});
} else
cb();
} else if (reentryCount === 3) {
self.removeDeleted(function(e) {
ccb(e, info, reentryCount + 1, deletedUIDs);
});
} else if (reentryCount === 4) {
if (counter < deletedUIDs.length) {
self.addFlags(deletedUIDs[counter], 'Deleted', function(e) {
process.nextTick(function() {
ccb(e, info, reentryCount, deletedUIDs, counter + 1);
});
});
} else
cb(err, info);
}
}
});
);
}
};
@ -1372,7 +1444,7 @@ ImapConnection.prototype.__defineGetter__('seq', function() {
// Private/Internal Functions
ImapConnection.prototype._serverSupports = function(capability) {
ImapConnection.prototype.serverSupports = function(capability) {
return (this.capabilities.indexOf(capability) > -1);
};
@ -1435,13 +1507,13 @@ ImapConnection.prototype._login = function(cb) {
};
if (this._state.status === STATES.NOAUTH) {
if (this._serverSupports('LOGINDISABLED'))
if (this.serverSupports('LOGINDISABLED'))
return cb(new Error('Logging in is disabled on this server'));
if (this._serverSupports('AUTH=XOAUTH') && this._options.xoauth) {
if (this.serverSupports('AUTH=XOAUTH') && this._options.xoauth) {
this._send('AUTHENTICATE XOAUTH ' + utils.escape(this._options.xoauth),
fnReturn);
} else if (this._serverSupports('AUTH=XOAUTH2') && this._options.xoauth2) {
} else if (this.serverSupports('AUTH=XOAUTH2') && this._options.xoauth2) {
this._send('AUTHENTICATE XOAUTH2 ' + utils.escape(this._options.xoauth2),
fnReturn);
} else if (this._options.username && this._options.password) {
@ -1467,7 +1539,6 @@ ImapConnection.prototype._reset = function() {
this._state.tmrConn = null;
this._state.ext.idle.state = IDLE_NONE;
this._state.ext.idle.timeStarted = undefined;
this._state.ext.idle.reIDLE = false;
this._state.indata.literals = [];
this._state.indata.line = undefined;
@ -1503,47 +1574,59 @@ ImapConnection.prototype._noop = function() {
this._send('NOOP');
};
ImapConnection.prototype._send = function(cmdstr, cb, bypass) {
ImapConnection.prototype._send = function(cmdstr, cb) {
if (!this._state.conn.writable)
return;
if (cmdstr !== undefined && !bypass) {
this._state.requests.push({
var reqs = this._state.requests, idle = this._state.ext.idle;
if (cmdstr !== undefined) {
var info = {
cmd: cmdstr.match(RE_CMD)[1],
cmdstr: cmdstr,
callback: cb,
cbargs: []
});
};
if (cmdstr === 'IDLE' || cmdstr === 'DONE' || cmdstr === 'NOOP')
reqs.unshift(info);
else
reqs.push(info);
}
if (this._state.ext.idle.state === IDLE_WAIT
|| (this._state.ext.idle.state === IDLE_DONE && cmdstr !== 'DONE'))
if (idle.state !== IDLE_NONE && cmdstr !== 'DONE') {
if ((cmdstr !== undefined || reqs.length > 1)
&& idle.state === IDLE_IDLING) {
idle.state = IDLE_DONE;
this._send('DONE');
}
return;
if ((cmdstr === undefined && this._state.requests.length)
|| this._state.requests.length === 1 || bypass) {
var prefix = '',
cmd = (bypass ? cmdstr : this._state.requests[0].cmdstr);
}
if ((cmdstr === undefined && reqs.length) || reqs.length === 1
|| cmdstr === 'DONE') {
var prefix = '', curReq = reqs[0];
cmdstr = curReq.cmdstr;
clearTimeout(this._state.tmrKeepalive);
if (this._state.ext.idle.state === IDLE_READY && cmd !== 'DONE') {
this._state.ext.idle.state = IDLE_DONE;
if (cmd === 'IDLE')
this._state.ext.idle.reIDLE = true;
return this._send('DONE', undefined, true);
} else if (cmd === 'IDLE') {
// we use a different prefix to differentiate and disregard the tagged
// response the server will send us when we issue DONE
if (cmdstr === 'IDLE') {
// we use a different prefix to differentiate and disregard the tagged
// response the server will send us when we issue DONE
prefix = 'IDLE ';
this._state.ext.idle.state = IDLE_WAIT;
}
if (cmd !== 'IDLE' && cmd !== 'DONE')
} else if (cmdstr === 'NOOP')
prefix = 'NOOP ';
else if (cmdstr !== 'DONE')
prefix = 'A' + (++this._state.curId) + ' ';
this._state.conn.write(prefix);
this._state.conn.write(cmd);
this._state.conn.write(CRLF);
this.debug&&this.debug('\n==> ' + prefix + cmd + '\n');
if (this._state.requests[0]
&& (this._state.requests[0].cmd === 'EXAMINE'
|| this._state.requests[0].cmd === 'SELECT'))
this._state.conn.write(prefix + cmdstr + CRLF);
this.debug&&this.debug('\n==> ' + prefix + cmdstr + '\n');
if (curReq.cmd === 'EXAMINE' || curReq.cmd === 'SELECT')
this._state.status = STATES.BOXSELECTING;
else if (cmdstr === 'DONE')
reqs.shift();
}
};

Loading…
Cancel
Save