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

Annotation of /imapfilter/filter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (hide annotations)
Sat Dec 6 20:51:18 2003 UTC (20 years, 3 months ago) by lefcha
Branch: MAIN
Changes since 1.6: +2 -0 lines
File MIME type: text/plain
A maybe unitialized variable.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26