/[imapfilter]/imapfilter/match.c
ViewVC logotype

Contents of /imapfilter/match.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations)
Sat Nov 8 14:23:18 2003 UTC (20 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.1: +68 -4 lines
File MIME type: text/plain
Bugfix; while in daemon mode the dates of BEFORE and SINCE search queries
where not updated.

1 #include <stdio.h>
2 #include <string.h>
3
4 #include "config.h"
5 #include "imapfilter.h"
6 #include "account.h"
7 #include "filter.h"
8
9
10 extern conn_t connpri, connaux;
11 extern char charset[CHARSET_LEN];
12
13
14 int match_filter(filter_t * filter, char **mesgs);
15
16 char *generate_filter_and(mask_t * mask, unsigned int masknum, unsigned int masklen);
17 char *generate_filter_or(mask_t * mask, unsigned int masknum, unsigned int masklen);
18 char *normalize_mask(char *body);
19 void convert_date(char *body);
20
21 void empty_fifo(mask_t ** mfifo);
22 void queue_fifo(mask_t ** mfifo, mask_t * mask);
23 mask_t *dequeue_fifo(mask_t ** mfifo);
24
25
26 /*
27 * Match and apply filters assigned to a mailbox.
28 */
29 int
30 apply_filters(char *mbox, filter_t ** filters)
31 {
32 int i;
33 char *mesgs;
34
35 for (i = 0; filters[i] != NULL; i++) {
36 mesgs = NULL;
37
38 if (match_filter(filters[i], &mesgs))
39 continue;
40
41 log_info(LOG_FILTER, filters[i]->key);
42
43 apply_action(mbox, mesgs, &(filters[i]->action.type),
44 filters[i]->action.raccount, filters[i]->action.destmbox,
45 &filters[i]->action.msgflags, filters[i]->action.args);
46
47 xfree(mesgs);
48 }
49
50 return 0;
51 }
52
53
54 /*
55 * Generate the search request by the masks of the filter and try to
56 * match the generated filter.
57 */
58 int
59 match_filter(filter_t * filter, char **mesgs)
60 {
61 char *search;
62
63 if (filter->mode == FILTER_MODE_OR)
64 search = generate_filter_or(filter->masks, filter->masknum,
65 filter->masklen);
66 else
67 search = generate_filter_and(filter->masks, filter->masknum,
68 filter->masklen);
69
70 search_response(&connpri, imap_search(&connpri, charset, search),
71 mesgs);
72
73 xfree(search);
74
75 if (*mesgs == '\0')
76 return 1;
77
78 return 0;
79 }
80
81
82 /*
83 * Generate the filter search command from the masks, assuming that
84 * masks are AND-ed.
85 */
86 char *
87 generate_filter_and(mask_t * mask, unsigned int masknum,
88 unsigned int masklen)
89 {
90 const unsigned int searchbuf = masklen + masknum * 6 + 8;
91 unsigned int len;
92 char *search;
93 mask_t *tmp;
94
95 len = 0;
96
97 search = (char *)xmalloc(sizeof(char) * searchbuf);
98 search[0] = '\0';
99
100 tmp = mask;
101 if (tmp == NULL) {
102 strncat(search, "ALL ", searchbuf - len - 1);
103 len += 4;
104 } else
105 while ((tmp = tmp->next) != NULL) {
106 if (tmp->type != MASK_TYPE_OR) {
107 strncat(search, "ALL ", searchbuf - len - 1);
108 len += 4;
109 break;
110 }
111 }
112
113 tmp = NULL;
114 while (mask != NULL) {
115 tmp = mask;
116 mask = mask->next;
117
118 if (mask != NULL && mask->type == MASK_TYPE_OR) {
119 strncat(search, "OR (", searchbuf - len - 1);
120 len += 4;
121
122 strncat(search, normalize_mask(tmp->body),
123 searchbuf - len - 1);
124 len = strlen(search);
125 search[len] = ' ';
126 search[++len] = '\0';
127
128 search[len - 1] = ')';
129 search[len] = ' ';
130 search[++len] = '\0';
131
132 if (mask->next == NULL ||
133 mask->next->type != MASK_TYPE_OR) {
134 search[len] = '(';
135 search[++len] = '\0';
136 strncat(search, normalize_mask(mask->body),
137 searchbuf - len - 1);
138 len = strlen(search);
139 search[len] = ')';
140 search[++len] = ' ';
141 search[++len] = '\0';
142 mask = mask->next;
143 }
144 } else {
145 strncat(search, normalize_mask(tmp->body),
146 searchbuf - len - 1);
147 len = strlen(search);
148 search[len] = ' ';
149 search[++len] = '\0';
150 }
151 }
152
153 search[len - 1] = '\0';
154
155 return search;
156 }
157
158
159 /*
160 * Generate the filter search command from the masks, assuming that
161 * masks are OR-ed.
162 */
163 char *
164 generate_filter_or(mask_t * mask, unsigned int masknum,
165 unsigned int masklen)
166 {
167 const unsigned int searchbuf = masklen + masknum * 6 + 8;
168 unsigned int len;
169 char *search;
170 mask_t **mfifo; /* Mailbox FIFO queue. */
171 mask_t *mf; /* Mask returned from FIFO. */
172
173 len = 0;
174
175 search = (char *)xmalloc(sizeof(char) * searchbuf);
176 mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
177
178 search[0] = '\0';
179 empty_fifo(mfifo);
180
181 strncat(search, "ALL ", searchbuf - len - 1);
182 len += 4;
183
184 while (mask != NULL) {
185 queue_fifo(mfifo, mask);
186 mask = mask->next;
187
188 while (mask != NULL && mask->type == MASK_TYPE_AND) {
189 queue_fifo(mfifo, mask);
190 mask = mask->next;
191 }
192
193 if (mask != NULL) {
194 if (len == 4 && search[0] == 'A') {
195 search[0] = '\0';
196 len = 0;
197 }
198 strncat(search, "OR ", searchbuf - len - 1);
199 len += 3;
200 }
201 if (search[0] != 'A') {
202 search[len] = '(';
203 search[++len] = '\0';
204 }
205 while ((mf = dequeue_fifo(mfifo)) != NULL) {
206 strncat(search, normalize_mask(mf->body), searchbuf - len - 1);
207 len = strlen(search);
208 search[len] = ' ';
209 search[++len] = '\0';
210 }
211
212 if (strchr(search, '(')) {
213 search[len - 1] = ')';
214 search[len] = ' ';
215 search[++len] = '\0';
216 }
217 empty_fifo(mfifo);
218 }
219
220 search[len - 1] = '\0';
221
222 xfree(mfifo);
223
224 return search;
225 }
226
227
228 /*
229 * Make any necessary conversions to the mask body before sending it to server.
230 */
231 char *
232 normalize_mask(char *body)
233 {
234 static char nb[MASK_BODY_LEN];
235
236
237 if (strstr(body, "OLDER") ||
238 strstr(body, "NEWER")) {
239 xstrncpy(nb, body, MASK_BODY_LEN - 1);
240 convert_date(nb);
241
242 return nb;
243 }
244 return body;
245 }
246
247
248 /*
249 * Converts masks related to date filtering, because IMAP servers do not
250 * understand for example "OLDER 3", but "BEFORE 18-Oct-2001" (if
251 * hypothetically current date was 21-Oct-2001).
252 */
253 void
254 convert_date(char *body)
255 {
256 char *cp, *c;
257 char s[16];
258 time_t te;
259 struct tm *tl;
260
261 cp = xstrdup(body);
262 body[0] = '\0';
263
264 if (strstr(cp, "NOT"))
265 strncat(body, "NOT ", 4);
266
267 if ((c = strstr(cp, "OLDER")))
268 strncat(body, "BEFORE ", 7);
269 else if ((c = strstr(cp, "NEWER")))
270 strncat(body, "SINCE ", 6);
271
272 c += 6;
273
274 te = time(NULL) - (time_t) (strtoul(c, NULL, 10) * 24 * 60 * 60);
275 tl = localtime(&te);
276
277 if (strftime(s, 15, "%d-%b-%Y", tl))
278 strncat(body, s, 15);
279
280 xfree(cp);
281 }
282
283
284
285
286
287
288 /*
289 * Empty the FIFO inventory.
290 */
291 void
292 empty_fifo(mask_t ** mfifo)
293 {
294 mfifo[0] = NULL;
295
296 queue_fifo(NULL, NULL);
297 dequeue_fifo(NULL);
298 }
299
300
301 /*
302 * Add item to FIFO inventory.
303 */
304 void
305 queue_fifo(mask_t ** mfifo, mask_t * mask)
306 {
307 static unsigned int i;
308
309 if (mfifo == NULL) {
310 i = 0;
311 return;
312 }
313 mfifo[i++] = mask;
314 mfifo[i] = NULL;
315 }
316
317
318 /*
319 * Get next item from FIFO inventory.
320 */
321 mask_t *
322 dequeue_fifo(mask_t ** mfifo)
323 {
324 static unsigned int j;
325
326 if (mfifo == NULL) {
327 j = 0;
328 return NULL;
329 }
330 return mfifo[j++];
331 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26