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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.41 - (hide annotations)
Mon Feb 3 20:22:01 2003 UTC (21 years, 1 month ago) by lefcha
Branch: MAIN
Changes since 1.40: +2 -1 lines
File MIME type: text/plain
Added i18n support, variable charset to declare character set to the server.

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 lefcha 1.21 extern int sockpri, sockaux;
12 lefcha 1.1 extern unsigned int options;
13 lefcha 1.41 extern char charset[CHARSET_LEN];
14 lefcha 1.18 extern unsigned int capabilities;
15    
16 lefcha 1.21 namesp_t nsppri, nspaux; /* Primary and auxiliary namespace. */
17 lefcha 1.1
18 lefcha 1.3
19 lefcha 1.2 #ifdef DEBUG
20 lefcha 1.1 /*
21     * Test/ping server.
22     */
23 lefcha 1.21 int test(int *sock)
24 lefcha 1.1 {
25 lefcha 1.21 return server_response(sock, imap_noop(sock));
26 lefcha 1.1 }
27 lefcha 1.25
28 lefcha 1.2 #endif
29 lefcha 1.1
30 lefcha 1.10
31 lefcha 1.1 /*
32 lefcha 1.10 * Check server's capabilities.
33 lefcha 1.1 */
34 lefcha 1.21 int check_capabilities(int *sock)
35 lefcha 1.1 {
36 lefcha 1.18 capabilities = CAPABILITY_NONE;
37    
38 lefcha 1.21 return capability_response(sock, imap_capability(sock));
39 lefcha 1.1 }
40    
41    
42     /*
43 lefcha 1.18 * Get namespace of mail server's mailboxes.
44     */
45 lefcha 1.25 int check_namespace(int *sock, namesp_t * nsp)
46 lefcha 1.18 {
47 lefcha 1.21 nsp->prefix[0] = nsp->delim = 0;
48 lefcha 1.18
49     if (!(options & OPTION_NAMESPACE) ||
50     !(capabilities & CAPABILITY_NAMESPACE))
51     return 0;
52     else
53 lefcha 1.21 return namespace_response(sock, imap_namespace(sock), nsp);
54 lefcha 1.18 }
55    
56    
57     /*
58 lefcha 1.10 * Login to server.
59 lefcha 1.8 */
60 lefcha 1.21 int login(int *sock, char *user, char *pass)
61 lefcha 1.8 {
62 lefcha 1.10 log_info(LOG_USERNAME, user);
63 lefcha 1.8
64 lefcha 1.21 return server_response(sock, imap_login(sock, user, pass));
65     }
66    
67    
68    
69     /*
70     * Check if a mailbox exists.
71     */
72 lefcha 1.25 int check_mailbox(int *sock, char *mbox, namesp_t * nsp)
73 lefcha 1.21 {
74 lefcha 1.25 return server_response(sock, imap_examine(sock,
75 lefcha 1.21 apply_namespace(mbox,
76     nsp->prefix,
77     nsp->delim)));
78 lefcha 1.8 }
79    
80 lefcha 1.18
81 lefcha 1.8 /*
82 lefcha 1.3 * Open mailbox in read-write mode.
83 lefcha 1.1 */
84 lefcha 1.25 int select_mailbox(int *sock, char *mbox, namesp_t * nsp)
85 lefcha 1.1 {
86     int r;
87 lefcha 1.5
88 lefcha 1.21 if (mailbox_status(sock, mbox, nsp) == -2)
89 lefcha 1.25 return -2; /* No messages exist. No filters need to be
90     applied. */
91 lefcha 1.5
92 lefcha 1.21 r = select_response(sock, imap_select(sock,
93     apply_namespace(mbox, nsp->prefix,
94     nsp->delim)));
95 lefcha 1.5
96 lefcha 1.4 log_info(LOG_MAILBOX, mbox);
97 lefcha 1.5
98 lefcha 1.1 return r;
99     }
100    
101    
102     /*
103 lefcha 1.3 * Get mailbox's status.
104 lefcha 1.1 */
105 lefcha 1.25 int mailbox_status(int *sock, char *mbox, namesp_t * nsp)
106 lefcha 1.1 {
107 lefcha 1.21 return status_response(sock, imap_status(sock,
108 lefcha 1.25 apply_namespace(mbox, nsp->prefix,
109     nsp->delim),
110     "MESSAGES RECENT UNSEEN"), mbox);
111 lefcha 1.16 }
112 lefcha 1.5
113 lefcha 1.9
114 lefcha 1.1 /*
115     * Close examined/selected mailbox.
116     */
117 lefcha 1.21 int close_mailbox(int *sock)
118 lefcha 1.1 {
119 lefcha 1.21 return server_response(sock, imap_close(sock));
120 lefcha 1.1 }
121    
122    
123     /*
124     * Logout from server.
125     */
126 lefcha 1.21 int logout(int *sock)
127 lefcha 1.1 {
128 lefcha 1.35 return logout_response(sock, imap_logout(sock));
129 lefcha 1.1 }
130    
131    
132     /*
133     * Match and apply filters assigned to a mailbox.
134     */
135 lefcha 1.10 int apply_filters(filter_t ** filters)
136 lefcha 1.1 {
137 lefcha 1.3 int i;
138 lefcha 1.12 char *mesgs;
139 lefcha 1.1
140     for (i = 0; filters[i]; i++) {
141 lefcha 1.16 mesgs = NULL;
142 lefcha 1.1
143 lefcha 1.12 if (match_filter(filters[i], &mesgs))
144 lefcha 1.1 continue;
145 lefcha 1.5
146 lefcha 1.4 log_info(LOG_FILTER, filters[i]->key);
147 lefcha 1.1
148 lefcha 1.3 apply_action(mesgs, &(filters[i]->action.type),
149 lefcha 1.25 filters[i]->action.raccount, filters[i]->action.destmbox,
150 lefcha 1.26 &filters[i]->action.msgflags, filters[i]->action.args);
151 lefcha 1.12
152 lefcha 1.19 xfree(mesgs);
153 lefcha 1.1 }
154    
155     return 0;
156     }
157    
158    
159     /*
160     * Generate the search request by the masks of the filter and try to
161     * match the generated filter.
162     */
163 lefcha 1.12 int match_filter(filter_t * filter, char **mesgs)
164 lefcha 1.1 {
165 lefcha 1.3 char *search;
166 lefcha 1.5
167 lefcha 1.1 if (filter->mode == FILTER_MODE_OR)
168 lefcha 1.5 search = generate_filter_or(filter->masks, filter->masknum,
169     filter->masklen);
170 lefcha 1.1 else
171 lefcha 1.5 search = generate_filter_and(filter->masks, filter->masknum,
172     filter->masklen);
173 lefcha 1.1
174 lefcha 1.41 search_response(&sockpri, imap_search(&sockpri, charset, search), mesgs);
175 lefcha 1.5
176 lefcha 1.19 xfree(search);
177 lefcha 1.5
178 lefcha 1.16 if (!*mesgs)
179 lefcha 1.1 return 1;
180 lefcha 1.5
181 lefcha 1.1 return 0;
182     }
183    
184    
185     /*
186     * Empty the FIFO inventory.
187     */
188     void empty_fifo(mask_t ** mfifo)
189     {
190     mfifo[0] = NULL;
191    
192 lefcha 1.3 queue_fifo(NULL, NULL);
193     dequeue_fifo(NULL);
194 lefcha 1.1 }
195    
196    
197     /*
198     * Add item to FIFO inventory.
199     */
200 lefcha 1.3 void queue_fifo(mask_t ** mfifo, mask_t * mask)
201 lefcha 1.1 {
202 lefcha 1.15 static unsigned int i;
203 lefcha 1.1
204     if (!mfifo) {
205     i = 0;
206     return;
207     }
208     mfifo[i++] = mask;
209     mfifo[i] = NULL;
210     }
211    
212    
213     /*
214     * Get next item from FIFO inventory.
215     */
216 lefcha 1.3 mask_t *dequeue_fifo(mask_t ** mfifo)
217 lefcha 1.1 {
218 lefcha 1.15 static unsigned int j;
219 lefcha 1.1
220     if (!mfifo) {
221     j = 0;
222     return NULL;
223     }
224     return mfifo[j++];
225     }
226    
227    
228     /*
229     * Generate the filter search command from the masks, assuming that
230     * masks are AND-ed.
231     */
232 lefcha 1.9 char *generate_filter_and(mask_t * mask, unsigned int masknum,
233 lefcha 1.10 unsigned int masklen)
234 lefcha 1.1 {
235 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
236 lefcha 1.15 unsigned int len = 0;
237 lefcha 1.3 char *search;
238 lefcha 1.9 mask_t *tmp;
239 lefcha 1.5
240 lefcha 1.25 search = (char *)xmalloc(sizeof(char) * searchbuf);
241 lefcha 1.5
242 lefcha 1.3 search[0] = 0;
243 lefcha 1.1
244 lefcha 1.9 tmp = mask;
245 lefcha 1.10 if (!tmp) {
246     strncat(search, "ALL ", searchbuf - len - 1);
247     len += 4;
248     } else
249     while ((tmp = tmp->next)) {
250 lefcha 1.12 if (tmp->type != MASK_TYPE_OR) {
251     strncat(search, "ALL ", searchbuf - len - 1);
252     len += 4;
253     break;
254     }
255 lefcha 1.9 }
256 lefcha 1.1
257 lefcha 1.9 tmp = NULL;
258 lefcha 1.1 while (mask) {
259 lefcha 1.9 tmp = mask;
260     mask = mask->next;
261 lefcha 1.1
262 lefcha 1.9 if (mask && mask->type == MASK_TYPE_OR) {
263 lefcha 1.3 strncat(search, "OR (", searchbuf - len - 1);
264 lefcha 1.1 len += 4;
265    
266 lefcha 1.9 strncat(search, tmp->body, searchbuf - len - 1);
267     len = strlen(search);
268     search[len] = ' ';
269     search[++len] = 0;
270    
271     search[len - 1] = ')';
272     search[len] = ' ';
273     search[++len] = 0;
274    
275     if (!mask->next || mask->next->type != MASK_TYPE_OR) {
276     search[len] = '(';
277     search[++len] = 0;
278     strncat(search, mask->body, searchbuf - len - 1);
279 lefcha 1.1 len = strlen(search);
280 lefcha 1.9 search[len] = ')';
281     search[++len] = ' ';
282 lefcha 1.3 search[++len] = 0;
283 lefcha 1.9 mask = mask->next;
284 lefcha 1.1 }
285 lefcha 1.9 } else {
286     strncat(search, tmp->body, searchbuf - len - 1);
287     len = strlen(search);
288 lefcha 1.3 search[len] = ' ';
289     search[++len] = 0;
290 lefcha 1.1 }
291     }
292 lefcha 1.10
293 lefcha 1.9 search[len - 1] = 0;
294 lefcha 1.5
295 lefcha 1.3 return search;
296 lefcha 1.1 }
297    
298    
299     /*
300     * Generate the filter search command from the masks, assuming that
301 lefcha 1.22 * masks are OR-ed.
302 lefcha 1.1 */
303 lefcha 1.9 char *generate_filter_or(mask_t * mask, unsigned int masknum,
304 lefcha 1.10 unsigned int masklen)
305 lefcha 1.1 {
306 lefcha 1.3 const unsigned int searchbuf = masklen + masknum * 6 + 8;
307 lefcha 1.15 unsigned int len = 0;
308 lefcha 1.3 char *search;
309     mask_t **mfifo; /* Mailbox FIFO queue. */
310 lefcha 1.1 mask_t *mf; /* Mask returned from FIFO. */
311 lefcha 1.5
312 lefcha 1.25 search = (char *)xmalloc(sizeof(char) * searchbuf);
313 lefcha 1.5 mfifo = (mask_t **) xmalloc(sizeof(mask_t *) * (masknum + 1));
314 lefcha 1.1
315 lefcha 1.3 search[0] = 0;
316 lefcha 1.1 empty_fifo(mfifo);
317    
318 lefcha 1.3 strncat(search, "ALL ", searchbuf - len - 1);
319 lefcha 1.1 len += 4;
320    
321     while (mask) {
322 lefcha 1.3 queue_fifo(mfifo, mask);
323 lefcha 1.1 mask = mask->next;
324    
325     while (mask && mask->type == MASK_TYPE_AND) {
326 lefcha 1.3 queue_fifo(mfifo, mask);
327 lefcha 1.1 mask = mask->next;
328     }
329    
330     if (mask) {
331 lefcha 1.3 if (len == 4 && search[0] == 'A')
332     search[0] = len = 0;
333 lefcha 1.5
334 lefcha 1.3 strncat(search, "OR ", searchbuf - len - 1);
335 lefcha 1.1 len += 3;
336     }
337 lefcha 1.3 if (search[0] != 'A') {
338     search[len] = '(';
339     search[++len] = 0;
340     }
341     while ((mf = dequeue_fifo(mfifo))) {
342     strncat(search, mf->body, searchbuf - len - 1);
343 lefcha 1.1 len = strlen(search);
344 lefcha 1.3 search[len] = ' ';
345     search[++len] = 0;
346 lefcha 1.1 }
347    
348 lefcha 1.3 if (strchr(search, '(')) {
349     search[len - 1] = ')';
350     search[len] = ' ';
351     search[++len] = 0;
352     }
353 lefcha 1.1 empty_fifo(mfifo);
354     }
355    
356     search[len - 1] = 0;
357 lefcha 1.10
358 lefcha 1.19 xfree(mfifo);
359 lefcha 1.3
360     return search;
361 lefcha 1.1 }
362    
363    
364     /*
365     * Apply the appropriate action.
366     */
367 lefcha 1.25 int apply_action(char *mesgs, unsigned int *type, account_t * raccount,
368 lefcha 1.26 char *destmbox, unsigned int *msgflags, char *args)
369 lefcha 1.1 {
370 lefcha 1.3 unsigned int cnt;
371 lefcha 1.5
372 lefcha 1.3 if (!*mesgs)
373 lefcha 1.1 return 0;
374 lefcha 1.25
375 lefcha 1.4 log_info(LOG_ACTION, type);
376     log_info(LOG_DESTINATION_MAILBOX, destmbox);
377 lefcha 1.25
378 lefcha 1.21 cnt = count_messages(mesgs);
379 lefcha 1.25
380 lefcha 1.3 switch (*type) {
381 lefcha 1.1 case FILTER_ACTION_DELETE:
382 lefcha 1.8 info("%d message%s deleted.\n", cnt, plural(cnt));
383 lefcha 1.1 action_delete(mesgs, args);
384     break;
385     case FILTER_ACTION_COPY:
386 lefcha 1.20 info("%d message%s copied to mailbox \"%s\".\n", cnt, plural(cnt),
387 lefcha 1.8 destmbox);
388 lefcha 1.21 action_copy(mesgs, apply_namespace(destmbox, nsppri.prefix,
389     nsppri.delim), args);
390 lefcha 1.1 break;
391     case FILTER_ACTION_MOVE:
392 lefcha 1.20 info("%d message%s moved to mailbox \"%s\".\n", cnt, plural(cnt),
393 lefcha 1.8 destmbox);
394 lefcha 1.21 action_move(mesgs, apply_namespace(destmbox, nsppri.prefix,
395     nsppri.delim), args);
396     break;
397     case FILTER_ACTION_RCOPY:
398 lefcha 1.29 info("%d message%s copied to mailbox \"%s\" at account %s.\n", cnt,
399 lefcha 1.21 plural(cnt), destmbox, raccount->key);
400     action_rcopy(mesgs, raccount, destmbox, args);
401     break;
402     case FILTER_ACTION_RMOVE:
403 lefcha 1.32 info("%d message%s moved to mailbox \"%s\" at account %s.\n", cnt,
404 lefcha 1.21 plural(cnt), destmbox, raccount->key);
405     action_rmove(mesgs, raccount, destmbox, args);
406 lefcha 1.1 break;
407 lefcha 1.26 case FILTER_ACTION_FLAG_REPLACE:
408     case FILTER_ACTION_FLAG_ADD:
409     case FILTER_ACTION_FLAG_REMOVE:
410     info("%d message%s flagged.\n", cnt, plural(cnt));
411     action_flag(mesgs, type, msgflags, args);
412     break;
413 lefcha 1.1 case FILTER_ACTION_LIST:
414 lefcha 1.8 info("%d message%s listed.\n", cnt, plural(cnt));
415 lefcha 1.1 action_list(mesgs, args);
416     break;
417     }
418 lefcha 1.5
419     if (!*args)
420 lefcha 1.4 log_info(LOG_WRITE, NULL);
421 lefcha 1.5
422 lefcha 1.1 return 0;
423     }
424    
425    
426     /*
427     * Delete messages and optionally list some of their headers.
428     */
429     int action_delete(char *mesgs, char *args)
430     {
431 lefcha 1.26 char *tok, *m, *mcp;
432 lefcha 1.23
433     action_list(mesgs, args);
434 lefcha 1.25
435 lefcha 1.26 m = mcp = convert_messages(mesgs);
436 lefcha 1.25
437 lefcha 1.34 tok = strtok_r(m, " ", &m);
438     while (tok) {
439 lefcha 1.26 server_response(&sockpri, imap_store(&sockpri, tok,
440     STORE_FLAG_ADD, "\\Deleted"));
441 lefcha 1.5
442 lefcha 1.34 tok = strtok_r(NULL, " ", &m);
443     }
444    
445 lefcha 1.25 if (options & OPTION_EXPUNGE)
446     server_response(&sockpri, imap_expunge(&sockpri));
447    
448 lefcha 1.19 xfree(mcp);
449 lefcha 1.10
450 lefcha 1.1 return 0;
451     }
452    
453    
454     /*
455     * Copy messages to specified mailbox.
456     */
457 lefcha 1.3 int action_copy(char *mesgs, char *destmbox, char *args)
458 lefcha 1.1 {
459 lefcha 1.20 int r = 0;
460 lefcha 1.26 char *tok = NULL, *mcp, *m;
461 lefcha 1.25
462 lefcha 1.21 action_list(mesgs, args);
463 lefcha 1.25
464 lefcha 1.26 m = mcp = convert_messages(mesgs);
465 lefcha 1.23
466 lefcha 1.34 tok = strtok_r(m, " ", &m);
467     while (tok) {
468 lefcha 1.22 if ((r = copy_response(&sockpri,
469     imap_copy(&sockpri, tok, destmbox))) ==
470     RESPONSE_TRYCREATE)
471     if (!server_response(&sockpri, imap_create(&sockpri, destmbox))) {
472 lefcha 1.27 if ((options & OPTION_SUBSCRIBE))
473     server_response(&sockpri,
474     imap_subscribe(&sockpri, destmbox));
475     r = copy_response(&sockpri,
476     imap_copy(&sockpri, tok, destmbox));
477 lefcha 1.22 }
478 lefcha 1.34 tok = strtok_r(NULL, " ", &m);
479 lefcha 1.22 }
480 lefcha 1.23
481 lefcha 1.19 xfree(mcp);
482 lefcha 1.8
483 lefcha 1.20 return r;
484 lefcha 1.1 }
485    
486    
487     /*
488     * Move messages to specified mailbox.
489     */
490 lefcha 1.3 int action_move(char *mesgs, char *destmbox, char *args)
491 lefcha 1.1 {
492 lefcha 1.20 if (!action_copy(mesgs, destmbox, args))
493     action_delete(mesgs, "\0");
494 lefcha 1.16
495 lefcha 1.1 return 0;
496     }
497    
498    
499     /*
500 lefcha 1.21 * Copy messages to the specified mailbox of another mail server.
501     */
502 lefcha 1.25 int action_rcopy(char *mesgs, account_t * destacc, char *destmbox, char *args)
503 lefcha 1.21 {
504 lefcha 1.37 int r, ta, tf;
505 lefcha 1.21 char *tok, *m, *mcp, *ndm;
506 lefcha 1.30 unsigned int n;
507 lefcha 1.37 char buf[RESPONSE_BUF * 2];
508 lefcha 1.25
509 lefcha 1.21 if (init_connection(&sockaux, destacc->server, destacc->port,
510     destacc->ssl))
511     return ERROR_NETWORK;
512 lefcha 1.25
513 lefcha 1.21 r = greeting_response(&sockaux);
514 lefcha 1.25
515 lefcha 1.21 if (r == RESPONSE_BYE || check_capabilities(&sockaux))
516     return ERROR_NETWORK;
517 lefcha 1.25
518 lefcha 1.21 #ifdef DEBUG
519     test(&sockaux);
520     #endif
521 lefcha 1.25
522 lefcha 1.21 if (r != RESPONSE_PREAUTH) {
523     if (destacc->passwdattr == PASSWORD_NONE) {
524     printf("Enter password for %s@%s: ", destacc->username,
525     destacc->server);
526     get_password(destacc->password, PASSWORD_LEN);
527     destacc->passwdattr = PASSWORD_PLAIN;
528     }
529     if (login(&sockaux, destacc->username,
530     destacc->password) == RESPONSE_NO) {
531     error("imapfilter: username %s or password rejected at %s\n",
532     destacc->username, destacc->server);
533     return ERROR_NETWORK;
534     }
535     }
536     check_namespace(&sockaux, &nspaux);
537    
538     /* apply_namespace() returns a pointer to a static buffer. */
539     ndm = apply_namespace(destmbox, nspaux.prefix, nspaux.delim);
540 lefcha 1.25
541 lefcha 1.40 r = check_mailbox(&sockaux, destmbox, &nspaux);
542 lefcha 1.21
543     if (r == RESPONSE_OK)
544     close_mailbox(&sockaux);
545     else if (r == RESPONSE_NO) {
546     server_response(&sockaux, imap_create(&sockaux, ndm));
547 lefcha 1.27 if ((options & OPTION_SUBSCRIBE))
548     server_response(&sockaux, imap_subscribe(&sockaux, ndm));
549 lefcha 1.21 }
550     m = mcp = xstrdup(mesgs);
551    
552 lefcha 1.34 tok = strtok_r(m, " ", &m);
553     while (tok) {
554 lefcha 1.21 fetchsize_response(&sockpri, &n,
555 lefcha 1.25 imap_fetch(&sockpri, tok, "RFC822.SIZE"));
556    
557 lefcha 1.37 ta = imap_append(&sockaux, ndm, n);
558 lefcha 1.21
559 lefcha 1.37 fetch_response(&sockpri, 0, 1, NULL);
560     tf = imap_fetch(&sockpri, tok, "RFC822.HEADER");
561 lefcha 1.21 do {
562 lefcha 1.37 r = fetch_response(&sockpri, tf, 0, buf);
563 lefcha 1.21 socket_write(&sockaux, buf);
564     } while (r == RESPONSE_NONE);
565 lefcha 1.25
566 lefcha 1.21 socket_write(&sockaux, "\r\n");
567    
568 lefcha 1.37 fetch_response(&sockpri, 0, 1, NULL);
569     tf = imap_fetch(&sockpri, tok, "BODY[TEXT]");
570 lefcha 1.21 do {
571 lefcha 1.37 r = fetch_response(&sockpri, tf, 0, buf);
572 lefcha 1.39 if (r != RESPONSE_NULLBODY)
573 lefcha 1.38 socket_write(&sockaux, buf);
574 lefcha 1.21 } while (r == RESPONSE_NONE);
575 lefcha 1.25
576 lefcha 1.39 if (r != RESPONSE_NULLBODY)
577 lefcha 1.38 socket_write(&sockaux, "\r\n\r\n");
578     else
579     socket_write(&sockaux, "\r\n");
580 lefcha 1.25
581 lefcha 1.37 append_response(&sockaux, ta);
582 lefcha 1.34
583     tok = strtok_r(NULL, " ", &m);
584 lefcha 1.21 }
585    
586     logout(&sockaux);
587 lefcha 1.25
588 lefcha 1.21 action_list(mesgs, args);
589 lefcha 1.25
590 lefcha 1.21 xfree(mcp);
591    
592     return 0;
593     }
594    
595    
596     /*
597     * Move messages to the specified mailbox of another mail server.
598     */
599 lefcha 1.25 int action_rmove(char *mesgs, account_t * destacc, char *destmbox, char *args)
600 lefcha 1.21 {
601     if (!action_rcopy(mesgs, destacc, destmbox, args))
602     action_delete(mesgs, "\0");
603 lefcha 1.25
604 lefcha 1.21 return 0;
605     }
606    
607 lefcha 1.26
608     /*
609 lefcha 1.27 * Flag messages by replacing, adding or removing specified flags.
610 lefcha 1.26 */
611     int action_flag(char *mesgs, unsigned int *type, unsigned int *msgflags,
612     char *args)
613     {
614     unsigned int t;
615     char s[STORE_FLAGS_BUF];
616     char *tok, *m, *mcp;
617    
618     *s = 0;
619    
620     switch (*type) {
621     case FILTER_ACTION_FLAG_ADD:
622     t = STORE_FLAG_ADD;
623     break;
624     case FILTER_ACTION_FLAG_REMOVE:
625     t = STORE_FLAG_REMOVE;
626     break;
627 lefcha 1.28 default:
628     t = STORE_FLAG_REPLACE;
629 lefcha 1.26 }
630    
631     if ((*msgflags != MESSAGE_FLAG_NONE)) {
632     if ((*msgflags & MESSAGE_FLAG_SEEN))
633     strncat(s, "\\Seen ", STORE_FLAGS_BUF - strlen(s) - 1);
634     if ((*msgflags & MESSAGE_FLAG_ANSWERED))
635     strncat(s, "\\Answered ", STORE_FLAGS_BUF - strlen(s) - 1);
636     if ((*msgflags & MESSAGE_FLAG_FLAGGED))
637     strncat(s, "\\Flagged ", STORE_FLAGS_BUF - strlen(s) - 1);
638     if ((*msgflags & MESSAGE_FLAG_DELETED))
639     strncat(s, "\\Deleted ", STORE_FLAGS_BUF - strlen(s) - 1);
640     if ((*msgflags & MESSAGE_FLAG_DRAFT))
641     strncat(s, "\\Draft", STORE_FLAGS_BUF - strlen(s) - 1);
642     if ((s[strlen(s) - 1] == ' '))
643     s[strlen(s) - 1] = 0;
644     }
645     action_list(mesgs, args);
646    
647     m = mcp = convert_messages(mesgs);
648    
649 lefcha 1.34 tok = strtok_r(m, " ", &m);
650     while (tok) {
651 lefcha 1.26 server_response(&sockpri, imap_store(&sockpri, tok, t, s));
652    
653 lefcha 1.34 tok = strtok_r(NULL, " ", &m);
654     }
655    
656 lefcha 1.26 if (options & OPTION_EXPUNGE)
657     server_response(&sockpri, imap_expunge(&sockpri));
658    
659     xfree(mcp);
660    
661     return 0;
662     }
663 lefcha 1.21
664     /*
665 lefcha 1.1 * List user selected headers of messages.
666     */
667     int action_list(char *mesgs, char *args)
668     {
669 lefcha 1.37 int r, t;
670 lefcha 1.21 char *tok, *mcp, *m;
671     char s[ARGS_LEN + 27];
672     char hdrs[RESPONSE_BUF];
673 lefcha 1.5
674 lefcha 1.2 if (!*args)
675     return 0;
676 lefcha 1.1
677 lefcha 1.5 m = mcp = xstrdup(mesgs);
678 lefcha 1.6
679 lefcha 1.21 snprintf(s, ARGS_LEN + 27 - 1, "BODY.PEEK[HEADER.FIELDS (%s)]", args);
680 lefcha 1.1
681 lefcha 1.34 tok = strtok_r(m, " ", &m);
682     while (tok) {
683 lefcha 1.21 /* Reset internal fetch counter. */
684 lefcha 1.37 fetch_response(&sockpri, 0, 1, NULL);
685     t = imap_fetch(&sockpri, tok, s);
686 lefcha 1.33 do
687 lefcha 1.37 r = fetch_response(&sockpri, t, 0, hdrs);
688 lefcha 1.33 while (r == RESPONSE_NONE);
689 lefcha 1.25
690 lefcha 1.33 if (*hdrs) {
691     if (options & OPTION_HEADERS)
692     info("%s\n", hdrs);
693     log_info(LOG_WRITE, hdrs);
694     } else {
695     log_info(LOG_WRITE, NULL);
696     }
697 lefcha 1.34
698     tok = strtok_r(NULL, " ", &m);
699 lefcha 1.21 }
700 lefcha 1.1
701 lefcha 1.19 xfree(mcp);
702 lefcha 1.1
703     return 0;
704     }
705    
706    
707     /*
708 lefcha 1.21 * Count how many messages matched the filter.
709     */
710     unsigned int count_messages(char *mesgs)
711     {
712     unsigned int cnt = 0;
713     char *c = mesgs;
714 lefcha 1.25
715 lefcha 1.21 while ((c = strchr(c, ' '))) {
716     cnt++;
717     c++;
718     }
719    
720     return ++cnt;
721     }
722    
723    
724     /*
725 lefcha 1.11 * Convert messages with contiguous sequence number to the corresponding
726 lefcha 1.27 * number range, eg. 1 2 3 5 7 8 --> 1:3 5 7:8 and return a newly allocated
727     * buffer with the results.
728 lefcha 1.1 */
729 lefcha 1.23 char *convert_messages(char *mesgs)
730 lefcha 1.1 {
731 lefcha 1.36 int maxlen;
732 lefcha 1.1 unsigned int start, end, tmp;
733 lefcha 1.23 char *c, *cp, *tail;
734 lefcha 1.25
735 lefcha 1.21 start = end = tmp = 0;
736 lefcha 1.13 maxlen = strlen(mesgs) + 1;
737     tail = NULL;
738 lefcha 1.1
739 lefcha 1.23 c = cp = xstrdup(mesgs);
740 lefcha 1.1
741 lefcha 1.25 start = (unsigned int)strtoul(mesgs, &tail, 10);
742 lefcha 1.1 end = start;
743    
744     do {
745     if (tail) {
746 lefcha 1.25 tmp = (unsigned int)strtoul(tail, &tail, 10);
747 lefcha 1.21 if (!tmp)
748 lefcha 1.15 tail = NULL;
749 lefcha 1.1 }
750     if (tmp == end + 1)
751     end++;
752     else {
753 lefcha 1.13 if (start == end) {
754 lefcha 1.23 xstrncpy(c, ultostr(start, 10), maxlen);
755     c += strlen(c);
756 lefcha 1.13 } else {
757 lefcha 1.23 xstrncpy(c, ultostr(start, 10), maxlen - 1);
758     c += strlen(c);
759     *c = ':';
760     *++c = 0;
761     xstrncpy(c, ultostr(end, 10), maxlen);
762     c += strlen(c);
763 lefcha 1.13 }
764 lefcha 1.1
765 lefcha 1.23 if (tail && c - cp < maxlen) {
766     *c = ' ';
767     *++c = 0;
768 lefcha 1.13 }
769 lefcha 1.1 start = end = tmp;
770     }
771     } while (tmp);
772    
773 lefcha 1.23 return cp;
774 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26