search.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <auth.h>
  5. #include "imap4d.h"
  6. static int dateCmp(char *date, Search *s);
  7. static int addrSearch(MAddr *a, char *s);
  8. static int fileSearch(Msg *m, char *file, char *pat);
  9. static int headerSearch(Msg *m, char *hdr, char *pat);
  10. /*
  11. * free to exit, parseErr, since called before starting any client reply
  12. *
  13. * the header and envelope searches should convert mime character set escapes.
  14. */
  15. int
  16. searchMsg(Msg *m, Search *s)
  17. {
  18. MsgSet *ms;
  19. int ok;
  20. if(!msgStruct(m, 1) || m->expunged)
  21. return 0;
  22. for(ok = 1; ok && s != nil; s = s->next){
  23. switch(s->key){
  24. default:
  25. ok = 0;
  26. break;
  27. case SKNot:
  28. ok = !searchMsg(m, s->left);
  29. break;
  30. case SKOr:
  31. ok = searchMsg(m, s->left) || searchMsg(m, s->right);
  32. break;
  33. case SKAll:
  34. ok = 1;
  35. break;
  36. case SKAnswered:
  37. ok = (m->flags & MAnswered) == MAnswered;
  38. break;
  39. case SKDeleted:
  40. ok = (m->flags & MDeleted) == MDeleted;
  41. break;
  42. case SKDraft:
  43. ok = (m->flags & MDraft) == MDraft;
  44. break;
  45. case SKFlagged:
  46. ok = (m->flags & MFlagged) == MFlagged;
  47. break;
  48. case SKKeyword:
  49. ok = (m->flags & s->num) == s->num;
  50. break;
  51. case SKNew:
  52. ok = (m->flags & (MRecent|MSeen)) == MRecent;
  53. break;
  54. case SKOld:
  55. ok = (m->flags & MRecent) != MRecent;
  56. break;
  57. case SKRecent:
  58. ok = (m->flags & MRecent) == MRecent;
  59. break;
  60. case SKSeen:
  61. ok = (m->flags & MSeen) == MSeen;
  62. break;
  63. case SKUnanswered:
  64. ok = (m->flags & MAnswered) != MAnswered;
  65. break;
  66. case SKUndeleted:
  67. ok = (m->flags & MDeleted) != MDeleted;
  68. break;
  69. case SKUndraft:
  70. ok = (m->flags & MDraft) != MDraft;
  71. break;
  72. case SKUnflagged:
  73. ok = (m->flags & MFlagged) != MFlagged;
  74. break;
  75. case SKUnkeyword:
  76. ok = (m->flags & s->num) != s->num;
  77. break;
  78. case SKUnseen:
  79. ok = (m->flags & MSeen) != MSeen;
  80. break;
  81. case SKLarger:
  82. ok = msgSize(m) > s->num;
  83. break;
  84. case SKSmaller:
  85. ok = msgSize(m) < s->num;
  86. break;
  87. case SKBcc:
  88. ok = addrSearch(m->bcc, s->s);
  89. break;
  90. case SKCc:
  91. ok = addrSearch(m->cc, s->s);
  92. break;
  93. case SKFrom:
  94. ok = addrSearch(m->from, s->s);
  95. break;
  96. case SKTo:
  97. ok = addrSearch(m->to, s->s);
  98. break;
  99. case SKSubject:
  100. ok = 0;
  101. if(m->info[ISubject])
  102. ok = cistrstr(m->info[ISubject], s->s) != nil;
  103. break;
  104. case SKBefore:
  105. ok = dateCmp(m->unixDate, s) < 0;
  106. break;
  107. case SKOn:
  108. ok = dateCmp(m->unixDate, s) == 0;
  109. break;
  110. case SKSince:
  111. ok = dateCmp(m->unixDate, s) > 0;
  112. break;
  113. case SKSentBefore:
  114. ok = dateCmp(m->info[IDate], s) < 0;
  115. break;
  116. case SKSentOn:
  117. ok = dateCmp(m->info[IDate], s) == 0;
  118. break;
  119. case SKSentSince:
  120. ok = dateCmp(m->info[IDate], s) > 0;
  121. break;
  122. case SKUid:
  123. case SKSet:
  124. for(ms = s->set; ms != nil; ms = ms->next)
  125. if(s->key == SKUid && m->uid >= ms->from && m->uid <= ms->to
  126. || s->key == SKSet && m->seq >= ms->from && m->seq <= ms->to)
  127. break;
  128. ok = ms != nil;
  129. break;
  130. case SKHeader:
  131. ok = headerSearch(m, s->hdr, s->s);
  132. break;
  133. case SKBody:
  134. case SKText:
  135. if(s->key == SKText && cistrstr(m->head.buf, s->s)){
  136. ok = 1;
  137. break;
  138. }
  139. ok = fileSearch(m, "body", s->s);
  140. break;
  141. }
  142. }
  143. return ok;
  144. }
  145. static int
  146. fileSearch(Msg *m, char *file, char *pat)
  147. {
  148. char buf[BufSize + 1];
  149. int n, nbuf, npat, fd, ok;
  150. npat = strlen(pat);
  151. if(npat >= BufSize / 2)
  152. return 0;
  153. fd = msgFile(m, file);
  154. if(fd < 0)
  155. return 0;
  156. ok = 0;
  157. nbuf = 0;
  158. for(;;){
  159. n = read(fd, &buf[nbuf], BufSize - nbuf);
  160. if(n <= 0)
  161. break;
  162. nbuf += n;
  163. buf[nbuf] = '\0';
  164. if(cistrstr(buf, pat) != nil){
  165. ok = 1;
  166. break;
  167. }
  168. if(nbuf > npat){
  169. memmove(buf, &buf[nbuf - npat], npat);
  170. nbuf = npat;
  171. }
  172. }
  173. close(fd);
  174. return ok;
  175. }
  176. static int
  177. headerSearch(Msg *m, char *hdr, char *pat)
  178. {
  179. SList hdrs;
  180. char *s, *t;
  181. int ok, n;
  182. n = m->head.size + 3;
  183. s = emalloc(n);
  184. hdrs.next = nil;
  185. hdrs.s = hdr;
  186. ok = 0;
  187. if(selectFields(s, n, m->head.buf, &hdrs, 1) > 0){
  188. t = strchr(s, ':');
  189. if(t != nil && cistrstr(t+1, pat) != nil)
  190. ok = 1;
  191. }
  192. free(s);
  193. return ok;
  194. }
  195. static int
  196. addrSearch(MAddr *a, char *s)
  197. {
  198. char *ok, *addr;
  199. for(; a != nil; a = a->next){
  200. addr = maddrStr(a);
  201. ok = cistrstr(addr, s);
  202. free(addr);
  203. if(ok != nil)
  204. return 1;
  205. }
  206. return 0;
  207. }
  208. static int
  209. dateCmp(char *date, Search *s)
  210. {
  211. Tm tm;
  212. date2tm(&tm, date);
  213. if(tm.year < s->year)
  214. return -1;
  215. if(tm.year > s->year)
  216. return 1;
  217. if(tm.mon < s->mon)
  218. return -1;
  219. if(tm.mon > s->mon)
  220. return 1;
  221. if(tm.mday < s->mday)
  222. return -1;
  223. if(tm.mday > s->mday)
  224. return 1;
  225. return 0;
  226. }