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

Contents of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (show annotations)
Sat Oct 6 12:31:39 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
Changes since 1.8: +45 -42 lines
File MIME type: text/plain
Fixed a filter's logical operators bug.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26