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

Contents of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show 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 #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-write mode.
40 */
41 int select_mailbox(char *mbox)
42 {
43 int r;
44
45 imap_select(mbox);
46 r = server_response("SELECT");
47
48 if (!r)
49 mailbox_status(mbox);
50
51 log_info(LOG_MAILBOX, mbox);
52
53 return r;
54 }
55
56
57 /*
58 * Get mailbox's status.
59 */
60 int mailbox_status(char *mbox)
61 {
62 int r = 0;
63
64 if (!(options & OPTION_DETAILS_QUITE)) {
65 imap_status(mbox, "MESSAGES RECENT UNSEEN");
66 info ("In mailbox %s,", mbox);
67 r = status_response();
68 }
69 return r;
70 }
71 /*
72 * Close examined/selected mailbox.
73 */
74 int close_mailbox(void)
75 {
76 imap_close();
77 return server_response("CLOSE");
78 }
79
80
81 /*
82 * Logout from server.
83 */
84 int logout(void)
85 {
86 imap_logout();
87 return server_response("LOGOUT");
88 }
89
90
91 /*
92 * Match and apply filters assigned to a mailbox.
93 */
94 int apply_filters(filter_t ** filters, char *mbox)
95 {
96 int i;
97 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
106 log_info(LOG_FILTER, filters[i]->key);
107
108 apply_action(mesgs, &(filters[i]->action.type),
109 filters[i]->action.destmbox, filters[i]->action.args);
110 }
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 char *search;
123
124 if (filter->mode == FILTER_MODE_OR)
125 search = generate_filter_or(filter->masks, filter->masknum,
126 filter->masklen);
127 else
128 search = generate_filter_and(filter->masks, filter->masknum,
129 filter->masklen);
130
131 imap_search(search);
132 search_response(mesgs);
133
134 free(search);
135
136 if (!*mesgs)
137 return 1;
138
139 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 queue_fifo(NULL, NULL);
151 dequeue_fifo(NULL);
152 }
153
154
155 /*
156 * Add item to FIFO inventory.
157 */
158 void queue_fifo(mask_t ** mfifo, mask_t * mask)
159 {
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 mask_t *dequeue_fifo(mask_t ** mfifo)
175 {
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 char *generate_filter_and(mask_t * mask, unsigned int masknum, unsigned int masklen)
191 {
192 const unsigned int searchbuf = masklen + masknum * 6 + 8;
193 int len = 0;
194 char *search;
195 mask_t **mfifo; /* Mailbox FIFO queue. */
196 mask_t *mf; /* Mask returned from FIFO. */
197
198 search = (char *) xmalloc(sizeof(char) * searchbuf);
199 mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
200
201 search[0] = 0;
202 empty_fifo(mfifo);
203
204 strncat(search, "ALL ", searchbuf - len - 1);
205 len += 4;
206
207 while (mask) {
208 if (mask->type == MASK_TYPE_OR) {
209
210 if (len == 4 && search[0] == 'A')
211 search[0] = len = 0;
212
213 strncat(search, "OR (", searchbuf - len - 1);
214 len += 4;
215
216 while ((mf = dequeue_fifo(mfifo))) {
217 strncat(search, mf->body, searchbuf - len - 1);
218 len = strlen(search);
219 search[len] = ' ';
220 search[++len] = 0;
221 }
222
223 empty_fifo(mfifo);
224
225 search[len - 1] = ')';
226 search[len] = ' ';
227 search[++len] = 0;
228 }
229 queue_fifo(mfifo, mask);
230
231 mask = mask->next;
232 }
233
234 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 len = strlen(search);
241 search[len] = ' ';
242 search[++len] = 0;
243 }
244
245 if (strchr(search, '(')) {
246 search[len - 1] = ')';
247 search[len] = 0;
248 }
249 if (search[len - 1] == ' ')
250 search[len - 1] = 0;
251
252 return search;
253 }
254
255
256 /*
257 * Generate the filter search command from the masks, assuming that
258 * masks are OR-ed
259 */
260 char *generate_filter_or(mask_t * mask, unsigned int masknum, unsigned int masklen)
261 {
262 const unsigned int searchbuf = masklen + masknum * 6 + 8;
263 int len = 0;
264 char *search;
265 mask_t **mfifo; /* Mailbox FIFO queue. */
266 mask_t *mf; /* Mask returned from FIFO. */
267
268 search = (char *) xmalloc(sizeof(char) * searchbuf);
269 mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
270
271 search[0] = 0;
272 empty_fifo(mfifo);
273
274 strncat(search, "ALL ", searchbuf - len - 1);
275 len += 4;
276
277 while (mask) {
278 queue_fifo(mfifo, mask);
279 mask = mask->next;
280
281 while (mask && mask->type == MASK_TYPE_AND) {
282 queue_fifo(mfifo, mask);
283 mask = mask->next;
284 }
285
286 if (mask) {
287 if (len == 4 && search[0] == 'A')
288 search[0] = len = 0;
289
290 strncat(search, "OR ", searchbuf - len - 1);
291 len += 3;
292 }
293 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 len = strlen(search);
300 search[len] = ' ';
301 search[++len] = 0;
302 }
303
304 if (strchr(search, '(')) {
305 search[len - 1] = ')';
306 search[len] = ' ';
307 search[++len] = 0;
308 }
309 empty_fifo(mfifo);
310 }
311
312 search[len - 1] = 0;
313
314 return search;
315 }
316
317
318 /*
319 * Apply the appropriate action.
320 */
321 int apply_action(char *mesgs, unsigned int *type, char *destmbox, char *args)
322 {
323 unsigned int cnt;
324
325 if (!*mesgs)
326 return 0;
327
328 log_info(LOG_ACTION, type);
329 log_info(LOG_DESTINATION_MAILBOX, destmbox);
330
331 cnt = convert_messages(mesgs);
332
333 switch (*type) {
334 case FILTER_ACTION_DELETE:
335 info("%d messages deleted.\n", cnt);
336 action_delete(mesgs, args);
337 break;
338 case FILTER_ACTION_COPY:
339 info("%d messages copied to mailbox %s.\n", cnt, destmbox);
340 action_copy(mesgs, destmbox, args);
341 break;
342 case FILTER_ACTION_MOVE:
343 info("%d messages moved to mailbox %s.\n", cnt, destmbox);
344 action_move(mesgs, destmbox, args);
345 break;
346 case FILTER_ACTION_LIST:
347 info("%d messages listed.\n", cnt);
348 action_list(mesgs, args);
349 break;
350 }
351
352 if (!*args)
353 log_info(LOG_WRITE, NULL);
354
355 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 char *tok, *mcp, *m, *acp, *occur;
366
367 m = mcp = xstrdup(mesgs);
368
369 if (*args) {
370 acp = xstrdup(args);
371 while ((occur = strchr(acp, ',')))
372 *occur = ' ';
373 }
374
375 while ((tok = strsep(&m, delim))) {
376 if (*args) {
377 imap_fetch(0, tok, acp);
378 fetch_response();
379 }
380 imap_store(tok, "\\Deleted");
381 server_response("STORE");
382 }
383
384 free(mcp);
385 if (*args)
386 free(acp);
387
388 return 0;
389 }
390
391
392 /*
393 * Copy messages to specified mailbox.
394 */
395 int action_copy(char *mesgs, char *destmbox, char *args)
396 {
397 const char *delim = " ";
398 char *tok, *mcp, *m, *acp, *occur;
399
400 m = mcp = xstrdup(mesgs);
401
402 if (*args) {
403 acp = xstrdup(args);
404
405 while ((occur = strchr(acp, ',')))
406 *occur = ' ';
407 }
408
409 while ((tok = strsep(&m, delim))) {
410 if (*args) {
411 imap_fetch(1, tok, acp);
412 fetch_response();
413 }
414 imap_copy(tok, destmbox);
415 if (copy_response() == 1) {
416 imap_create(destmbox);
417 if (!server_response("CREATE")) {
418 imap_copy(tok, destmbox);
419 copy_response();
420 }
421 }
422 }
423
424 free(mcp);
425
426 if (*args)
427 free(acp);
428
429 return 0;
430 }
431
432
433 /*
434 * Move messages to specified mailbox.
435 */
436 int action_move(char *mesgs, char *destmbox, char *args)
437 {
438 action_copy(mesgs, destmbox, args);
439 action_delete(mesgs, "\0");
440 imap_expunge();
441 server_response("EXPUNGE");
442
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 char *tok, *mcp, *m, *acp, *occur;
454
455 if (!*args)
456 return 0;
457
458 m = mcp = xstrdup(mesgs);
459 acp = xstrdup(args);
460
461 while ((occur = strchr(acp, ',')))
462 *occur = ' ';
463
464 while ((tok = strsep(&m, delim))) {
465 imap_fetch(1, tok, acp);
466 fetch_response();
467 }
468
469 free(mcp);
470 free(acp);
471
472 return 0;
473 }
474
475
476 /*
477 * Convert messages with contiguous sequense number to the corresponding
478 * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8
479 */
480 unsigned int convert_messages(char *mesgs)
481 {
482 unsigned int cnt, len;
483 unsigned int start, end, tmp;
484 char *cp, *tail = NULL;
485
486 cnt = len = start = end = tmp = 0;
487
488 cp = xstrdup(mesgs);
489
490 start = (unsigned int) strtoul(cp, &tail, 0);
491 cnt++;
492 end = start;
493
494 do {
495 if (tail) {
496 tmp = (unsigned int) strtoul(tail, &tail, 0);
497 if (tmp)
498 cnt++;
499 }
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
519 return cnt;
520 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26