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

Contents of /imapfilter/data.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (show annotations)
Mon Oct 8 08:47:48 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_6_2
Branch point for: release-0_6_2-patches
Changes since 1.10: +3 -5 lines
File MIME type: text/plain
Small changes.

1 #include <stdio.h>
2 #include <errno.h>
3 #include <sys/types.h>
4 #include <regex.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <limits.h>
8 #include <sys/stat.h>
9 #include <ctype.h>
10
11 #include "config.h"
12 #include "imapfilter.h"
13 #include "data.h"
14
15
16 account_t *accounts = NULL; /* First node of accounts linked list. */
17 filter_t *filters = NULL; /* First node of filters tree. */
18
19 static mboxgrp_t *mboxgrps = NULL; /* First node of mailbox-groups
20 tree. */
21
22 static account_t *cur_acct = NULL; /* Current account. */
23 static filter_t *cur_fltr = NULL; /* Current filter. */
24
25
26 /*
27 * Set new account's variables to safe values.
28 */
29 void init_account(account_t * node)
30 {
31 node->next = NULL;
32 node->server[0] = node->username[0] = node->password[0] = 0;
33 node->port = 143;
34 node->mboxes = NULL;
35 }
36
37
38 /*
39 * Append account node to linked list.
40 */
41 void append_account(account_t * node)
42 {
43 account_t *pos;
44 account_t **app;
45
46 APPEND_LINKED_LIST(accounts, node, pos, app);
47 }
48
49
50 /*
51 * A new account entry was declared. Create it and set it's variables
52 * accordingly.
53 */
54 int set_account(char *line, regmatch_t * match)
55 {
56 int s;
57 char p[6];
58 account_t *node;
59
60 node = (account_t *) create_node(sizeof(account_t));
61
62 init_account(node);
63
64 strncat(node->username, line + match[1].rm_so,
65 min(match[1].rm_eo - match[1].rm_so, USERNAME_LEN - 1));
66 if (strchr(node->username, '%'))
67 if (string_decode(node->username))
68 return ERROR_CONFIG_PARSE;
69 #ifdef DEBUG
70 printf("debug: USERNAME: '%s'\n", node->username);
71 #endif
72
73 strncat(node->password, line + match[2].rm_so,
74 min(match[2].rm_eo - match[2].rm_so, PASSWORD_LEN - 1));
75 if (strchr(node->password, '%'))
76 if (string_decode(node->password))
77 return ERROR_CONFIG_PARSE;
78 #ifdef DEBUG
79 printf("debug: PASSWORD: '%s'\n", node->password);
80 #endif
81
82 strncat(node->server, line + match[3].rm_so,
83 min(match[3].rm_eo - match[3].rm_so, SERVER_LEN - 1));
84 #ifdef DEBUG
85 printf("debug: SERVER: '%s'\n", node->server);
86 #endif
87
88 if (match[4].rm_so != -1) {
89 s = min(match[4].rm_eo - match[4].rm_so - 1, 5);
90 strncpy(p, line + match[4].rm_so + 1, s);
91 p[s] = 0;
92 node->port = strtoul(p, NULL, 10);
93 #ifdef DEBUG
94 printf("debug: PORT: %d\n", node->port);
95 #endif
96 }
97 append_account(node);
98 cur_acct = node;
99
100 return 0;
101 }
102
103
104 /*
105 * Set new mailbox-group's variables to safe values.
106 */
107 void init_mboxgrp(mboxgrp_t * node)
108 {
109 node->left = node->right = NULL;
110 node->key[0] = 0;
111 node->mboxes[0] = NULL;
112 }
113
114
115 /*
116 * Insert mailbox-group node in tree.
117 */
118 void insert_mboxgrp(mboxgrp_t * node)
119 {
120 int cmp;
121 mboxgrp_t *pos;
122 mboxgrp_t **ins;
123
124 INSERT_TREE(mboxgrps, node, pos, ins, cmp);
125 }
126
127
128 /*
129 * A new mailbox-group entry was declared. Create it and set it's variables
130 * accordingly.
131 */
132 int set_mboxgrp(char *line, regmatch_t * match)
133 {
134 mboxgrp_t *node;
135 char mboxs[LINE_MAX];
136
137 mboxs[0] = 0;
138
139 if (!accounts)
140 return ERROR_CONFIG_PARSE;
141
142 node = (mboxgrp_t *) create_node(sizeof(mboxgrp_t));
143
144 init_mboxgrp(node);
145
146 strncat(node->key, line + match[1].rm_so,
147 min(match[1].rm_eo - match[1].rm_so, KEY_LEN - 1));
148
149 #ifdef DEBUG
150 printf("debug: FOLDER: '%s'\n", node->key);
151 #endif
152
153 strncat(mboxs, line + match[2].rm_so,
154 min(match[2].rm_eo - match[2].rm_so, LINE_MAX - 1));
155
156 process_mboxgrp(node, mboxs);
157
158 insert_mboxgrp(node);
159
160 return 0;
161 }
162
163
164 /*
165 * Calls set_mbox() in order to create mailboxes that are part of
166 * the mailbox-group.
167 */
168 void process_mboxgrp(mboxgrp_t * node, char *mboxs)
169 {
170 int i = 0;
171 const char *delim = ",";
172 char *tok;
173
174 while (i < MBOXGRP_MBOXES_MAX - 1 && (tok = strsep(&mboxs, delim))) {
175 node->mboxes[i] = (mbox_t *) set_mbox(tok);
176 node->mboxes[++i] = NULL;
177 }
178 }
179
180
181 /*
182 * Find in the mailbox-group tree, the node with the specified key,
183 * and return a pointer to it.
184 */
185 mboxgrp_t *find_mboxgrp(char *key)
186 {
187 int cmp;
188 mboxgrp_t *pos;
189
190 FIND_TREE(mboxgrps, key, pos, cmp);
191 }
192
193
194 /*
195 * Set new mailbox's variables to safe values.
196 */
197 void init_mbox(mbox_t * node)
198 {
199 node->next = NULL;
200 node->name[0] = 0;
201 node->filters[0] = NULL;
202 }
203
204
205 /*
206 * Append mailbox node to linked list.
207 */
208 void append_mbox(mbox_t * node)
209 {
210 mbox_t *pos;
211 mbox_t **ins;
212
213 APPEND_LINKED_LIST(cur_acct->mboxes, node, pos, ins);
214 }
215
216
217 /*
218 * A new mailbox was declared, create it and set it's variables accordingly.
219 */
220 mbox_t *set_mbox(char *name)
221 {
222 mbox_t *node;
223
224 node = (mbox_t *) create_node(sizeof(mbox_t));
225
226 init_mbox(node);
227
228 strncat(node->name, name, min(strlen(name), MBOX_NAME_LEN - 1));
229
230 #ifdef DEBUG
231 printf("debug: MBOX: '%s'\n", node->name);
232 #endif
233
234 append_mbox(node);
235
236 return node;
237 }
238
239
240 /*
241 * Set new filter's variables to safe values.
242 */
243 void init_filter(filter_t * node)
244 {
245 node->left = node->right = NULL;
246 node->key[0] = 0;
247 node->mode = FILTER_MODE_AND;
248 node->action.type = 0;
249 node->action.destmbox[0] = node->action.args[0] = 0;
250 node->masks = NULL;
251 node->masknum = node->masklen = 0;
252 }
253
254
255 /*
256 * Insert filter node to tree.
257 */
258 void insert_filter(filter_t * node)
259 {
260 int cmp;
261 filter_t *pos;
262 filter_t **ins;
263
264 INSERT_TREE(filters, node, pos, ins, cmp);
265 }
266
267
268 /*
269 * A filter entry was declared, create it and set it's variables accordingly.
270 */
271 int set_filter(char *line, regmatch_t * match)
272 {
273 filter_t *node;
274
275 if (cur_fltr && !cur_fltr->action.type)
276 return ERROR_CONFIG_PARSE;
277
278 node = (filter_t *) create_node(sizeof(filter_t));
279
280 init_filter(node);
281
282 strncat(node->key, line + match[1].rm_so,
283 min(match[1].rm_eo - match[1].rm_so, KEY_LEN - 1));
284
285 if (match[2].rm_so != -1) {
286 if (!strncasecmp(line + match[2].rm_so + 1, "or", 2))
287 node->mode = FILTER_MODE_OR;
288 else
289 node->mode = FILTER_MODE_AND;
290 }
291 #ifdef DEBUG
292 printf("debug: FILTER: '%s' %s\n", node->key,
293 (node->mode == FILTER_MODE_OR ? "OR" : "AND"));
294 #endif
295
296 insert_filter(node);
297 cur_fltr = node;
298
299 return 0;
300 }
301
302
303 /*
304 * Find in the filter tree, the node with the specified key and
305 * return a pointer to it.
306 */
307 filter_t *find_filter(char *key)
308 {
309 int cmp;
310 filter_t *pos;
311
312 FIND_TREE(filters, key, pos, cmp);
313 }
314
315
316 /*
317 * Assign an action to the last declared filter.
318 */
319 int set_action(char *line, regmatch_t * match)
320 {
321 if (!cur_fltr)
322 return ERROR_CONFIG_PARSE;
323
324 if (!strncasecmp(line + match[1].rm_so, "delete", 6))
325 cur_fltr->action.type = FILTER_ACTION_DELETE;
326 else if (!strncasecmp(line + match[1].rm_so, "copy", 4)) {
327 cur_fltr->action.type = FILTER_ACTION_COPY;
328 strncat(cur_fltr->action.destmbox, line + match[2].rm_so,
329 min(match[2].rm_eo - match[2].rm_so, MBOX_NAME_LEN - 1));
330 } else if (!strncasecmp(line + match[1].rm_so, "move", 4)) {
331 cur_fltr->action.type = FILTER_ACTION_MOVE;
332 strncat(cur_fltr->action.destmbox, line + match[3].rm_so,
333 min(match[3].rm_eo - match[3].rm_so, MBOX_NAME_LEN - 1));
334 } else if (!strncasecmp(line + match[1].rm_so, "list", 4))
335 cur_fltr->action.type = FILTER_ACTION_LIST;
336
337 if (match[4].rm_so != -1)
338 strncat(cur_fltr->action.args, line + match[4].rm_so,
339 min(match[4].rm_eo - match[4].rm_so, ARGS_LEN - 1));
340
341 return 0;
342
343 }
344
345
346 /*
347 * Set new mask's variables to safe values.
348 */
349 void init_mask(mask_t * node)
350 {
351 node->next = NULL;
352 node->body[0] = 0;
353 node->type = 0;
354 }
355
356
357 /*
358 * Append mask node to linked list.
359 */
360 void append_mask(mask_t * node)
361 {
362 mask_t *pos;
363 mask_t **app;
364
365 APPEND_LINKED_LIST(cur_fltr->masks, node, pos, app);
366 }
367
368
369 /*
370 * A new mask entry was declared, create it and set it's
371 * variables accordingly.
372 */
373 int set_mask(char *line, regmatch_t * match)
374 {
375 int s, i, f = 0;
376 mask_t *node;
377 char *bp;
378
379 if (!cur_fltr)
380 return ERROR_CONFIG_PARSE;
381
382 node = (mask_t *) create_node(sizeof(mask_t));
383
384 init_mask(node);
385
386 bp = node->body;
387
388 /* If specified set mask's type. */
389 if (match[2].rm_so != -1 && cur_fltr->masks) {
390 if (!strncasecmp(line + match[2].rm_so, "or", 2))
391 node->type = MASK_TYPE_OR;
392 else
393 node->type = MASK_TYPE_AND;
394 }
395 /* Add NOT if specified. */
396 if (match[3].rm_so != -1) {
397 s = min(match[3].rm_eo - match[3].rm_so,
398 MASK_BODY_LEN - (bp - node->body) - 1);
399 strncpy(bp, line + match[3].rm_so, s);
400 string_upper(bp, s);
401 *(bp + s - 1) = ' '; /* In case it's '\t'. */
402 *(bp + s) = 0;
403 bp += s;
404 }
405 /* Keyword of the search key. */
406 s = min(match[4].rm_eo - match[4].rm_so,
407 MASK_BODY_LEN - (bp - node->body) - 3);
408 strncpy(bp, line + match[4].rm_so, s);
409 string_upper(bp, s);
410 *(bp + s) = 0;
411 bp += s;
412
413 /* Body of the search key (string/number). */
414 for (i = 5; i <= 6; i++)
415 if (match[i].rm_so != -1) {
416 *(bp++) = ' ';
417
418 /* Add '"' if not supplied and search key not a number. */
419 if (match[6].rm_so == -1 &&
420 (strstr(node->body, "LARGER") ||
421 strstr(node->body, "SMALLER")))
422 f = 1;
423 else if (*(line + match[i].rm_so) != '"')
424 *(bp++) = '"';
425
426 *bp = 0;
427
428 s = min(match[i].rm_eo - match[i].rm_so,
429 MASK_BODY_LEN - (bp - node->body) - 2);
430 strncpy(bp, line + match[i].rm_so, s);
431 *(bp + s) = 0;
432 bp += s;
433
434 if (*(line + match[i].rm_so) != '"' && !f)
435 *(bp++) = '"';
436 *bp = 0;
437 }
438 append_mask(node);
439
440 cur_fltr->masknum++;
441 cur_fltr->masklen += (bp - node->body);
442
443
444 #ifdef DEBUG
445 printf("debug: MASK: '%s'\n", node->body);
446 #endif
447
448 return 0;
449 }
450
451
452 /*
453 * A new job was declared, link filters with mailbox-groups.
454 */
455 int set_job(char *line, regmatch_t * match)
456 {
457 int s;
458 const char *delim = ",";
459 char *ftok, *gtok, *fltr, *mbgrp, *f, *g;
460 filter_t *cf;
461 mboxgrp_t *cg;
462
463 if (!accounts || !filters || !cur_fltr->action.type)
464 return ERROR_CONFIG_PARSE;
465
466 s = match[1].rm_eo - match[1].rm_so;
467 fltr = (char *) xmalloc(s + 1);
468
469 f = strncpy(fltr, line + match[1].rm_so, s);
470 f[s] = 0;
471
472 s = match[2].rm_eo - match[2].rm_so;
473 mbgrp = (char *) xmalloc(s + 1);
474
475 /* Go through filters. */
476 while ((ftok = strsep(&f, delim))) {
477 cf = (filter_t *) find_filter(ftok);
478 if (!cf)
479 return ERROR_CONFIG_PARSE;
480
481 g = strncpy(mbgrp, line + match[2].rm_so, s);
482 g[s] = 0;
483
484 /* Go through mailbox groups. */
485 while ((gtok = strsep(&g, delim))) {
486 cg = (mboxgrp_t *) find_mboxgrp(gtok);
487 if (!cg)
488 return ERROR_CONFIG_PARSE;
489 link_mbox_filter(cf, cg);
490 }
491 }
492
493 free(fltr);
494 free(mbgrp);
495
496 return 0;
497 }
498
499
500 /*
501 * Link a filter with a mailbox.
502 */
503 void link_mbox_filter(filter_t * cf, mboxgrp_t * cg)
504 {
505 int i, j;
506 int f;
507
508 for (i = 0; cg->mboxes[i]; i++) {
509
510 for (f = j = 0; cg->mboxes[i]->filters[j]; j++)
511 if (j == MBOX_FILTERS_MAX - 1 ||
512 !strncmp(cf->key, cg->mboxes[i]->filters[j]->key, KEY_LEN))
513 f = 1;
514
515 if (f)
516 continue;
517
518 cg->mboxes[i]->filters[j] = cf;
519 cg->mboxes[i]->filters[j + 1] = NULL;
520
521 }
522
523 #ifdef DEBUG
524 printf("debug: JOB: '%s' '%s'\n", cf->key, cg->key);
525 #endif
526 }
527
528
529 /*
530 * Free allocated memory of data structures that are not needed anymore.
531 */
532 void destroy_data(void)
533 {
534 destroy_mboxgrp(mboxgrps);
535 }
536
537
538 /*
539 * Go through the mailbox-group tree, and free the memory of each node.
540 */
541 void destroy_mboxgrp(mboxgrp_t * node)
542 {
543 if (node->left) {
544 destroy_mboxgrp(node->left);
545 node->left = NULL;
546 }
547 if (node->right) {
548 destroy_mboxgrp(node->right);
549 node->right = NULL;
550 }
551 #ifdef DEBUG
552 printf("debug: deleting FOLDER: '%s'\n", node->key);
553 #endif
554
555 free(node);
556 }
557
558
559 /*
560 * Convert a string of specified size to upper case.
561 */
562 void string_upper(char *str, size_t size)
563 {
564 unsigned int i;
565
566 for (i = 0; i < size; i++, str++)
567 *str = toupper(*str);
568 }
569
570
571 /*
572 * Decode the character triplet, consisting of the character '%'
573 * followed by two hexadecimal digits to its corresponding ASCII
574 * character (described in Section 2.2 of RFC 1738).
575 */
576 int string_decode(char *str)
577 {
578 char *c;
579 char hex[3];
580
581 c = str;
582
583 while (*c) {
584 if (*c == '%') {
585 if (!isxdigit(*(c + 1)) || !isxdigit(*(c + 2)))
586 return ERROR_CONFIG_PARSE;
587
588 strncpy(hex, ++c, 2);
589 hex[2] = 0;
590
591 if (!isprint(*str = (char) strtoul(hex, NULL, 16)))
592 return ERROR_CONFIG_PARSE;
593
594 str++;
595 c += 2;
596 } else
597 *(str++) = *(c++);
598 }
599 *str = 0;
600
601 return 0;
602 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26