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

Contents of /imapfilter/filter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3.2.4 - (show annotations)
Sat Dec 6 20:51:33 2003 UTC (20 years, 3 months ago) by lefcha
Branch: release-0_9-patches
Changes since 1.3.2.3: +2 -0 lines
File MIME type: text/plain
A maybe unitialized variable.

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <strings.h>
5 #include <ctype.h>
6 #include <sys/types.h>
7 #include <time.h>
8 #include <regex.h>
9
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 filter_t *cur_fltr = NULL; /* Current filter. */
23
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 int n, len;
236 mask_t *node;
237 char *bp;
238
239 len = 0;
240
241 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 switch (mmt) {
276 case MASK_MATCH_1:
277 /* Mask is ANSWERED, DELETED, DRAFT, FLAGGED, NEW, OLD, etc. */
278
279 len = bp - node->body;
280
281 break;
282
283 case MASK_MATCH_2:
284 /* Mask is BCC, BODY, CC, FROM, SUBJECT, TEXT, TO. */
285
286 *(bp++) = ' ';
287
288 if (*(line + m[5].rm_so) != '"')
289 *(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 if (*(line + m[5].rm_so) != '"')
299 *(bp++) = '"';
300 *bp = '\0';
301
302 len = bp - node->body;
303
304 break;
305
306 case MASK_MATCH_3:
307 /* Mask is HEADER. */
308
309 *(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
321 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
331 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
337 if (*(line + m[6].rm_so) != '"')
338 *(bp++) = '"';
339 *bp = '\0';
340
341 len = bp - node->body;
342
343 break;
344
345 case MASK_MATCH_4:
346 /* Mask is LARGER, SMALLER, OLDER, NEWER. */
347
348 *(bp++) = ' ';
349
350 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
357 /* Mask length after conversion to IMAP4rev1 date format. */
358 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
365 break;
366 default:
367 break;
368 }
369
370 APPEND_LINKED_LIST(cur_fltr->masks, node, mask);
371
372 cur_fltr->masknum++;
373 cur_fltr->masklen += len;
374
375 #ifdef DEBUG
376 fprintf(stderr, "debug: MASK: '%s'\n", node->body);
377 #endif
378
379 return 0;
380 }
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