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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations)
Tue Oct 2 13:33:58 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.5: +21 -12 lines
File MIME type: text/plain
Fixed a small bug in logging.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26