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

Annotation of /imapfilter/data.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (hide annotations)
Thu Nov 1 16:35:06 2001 UTC (22 years, 5 months ago) by lefcha
Branch: MAIN
Changes since 1.13: +9 -0 lines
File MIME type: text/plain
Overwrite user passwords.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26