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

Contents of /imapfilter/match.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (show annotations)
Sat Feb 14 19:14:43 2004 UTC (16 years, 8 months ago) by lefcha
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +7 -8 lines
File MIME type: text/plain
Indentation.

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 options_t opts;
11 extern connection_t connpri, connaux;
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 match the
56 * 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 response_search(&connpri, imap_search(&connpri, opts.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 masks are
84 * 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 masks are
161 * 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") || strstr(body, "NEWER")) {
238 xstrncpy(nb, body, MASK_BODY_LEN - 1);
239 convert_date(nb);
240
241 return nb;
242 }
243 return body;
244 }
245
246
247 /*
248 * Converts masks related to date filtering, because IMAP servers do not
249 * understand for example "OLDER 3", but "BEFORE 18-Oct-2001" (if
250 * hypothetically current date was 21-Oct-2001).
251 */
252 void
253 convert_date(char *body)
254 {
255 char *cp, *c;
256 char s[16];
257 time_t te;
258 struct tm *tl;
259
260 cp = xstrdup(body);
261 body[0] = '\0';
262
263 if (strstr(cp, "NOT"))
264 strncat(body, "NOT ", 4);
265
266 if ((c = strstr(cp, "OLDER")))
267 strncat(body, "BEFORE ", 7);
268 else if ((c = strstr(cp, "NEWER")))
269 strncat(body, "SINCE ", 6);
270
271 c += 6;
272
273 te = time(NULL) - (time_t) (strtoul(c, NULL, 10) * 24 * 60 * 60);
274 tl = localtime(&te);
275
276 if (strftime(s, 15, "%d-%b-%Y", tl))
277 strncat(body, s, 15);
278
279 xfree(cp);
280 }
281
282
283 /*
284 * Empty the FIFO inventory.
285 */
286 void
287 empty_fifo(mask_t ** mfifo)
288 {
289
290 mfifo[0] = NULL;
291
292 queue_fifo(NULL, NULL);
293 dequeue_fifo(NULL);
294 }
295
296
297 /*
298 * Add item to FIFO inventory.
299 */
300 void
301 queue_fifo(mask_t ** mfifo, mask_t * mask)
302 {
303 static unsigned int i;
304
305 if (mfifo == NULL) {
306 i = 0;
307 return;
308 }
309 mfifo[i++] = mask;
310 mfifo[i] = NULL;
311 }
312
313
314 /*
315 * Get next item from FIFO inventory.
316 */
317 mask_t *
318 dequeue_fifo(mask_t ** mfifo)
319 {
320 static unsigned int j;
321
322 if (mfifo == NULL) {
323 j = 0;
324 return NULL;
325 }
326 return mfifo[j++];
327 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26