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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.32 - (hide annotations)
Sat Jul 27 14:56:51 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_8
Branch point for: release-0_8-patches
Changes since 1.31: +1 -1 lines
File MIME type: text/plain
Message printing typo error fix.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26