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

Contents of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Mon Sep 10 23:43:29 2001 UTC (22 years, 6 months ago) by lefcha
Branch: MAIN
File MIME type: text/plain
New imapfilter.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26