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

Contents of /imapfilter/match.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations)
Mon Feb 9 20:49:01 2004 UTC (20 years, 1 month ago) by lefcha
Branch: MAIN
Changes since 1.3: +4 -2 lines
File MIME type: text/plain
Wrap some long >80 lines.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26