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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Mon Oct 1 11:48:51 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.3: +9 -4 lines
File MIME type: text/plain
Added some log records.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26