|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|