17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <auth.h>
57dd7cddfSDavid du Colombier #include "imap4d.h"
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier static int dateCmp(char *date, Search *s);
87dd7cddfSDavid du Colombier static int addrSearch(MAddr *a, char *s);
97dd7cddfSDavid du Colombier static int fileSearch(Msg *m, char *file, char *pat);
107dd7cddfSDavid du Colombier static int headerSearch(Msg *m, char *hdr, char *pat);
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier /*
137dd7cddfSDavid du Colombier * free to exit, parseErr, since called before starting any client reply
147dd7cddfSDavid du Colombier *
157dd7cddfSDavid du Colombier * the header and envelope searches should convert mime character set escapes.
167dd7cddfSDavid du Colombier */
177dd7cddfSDavid du Colombier int
searchMsg(Msg * m,Search * s)187dd7cddfSDavid du Colombier searchMsg(Msg *m, Search *s)
197dd7cddfSDavid du Colombier {
207dd7cddfSDavid du Colombier MsgSet *ms;
217dd7cddfSDavid du Colombier int ok;
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier if(!msgStruct(m, 1) || m->expunged)
247dd7cddfSDavid du Colombier return 0;
257dd7cddfSDavid du Colombier for(ok = 1; ok && s != nil; s = s->next){
267dd7cddfSDavid du Colombier switch(s->key){
277dd7cddfSDavid du Colombier default:
287dd7cddfSDavid du Colombier ok = 0;
297dd7cddfSDavid du Colombier break;
307dd7cddfSDavid du Colombier case SKNot:
317dd7cddfSDavid du Colombier ok = !searchMsg(m, s->left);
327dd7cddfSDavid du Colombier break;
337dd7cddfSDavid du Colombier case SKOr:
347dd7cddfSDavid du Colombier ok = searchMsg(m, s->left) || searchMsg(m, s->right);
357dd7cddfSDavid du Colombier break;
367dd7cddfSDavid du Colombier case SKAll:
377dd7cddfSDavid du Colombier ok = 1;
387dd7cddfSDavid du Colombier break;
397dd7cddfSDavid du Colombier case SKAnswered:
407dd7cddfSDavid du Colombier ok = (m->flags & MAnswered) == MAnswered;
417dd7cddfSDavid du Colombier break;
427dd7cddfSDavid du Colombier case SKDeleted:
437dd7cddfSDavid du Colombier ok = (m->flags & MDeleted) == MDeleted;
447dd7cddfSDavid du Colombier break;
457dd7cddfSDavid du Colombier case SKDraft:
467dd7cddfSDavid du Colombier ok = (m->flags & MDraft) == MDraft;
477dd7cddfSDavid du Colombier break;
487dd7cddfSDavid du Colombier case SKFlagged:
497dd7cddfSDavid du Colombier ok = (m->flags & MFlagged) == MFlagged;
507dd7cddfSDavid du Colombier break;
517dd7cddfSDavid du Colombier case SKKeyword:
527dd7cddfSDavid du Colombier ok = (m->flags & s->num) == s->num;
537dd7cddfSDavid du Colombier break;
547dd7cddfSDavid du Colombier case SKNew:
557dd7cddfSDavid du Colombier ok = (m->flags & (MRecent|MSeen)) == MRecent;
567dd7cddfSDavid du Colombier break;
577dd7cddfSDavid du Colombier case SKOld:
587dd7cddfSDavid du Colombier ok = (m->flags & MRecent) != MRecent;
597dd7cddfSDavid du Colombier break;
607dd7cddfSDavid du Colombier case SKRecent:
617dd7cddfSDavid du Colombier ok = (m->flags & MRecent) == MRecent;
627dd7cddfSDavid du Colombier break;
637dd7cddfSDavid du Colombier case SKSeen:
647dd7cddfSDavid du Colombier ok = (m->flags & MSeen) == MSeen;
657dd7cddfSDavid du Colombier break;
667dd7cddfSDavid du Colombier case SKUnanswered:
677dd7cddfSDavid du Colombier ok = (m->flags & MAnswered) != MAnswered;
687dd7cddfSDavid du Colombier break;
697dd7cddfSDavid du Colombier case SKUndeleted:
707dd7cddfSDavid du Colombier ok = (m->flags & MDeleted) != MDeleted;
717dd7cddfSDavid du Colombier break;
727dd7cddfSDavid du Colombier case SKUndraft:
737dd7cddfSDavid du Colombier ok = (m->flags & MDraft) != MDraft;
747dd7cddfSDavid du Colombier break;
757dd7cddfSDavid du Colombier case SKUnflagged:
767dd7cddfSDavid du Colombier ok = (m->flags & MFlagged) != MFlagged;
777dd7cddfSDavid du Colombier break;
787dd7cddfSDavid du Colombier case SKUnkeyword:
797dd7cddfSDavid du Colombier ok = (m->flags & s->num) != s->num;
807dd7cddfSDavid du Colombier break;
817dd7cddfSDavid du Colombier case SKUnseen:
827dd7cddfSDavid du Colombier ok = (m->flags & MSeen) != MSeen;
837dd7cddfSDavid du Colombier break;
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier case SKLarger:
867dd7cddfSDavid du Colombier ok = msgSize(m) > s->num;
877dd7cddfSDavid du Colombier break;
887dd7cddfSDavid du Colombier case SKSmaller:
897dd7cddfSDavid du Colombier ok = msgSize(m) < s->num;
907dd7cddfSDavid du Colombier break;
917dd7cddfSDavid du Colombier
927dd7cddfSDavid du Colombier case SKBcc:
937dd7cddfSDavid du Colombier ok = addrSearch(m->bcc, s->s);
947dd7cddfSDavid du Colombier break;
957dd7cddfSDavid du Colombier case SKCc:
967dd7cddfSDavid du Colombier ok = addrSearch(m->cc, s->s);
977dd7cddfSDavid du Colombier break;
987dd7cddfSDavid du Colombier case SKFrom:
997dd7cddfSDavid du Colombier ok = addrSearch(m->from, s->s);
1007dd7cddfSDavid du Colombier break;
1017dd7cddfSDavid du Colombier case SKTo:
1027dd7cddfSDavid du Colombier ok = addrSearch(m->to, s->s);
1037dd7cddfSDavid du Colombier break;
1047dd7cddfSDavid du Colombier case SKSubject:
105*3a32e104SDavid du Colombier ok = 0;
106*3a32e104SDavid du Colombier if(m->info[ISubject])
1077dd7cddfSDavid du Colombier ok = cistrstr(m->info[ISubject], s->s) != nil;
1087dd7cddfSDavid du Colombier break;
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier case SKBefore:
1117dd7cddfSDavid du Colombier ok = dateCmp(m->unixDate, s) < 0;
1127dd7cddfSDavid du Colombier break;
1137dd7cddfSDavid du Colombier case SKOn:
1147dd7cddfSDavid du Colombier ok = dateCmp(m->unixDate, s) == 0;
1157dd7cddfSDavid du Colombier break;
1167dd7cddfSDavid du Colombier case SKSince:
1177dd7cddfSDavid du Colombier ok = dateCmp(m->unixDate, s) > 0;
1187dd7cddfSDavid du Colombier break;
1197dd7cddfSDavid du Colombier case SKSentBefore:
1207dd7cddfSDavid du Colombier ok = dateCmp(m->info[IDate], s) < 0;
1217dd7cddfSDavid du Colombier break;
1227dd7cddfSDavid du Colombier case SKSentOn:
1237dd7cddfSDavid du Colombier ok = dateCmp(m->info[IDate], s) == 0;
1247dd7cddfSDavid du Colombier break;
1257dd7cddfSDavid du Colombier case SKSentSince:
1267dd7cddfSDavid du Colombier ok = dateCmp(m->info[IDate], s) > 0;
1277dd7cddfSDavid du Colombier break;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier case SKUid:
1307dd7cddfSDavid du Colombier case SKSet:
1317dd7cddfSDavid du Colombier for(ms = s->set; ms != nil; ms = ms->next)
1327dd7cddfSDavid du Colombier if(s->key == SKUid && m->uid >= ms->from && m->uid <= ms->to
1337dd7cddfSDavid du Colombier || s->key == SKSet && m->seq >= ms->from && m->seq <= ms->to)
1347dd7cddfSDavid du Colombier break;
1357dd7cddfSDavid du Colombier ok = ms != nil;
1367dd7cddfSDavid du Colombier break;
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier case SKHeader:
1397dd7cddfSDavid du Colombier ok = headerSearch(m, s->hdr, s->s);
1407dd7cddfSDavid du Colombier break;
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier case SKBody:
1437dd7cddfSDavid du Colombier case SKText:
1447dd7cddfSDavid du Colombier if(s->key == SKText && cistrstr(m->head.buf, s->s)){
1457dd7cddfSDavid du Colombier ok = 1;
1467dd7cddfSDavid du Colombier break;
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier ok = fileSearch(m, "body", s->s);
1497dd7cddfSDavid du Colombier break;
1507dd7cddfSDavid du Colombier }
1517dd7cddfSDavid du Colombier }
1527dd7cddfSDavid du Colombier return ok;
1537dd7cddfSDavid du Colombier }
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier static int
fileSearch(Msg * m,char * file,char * pat)1567dd7cddfSDavid du Colombier fileSearch(Msg *m, char *file, char *pat)
1577dd7cddfSDavid du Colombier {
1587dd7cddfSDavid du Colombier char buf[BufSize + 1];
1597dd7cddfSDavid du Colombier int n, nbuf, npat, fd, ok;
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier npat = strlen(pat);
1627dd7cddfSDavid du Colombier if(npat >= BufSize / 2)
1637dd7cddfSDavid du Colombier return 0;
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier fd = msgFile(m, file);
1667dd7cddfSDavid du Colombier if(fd < 0)
1677dd7cddfSDavid du Colombier return 0;
1687dd7cddfSDavid du Colombier ok = 0;
1697dd7cddfSDavid du Colombier nbuf = 0;
1707dd7cddfSDavid du Colombier for(;;){
1717dd7cddfSDavid du Colombier n = read(fd, &buf[nbuf], BufSize - nbuf);
1727dd7cddfSDavid du Colombier if(n <= 0)
1737dd7cddfSDavid du Colombier break;
1747dd7cddfSDavid du Colombier nbuf += n;
1757dd7cddfSDavid du Colombier buf[nbuf] = '\0';
1767dd7cddfSDavid du Colombier if(cistrstr(buf, pat) != nil){
1777dd7cddfSDavid du Colombier ok = 1;
1787dd7cddfSDavid du Colombier break;
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier if(nbuf > npat){
1817dd7cddfSDavid du Colombier memmove(buf, &buf[nbuf - npat], npat);
1827dd7cddfSDavid du Colombier nbuf = npat;
1837dd7cddfSDavid du Colombier }
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier close(fd);
1867dd7cddfSDavid du Colombier return ok;
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier
1897dd7cddfSDavid du Colombier static int
headerSearch(Msg * m,char * hdr,char * pat)1907dd7cddfSDavid du Colombier headerSearch(Msg *m, char *hdr, char *pat)
1917dd7cddfSDavid du Colombier {
1927dd7cddfSDavid du Colombier SList hdrs;
1937dd7cddfSDavid du Colombier char *s, *t;
1947dd7cddfSDavid du Colombier int ok, n;
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier n = m->head.size + 3;
1977dd7cddfSDavid du Colombier s = emalloc(n);
1987dd7cddfSDavid du Colombier hdrs.next = nil;
1997dd7cddfSDavid du Colombier hdrs.s = hdr;
2007dd7cddfSDavid du Colombier ok = 0;
2017dd7cddfSDavid du Colombier if(selectFields(s, n, m->head.buf, &hdrs, 1) > 0){
2027dd7cddfSDavid du Colombier t = strchr(s, ':');
2037dd7cddfSDavid du Colombier if(t != nil && cistrstr(t+1, pat) != nil)
2047dd7cddfSDavid du Colombier ok = 1;
2057dd7cddfSDavid du Colombier }
2067dd7cddfSDavid du Colombier free(s);
2077dd7cddfSDavid du Colombier return ok;
2087dd7cddfSDavid du Colombier }
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier static int
addrSearch(MAddr * a,char * s)2117dd7cddfSDavid du Colombier addrSearch(MAddr *a, char *s)
2127dd7cddfSDavid du Colombier {
2137dd7cddfSDavid du Colombier char *ok, *addr;
2147dd7cddfSDavid du Colombier
2157dd7cddfSDavid du Colombier for(; a != nil; a = a->next){
2167dd7cddfSDavid du Colombier addr = maddrStr(a);
2177dd7cddfSDavid du Colombier ok = cistrstr(addr, s);
2187dd7cddfSDavid du Colombier free(addr);
2197dd7cddfSDavid du Colombier if(ok != nil)
2207dd7cddfSDavid du Colombier return 1;
2217dd7cddfSDavid du Colombier }
2227dd7cddfSDavid du Colombier return 0;
2237dd7cddfSDavid du Colombier }
2247dd7cddfSDavid du Colombier
2257dd7cddfSDavid du Colombier static int
dateCmp(char * date,Search * s)2267dd7cddfSDavid du Colombier dateCmp(char *date, Search *s)
2277dd7cddfSDavid du Colombier {
2287dd7cddfSDavid du Colombier Tm tm;
2297dd7cddfSDavid du Colombier
2307dd7cddfSDavid du Colombier date2tm(&tm, date);
2317dd7cddfSDavid du Colombier if(tm.year < s->year)
2327dd7cddfSDavid du Colombier return -1;
2337dd7cddfSDavid du Colombier if(tm.year > s->year)
2347dd7cddfSDavid du Colombier return 1;
2357dd7cddfSDavid du Colombier if(tm.mon < s->mon)
2367dd7cddfSDavid du Colombier return -1;
2377dd7cddfSDavid du Colombier if(tm.mon > s->mon)
2387dd7cddfSDavid du Colombier return 1;
2397dd7cddfSDavid du Colombier if(tm.mday < s->mday)
2407dd7cddfSDavid du Colombier return -1;
2417dd7cddfSDavid du Colombier if(tm.mday > s->mday)
2427dd7cddfSDavid du Colombier return 1;
2437dd7cddfSDavid du Colombier return 0;
2447dd7cddfSDavid du Colombier }
245