xref: /plan9-contrib/sys/src/cmd/ip/imap4d/search.c (revision 3a32e1046e411eba43a878ebe72e5b0033495136)
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