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

Annotation of /imapfilter/request.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.32.2.8 - (hide annotations)
Fri Mar 28 16:57:52 2003 UTC (21 years ago) by lefcha
Branch: release-0_8-patches
Changes since 1.32.2.7: +16 -18 lines
File MIME type: text/plain
Correct bug with long headers along with action list and logger.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26