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

Contents of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations)
Thu Oct 4 15:47:49 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.7: +30 -11 lines
File MIME type: text/plain
Use imap_examine() if no filters  to apply.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26