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

Contents of /imapfilter/data.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations)
Wed Oct 17 14:06:20 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.11: +18 -1 lines
File MIME type: text/plain
Added SSL/TLS support.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26