First go at parser and partial code rewrite

fork
Brian White 12 years ago
parent 5dc5c5ace0
commit 4c03c7519c

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
var utils = require('./imap.utilities');
exports.convStr = function(str) {
exports.convStr = function(str, literals) {
if (str[0] === '"')
return str.substring(1, str.length-1);
else if (str === 'NIL')
@ -10,67 +10,72 @@ exports.convStr = function(str) {
// can't handle natively, so we'll just keep it as a string if it's too big
var val = parseInt(str, 10);
return (val.toString() === str ? val : str);
} else
} else if (literals && literals.lp < literals.length && /^\{\d+\}$/.test(str))
return literals[literals.lp++];
else
return str;
}
exports.parseNamespaces = function(str, namespaces) {
var result = exports.parseExpr(str);
for (var grp=0; grp<3; ++grp) {
if (Array.isArray(result[grp])) {
var vals = [];
for (var i=0,len=result[grp].length; i<len; ++i) {
var val = { prefix: result[grp][i][0], delim: result[grp][i][1] };
if (result[grp][i].length > 2) {
// extension data
val.extensions = [];
for (var j=2,len2=result[grp][i].length; j<len2; j+=2) {
val.extensions.push({
name: result[grp][i][j],
flags: result[grp][i][j+1]
});
}
exports.parseNamespaces = function(str, literals) {
var result, vals;
if (str.length === 3 && str.toUpperCase() === 'NIL')
vals = null;
else {
result = exports.parseExpr(str, literals)
vals = [];
for (var i=0,len=result.length; i<len; ++i) {
var val = {
prefix: result[i][0],
delimeter: result[i][1]
};
if (result[i].length > 2) {
// extension data
val.extensions = [];
for (var j=2,len2=result[i].length; j<len2; j+=2) {
val.extensions.push({
name: result[i][j],
flags: result[i][j+1]
});
}
vals.push(val);
}
if (grp === 0)
namespaces.personal = vals;
else if (grp === 1)
namespaces.other = vals;
else if (grp === 2)
namespaces.shared = vals;
vals.push(val);
}
}
return vals;
}
exports.parseFetch = function(str, fetchData) {
var key, idxNext, result = exports.parseExpr(str);
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';
result[i] = result[i].toUpperCase();
if (result[i] === 'UID')
fetchData.id = parseInt(result[i+1], 10);
fetchData.uid = parseInt(result[i+1], 10);
else if (result[i] === 'INTERNALDATE')
fetchData.date = result[i+1];
else if (result[i] === 'FLAGS')
fetchData.flags = result[i+1].filter(utils.isNotEmpty);
else if (result[i] === 'BODYSTRUCTURE')
fetchData.structure = exports.parseBodyStructure(result[i+1]);
fetchData.structure = exports.parseBodyStructure(result[i+1], literals);
else if (typeof result[i] === 'string') // simple extensions
fetchData[result[i].toLowerCase()] = result[i+1];
}
}
exports.parseBodyStructure = function(cur, prefix, partID) {
exports.parseBodyStructure = function(cur, literals, prefix, partID) {
var ret = [];
if (prefix === undefined) {
var result = (Array.isArray(cur) ? cur : exports.parseExpr(cur));
var result = (Array.isArray(cur) ? cur : exports.parseExpr(cur, literals));
if (result.length)
ret = exports.parseBodyStructure(result, '', 1);
ret = exports.parseBodyStructure(result, literals, '', 1);
} else {
var part, partLen = cur.length, next;
if (Array.isArray(cur[0])) { // multipart
next = -1;
while (Array.isArray(cur[++next])) {
ret.push(exports.parseBodyStructure(cur[next], prefix
ret.push(exports.parseBodyStructure(cur[next], literals, prefix
+ (prefix !== '' ? '.' : '')
+ (partID++).toString(), 1));
}
@ -174,7 +179,7 @@ exports.parseBodyStructure = function(cur, prefix, partID) {
// body
if (partLen > next && Array.isArray(cur[next])) {
part.body = exports.parseBodyStructure(cur[next], prefix
part.body = exports.parseBodyStructure(cur[next], literals, prefix
+ (prefix !== '' ? '.' : '')
+ (partID++).toString(), 1);
} else
@ -239,15 +244,19 @@ exports.parseStructExtra = function(part, partLen, cur, next) {
}
}
exports.parseExpr = function(o, result, start) {
function isAlpha(ch) {
if (typeof ch === 'string')
ch = ch.charCodeAt(0);
return ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122));
}
exports.parseExpr = function(o, literals, result, start) {
start = start || 0;
var inQuote = false, lastPos = start - 1, isTop = false;
if (!result)
result = new Array();
result = [];
if (typeof o === 'string') {
var state = new Object();
state.str = o;
o = state;
o = { str: o };
isTop = true;
}
for (var i=start,len=o.str.length; i<len; ++i) {
@ -256,13 +265,14 @@ exports.parseExpr = function(o, result, start) {
inQuote = true;
else if (o.str[i] === ' ' || o.str[i] === ')' || o.str[i] === ']') {
if (i - (lastPos+1) > 0)
result.push(exports.convStr(o.str.substring(lastPos+1, i)));
if (o.str[i] === ')' || o.str[i] === ']')
result.push(exports.convStr(o.str.substring(lastPos+1, i), literals));
if ((o.str[i] === ')' || o.str[i] === ']') && !isTop)
return i;
lastPos = i;
} else if (o.str[i] === '(' || o.str[i] === '[') {
} else if ((o.str[i] === '(' || o.str[i] === '[')
/*&& (i === 0 || !isAlpha(o.str.charCodeAt(i-1)))*/) {
var innerResult = [];
i = exports.parseExpr(o, innerResult, i+1);
i = exports.parseExpr(o, literals, innerResult, i+1);
lastPos = i;
result.push(innerResult);
}
@ -271,7 +281,7 @@ exports.parseExpr = function(o, result, start) {
(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)));
result.push(exports.convStr(o.str.substring(lastPos+1), literals));
}
return (isTop ? result : start);
}

@ -125,93 +125,6 @@ exports.extend = function() {
return target;
};
exports.bufferAppend = function(buf1, buf2) {
var newBuf = new Buffer(buf1.length + buf2.length);
buf1.copy(newBuf, 0, 0);
if (Buffer.isBuffer(buf2))
buf2.copy(newBuf, buf1.length, 0);
else if (Array.isArray(buf2)) {
for (var i=buf1.length, len=buf2.length; i<len; i++)
newBuf[i] = buf2[i];
}
return newBuf;
};
exports.bufferSplit = function(buf, str) {
if ((typeof str !== 'string' && !Array.isArray(str))
|| str.length === 0 || str.length > buf.length)
return [buf];
var search = !Array.isArray(str)
? str.split('').map(function(el) { return el.charCodeAt(0); })
: str,
searchLen = search.length,
ret = [], pos, start = 0;
while ((pos = exports.bufferIndexOf(buf, search, start)) > -1) {
ret.push(buf.slice(start, pos));
start = pos + searchLen;
}
if (!ret.length)
ret = [buf];
else if (start < buf.length)
ret.push(buf.slice(start));
return ret;
};
exports.bufferIndexOf = function(buf, str, start) {
if (str.length > buf.length)
return -1;
var search = !Array.isArray(str)
? str.split('').map(function(el) { return el.charCodeAt(0); })
: str,
searchLen = search.length,
ret = -1, i, j, len;
for (i=start||0,len=buf.length; i<len; ++i) {
if (buf[i] === search[0] && (len-i) >= searchLen) {
if (searchLen > 1) {
for (j=1; j<searchLen; ++j) {
if (buf[i+j] !== search[j])
break;
else if (j === searchLen - 1) {
ret = i;
break;
}
}
} else
ret = i;
if (ret > -1)
break;
}
}
return ret;
};
exports.explode = function(str, delimiter, limit) {
if (arguments.length < 2 || arguments[0] === undefined
|| arguments[1] === undefined
|| !delimiter || delimiter === '' || typeof delimiter === 'function'
|| typeof delimiter === 'object')
return false;
delimiter = (delimiter === true ? '1' : delimiter.toString());
if (!limit || limit === 0)
return str.split(delimiter);
else if (limit < 0)
return false;
else if (limit > 0) {
var splitted = str.split(delimiter);
var partA = splitted.splice(0, limit - 1);
var partB = splitted.join(delimiter);
partA.push(partB);
return partA;
}
return false;
}
exports.isNotEmpty = function(str) {
return str.trim().length > 0;
}
@ -399,4 +312,55 @@ exports.validateUIDList = function(uids) {
} else if (typeof uids[i] !== 'number')
uids[i] = intval;
}
}
}
var CHARR_CRLF = [13, 10];
function line(b) {
var len = b.length, p = b.p, start = p, ret = false, retest = false;
while (p < len && !ret) {
if (b[p] === CHARR_CRLF[line.p]) {
if (++line.p === 2)
ret = true;
} else {
retest = (line.p > 0);
line.p = 0;
if (retest)
continue;
}
++p;
}
if (ret === false) {
if (line.ret)
line.ret += b.toString('ascii', start);
else
line.ret = b.toString('ascii', start);
} else {
var iCR = p - 2;
if (iCR < 0) {
// the CR is at the end of line.ret
if (line.ret && line.ret.length > 1)
ret = line.ret.substr(0, line.ret.length - 1);
else
ret = '';
} else {
// the entire CRLF is in b
if (iCR === 0)
ret = (line.ret ? line.ret : '');
else {
if (line.ret) {
ret = line.ret;
ret += b.toString('ascii', start, iCR);
} else
ret = b.toString('ascii', start, iCR);
}
}
line.p = 0;
line.ret = undefined;
}
b.p = p;
return ret;
}
line.p = 0;
line.ret = undefined;
exports.line = line;

Loading…
Cancel
Save