search.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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 = cistrstr(m->info[ISubject], s->s) != nil;
  101. break;
  102. case SKBefore:
  103. ok = dateCmp(m->unixDate, s) < 0;
  104. break;
  105. case SKOn:
  106. ok = dateCmp(m->unixDate, s) == 0;
  107. break;
  108. case SKSince:
  109. ok = dateCmp(m->unixDate, s) > 0;
  110. break;
  111. case SKSentBefore:
  112. ok = dateCmp(m->info[IDate], s) < 0;
  113. break;
  114. case SKSentOn:
  115. ok = dateCmp(m->info[IDate], s) == 0;
  116. break;
  117. case SKSentSince:
  118. ok = dateCmp(m->info[IDate], s) > 0;
  119. break;
  120. case SKUid:
  121. case SKSet:
  122. for(ms = s->set; ms != nil; ms = ms->next)
  123. if(s->key == SKUid && m->uid >= ms->from && m->uid <= ms->to
  124. || s->key == SKSet && m->seq >= ms->from && m->seq <= ms->to)
  125. break;
  126. ok = ms != nil;
  127. break;
  128. case SKHeader:
  129. ok = headerSearch(m, s->hdr, s->s);
  130. break;
  131. case SKBody:
  132. case SKText:
  133. if(s->key == SKText && cistrstr(m->head.buf, s->s)){
  134. ok = 1;
  135. break;
  136. }
  137. ok = fileSearch(m, "body", s->s);
  138. break;
  139. }
  140. }
  141. return ok;
  142. }
  143. static int
  144. fileSearch(Msg *m, char *file, char *pat)
  145. {
  146. char buf[BufSize + 1];
  147. int n, nbuf, npat, fd, ok;
  148. npat = strlen(pat);
  149. if(npat >= BufSize / 2)
  150. return 0;
  151. fd = msgFile(m, file);
  152. if(fd < 0)
  153. return 0;
  154. ok = 0;
  155. nbuf = 0;
  156. for(;;){
  157. n = read(fd, &buf[nbuf], BufSize - nbuf);
  158. if(n <= 0)
  159. break;
  160. nbuf += n;
  161. buf[nbuf] = '\0';
  162. if(cistrstr(buf, pat) != nil){
  163. ok = 1;
  164. break;
  165. }
  166. if(nbuf > npat){
  167. memmove(buf, &buf[nbuf - npat], npat);
  168. nbuf = npat;
  169. }
  170. }
  171. close(fd);
  172. return ok;
  173. }
  174. static int
  175. headerSearch(Msg *m, char *hdr, char *pat)
  176. {
  177. SList hdrs;
  178. char *s, *t;
  179. int ok, n;
  180. n = m->head.size + 3;
  181. s = emalloc(n);
  182. hdrs.next = nil;
  183. hdrs.s = hdr;
  184. ok = 0;
  185. if(selectFields(s, n, m->head.buf, &hdrs, 1) > 0){
  186. t = strchr(s, ':');
  187. if(t != nil && cistrstr(t+1, pat) != nil)
  188. ok = 1;
  189. }
  190. free(s);
  191. return ok;
  192. }
  193. static int
  194. addrSearch(MAddr *a, char *s)
  195. {
  196. char *ok, *addr;
  197. for(; a != nil; a = a->next){
  198. addr = maddrStr(a);
  199. ok = cistrstr(addr, s);
  200. free(addr);
  201. if(ok != nil)
  202. return 1;
  203. }
  204. return 0;
  205. }
  206. static int
  207. dateCmp(char *date, Search *s)
  208. {
  209. Tm tm;
  210. date2tm(&tm, date);
  211. if(tm.year < s->year)
  212. return -1;
  213. if(tm.year > s->year)
  214. return 1;
  215. if(tm.mon < s->mon)
  216. return -1;
  217. if(tm.mon > s->mon)
  218. return 1;
  219. if(tm.mday < s->mday)
  220. return -1;
  221. if(tm.mday > s->mday)
  222. return 1;
  223. return 0;
  224. }