123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <auth.h>
- #include "imap4d.h"
- static int dateCmp(char *date, Search *s);
- static int addrSearch(MAddr *a, char *s);
- static int fileSearch(Msg *m, char *file, char *pat);
- static int headerSearch(Msg *m, char *hdr, char *pat);
- /*
- * free to exit, parseErr, since called before starting any client reply
- *
- * the header and envelope searches should convert mime character set escapes.
- */
- int
- searchMsg(Msg *m, Search *s)
- {
- MsgSet *ms;
- int ok;
- if(!msgStruct(m, 1) || m->expunged)
- return 0;
- for(ok = 1; ok && s != nil; s = s->next){
- switch(s->key){
- default:
- ok = 0;
- break;
- case SKNot:
- ok = !searchMsg(m, s->left);
- break;
- case SKOr:
- ok = searchMsg(m, s->left) || searchMsg(m, s->right);
- break;
- case SKAll:
- ok = 1;
- break;
- case SKAnswered:
- ok = (m->flags & MAnswered) == MAnswered;
- break;
- case SKDeleted:
- ok = (m->flags & MDeleted) == MDeleted;
- break;
- case SKDraft:
- ok = (m->flags & MDraft) == MDraft;
- break;
- case SKFlagged:
- ok = (m->flags & MFlagged) == MFlagged;
- break;
- case SKKeyword:
- ok = (m->flags & s->num) == s->num;
- break;
- case SKNew:
- ok = (m->flags & (MRecent|MSeen)) == MRecent;
- break;
- case SKOld:
- ok = (m->flags & MRecent) != MRecent;
- break;
- case SKRecent:
- ok = (m->flags & MRecent) == MRecent;
- break;
- case SKSeen:
- ok = (m->flags & MSeen) == MSeen;
- break;
- case SKUnanswered:
- ok = (m->flags & MAnswered) != MAnswered;
- break;
- case SKUndeleted:
- ok = (m->flags & MDeleted) != MDeleted;
- break;
- case SKUndraft:
- ok = (m->flags & MDraft) != MDraft;
- break;
- case SKUnflagged:
- ok = (m->flags & MFlagged) != MFlagged;
- break;
- case SKUnkeyword:
- ok = (m->flags & s->num) != s->num;
- break;
- case SKUnseen:
- ok = (m->flags & MSeen) != MSeen;
- break;
- case SKLarger:
- ok = msgSize(m) > s->num;
- break;
- case SKSmaller:
- ok = msgSize(m) < s->num;
- break;
- case SKBcc:
- ok = addrSearch(m->bcc, s->s);
- break;
- case SKCc:
- ok = addrSearch(m->cc, s->s);
- break;
- case SKFrom:
- ok = addrSearch(m->from, s->s);
- break;
- case SKTo:
- ok = addrSearch(m->to, s->s);
- break;
- case SKSubject:
- ok = 0;
- if(m->info[ISubject])
- ok = cistrstr(m->info[ISubject], s->s) != nil;
- break;
- case SKBefore:
- ok = dateCmp(m->unixDate, s) < 0;
- break;
- case SKOn:
- ok = dateCmp(m->unixDate, s) == 0;
- break;
- case SKSince:
- ok = dateCmp(m->unixDate, s) > 0;
- break;
- case SKSentBefore:
- ok = dateCmp(m->info[IDate], s) < 0;
- break;
- case SKSentOn:
- ok = dateCmp(m->info[IDate], s) == 0;
- break;
- case SKSentSince:
- ok = dateCmp(m->info[IDate], s) > 0;
- break;
- case SKUid:
- case SKSet:
- for(ms = s->set; ms != nil; ms = ms->next)
- if(s->key == SKUid && m->uid >= ms->from && m->uid <= ms->to
- || s->key == SKSet && m->seq >= ms->from && m->seq <= ms->to)
- break;
- ok = ms != nil;
- break;
- case SKHeader:
- ok = headerSearch(m, s->hdr, s->s);
- break;
- case SKBody:
- case SKText:
- if(s->key == SKText && cistrstr(m->head.buf, s->s)){
- ok = 1;
- break;
- }
- ok = fileSearch(m, "body", s->s);
- break;
- }
- }
- return ok;
- }
- static int
- fileSearch(Msg *m, char *file, char *pat)
- {
- char buf[BufSize + 1];
- int n, nbuf, npat, fd, ok;
- npat = strlen(pat);
- if(npat >= BufSize / 2)
- return 0;
- fd = msgFile(m, file);
- if(fd < 0)
- return 0;
- ok = 0;
- nbuf = 0;
- for(;;){
- n = read(fd, &buf[nbuf], BufSize - nbuf);
- if(n <= 0)
- break;
- nbuf += n;
- buf[nbuf] = '\0';
- if(cistrstr(buf, pat) != nil){
- ok = 1;
- break;
- }
- if(nbuf > npat){
- memmove(buf, &buf[nbuf - npat], npat);
- nbuf = npat;
- }
- }
- close(fd);
- return ok;
- }
- static int
- headerSearch(Msg *m, char *hdr, char *pat)
- {
- SList hdrs;
- char *s, *t;
- int ok, n;
- n = m->head.size + 3;
- s = emalloc(n);
- hdrs.next = nil;
- hdrs.s = hdr;
- ok = 0;
- if(selectFields(s, n, m->head.buf, &hdrs, 1) > 0){
- t = strchr(s, ':');
- if(t != nil && cistrstr(t+1, pat) != nil)
- ok = 1;
- }
- free(s);
- return ok;
- }
- static int
- addrSearch(MAddr *a, char *s)
- {
- char *ok, *addr;
- for(; a != nil; a = a->next){
- addr = maddrStr(a);
- ok = cistrstr(addr, s);
- free(addr);
- if(ok != nil)
- return 1;
- }
- return 0;
- }
- static int
- dateCmp(char *date, Search *s)
- {
- Tm tm;
- date2tm(&tm, date);
- if(tm.year < s->year)
- return -1;
- if(tm.year > s->year)
- return 1;
- if(tm.mon < s->mon)
- return -1;
- if(tm.mon > s->mon)
- return 1;
- if(tm.mday < s->mday)
- return -1;
- if(tm.mday > s->mday)
- return 1;
- return 0;
- }
|