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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17.2.1 - (hide annotations)
Wed Dec 5 09:55:12 2001 UTC (22 years, 3 months ago) by lefcha
Branch: release-0_7-patches
Changes since 1.17: +30 -3 lines
File MIME type: text/plain
Take into consideration namespace.

1 lefcha 1.1 #include <stdio.h>
2     #include <stdlib.h>
3     #include <string.h>
4 lefcha 1.3 #include <errno.h>
5 lefcha 1.1
6     #include "config.h"
7     #include "imapfilter.h"
8     #include "data.h"
9    
10    
11     extern unsigned int options;
12 lefcha 1.17.2.1 extern unsigned int capabilities;
13    
14     static struct namespace_t namesp;
15 lefcha 1.1
16 lefcha 1.3
17 lefcha 1.2 #ifdef DEBUG
18 lefcha 1.1 /*
19     * Test/ping server.
20     */
21     int test(void)
22     {
23 lefcha 1.10 return server_response(imap_noop());
24 lefcha 1.1 }
25 lefcha 1.2 #endif
26 lefcha 1.1
27 lefcha 1.10
28 lefcha 1.1 /*
29 lefcha 1.10 * Check server's capabilities.
30 lefcha 1.1 */
31 lefcha 1.10 int check_capabilities(void)
32 lefcha 1.1 {
33 lefcha 1.17.2.1 capabilities = CAPABILITY_NONE;
34    
35 lefcha 1.10 return capability_response(imap_capability());
36 lefcha 1.1 }
37    
38    
39     /*
40 lefcha 1.17.2.1 * Get namespace of mail server's mailboxes.
41     */
42     int check_namespace(void)
43     {
44     namesp.prefix[0] = namesp.delim = 0;
45    
46     if (!(options & OPTION_NAMESPACE) ||
47     !(capabilities & CAPABILITY_NAMESPACE))
48     return 0;
49     else
50     return namespace_response(imap_namespace(), &namesp);
51     }
52    
53    
54     /*
55 lefcha 1.10 * Login to server.
56 lefcha 1.8 */
57 lefcha 1.10 int login(char *user, char *pass)
58 lefcha 1.8 {
59 lefcha 1.10 log_info(LOG_USERNAME, user);
60 lefcha 1.8
61 lefcha 1.10 return server_response(imap_login(user, pass));
62 lefcha 1.8 }
63    
64 lefcha 1.17.2.1
65 lefcha 1.8 /*
66 lefcha 1.3 * Open mailbox in read-write mode.
67 lefcha 1.1 */
68 lefcha 1.3 int select_mailbox(char *mbox)
69 lefcha 1.1 {
70     int r;
71 lefcha 1.5
72 lefcha 1.10 if (mailbox_status(mbox) == -2)
73     return -2; /* No messages exist. No filters need to
74     be applied. */
75 lefcha 1.5
76 lefcha 1.17.2.1 r = select_response(imap_select(apply_namespace(mbox, namesp.prefix,
77     namesp.delim)));
78 lefcha 1.5
79 lefcha 1.4 log_info(LOG_MAILBOX, mbox);
80 lefcha 1.5
81 lefcha 1.1 return r;
82     }
83    
84    
85     /*
86 lefcha 1.3 * Get mailbox's status.
87 lefcha 1.1 */
88 lefcha 1.3 int mailbox_status(char *mbox)
89 lefcha 1.1 {
90 lefcha 1.17.2.1 return status_response(imap_status(apply_namespace(mbox, namesp.prefix,
91     namesp.delim),
92     "MESSAGES RECENT UNSEEN"), mbox);
93    
94 lefcha 1.16 }
95 lefcha 1.5
96 lefcha 1.9
97 lefcha 1.1 /*
98     * Close examined/selected mailbox.
99     */
100     int close_mailbox(void)
101     {
102 lefcha 1.10 return server_response(imap_close());
103 lefcha 1.1 }
104    
105    
106     /*
107     * Logout from server.
108     */
109     int logout(void)
110     {
111 lefcha 1.10 return server_response(imap_logout());
112 lefcha 1.1 }
113    
114    
115     /*
116     * Match and apply filters assigned to a mailbox.
117     */
118 lefcha 1.10 int apply_filters(filter_t ** filters)
119 lefcha 1.1 {
120 lefcha 1.3 int i;
121 lefcha 1.12 char *mesgs;
122 lefcha 1.1
123     for (i = 0; filters[i]; i++) {
124 lefcha 1.16 mesgs = NULL;
125 lefcha 1.1
126 lefcha 1.12 if (match_filter(filters[i], &mesgs))
127 lefcha 1.1 continue;
128 lefcha 1.5
129 lefcha 1.4 log_info(LOG_FILTER, filters[i]->key);
130 lefcha 1.1
131 lefcha 1.3 apply_action(mesgs, &(filters[i]->action.type),
132 lefcha 1.17.2.1 apply_namespace(filters[i]->action.destmbox,
133     namesp.prefix, namesp.delim),
134     filters[i]->action.args);
135 lefcha 1.12
136     free(mesgs);
137 lefcha 1.1 }
138    
139     return 0;
140     }
141    
142    
143     /*
144     * Generate the search request by the masks of the filter and try to
145     * match the generated filter.
146     */
147 lefcha 1.12 int match_filter(filter_t * filter, char **mesgs)
148 lefcha 1.1 {
149 lefcha 1.3 char *search;
150 lefcha 1.5
151 lefcha 1.1 if (filter->mode == FILTER_MODE_OR)
152 lefcha 1.5 search = generate_filter_or(filter->masks, filter->masknum,
153     filter->masklen);
154 lefcha 1.1 else
155 lefcha 1.5 search = generate_filter_and(filter->masks, filter->masknum,
156     filter->masklen);
157 lefcha 1.1
158 lefcha 1.10 search_response(imap_search(search), mesgs);
159 lefcha 1.5
160 lefcha 1.3 free(search);
161 lefcha 1.5
162 lefcha 1.16 if (!*mesgs)
163 lefcha 1.1 return 1;
164 lefcha 1.5
165 lefcha 1.1 return 0;
166     }
167    
168    
169     /*
170     * Empty the FIFO inventory.
171     */
172     void empty_fifo(mask_t ** mfifo)
173     {
174     mfifo[0] = NULL;
175    
176 lefcha 1.3 queue_fifo(NULL, NULL);
177     dequeue_fifo(NULL);
178 lefcha 1.1 }
179    
180    
181     /*
182     * Add item to FIFO inventory.
183     */
184 lefcha 1.3 void queue_fifo(mask_t ** mfifo, mask_t * mask)
185 lefcha 1.1 {
186 lefcha 1.15 static unsigned int i;
187 lefcha 1.1
188     if (!mfifo) {
189     i = 0;
190     return;
191     }
192     mfifo[i++] = mask;
193     mfifo[i] = NULL;
194     }
195    
196    
197     /*
198     * Get next item from FIFO inventory.
199     */
200 lefcha 1.3 mask_t *dequeue_fifo(mask_t ** mfifo)
201 lefcha 1.1 {
202 lefcha 1.15 static unsigned int j;
203 lefcha 1.1
204     if (!mfifo) {
205     j = 0;
206     return NULL;
207     }
208     return mfifo[j++];
209     }
210    
211    
212     /*
213     * Generate the filter search command from the masks, assuming that
214     * masks are AND-ed.
215     */
216 lefcha 1.9 char *generate_filter_and(mask_t * mask, unsigned int masknum,
217 lefcha 1.10 unsigned int masklen)
218 lefcha 1.1 {
219 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
220 lefcha 1.15 unsigned int len = 0;
221 lefcha 1.3 char *search;
222 lefcha 1.9 mask_t *tmp;
223 lefcha 1.5
224     search = (char *) xmalloc(sizeof(char) * searchbuf);
225    
226 lefcha 1.3 search[0] = 0;
227 lefcha 1.1
228 lefcha 1.9 tmp = mask;
229 lefcha 1.10 if (!tmp) {
230     strncat(search, "ALL ", searchbuf - len - 1);
231     len += 4;
232     } else
233     while ((tmp = tmp->next)) {
234 lefcha 1.12 if (tmp->type != MASK_TYPE_OR) {
235     strncat(search, "ALL ", searchbuf - len - 1);
236     len += 4;
237     break;
238     }
239 lefcha 1.9 }
240 lefcha 1.1
241 lefcha 1.9 tmp = NULL;
242 lefcha 1.1 while (mask) {
243 lefcha 1.9 tmp = mask;
244     mask = mask->next;
245 lefcha 1.1
246 lefcha 1.9 if (mask && mask->type == MASK_TYPE_OR) {
247 lefcha 1.3 strncat(search, "OR (", searchbuf - len - 1);
248 lefcha 1.1 len += 4;
249    
250 lefcha 1.9 strncat(search, tmp->body, searchbuf - len - 1);
251     len = strlen(search);
252     search[len] = ' ';
253     search[++len] = 0;
254    
255     search[len - 1] = ')';
256     search[len] = ' ';
257     search[++len] = 0;
258    
259     if (!mask->next || mask->next->type != MASK_TYPE_OR) {
260     search[len] = '(';
261     search[++len] = 0;
262     strncat(search, mask->body, searchbuf - len - 1);
263 lefcha 1.1 len = strlen(search);
264 lefcha 1.9 search[len] = ')';
265     search[++len] = ' ';
266 lefcha 1.3 search[++len] = 0;
267 lefcha 1.9 mask = mask->next;
268 lefcha 1.1 }
269 lefcha 1.9 } else {
270     strncat(search, tmp->body, searchbuf - len - 1);
271     len = strlen(search);
272 lefcha 1.3 search[len] = ' ';
273     search[++len] = 0;
274 lefcha 1.1 }
275     }
276 lefcha 1.10
277 lefcha 1.9 search[len - 1] = 0;
278 lefcha 1.5
279 lefcha 1.3 return search;
280 lefcha 1.1 }
281    
282    
283     /*
284     * Generate the filter search command from the masks, assuming that
285     * masks are OR-ed
286     */
287 lefcha 1.9 char *generate_filter_or(mask_t * mask, unsigned int masknum,
288 lefcha 1.10 unsigned int masklen)
289 lefcha 1.1 {
290 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
291 lefcha 1.15 unsigned int len = 0;
292 lefcha 1.3 char *search;
293     mask_t **mfifo; /* Mailbox FIFO queue. */
294 lefcha 1.1 mask_t *mf; /* Mask returned from FIFO. */
295 lefcha 1.5
296     search = (char *) xmalloc(sizeof(char) * searchbuf);
297     mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
298 lefcha 1.1
299 lefcha 1.3 search[0] = 0;
300 lefcha 1.1 empty_fifo(mfifo);
301    
302 lefcha 1.3 strncat(search, "ALL ", searchbuf - len - 1);
303 lefcha 1.1 len += 4;
304    
305     while (mask) {
306 lefcha 1.3 queue_fifo(mfifo, mask);
307 lefcha 1.1 mask = mask->next;
308    
309     while (mask && mask->type == MASK_TYPE_AND) {
310 lefcha 1.3 queue_fifo(mfifo, mask);
311 lefcha 1.1 mask = mask->next;
312     }
313    
314     if (mask) {
315 lefcha 1.3 if (len == 4 && search[0] == 'A')
316     search[0] = len = 0;
317 lefcha 1.5
318 lefcha 1.3 strncat(search, "OR ", searchbuf - len - 1);
319 lefcha 1.1 len += 3;
320     }
321 lefcha 1.3 if (search[0] != 'A') {
322     search[len] = '(';
323     search[++len] = 0;
324     }
325     while ((mf = dequeue_fifo(mfifo))) {
326     strncat(search, mf->body, searchbuf - len - 1);
327 lefcha 1.1 len = strlen(search);
328 lefcha 1.3 search[len] = ' ';
329     search[++len] = 0;
330 lefcha 1.1 }
331    
332 lefcha 1.3 if (strchr(search, '(')) {
333     search[len - 1] = ')';
334     search[len] = ' ';
335     search[++len] = 0;
336     }
337 lefcha 1.1 empty_fifo(mfifo);
338     }
339    
340     search[len - 1] = 0;
341 lefcha 1.10
342 lefcha 1.9 free(mfifo);
343 lefcha 1.3
344     return search;
345 lefcha 1.1 }
346    
347    
348     /*
349     * Apply the appropriate action.
350     */
351 lefcha 1.9 int apply_action(char *mesgs, unsigned int *type, char *destmbox,
352 lefcha 1.10 char *args)
353 lefcha 1.1 {
354 lefcha 1.3 unsigned int cnt;
355 lefcha 1.5
356 lefcha 1.3 if (!*mesgs)
357 lefcha 1.1 return 0;
358 lefcha 1.5
359 lefcha 1.4 log_info(LOG_ACTION, type);
360     log_info(LOG_DESTINATION_MAILBOX, destmbox);
361 lefcha 1.5
362 lefcha 1.3 cnt = convert_messages(mesgs);
363 lefcha 1.5
364 lefcha 1.3 switch (*type) {
365 lefcha 1.1 case FILTER_ACTION_DELETE:
366 lefcha 1.8 info("%d message%s deleted.\n", cnt, plural(cnt));
367 lefcha 1.1 action_delete(mesgs, args);
368     break;
369     case FILTER_ACTION_COPY:
370 lefcha 1.8 info("%d message%s copied to mailbox %s.\n", cnt, plural(cnt),
371     destmbox);
372 lefcha 1.3 action_copy(mesgs, destmbox, args);
373 lefcha 1.1 break;
374     case FILTER_ACTION_MOVE:
375 lefcha 1.8 info("%d message%s moved to mailbox %s.\n", cnt, plural(cnt),
376     destmbox);
377 lefcha 1.3 action_move(mesgs, destmbox, args);
378 lefcha 1.1 break;
379     case FILTER_ACTION_LIST:
380 lefcha 1.8 info("%d message%s listed.\n", cnt, plural(cnt));
381 lefcha 1.1 action_list(mesgs, args);
382     break;
383     }
384 lefcha 1.5
385     if (!*args)
386 lefcha 1.4 log_info(LOG_WRITE, NULL);
387 lefcha 1.5
388 lefcha 1.1 return 0;
389     }
390    
391    
392     /*
393     * Delete messages and optionally list some of their headers.
394     */
395     int action_delete(char *mesgs, char *args)
396     {
397     const char *delim = " ";
398 lefcha 1.7 char *tok, *mcp, *m, *acp = NULL, *occur;
399 lefcha 1.1
400 lefcha 1.5 m = mcp = xstrdup(mesgs);
401 lefcha 1.7
402 lefcha 1.6 if (*args) {
403     acp = xstrdup(args);
404     while ((occur = strchr(acp, ',')))
405     *occur = ' ';
406     }
407 lefcha 1.3 while ((tok = strsep(&m, delim))) {
408 lefcha 1.10 if (*args)
409     fetch_response(imap_fetch(tok, acp, 0));
410    
411     server_response(imap_store(tok, "\\Deleted"));
412 lefcha 1.1 }
413 lefcha 1.5
414 lefcha 1.3 free(mcp);
415 lefcha 1.10
416 lefcha 1.6 if (*args)
417     free(acp);
418 lefcha 1.1
419     return 0;
420     }
421    
422    
423     /*
424     * Copy messages to specified mailbox.
425     */
426 lefcha 1.3 int action_copy(char *mesgs, char *destmbox, char *args)
427 lefcha 1.1 {
428     const char *delim = " ";
429 lefcha 1.7 char *tok, *mcp, *m, *acp = NULL, *occur;
430 lefcha 1.1
431 lefcha 1.5 m = mcp = xstrdup(mesgs);
432 lefcha 1.8
433 lefcha 1.6 if (*args) {
434     acp = xstrdup(args);
435 lefcha 1.8
436 lefcha 1.6 while ((occur = strchr(acp, ',')))
437     *occur = ' ';
438     }
439 lefcha 1.3 while ((tok = strsep(&m, delim))) {
440 lefcha 1.10 if (*args)
441     fetch_response(imap_fetch(tok, acp, 0));
442    
443     if (copy_response(imap_copy(tok, destmbox)) == RESPONSE_TRYCREATE)
444     if (!server_response(imap_create(destmbox)))
445     copy_response(imap_copy(tok, destmbox));
446 lefcha 1.1 }
447    
448 lefcha 1.3 free(mcp);
449 lefcha 1.8
450 lefcha 1.6 if (*args)
451     free(acp);
452 lefcha 1.1
453     return 0;
454     }
455    
456    
457     /*
458     * Move messages to specified mailbox.
459     */
460 lefcha 1.3 int action_move(char *mesgs, char *destmbox, char *args)
461 lefcha 1.1 {
462 lefcha 1.3 action_copy(mesgs, destmbox, args);
463 lefcha 1.1 action_delete(mesgs, "\0");
464 lefcha 1.16
465 lefcha 1.17 /* CLOSE -> SELECT much faster than EXPUNGE -> SELECT */
466 lefcha 1.16 /* server_response(imap_expunge()); */
467 lefcha 1.1
468     return 0;
469     }
470    
471    
472     /*
473     * List user selected headers of messages.
474     */
475     int action_list(char *mesgs, char *args)
476     {
477     const char *delim = " ";
478 lefcha 1.5 char *tok, *mcp, *m, *acp, *occur;
479    
480 lefcha 1.2 if (!*args)
481     return 0;
482 lefcha 1.1
483 lefcha 1.5 m = mcp = xstrdup(mesgs);
484     acp = xstrdup(args);
485 lefcha 1.6
486 lefcha 1.5 while ((occur = strchr(acp, ',')))
487 lefcha 1.1 *occur = ' ';
488    
489 lefcha 1.10 while ((tok = strsep(&m, delim)))
490     fetch_response(imap_fetch(tok, acp, 1));
491 lefcha 1.1
492 lefcha 1.3 free(mcp);
493 lefcha 1.5 free(acp);
494 lefcha 1.1
495     return 0;
496     }
497    
498    
499     /*
500 lefcha 1.11 * Convert messages with contiguous sequence number to the corresponding
501 lefcha 1.5 * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8
502 lefcha 1.1 */
503     unsigned int convert_messages(char *mesgs)
504     {
505 lefcha 1.13 unsigned int cnt, maxlen;
506 lefcha 1.1 unsigned int start, end, tmp;
507 lefcha 1.13 char *cp, *tail, *m;
508 lefcha 1.5
509 lefcha 1.13 cnt = start = end = tmp = 0;
510     maxlen = strlen(mesgs) + 1;
511     tail = NULL;
512 lefcha 1.1
513 lefcha 1.5 cp = xstrdup(mesgs);
514 lefcha 1.13 m = mesgs;
515 lefcha 1.1
516 lefcha 1.10 start = (unsigned int) strtoul(cp, &tail, 10);
517 lefcha 1.3 cnt++;
518 lefcha 1.1 end = start;
519    
520     do {
521     if (tail) {
522 lefcha 1.10 tmp = (unsigned int) strtoul(tail, &tail, 10);
523 lefcha 1.1 if (tmp)
524 lefcha 1.3 cnt++;
525 lefcha 1.15 else
526     tail = NULL;
527 lefcha 1.1 }
528     if (tmp == end + 1)
529     end++;
530     else {
531 lefcha 1.13 if (start == end) {
532     xstrncpy(m, ultostr(start, 10), maxlen);
533     m += strlen(m);
534     } else {
535     xstrncpy(m, ultostr(start, 10), maxlen - 1);
536     m += strlen(m);
537     *m = ':';
538     *++m = 0;
539     xstrncpy(m, ultostr(end, 10), maxlen);
540     m += strlen(m);
541     }
542 lefcha 1.1
543 lefcha 1.13 if (tail && m - mesgs < maxlen) {
544     *m = ' ';
545     *++m = 0;
546     }
547 lefcha 1.1 start = end = tmp;
548     }
549     } while (tmp);
550    
551     free(cp);
552 lefcha 1.5
553 lefcha 1.3 return cnt;
554 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26