diff --git a/exec/imapservice.js b/exec/imapservice.js index ec4eff36ea7fd85dedfd98e1bc6766cf4fba8c90..36bcfc7ca8313c4460ab5ec2d47891d7e8b6da73 100644 --- a/exec/imapservice.js +++ b/exec/imapservice.js @@ -11,12 +11,112 @@ load("sbbsdefs.js"); load("822header.js"); load("mime.js"); -const RFC822HEADER = 0xb0; // from smbdefs.h var sepchar="|"; var debug=true; var debugRX=true; + +/*****************************/ +/* Message header extensions */ +/*****************************/ + +MsgBase.HeaderPrototype.get_from=function (force) +{ + if(force===true) + delete this.from_header; + + if(this.from_header==undefined) { + if(!this.from_net_type || this.from_net_addr.length==0) /* local message */ + this.from_header = this.from + " <" + this.from.replace(/ /g,".").toLowerCase() + "@" + system.inetaddr + ">"; + else if(!this.from_net_addr.length) + this.from_header = this.from; + else if(this.from_net_addr.indexOf('@')!=-1) + this.from_header = this.from+" <"+this.from_net_addr+">"; + else + this.from_header = this.from+" <"+this.from.replace(/ /g,".").toLowerCase()+"@"+this.from_net_addr+">"; + } + return(this.from_header); +} + +MsgBase.HeaderPrototype.parse_headers=function(force) +{ + if(force===true) + delete this.parsed_headers; + + if(this.parsed_headers==undefined) + this.parsed_headers=parse_headers(this.get_rfc822_header(force)) + return(this.parsed_headers); +} + +MsgBase.HeaderPrototype.get_envelope=function (force) +{ + function parse_header(header, is_addresses) { + if(header==undefined || header.length==0) + return("NIL"); + + header=header.pop().replace(new RegExp("^"+abnf.field_name+abnf.WSP+"*:","i"),""); + header=strip_CFWS(header); + + /* : Use mime.js ABNF to parse this correctly */ + if(is_addresses) { + if((m2=header.match(/^\s*(.*)\s+<([^@]*)@(.*)>\s*$/))!=null) { + m2[1]=m2[1].replace(/^"(.*)"$/, "$1"); + return '(('+[encode_string(m2[1]), "NIL", encode_string(m2[2]), encode_string(m2[3])].join(" ")+'))'; + } + else if((m2=header.match(/^\s*(.*)\s+<([^@]*)>\s*$/))!=null) { + m2[1]=m2[1].replace(/^"(.*)"$/, "$1"); + return '(('+[encode_string(m2[1]), "NIL", encode_string(m2[2]), "NIL"].join(" ")+'))'; + } + else if((m2=header.match(/^\s*<([^@]*)@(.*)>\s*$/))!=null) { + return '(('+["NIL", "NIL", encode_string(m2[1]), encode_string(m2[2])].join(" ")+'))'; + } + else if((m2=header.match(/^\s*([^@]*)@(.*)\s*$/))!=null) { + return '(('+["NIL", "NIL", encode_string(m2[1]), encode_string(m2[2])].join(" ")+'))'; + } + else + return '(('+[encode_string(header), "NIL", "NIL", "NIL"].join(" ")+'))'; + } + else + return(encode_string(header)); + } + + var hdrs; + + if(this.envelope==undefined) { + hdrs=this.parse_headers(); + envelope=[]; + envelope.push(parse_header(hdrs.date, false)); + envelope.push(parse_header(hdrs.subject, false)); + envelope.push(parse_header(hdrs.from, true)); + envelope.push(parse_header(hdrs.sender, true)); + envelope.push(parse_header(hdrs['reply-to'], true)); + envelope.push(parse_header(hdrs.to, true)); + envelope.push(parse_header(hdrs.cc, true)); + envelope.push(parse_header(hdrs.bcc, true)); + envelope.push(parse_header(hdrs['in-reply-to'], false)); + envelope.push(parse_header(hdrs['message-id'], false)); + } + return(envelope); +} + + +/***********************/ +/* Debugging Functions */ +/***********************/ + +function dump_obj(obj, name) +{ + var i; + + for(i in obj) { + if(typeof(obj[i])=='object') + dump_obj(obj[i], name+'['+i+']'); + else + log(name+'['+i+']="'+obj[i]+'"'); + } +} + function debug_log(line, rx) { if(debug) @@ -25,7 +125,11 @@ function debug_log(line, rx) log(line); } -// Output handling functions + +/**************/ +/* Socket I/O */ +/**************/ + function tagged(tag, msg, desc) { client.socket.send(tag+" "+msg+" "+desc+"\r\n"); @@ -38,44 +142,18 @@ function untagged(msg) debug_log("IMAP Send: * "+msg, false); } -function handle_command(command, args, defs) -{ - if(defs[command] != undefined) { - if(defs[command].arguments != undefined) { - if(args.length-1 == defs[command].arguments) { - defs[command].handler(args); - return(true); - } - } - else if(defs[command].arguments_valid(args.length-1)) { - defs[command].handler(args); - return(true); - } - } - return false; -} - -function compNumbers(a,b) -{ - return(a-b); -} +/**********************/ +/* Encoding functions */ +/**********************/ +/* + * These encode at least as is passed (token/string/binary) + */ function encode_binary(str) { return '{'+str.length+'}\r\n'+str; } -function encode_token(str) -{ - if(str=='') - return(encode_string(str)); - - if(str.search(/[\(\)\{ \x00-\x1F\*\%\"\\\]]/)==-1) - return str; - - return(encode_string(str)); -} - function encode_string(str) { if(str=='') @@ -89,30 +167,20 @@ function encode_string(str) return encode_binary(str); } -function get_from(hdr) +function encode_token(str) { - // From - if(!hdr.from_net_type || hdr.from_net_addr.length==0) /* local message */ - return(hdr.from + " <" + hdr.from.replace(/ /g,".").toLowerCase() + "@" + system.inetaddr + ">"); - else if(!hdr.from_net_addr.length) - return(hdr.from); - else if(hdr.from_net_addr.indexOf('@')!=-1) - return(hdr.from+" <"+hdr.from_net_addr+">"); - return(hdr.from+" <"+hdr.from.replace(/ /g,".").toLowerCase()+"@"+hdr.from_net_addr+">"); -} + if(str=='') + return(encode_string(str)); -function dump_obj(obj, name) -{ - var i; + if(str.search(/[\(\)\{ \x00-\x1F\*\%\"\\\]]/)==-1) + return str; - for(i in obj) { - if(typeof(obj[i])=='object') - dump_obj(obj[i], name+'['+i+']'); - else - log(name+'['+i+']="'+obj[i]+'"'); - } + return(encode_string(str)); } +/*************************************************************/ +/* Fetch response generation... this is the tricky bit. :-) */ +/*************************************************************/ function send_fetch_response(msgnum, fmat, uid) { var idx; @@ -130,9 +198,11 @@ function send_fetch_response(msgnum, fmat, uid) var envelope; var mime; var part; + var extension; - idx=index.idx[msgnum]; - + /* + * Most of these functions just diddle variables in this function + */ function get_mime() { if(mime==undefined) { get_rfc822(); @@ -166,6 +236,9 @@ function send_fetch_response(msgnum, fmat, uid) rfc822.size=rfc822.header.length+rfc822.text.length; } + /* + * Sets the seen flag on a message (for INBOX only) + */ function set_seen_flag() { if(readonly) return; @@ -185,63 +258,6 @@ function send_fetch_response(msgnum, fmat, uid) } } - function get_envelope() { - function parse_header(header, is_addresses) { - var m; - var m2; - var re; - - re=new RegExp("^"+header+":\\s*(.*?)$","im"); - m=re.exec(rfc822.header); - if(m==null) { - return("NIL"); - } - else { - if(is_addresses) { - if((m2=m[1].match(/^\s*(.*)\s+<([^@]*)@(.*)>\s*$/))!=null) { - m2[1]=m2[1].replace(/^"(.*)"$/, "$1"); - return '(('+[encode_string(m2[1]), "NIL", encode_string(m2[2]), encode_string(m2[3])].join(" ")+'))'; - } - else if((m2=m[1].match(/^\s*(.*)\s+<([^@]*)>\s*$/))!=null) { - m2[1]=m2[1].replace(/^"(.*)"$/, "$1"); - return '(('+[encode_string(m2[1]), "NIL", encode_string(m2[2]), "NIL"].join(" ")+'))'; - } - else if((m2=m[1].match(/^\s*<([^@]*)@(.*)>\s*$/))!=null) { - return '(('+["NIL", "NIL", encode_string(m2[1]), encode_string(m2[2])].join(" ")+'))'; - } - else if((m2=m[1].match(/^\s*([^@]*)@(.*)\s*$/))!=null) { - return '(('+["NIL", "NIL", encode_string(m2[1]), encode_string(m2[2])].join(" ")+'))'; - } - else - return '(('+[encode_string(m[1]), "NIL", "NIL", "NIL"].join(" ")+'))'; - } - else - return(encode_string(m[1])); - } - } - - var m; - - if(envelope==undefined) { - get_rfc822_header(); - - envelope=[]; - envelope.push(parse_header("Date", false)); - envelope.push(parse_header("Subject", false)); - envelope.push(parse_header("From", true)); - envelope.push(parse_header("Sender", true)); - envelope.push(parse_header("Reply-To", true)); - envelope.push(parse_header("To", true)); - envelope.push(parse_header("CC", true)); - envelope.push(parse_header("BCC", true)); - envelope.push(parse_header("In-Reply-To", false)); - envelope.push(parse_header("Message-ID", false)); - } - } - - resp=idx.offset; - resp += " FETCH ("; - // Moves flags to the end... function sort_format(a,b) { @@ -265,15 +281,21 @@ function send_fetch_response(msgnum, fmat, uid) return a-b; } + idx=index.idx[msgnum]; + resp=idx.offset; + resp += " FETCH ("; fmat=fmat.sort(sort_format); for(i in fmat) { + /* + * This bit is for when a paremeter includes a list. + * This list will be an object, so we need special handling + */ if(typeof(fmat[i])=='object') { // We already handled this I hope... if(objtype == undefined) continue; - // TODO: Handle partial HEADER.FIELDS and HEADER.FIELDS.NOT if(objtype.search(/^BODY\[[0-9.]*HEADER\.FIELDS$/)==0) { tmp=''; for(j in fmat[i]) { @@ -299,6 +321,9 @@ function send_fetch_response(msgnum, fmat, uid) } continue; } + /* + * Handle the MIME stuff + */ if(fmat[i].toUpperCase().substr(0,4)=='BODY') { function get_mime_part(fmat) { var m=fmat.match(/^BODY((?:\.PEEK)?)\[([^[\]]*)(?:\]\<([0-9]+)\.([0-9]+)\>)?/i); @@ -362,9 +387,10 @@ function send_fetch_response(msgnum, fmat, uid) get_mime(); if((tmp=get_mime_part(fmat[i].toUpperCase()))==undefined) { + extension=true; switch(fmat[i].toUpperCase()) { case 'BODY': - // TODO: BODY is actually *not* extensible... it's slightly different than BIDYSTRUCTURE + extension=false; case 'BODYSTRUCTURE': function add_part(mime) { var i; @@ -410,6 +436,11 @@ function send_fetch_response(msgnum, fmat, uid) i=mime.text.split(/\x0d\x0a/); ret=ret+encode_token(i.length.toString())+' '; } + + if(extension) { + // TODO Add extension data... + } + ret=ret.replace(/ $/, ') '); return ret; } @@ -457,8 +488,8 @@ function send_fetch_response(msgnum, fmat, uid) break; case 'ENVELOPE': set_seen_flag(); - get_envelope(); - resp += 'ENVELOPE ('+envelope.join(" ")+') '; + get_header(); + resp += 'ENVELOPE ('+hdr.get_envelope().join(" ")+') '; break; } } @@ -513,7 +544,7 @@ function parse_seq_set(set, uid) { if(uid) max=base.last_msg; else - max=index.offsets.length-1; + max=index.offsets.length; for(chunk in chunks) { range=chunks[chunk].split(/:/); if(range.length == 1) @@ -538,7 +569,7 @@ function parse_seq_set(set, uid) { response.push(msgnum); } } - response=response.sort(compNumbers); + response=response.sort(function(a,b) { return a-b; }); for(i=0; i<response.length; i++) { if(response[i]==response[i+1]) { response.splice(i+1,1); @@ -548,6 +579,23 @@ function parse_seq_set(set, uid) { return(response); } +function handle_command(command, args, defs) +{ + if(defs[command] != undefined) { + if(defs[command].arguments != undefined) { + if(args.length-1 == defs[command].arguments) { + defs[command].handler(args); + return(true); + } + } + else if(defs[command].arguments_valid(args.length-1)) { + defs[command].handler(args); + return(true); + } + } + return false; +} + function parse_command(line) { function execute_line(args) { @@ -1478,110 +1526,197 @@ function parse_rfc822_date(date) function do_search(args, uid) { - var search_set={idx:[],hdr:[],body:[]}; + var search_set={idx:[],hdr:[],body:[],all:[]}; var i,j; var failed; var idx,hdr,body; var result=[]; - while(args.length) { + function get_func(args) + { + var next1,next2; + var tmp; + switch(args.shift().toUpperCase()) { case 'ALL': - search_set.idx.push(function(idx) { return true; }); + type="idx"; + search=(function(idx) { return true; }); break; case 'ANSWERED': - search_set.idx.push(function(idx) { if(base.subnum==-1 && (idx.attr & MSG_REPLIED)) return true; return false; }); + type="idx"; + search=(function(idx) { if(base.subnum==-1 && (idx.attr & MSG_REPLIED)) return true; return false; }); break; case 'BODY': - search_set.body.push(eval("function(body) { return(body.indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); + type="body"; + search=(eval("function(body) { return(body.indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); break; case 'DELETED': - search_set.idx.push(function(idx) { if(idx.attr & MSG_DELETE) return true; return false; }); + type="idx"; + search=(function(idx) { if(idx.attr & MSG_DELETE) return true; return false; }); break; case 'DRAFT': - search_set.idx.push(function(idx) { return false; }); + type="idx"; + search=(function(idx) { return false; }); break; case 'FLAGGED': - search_set.idx.push(function(idx) { if(idx.attr & MSG_VERIFIED) return true; return false; }); + type="idx"; + search=(function(idx) { if(idx.attr & MSG_VERIFIED) return true; return false; }); break; case 'FROM': - search_set.hdr.push(eval("function(hdr) { return(get_from(hdr).toUpperCase().indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); + type="hdr"; + search=(eval("function(hdr) { return(hdr.get_from()).toUpperCase().indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); break; case 'KEYWORD': - search_set.hdr.push(eval("function(hdr) { var flags="+parse_flags([args.shift()]).toSource()+"; if((hdr.attr & flags.attr)==flags.attr && (hdr.netattr & flags.netattr)==flags.netattr) return true; return false;}")); + type="hdr"; + search=(eval("function(hdr) { var flags="+parse_flags([args.shift()]).toSource()+"; if((hdr.attr & flags.attr)==flags.attr && (hdr.netattr & flags.netattr)==flags.netattr) return true; return false;}")); break; case 'NEW': - search_set.idx.push(eval("function(idx) { if((idx.number > orig_ptrs[base.subnum]) && (idx.attr & MSG_READ)==0) return true; return false; }")); + type="idx"; + search=(eval("function(idx) { if((idx.number > orig_ptrs[base.subnum]) && (idx.attr & MSG_READ)==0) return true; return false; }")); break; case 'OLD': - search_set.idx.push(eval("function(idx) { if(idx.number <= orig_ptrs[base.subnum]) return true; return false; }")); + type="idx"; + search=(eval("function(idx) { if(idx.number <= orig_ptrs[base.subnum]) return true; return false; }")); break; case 'RECENT': - search_set.idx.push(eval("function(idx) { if(idx.number > orig_ptrs[base.subnum]) return true; return false; }")); + type="idx"; + search=(eval("function(idx) { if(idx.number > orig_ptrs[base.subnum]) return true; return false; }")); break; case 'SEEN': - search_set.idx.push(function(idx) { if(idx.attr & MSG_READ) return true; return false }); + type="idx"; + search=(function(idx) { if(idx.attr & MSG_READ) return true; return false }); break; case 'SUBJECT': - search_set.hdr.push(eval("function(hdr) { return(hdr.subject.toUpperCase().indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); + type="hdr"; + search=(eval("function(hdr) { return(hdr.subject.toUpperCase().indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); break; case 'TO': - search_set.hdr.push(eval("function(hdr) { return(hdr.to.toUpperCase().indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); + type="hdr"; + search=(eval("function(hdr) { return(hdr.to.toUpperCase().indexOf("+args.shift().toUpperCase().toSource()+")!=-1) }")); break; case 'UID': - search_set.idx.push(eval("function(idx) { var good_uids="+parse_seq_set(args.shift(), true).toSource()+"; var i; for(i in good_uids) { if(good_uids[i]==idx.number) return true; } return false; }")); + type="idx"; + search=(eval("function(idx) { var good_uids="+parse_seq_set(args.shift(), true).toSource()+"; var i; for(i in good_uids) { if(good_uids[i]==idx.number) return true; } return false; }")); break; case 'UNANSWERED': - search_set.idx.push(function(idx) { if(base.subnum==-1 && (idx.attr & MSG_REPLIED)) return false; return true; }); + type="idx"; + search=(function(idx) { if(base.subnum==-1 && (idx.attr & MSG_REPLIED)) return false; return true; }); break; case 'UNDELETED': - search_set.idx.push(function(idx) { if(idx.attr & MSG_DELETE) return false; return true; }); + type="idx"; + search=(function(idx) { if(idx.attr & MSG_DELETE) return false; return true; }); break; case 'UNDRAFT': - search_set.idx.push(function(idx) { return true; }); + type="idx"; + search=(function(idx) { return true; }); break; case 'UNFLAGGED': - search_set.idx.push(function(idx) { if(idx.attr & MSG_VERIFIED) return false; return true; }); + type="idx"; + search=(function(idx) { if(idx.attr & MSG_VERIFIED) return false; return true; }); break; case 'UNKEYWORD': - search_set.hdr.push(eval("function(hdr) { var flags="+parse_flags([args.shift()]).toSource()+"; if((hdr.attr & flags.attr)==flags.attr && (hdr.netattr & flags.netattr)==flags.netattr) return false; return true;}")); + type="hdr"; + search=(eval("function(hdr) { var flags="+parse_flags([args.shift()]).toSource()+"; if((hdr.attr & flags.attr)==flags.attr && (hdr.netattr & flags.netattr)==flags.netattr) return false; return true;}")); break; case 'BEFORE': - search_set.hdr.push(eval("function(hdr) { var before="+parse_date(args.shift()).toSource()+"; if(hdr.when_imported_time < before) return true; return false; }")); + type="hdr"; + search=(eval("function(hdr) { var before="+parse_date(args.shift()).toSource()+"; if(hdr.when_imported_time < before) return true; return false; }")); break; case 'ON': - search_set.hdr.push(eval("function(hdr) { var on="+datestr(parse_date(args.shift())).toSource()+"; if(datestr(hdr.when_imported_time) == on) return true; return false; }")); + type="hdr"; + search=(eval("function(hdr) { var on="+datestr(parse_date(args.shift())).toSource()+"; if(datestr(hdr.when_imported_time) == on) return true; return false; }")); break; case 'SINCE': - search_set.hdr.push(eval("function(hdr) { var since="+parse_date(args[0]).toSource()+"; var since_str="+datestr(parse_date(args.shift())).toSource()+"; if(hdr.when_imported_time > since && datestr(hdr.when_imported_time) != since_str) return true; return false; }")); + type="hdr"; + search=(eval("function(hdr) { var since="+parse_date(args[0]).toSource()+"; var since_str="+datestr(parse_date(args.shift())).toSource()+"; if(hdr.when_imported_time > since && datestr(hdr.when_imported_time) != since_str) return true; return false; }")); break; case 'SENTBEFORE': - search_set.hdr.push(eval("function(hdr) { var before="+parse_date(args.shift()).toSource()+"; if(parse_rfc822_date(hdr.date) < before) return true; return false; }")); + type="hdr"; + search=(eval("function(hdr) { var before="+parse_date(args.shift()).toSource()+"; if(parse_rfc822_date(hdr.date) < before) return true; return false; }")); break; case 'SENTON': - search_set.hdr.push(eval("function(hdr) { var on="+datestr(parse_date(args.shift())).toSource()+"; if(datestr(parse_rfc822_date(hdr.date)) == on) return true; return false; }")); + type="hdr"; + search=(eval("function(hdr) { var on="+datestr(parse_date(args.shift())).toSource()+"; if(datestr(parse_rfc822_date(hdr.date)) == on) return true; return false; }")); break; case 'SENTSINCE': - search_set.hdr.push(eval("function(hdr) { var since="+parse_date(args[0]).toSource()+"; var since_str="+datestr(parse_date(args.shift())).toSource()+"; if(parse_rfc822_date(hdrdate) > since && datestr(parse_rfc822_date(hdr.date)) != since_str) return true; return false; }")); + type="hdr"; + search=(eval("function(hdr) { var since="+parse_date(args[0]).toSource()+"; var since_str="+datestr(parse_date(args.shift())).toSource()+"; if(parse_rfc822_date(hdrdate) > since && datestr(parse_rfc822_date(hdr.date)) != since_str) return true; return false; }")); break; - // TODO: Unhandled SEARCH terms case 'HEADER': - args.shift(); + type="hdr"; + search=(eval("function(hdr) { var hname="+args.shift().toLowerCase().toSource()+"; var match=new RegExp('^('+abnf.field_name+')'+abnf.WSP+'*:.*'+"+args.shift().toSource()+"; var hdrs=hdr.parse_headers(); var i; for(i in hdrs[hname]) if(hdrs[hname][i].search(match)==0) return true; return false;}")); + break; case 'LARGER': + type="all"; + search=(eval("function(idx,hdr,body) { var min="+parseInt(args.shift(),10)+"; if(body.length + hdr.get_rfc822_header().length > min) return true; return false;}")); + break; case 'SMALLER': - // Calculate RFC822.SIZE + type="all"; + search=(eval("function(idx,hdr,body) { var max="+parseInt(args.shift(),10)+"; if(body.length + hdr.get_rfc822_header().length < max) return true; return false;}")); + break; case 'CC': - // Is there a CC header? + type="hdr"; + search=(eval("function(hdr) { var match=new RegExp('^('+abnf.field_name+')'+abnf.WSP+'*:.*'+"+args.shift().toSource()+"; var hdrs=hdr.parse_headers(); var i; if(hdrs.cc == undefined) return false; for(i in hdrs.cc) if(hdrs.cc[i].search(match)==0) return true; return false;}")); + break; case 'BCC': - // There's a BCC header? + type="hdr"; + search=(eval("function(hdr) { var match=new RegExp('^('+abnf.field_name+')'+abnf.WSP+'*:.*'+"+args.shift().toSource()+"; var hdrs=hdr.parse_headers(); var i; if(hdrs.bcc == undefined) return false; for(i in hdrs.bcc) if(hdrs.bcc[i].search(match)==0) return true; return false;}")); + break; case 'TEXT': - // Needs RFC822 - args.shift(); + type="all"; + search=(eval("function(idx,hdr,body) { var str="+args.shift().toSource()+"; if(hdr.get_rfc822_header().indexOf(str)!=-1) return true; if(body.indexOf(str)!=-1) return true; return false}")); + break; case 'NOT': + next1=get_func(args); + type=next1[0]; + search=(eval("function(x) { return !"+next1[1].toSource()+"(x)}")); + break; case 'OR': + next1=get_func(args); + next2=get_func(args); + if(next1[0]==next1[1]) { + type=next1[0]; + search=(eval("function(x) { return ("+next1[1].toSource()+"(x)||"+next2[1].toSource()+"(x))}")); + } + else { + // Needs to be all (sigh) + type='all'; + tmp="function(idx,hdr,body) { return ("+next1[1].toSource(); + switch(next1[0]) { + case 'idx': + case 'hdr': + case 'body': + tmp += '('+next1[0]+')'; + break; + case 'all': + tmp += '(idx,hdr,body)'; + break; + } + tmp += '||'+next2[1].toSource(); + switch(next2[0]) { + case 'idx': + case 'hdr': + case 'body': + tmp += '('+next2[0]+')'; + break; + case 'all': + tmp += '(idx,hdr,body)'; + break; + } + tmp += ')}'; + search=eval(tmp); + } + break; default: - search_set.idx.push(function(idx) { return false; }); + type="idx"; + search=(function(idx) { return false; }); } + return([type,search]); + } + + while(args.length) { + i=get_func(args); + search_set[i[0]].push(i[1]); } for(i in index.offsets) { @@ -1595,7 +1730,7 @@ function do_search(args, uid) if(failed) continue; } - if(search_set.hdr.length > 0) { + if(search_set.hdr.length > 0 || search_set.all.length > 0) { hdr=base.get_msg_header(idx.number); for(j in search_set.hdr) { if(search_set.hdr[j](hdr)==false) @@ -1604,7 +1739,7 @@ function do_search(args, uid) if(failed) continue; } - if(search_set.body.length > 0) { + if(search_set.body.length > 0 || search_set.all.length > 0) { body=base.get_msg_body(idx.number,true,true,true).toUpperCase(); for(j in search_set.body) { if(search_set.body[j](body)==false) @@ -1613,6 +1748,14 @@ function do_search(args, uid) if(failed) continue; } + if(search_set.all.length > 0) { + for(j in search_set.all) { + if(search_set.all[j](idx,hdr,body)==false) + failed=true; + } + if(failed) + continue; + } if(!failed) result.push(uid?idx.number:idx.offset); } @@ -1775,6 +1918,7 @@ var msg_ptrs={}; var curr_status={exists:0,recent:0,unseen:0,uidnext:0,uidvalidity:0}; var saved_config={inbox:{scan_ptr:0}}; var scan_ptr; +const RFC822HEADER = 0xb0; // from smbdefs.h js.on_exit("exit_func()"); client.socket.send("* OK Give 'er\r\n");