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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (hide annotations)
Thu Nov 8 17:53:53 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.12: +22 -12 lines
File MIME type: text/plain
Changed to support dynamically allocated messages buffer.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26