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

Annotation of /imapfilter/filter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations)
Sun Nov 23 22:45:10 2003 UTC (20 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.5: +9 -0 lines
File MIME type: text/plain
Added some comments to set_mask().

1 lefcha 1.1 #include <stdio.h>
2 lefcha 1.3 #include <stdlib.h>
3 lefcha 1.1 #include <string.h>
4 lefcha 1.4 #include <strings.h>
5 lefcha 1.1 #include <ctype.h>
6 lefcha 1.4 #include <sys/types.h>
7 lefcha 1.3 #include <time.h>
8 lefcha 1.4 #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.5 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.5 switch (mmt) {
274     case MASK_MATCH_1:
275 lefcha 1.6 /* Mask is ANSWERED, DELETED, DRAFT, FLAGGED, NEW, OLD, etc. */
276    
277 lefcha 1.5 len = bp - node->body;
278    
279     break;
280    
281     case MASK_MATCH_2:
282 lefcha 1.6 /* Mask is BCC, BODY, CC, FROM, SUBJECT, TEXT, TO. */
283    
284 lefcha 1.1 *(bp++) = ' ';
285    
286 lefcha 1.5 if (*(line + m[5].rm_so) != '"')
287 lefcha 1.1 *(bp++) = '"';
288     *bp = '\0';
289    
290     n = min(m[5].rm_eo - m[5].rm_so,
291     MASK_BODY_LEN - (bp - node->body) - 2);
292     xstrncpy(bp, line + m[5].rm_so, n);
293     *(bp + n) = '\0';
294     bp += n;
295    
296 lefcha 1.5 if (*(line + m[5].rm_so) != '"')
297 lefcha 1.1 *(bp++) = '"';
298     *bp = '\0';
299    
300 lefcha 1.5 len = bp - node->body;
301    
302     break;
303    
304     case MASK_MATCH_3:
305 lefcha 1.6 /* Mask is HEADER. */
306    
307 lefcha 1.5 *(bp++) = ' ';
308    
309     if (*(line + m[5].rm_so) != '"')
310     *(bp++) = '"';
311     *bp = '\0';
312    
313     n = min(m[5].rm_eo - m[5].rm_so,
314     MASK_BODY_LEN - (bp - node->body) - 2);
315     xstrncpy(bp, line + m[5].rm_so, n);
316     *(bp + n) = '\0';
317     bp += n;
318 lefcha 1.1
319 lefcha 1.5 if (*(line + m[5].rm_so) != '"')
320     *(bp++) = '"';
321     *bp = '\0';
322    
323     *(bp++) = ' ';
324    
325     if (*(line + m[6].rm_so) != '"')
326     *(bp++) = '"';
327     *bp = '\0';
328 lefcha 1.1
329 lefcha 1.5 n = min(m[6].rm_eo - m[6].rm_so,
330     MASK_BODY_LEN - (bp - node->body) - 2);
331     xstrncpy(bp, line + m[6].rm_so, n);
332     *(bp + n) = '\0';
333     bp += n;
334 lefcha 1.1
335 lefcha 1.5 if (*(line + m[6].rm_so) != '"')
336     *(bp++) = '"';
337     *bp = '\0';
338 lefcha 1.1
339 lefcha 1.5 len = bp - node->body;
340 lefcha 1.1
341 lefcha 1.5 break;
342 lefcha 1.1
343 lefcha 1.5 case MASK_MATCH_4:
344 lefcha 1.6 /* Mask is LARGER, SMALLER, OLDER, NEWER. */
345    
346 lefcha 1.5 *(bp++) = ' ';
347 lefcha 1.1
348 lefcha 1.5 n = min(m[5].rm_eo - m[5].rm_so,
349     MASK_BODY_LEN - (bp - node->body) - 2);
350     xstrncpy(bp, line + m[5].rm_so, n);
351     *(bp + n) = '\0';
352     bp += n;
353     *bp = '\0';
354 lefcha 1.1
355 lefcha 1.6 /* Mask length after conversion to IMAP4rev1 date format. */
356 lefcha 1.5 if (strstr(node->body, "OLDER"))
357     len = strlen("NOT BEFORE DD-MMM-YYYY");
358     else if (strstr(node->body, "NEWER"))
359     len = strlen("NOT SINCE DD-MMM-YYYY");
360     else
361     len = bp - node->body;
362 lefcha 1.1
363 lefcha 1.5 break;
364     default:
365     break;
366     }
367 lefcha 1.1
368 lefcha 1.5 APPEND_LINKED_LIST(cur_fltr->masks, node, mask);
369 lefcha 1.1
370 lefcha 1.5 cur_fltr->masknum++;
371     cur_fltr->masklen += len;
372 lefcha 1.1
373 lefcha 1.5 #ifdef DEBUG
374     fprintf(stderr, "debug: MASK: '%s'\n", node->body);
375     #endif
376 lefcha 1.1
377 lefcha 1.5 return 0;
378 lefcha 1.1 }
379    
380    
381     /*
382     * A new job was declared, link filters with mailbox-groups.
383     */
384     int
385     set_job(char *line, regmatch_t * match)
386     {
387     int n;
388     char *ftok, *gtok, *fltr, *mbgrp, *f, *g;
389     filter_t *cf;
390     mboxgrp_t *cg;
391    
392     if (accounts == NULL || filters == NULL || cur_fltr->action.type == 0)
393     return ERROR_CONFIG_PARSE;
394    
395     n = match[1].rm_eo - match[1].rm_so;
396     fltr = (char *)xmalloc(n + 1);
397    
398     f = xstrncpy(fltr, line + match[1].rm_so, n);
399     f[n] = '\0';
400    
401     n = match[2].rm_eo - match[2].rm_so;
402     mbgrp = (char *)xmalloc(n + 1);
403    
404     /* Go through filters. */
405     ftok = strtok_r(f, ",", &f);
406     while (ftok != NULL) {
407     FIND_TREE(filters, ftok, cf);
408     if (cf == NULL)
409     return ERROR_CONFIG_PARSE;
410    
411     g = xstrncpy(mbgrp, line + match[2].rm_so, n);
412     g[n] = '\0';
413    
414     /* Go through mailbox groups. */
415     gtok = strtok_r(g, ",", &g);
416     while (gtok != NULL) {
417     FIND_TREE(mboxgrps, gtok, cg);
418     if (cg == NULL)
419     return ERROR_CONFIG_PARSE;
420     link_mbox_filter(cf, cg);
421    
422     gtok = strtok_r(NULL, ",", &g);
423     }
424    
425     ftok = strtok_r(NULL, ",", &f);
426     }
427    
428     xfree(fltr);
429     xfree(mbgrp);
430    
431     return 0;
432     }
433    
434    
435     /*
436     * Link a filter with a mailbox.
437     */
438     void
439     link_mbox_filter(filter_t * cf, mboxgrp_t * cg)
440     {
441     int i, j, f;
442    
443     for (i = 0; cg->mboxes[i] != NULL; i++) {
444     for (f = j = 0; cg->mboxes[i]->filters[j] != NULL; j++)
445     if (j == MBOX_FILTERS_MAX - 1 ||
446     !strcmp(cf->key, cg->mboxes[i]->filters[j]->key))
447     f = 1;
448    
449     if (f)
450     continue;
451    
452     cg->mboxes[i]->filters[j] = cf;
453     cg->mboxes[i]->filters[j + 1] = NULL;
454    
455     }
456    
457     #ifdef DEBUG
458     fprintf(stderr, "debug: JOB: '%s' '%s'\n", cf->key, cg->key);
459     #endif
460     }
461    
462    
463     /*
464     * Convert a string of specified size to upper case.
465     */
466     void
467     string_upper(char *str, size_t size)
468     {
469     unsigned int i;
470    
471     for (i = 0; i < size; i++, str++)
472     *str = toupper(*str);
473     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26