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

Annotation of /imapfilter/filter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3.2.2 - (hide annotations)
Sat Nov 8 16:59:54 2003 UTC (20 years, 4 months ago) by lefcha
Branch: release-0_9-patches
Changes since 1.3.2.1: +70 -61 lines
File MIME type: text/plain
Bugfix; while in daemon mode the dates of BEFORE and SINCE search queries
where not updated.

1 lefcha 1.1 #include <stdio.h>
2 lefcha 1.3 #include <stdlib.h>
3 lefcha 1.1 #include <string.h>
4 lefcha 1.3.2.1 #include <strings.h>
5 lefcha 1.1 #include <ctype.h>
6 lefcha 1.3.2.1 #include <sys/types.h>
7 lefcha 1.3 #include <time.h>
8 lefcha 1.3.2.1 #include <regex.h>
9 lefcha 1.1
10     #include "config.h"
11     #include "imapfilter.h"
12     #include "account.h"
13     #include "filter.h"
14     #include "struct.h"
15    
16    
17     extern account_t *accounts;
18     extern mboxgrp_t *mboxgrps;
19    
20     filter_t *filters = NULL; /* First node of filters tree. */
21    
22 lefcha 1.2 filter_t *cur_fltr = NULL; /* Current filter. */
23 lefcha 1.1
24    
25     void init_filter(filter_t * node);
26    
27     void init_mask(mask_t * node);
28    
29     void link_mbox_filter(filter_t * cf, mboxgrp_t * cg);
30    
31     void string_upper(char *str, size_t size);
32    
33    
34     /*
35     * Set new filter's variables to safe values.
36     */
37     void
38     init_filter(filter_t * node)
39     {
40     node->left = node->right = NULL;
41     node->key[0] = '\0';
42     node->mode = FILTER_MODE_AND;
43     node->action.type = node->action.msgflags = 0;
44     node->action.raccount = NULL;
45     node->action.destmbox[0] = node->action.args[0] = '\0';
46     node->masks = NULL;
47     node->masknum = node->masklen = 0;
48     }
49    
50    
51     /*
52     * A filter entry was declared, create it and set it's variables accordingly.
53     */
54     int
55     set_filter(char *line, regmatch_t * m)
56     {
57     filter_t *node;
58    
59     if (cur_fltr != NULL && cur_fltr->action.type == 0)
60     return ERROR_CONFIG_PARSE;
61    
62     node = (filter_t *) xmalloc(sizeof(filter_t));
63    
64     init_filter(node);
65    
66     strncat(node->key, line + m[1].rm_so,
67     min(m[1].rm_eo - m[1].rm_so, KEY_LEN - 1));
68    
69     if (m[2].rm_so != -1) {
70     if (!strncasecmp(line + m[2].rm_so + 1, "or", 2))
71     node->mode = FILTER_MODE_OR;
72     else
73     node->mode = FILTER_MODE_AND;
74     }
75     #ifdef DEBUG
76     fprintf(stderr, "debug: FILTER: '%s' %s\n", node->key,
77     (node->mode == FILTER_MODE_OR ? "OR" : "AND"));
78     #endif
79    
80     INSERT_TREE(filters, node, filter);
81    
82     cur_fltr = node;
83    
84     return 0;
85     }
86    
87    
88     /*
89     * Assign an action to the last declared filter.
90     */
91     int
92     set_action(char *line, regmatch_t * m)
93     {
94     char *c, *cp, *t;
95     account_t *a;
96    
97     if (cur_fltr == NULL)
98     return ERROR_CONFIG_PARSE;
99    
100     if (!strncasecmp(line + m[1].rm_so, "delete", 6))
101     cur_fltr->action.type = FILTER_ACTION_DELETE;
102     else if (!strncasecmp(line + m[1].rm_so, "copy", 4)) {
103     cur_fltr->action.type = FILTER_ACTION_COPY;
104     if (*(line + m[2].rm_so) == '"' &&
105     *(line + m[2].rm_eo - 1) == '"')
106     strncat(cur_fltr->action.destmbox,
107     line + m[2].rm_so + 1,
108     min(m[2].rm_eo - m[2].rm_so - 2,
109     MBOX_NAME_LEN - 1));
110     else
111     strncat(cur_fltr->action.destmbox, line + m[2].rm_so,
112     min(m[2].rm_eo - m[2].rm_so, MBOX_NAME_LEN - 1));
113     } else if (!strncasecmp(line + m[1].rm_so, "move", 4)) {
114     cur_fltr->action.type = FILTER_ACTION_MOVE;
115     if (*(line + m[3].rm_so) == '"' &&
116     *(line + m[3].rm_eo - 1) == '"')
117     strncat(cur_fltr->action.destmbox,
118     line + m[3].rm_so + 1,
119     min(m[3].rm_eo - m[3].rm_so - 2,
120     MBOX_NAME_LEN - 1));
121     else
122     strncat(cur_fltr->action.destmbox, line + m[3].rm_so,
123     min(m[3].rm_eo - m[3].rm_so, MBOX_NAME_LEN - 1));
124     } else if (!strncasecmp(line + m[1].rm_so, "rcopy", 5)) {
125     cur_fltr->action.type = FILTER_ACTION_RCOPY;
126     for (a = accounts; a; a = a->next)
127     if (!strncasecmp(line + m[4].rm_so, a->key,
128     strlen(a->key)))
129     cur_fltr->action.raccount = a;
130     if (!cur_fltr->action.raccount)
131     return ERROR_CONFIG_PARSE;
132    
133     if (*(line + m[5].rm_so) == '"' &&
134     *(line + m[5].rm_eo - 1) == '"')
135     strncat(cur_fltr->action.destmbox,
136     line + m[5].rm_so + 1,
137     min(m[5].rm_eo - m[5].rm_so - 2,
138     MBOX_NAME_LEN - 1));
139     else
140     strncat(cur_fltr->action.destmbox, line + m[5].rm_so,
141     min(m[5].rm_eo - m[5].rm_so, MBOX_NAME_LEN - 1));
142     } else if (!strncasecmp(line + m[1].rm_so, "rmove", 5)) {
143     cur_fltr->action.type = FILTER_ACTION_RMOVE;
144     for (a = accounts; a; a = a->next)
145     if (!strncasecmp(line + m[6].rm_so, a->key,
146     strlen(a->key)))
147     cur_fltr->action.raccount = a;
148     if (!cur_fltr->action.raccount)
149     return ERROR_CONFIG_PARSE;
150    
151     if (*(line + m[7].rm_so) == '"' &&
152     *(line + m[7].rm_eo - 1) == '"')
153     strncat(cur_fltr->action.destmbox,
154     line + m[7].rm_so + 1,
155     min(m[7].rm_eo - m[7].rm_so - 2,
156     MBOX_NAME_LEN - 1));
157     else
158     strncat(cur_fltr->action.destmbox, line + m[7].rm_so,
159     min(m[7].rm_eo - m[7].rm_so, MBOX_NAME_LEN - 1));
160     } else if (!strncasecmp(line + m[1].rm_so, "flag", 4)) {
161     if (!strncasecmp(line + m[8].rm_so, "replace", 7))
162     cur_fltr->action.type = FILTER_ACTION_FLAG_REPLACE;
163     else if (!strncasecmp(line + m[8].rm_so, "add", 3))
164     cur_fltr->action.type = FILTER_ACTION_FLAG_ADD;
165     else
166     cur_fltr->action.type = FILTER_ACTION_FLAG_REMOVE;
167    
168     c = cp = (char *)malloc(m[9].rm_eo - m[9].rm_so + 1);
169     xstrncpy(c, line + m[9].rm_so, m[9].rm_eo - m[9].rm_so);
170    
171     t = strtok_r(c, ",", &c);
172     while (t) {
173     if (!strcasecmp(t, "none")) {
174     if (m[9].rm_eo - m[9].rm_so != strlen("none"))
175     return ERROR_CONFIG_PARSE;
176     } else if (!strcasecmp(t, "seen"))
177     cur_fltr->action.msgflags |= MESSAGE_FLAG_SEEN;
178     else if (!strcasecmp(t, "answered"))
179     cur_fltr->action.msgflags |=
180     MESSAGE_FLAG_ANSWERED;
181     else if (!strcasecmp(t, "flagged"))
182     cur_fltr->action.msgflags |=
183     MESSAGE_FLAG_FLAGGED;
184     else if (!strcasecmp(t, "deleted"))
185     cur_fltr->action.msgflags |=
186     MESSAGE_FLAG_DELETED;
187     else if (!strcasecmp(t, "draft"))
188     cur_fltr->action.msgflags |= MESSAGE_FLAG_DRAFT;
189     else
190     return ERROR_CONFIG_PARSE;
191    
192     t = strtok_r(NULL, ",", &c);
193     }
194     xfree(cp);
195     } else if (!strncasecmp(line + m[1].rm_so, "list", 4)) {
196     cur_fltr->action.type = FILTER_ACTION_LIST;
197     }
198     if (m[10].rm_so != -1) {
199     strncat(cur_fltr->action.args, line + m[10].rm_so,
200     min(m[10].rm_eo - m[10].rm_so, ARGS_LEN - 2));
201     while ((c = strchr(cur_fltr->action.args, ',')))
202     *c = ' ';
203     }
204     #ifdef DEBUG
205     fprintf(stderr, "debug: ACTION: %d '%s' '%s' %d '%s'\n",
206     cur_fltr->action.type,
207     (cur_fltr->action.raccount ? cur_fltr->action.raccount->key : ""),
208     cur_fltr->action.destmbox,
209     cur_fltr->action.msgflags,
210     cur_fltr->action.args);
211     #endif
212     return 0;
213     }
214    
215    
216     /*
217     * Set new mask's variables to safe values.
218     */
219     void
220     init_mask(mask_t * node)
221     {
222     node->next = NULL;
223     node->body[0] = '\0';
224     node->type = 0;
225     }
226    
227    
228     /*
229     * A new mask entry was declared, create it and set it's
230     * variables accordingly.
231     */
232     int
233     set_mask(char *line, regmatch_t * m, int mmt)
234     {
235 lefcha 1.3.2.2 int n, len;
236 lefcha 1.1 mask_t *node;
237     char *bp;
238    
239     if (cur_fltr == NULL)
240     return ERROR_CONFIG_PARSE;
241    
242     node = (mask_t *) xmalloc(sizeof(mask_t));
243    
244     init_mask(node);
245    
246     bp = node->body;
247    
248     /* If specified set mask's type. */
249     if (m[2].rm_so != -1 && cur_fltr->masks) {
250     if (!strncasecmp(line + m[2].rm_so, "or", 2)) {
251     node->type = MASK_TYPE_OR;
252     } else
253     node->type = MASK_TYPE_AND;
254     }
255     /* Add NOT if specified. */
256     if (m[3].rm_so != -1) {
257     n = min(m[3].rm_eo - m[3].rm_so,
258     MASK_BODY_LEN - (bp - node->body) - 1);
259     xstrncpy(bp, line + m[3].rm_so, n);
260     string_upper(bp, n);
261     *(bp + n - 1) = ' '; /* In case it's '\t'. */
262     *(bp + n) = '\0';
263     bp += n;
264     }
265     /* Keyword of the search key. */
266     n = min(m[4].rm_eo - m[4].rm_so,
267     MASK_BODY_LEN - (bp - node->body) - 3);
268     xstrncpy(bp, line + m[4].rm_so, n);
269     string_upper(bp, n);
270     *(bp + n) = '\0';
271     bp += n;
272    
273 lefcha 1.3.2.2 switch (mmt) {
274     case MASK_MATCH_1:
275     len = bp - node->body;
276    
277     break;
278    
279     case MASK_MATCH_2:
280 lefcha 1.1 *(bp++) = ' ';
281    
282 lefcha 1.3.2.2 if (*(line + m[5].rm_so) != '"')
283 lefcha 1.1 *(bp++) = '"';
284     *bp = '\0';
285    
286     n = min(m[5].rm_eo - m[5].rm_so,
287     MASK_BODY_LEN - (bp - node->body) - 2);
288     xstrncpy(bp, line + m[5].rm_so, n);
289     *(bp + n) = '\0';
290     bp += n;
291    
292 lefcha 1.3.2.2 if (*(line + m[5].rm_so) != '"')
293 lefcha 1.1 *(bp++) = '"';
294     *bp = '\0';
295    
296 lefcha 1.3.2.2 len = bp - node->body;
297 lefcha 1.1
298 lefcha 1.3.2.2 break;
299 lefcha 1.1
300 lefcha 1.3.2.2 case MASK_MATCH_3:
301     *(bp++) = ' ';
302 lefcha 1.1
303 lefcha 1.3.2.2 if (*(line + m[5].rm_so) != '"')
304     *(bp++) = '"';
305     *bp = '\0';
306 lefcha 1.1
307 lefcha 1.3.2.2 n = min(m[5].rm_eo - m[5].rm_so,
308     MASK_BODY_LEN - (bp - node->body) - 2);
309     xstrncpy(bp, line + m[5].rm_so, n);
310     *(bp + n) = '\0';
311     bp += n;
312 lefcha 1.1
313 lefcha 1.3.2.2 if (*(line + m[5].rm_so) != '"')
314     *(bp++) = '"';
315     *bp = '\0';
316 lefcha 1.1
317 lefcha 1.3.2.2 *(bp++) = ' ';
318 lefcha 1.1
319 lefcha 1.3.2.2 if (*(line + m[6].rm_so) != '"')
320     *(bp++) = '"';
321     *bp = '\0';
322    
323     n = min(m[6].rm_eo - m[6].rm_so,
324     MASK_BODY_LEN - (bp - node->body) - 2);
325     xstrncpy(bp, line + m[6].rm_so, n);
326     *(bp + n) = '\0';
327     bp += n;
328    
329     if (*(line + m[6].rm_so) != '"')
330     *(bp++) = '"';
331     *bp = '\0';
332    
333     len = bp - node->body;
334    
335     break;
336    
337     case MASK_MATCH_4:
338     *(bp++) = ' ';
339    
340     n = min(m[5].rm_eo - m[5].rm_so,
341     MASK_BODY_LEN - (bp - node->body) - 2);
342     xstrncpy(bp, line + m[5].rm_so, n);
343     *(bp + n) = '\0';
344     bp += n;
345     *bp = '\0';
346 lefcha 1.1
347 lefcha 1.3.2.2 if (strstr(node->body, "OLDER"))
348     len = strlen("NOT BEFORE DD-MMM-YYYY");
349     else if (strstr(node->body, "NEWER"))
350     len = strlen("NOT SINCE DD-MMM-YYYY");
351     else
352     len = bp - node->body;
353 lefcha 1.1
354 lefcha 1.3.2.2 break;
355     default:
356     break;
357     }
358 lefcha 1.1
359 lefcha 1.3.2.2 APPEND_LINKED_LIST(cur_fltr->masks, node, mask);
360 lefcha 1.1
361 lefcha 1.3.2.2 cur_fltr->masknum++;
362     cur_fltr->masklen += len;
363 lefcha 1.1
364 lefcha 1.3.2.2 #ifdef DEBUG
365     fprintf(stderr, "debug: MASK: '%s'\n", node->body);
366     #endif
367 lefcha 1.1
368 lefcha 1.3.2.2 return 0;
369 lefcha 1.1 }
370    
371    
372     /*
373     * A new job was declared, link filters with mailbox-groups.
374     */
375     int
376     set_job(char *line, regmatch_t * match)
377     {
378     int n;
379     char *ftok, *gtok, *fltr, *mbgrp, *f, *g;
380     filter_t *cf;
381     mboxgrp_t *cg;
382    
383     if (accounts == NULL || filters == NULL || cur_fltr->action.type == 0)
384     return ERROR_CONFIG_PARSE;
385    
386     n = match[1].rm_eo - match[1].rm_so;
387     fltr = (char *)xmalloc(n + 1);
388    
389     f = xstrncpy(fltr, line + match[1].rm_so, n);
390     f[n] = '\0';
391    
392     n = match[2].rm_eo - match[2].rm_so;
393     mbgrp = (char *)xmalloc(n + 1);
394    
395     /* Go through filters. */
396     ftok = strtok_r(f, ",", &f);
397     while (ftok != NULL) {
398     FIND_TREE(filters, ftok, cf);
399     if (cf == NULL)
400     return ERROR_CONFIG_PARSE;
401    
402     g = xstrncpy(mbgrp, line + match[2].rm_so, n);
403     g[n] = '\0';
404    
405     /* Go through mailbox groups. */
406     gtok = strtok_r(g, ",", &g);
407     while (gtok != NULL) {
408     FIND_TREE(mboxgrps, gtok, cg);
409     if (cg == NULL)
410     return ERROR_CONFIG_PARSE;
411     link_mbox_filter(cf, cg);
412    
413     gtok = strtok_r(NULL, ",", &g);
414     }
415    
416     ftok = strtok_r(NULL, ",", &f);
417     }
418    
419     xfree(fltr);
420     xfree(mbgrp);
421    
422     return 0;
423     }
424    
425    
426     /*
427     * Link a filter with a mailbox.
428     */
429     void
430     link_mbox_filter(filter_t * cf, mboxgrp_t * cg)
431     {
432     int i, j, f;
433    
434     for (i = 0; cg->mboxes[i] != NULL; i++) {
435     for (f = j = 0; cg->mboxes[i]->filters[j] != NULL; j++)
436     if (j == MBOX_FILTERS_MAX - 1 ||
437     !strcmp(cf->key, cg->mboxes[i]->filters[j]->key))
438     f = 1;
439    
440     if (f)
441     continue;
442    
443     cg->mboxes[i]->filters[j] = cf;
444     cg->mboxes[i]->filters[j + 1] = NULL;
445    
446     }
447    
448     #ifdef DEBUG
449     fprintf(stderr, "debug: JOB: '%s' '%s'\n", cf->key, cg->key);
450     #endif
451     }
452    
453    
454     /*
455     * Convert a string of specified size to upper case.
456     */
457     void
458     string_upper(char *str, size_t size)
459     {
460     unsigned int i;
461    
462     for (i = 0; i < size; i++, str++)
463     *str = toupper(*str);
464     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26