Implement editheader sieve extension (RFC 5293).
Also fix iterator synchronization after removing an element and improve Sieve API. * include/mailutils/header.h (mu_header_get_itemptr): New proto. * include/mailutils/iterator.h (mu_iterator_advance): Remove. (mu_iterator_delitem): New proto. (mu_iterator_set_delitem): New proto. * include/mailutils/sieve.h (mu_sieve_register_t) <opt_args>: New member. (mu_sieve_register_test_ext) (mu_sieve_register_action_ext): New protos. * include/mailutils/sys/iterator.h (_mu_iterator) <curitem_p>: Remove. <delitem>: New member. All uses updated. * libmailutils/base/iterator.c (mu_iterator_set_delitem): New function. * libmailutils/mailbox/hdritr.c: Implement bidirectional iteration. Implement itrctl method. * libmailutils/mailbox/header.c: Likewise. * libmailutils/base/assoc.c: Use delitem method instead of curitem_p. (mu_iterator_delitem): New function. * libmailutils/base/opool.c * libmailutils/diag/debug.c * libmailutils/list/iterator.c * libmailutils/list/pop.c * libmailutils/list/remove.c * libmailutils/list/removenth.c * libmailutils/mailbox/imapenv.c * libmailutils/mailbox/mbxitr.c * libproto/pop/pop3_iterator.c * libmu_sieve/extensions/Makefile.am: Add editheader.c * libmu_sieve/extensions/editheader.c: New file. * libmu_sieve/prog.c (mu_sv_code_command): Allow for optional positional arguments. * libmu_sieve/register.c (mu_sieve_test_lookup) (mu_sieve_action_lookup): Return NULL if a record with empty (NULL) handler is found. (mu_sieve_register_test_ext) (mu_sieve_register_action_ext): New functions. (mu_sieve_register_test) (mu_sieve_register_action): Rewrite as wrappers to the above. * libmu_sieve/util.c (mu_sieve_vlist_do): Allow for SVT_STRING argument. * sieve/tests/Makefile.am: Add new testcases. * sieve/tests/testsuite.at: Include new testcases. * sieve/tests/addheader.at: New testcase. * sieve/tests/delheader.at: New testcase. * NEWS: Update. * doc/rfc/README: Update.
Showing
28 changed files
with
870 additions
and
80 deletions
1 | GNU mailutils NEWS -- history of user-visible changes. 2012-08-07 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2012-11-12 |
2 | Copyright (C) 2002-2012 Free Software Foundation, Inc. | 2 | Copyright (C) 2002-2012 Free Software Foundation, Inc. |
3 | See the end of file for copying conditions. | 3 | See the end of file for copying conditions. |
4 | 4 | ||
... | @@ -114,6 +114,10 @@ header field with the given date. | ... | @@ -114,6 +114,10 @@ header field with the given date. |
114 | 114 | ||
115 | See <http://mailutils.org/wiki/Timestamp_(Sieve_test)>. | 115 | See <http://mailutils.org/wiki/Timestamp_(Sieve_test)>. |
116 | 116 | ||
117 | Implemented the Editheader extension: `addheader' and `delheader' actions. | ||
118 | |||
119 | See <http://tools.ietf.org/html/rfc5293>. | ||
120 | |||
117 | ** mail: sending attachments | 121 | ** mail: sending attachments |
118 | 122 | ||
119 | The mail[x] utility now allows for sending attachments. Any number of | 123 | The mail[x] utility now allows for sending attachments. Any number of | ... | ... |
... | @@ -53,3 +53,4 @@ the actual RFC number. | ... | @@ -53,3 +53,4 @@ the actual RFC number. |
53 | 3501 INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 | 53 | 3501 INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 |
54 | 3691 Internet Message Access Protocol (IMAP) UNSELECT command | 54 | 3691 Internet Message Access Protocol (IMAP) UNSELECT command |
55 | 4314 IMAP4 Access Control List (ACL) Extension | 55 | 4314 IMAP4 Access Control List (ACL) Extension |
56 | 5293 Sieve Email Filtering: Editheader Extension | ... | ... |
... | @@ -169,6 +169,8 @@ extern int mu_header_set_fill (mu_header_t, | ... | @@ -169,6 +169,8 @@ extern int mu_header_set_fill (mu_header_t, |
169 | int (*_fill) (void *data, char **, size_t *), | 169 | int (*_fill) (void *data, char **, size_t *), |
170 | void *data); | 170 | void *data); |
171 | 171 | ||
172 | extern int mu_header_get_itemptr (mu_header_t header, size_t num, | ||
173 | const void **sptr); | ||
172 | 174 | ||
173 | #ifdef __cplusplus | 175 | #ifdef __cplusplus |
174 | } | 176 | } | ... | ... |
... | @@ -37,7 +37,7 @@ enum mu_itrctl_req | ... | @@ -37,7 +37,7 @@ enum mu_itrctl_req |
37 | mu_itrctl_qry_direction, /* Query iteration direction */ | 37 | mu_itrctl_qry_direction, /* Query iteration direction */ |
38 | mu_itrctl_set_direction /* Set iteration direction */ | 38 | mu_itrctl_set_direction /* Set iteration direction */ |
39 | }; | 39 | }; |
40 | 40 | ||
41 | extern int mu_iterator_create (mu_iterator_t *, void *); | 41 | extern int mu_iterator_create (mu_iterator_t *, void *); |
42 | extern int mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig); | 42 | extern int mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig); |
43 | extern void mu_iterator_destroy (mu_iterator_t *); | 43 | extern void mu_iterator_destroy (mu_iterator_t *); |
... | @@ -53,7 +53,7 @@ extern int mu_iterator_ctl (mu_iterator_t, enum mu_itrctl_req, void *); | ... | @@ -53,7 +53,7 @@ extern int mu_iterator_ctl (mu_iterator_t, enum mu_itrctl_req, void *); |
53 | 53 | ||
54 | extern int mu_iterator_attach (mu_iterator_t *root, mu_iterator_t iterator); | 54 | extern int mu_iterator_attach (mu_iterator_t *root, mu_iterator_t iterator); |
55 | extern int mu_iterator_detach (mu_iterator_t *root, mu_iterator_t iterator); | 55 | extern int mu_iterator_detach (mu_iterator_t *root, mu_iterator_t iterator); |
56 | extern void mu_iterator_advance (mu_iterator_t iterator, void *e); | 56 | extern void mu_iterator_delitem (mu_iterator_t iterator, void *e); |
57 | 57 | ||
58 | extern int mu_iterator_set_first (mu_iterator_t, int (*first) (void *)); | 58 | extern int mu_iterator_set_first (mu_iterator_t, int (*first) (void *)); |
59 | extern int mu_iterator_set_next (mu_iterator_t, int (*next) (void *)); | 59 | extern int mu_iterator_set_next (mu_iterator_t, int (*next) (void *)); |
... | @@ -66,8 +66,13 @@ extern int mu_iterator_set_dup (mu_iterator_t itr, | ... | @@ -66,8 +66,13 @@ extern int mu_iterator_set_dup (mu_iterator_t itr, |
66 | int (*dup) (void **ptr, void *data)); | 66 | int (*dup) (void **ptr, void *data)); |
67 | extern int mu_iterator_set_destroy (mu_iterator_t itr, | 67 | extern int mu_iterator_set_destroy (mu_iterator_t itr, |
68 | int (*destroy) (mu_iterator_t, void *data)); | 68 | int (*destroy) (mu_iterator_t, void *data)); |
69 | extern int mu_iterator_set_curitem_p (mu_iterator_t itr, | 69 | |
70 | int (*curitem_p) (void *, void *)); | 70 | #define MU_ITR_DELITEM_NOTHING 0 |
71 | #define MU_ITR_DELITEM_NEXT 1 | ||
72 | #define MU_ITR_DELITEM_ADVANCE 2 | ||
73 | |||
74 | extern int mu_iterator_set_delitem (mu_iterator_t itr, | ||
75 | int (*delitem) (void *, void *)); | ||
71 | extern int mu_iterator_set_itrctl (mu_iterator_t itr, | 76 | extern int mu_iterator_set_itrctl (mu_iterator_t itr, |
72 | int (*itrctl) (void *, | 77 | int (*itrctl) (void *, |
73 | enum mu_itrctl_req, | 78 | enum mu_itrctl_req, | ... | ... |
... | @@ -100,6 +100,7 @@ typedef struct | ... | @@ -100,6 +100,7 @@ typedef struct |
100 | int required; | 100 | int required; |
101 | mu_sieve_handler_t handler; | 101 | mu_sieve_handler_t handler; |
102 | mu_sieve_data_type *req_args; | 102 | mu_sieve_data_type *req_args; |
103 | mu_sieve_data_type *opt_args; | ||
103 | mu_sieve_tag_group_t *tags; | 104 | mu_sieve_tag_group_t *tags; |
104 | } mu_sieve_register_t; | 105 | } mu_sieve_register_t; |
105 | 106 | ||
... | @@ -146,10 +147,21 @@ mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach, | ... | @@ -146,10 +147,21 @@ mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach, |
146 | const char *name); | 147 | const char *name); |
147 | mu_sieve_register_t *mu_sieve_action_lookup (mu_sieve_machine_t mach, | 148 | mu_sieve_register_t *mu_sieve_action_lookup (mu_sieve_machine_t mach, |
148 | const char *name); | 149 | const char *name); |
150 | int mu_sieve_register_test_ext (mu_sieve_machine_t mach, | ||
151 | const char *name, mu_sieve_handler_t handler, | ||
152 | mu_sieve_data_type *req_args, | ||
153 | mu_sieve_data_type *opt_args, | ||
154 | mu_sieve_tag_group_t *tags, int required); | ||
149 | int mu_sieve_register_test (mu_sieve_machine_t mach, | 155 | int mu_sieve_register_test (mu_sieve_machine_t mach, |
150 | const char *name, mu_sieve_handler_t handler, | 156 | const char *name, mu_sieve_handler_t handler, |
151 | mu_sieve_data_type * arg_types, | 157 | mu_sieve_data_type * arg_types, |
152 | mu_sieve_tag_group_t * tags, int required); | 158 | mu_sieve_tag_group_t * tags, int required); |
159 | |||
160 | int mu_sieve_register_action_ext (mu_sieve_machine_t mach, | ||
161 | const char *name, mu_sieve_handler_t handler, | ||
162 | mu_sieve_data_type *req_args, | ||
163 | mu_sieve_data_type *opt_args, | ||
164 | mu_sieve_tag_group_t *tags, int required); | ||
153 | int mu_sieve_register_action (mu_sieve_machine_t mach, | 165 | int mu_sieve_register_action (mu_sieve_machine_t mach, |
154 | const char *name, mu_sieve_handler_t handler, | 166 | const char *name, mu_sieve_handler_t handler, |
155 | mu_sieve_data_type * arg_types, | 167 | mu_sieve_data_type * arg_types, | ... | ... |
... | @@ -36,7 +36,7 @@ struct _mu_iterator | ... | @@ -36,7 +36,7 @@ struct _mu_iterator |
36 | int (*first) (void *owner); | 36 | int (*first) (void *owner); |
37 | int (*next) (void *owner); | 37 | int (*next) (void *owner); |
38 | int (*getitem) (void *owner, void **pret, const void **pkey); | 38 | int (*getitem) (void *owner, void **pret, const void **pkey); |
39 | int (*curitem_p) (void *owner, void *item); | 39 | int (*delitem) (void *owner, void *item); |
40 | int (*finished_p) (void *owner); | 40 | int (*finished_p) (void *owner); |
41 | int (*itrctl) (void *owner, enum mu_itrctl_req req, void *arg); | 41 | int (*itrctl) (void *owner, enum mu_itrctl_req req, void *arg); |
42 | void *(*dataptr) (void *); | 42 | void *(*dataptr) (void *); | ... | ... |
... | @@ -452,13 +452,13 @@ destroy (mu_iterator_t iterator, void *data) | ... | @@ -452,13 +452,13 @@ destroy (mu_iterator_t iterator, void *data) |
452 | } | 452 | } |
453 | 453 | ||
454 | static int | 454 | static int |
455 | curitem_p (void *owner, void *item) | 455 | delitem (void *owner, void *item) |
456 | { | 456 | { |
457 | struct assoc_iterator *itr = owner; | 457 | struct assoc_iterator *itr = owner; |
458 | mu_assoc_t assoc = itr->assoc; | 458 | mu_assoc_t assoc = itr->assoc; |
459 | struct _mu_assoc_elem *elem = ASSOC_ELEM (assoc, itr->index); | 459 | struct _mu_assoc_elem *elem = ASSOC_ELEM (assoc, itr->index); |
460 | 460 | ||
461 | return elem == item; | 461 | return elem == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; |
462 | } | 462 | } |
463 | 463 | ||
464 | static int | 464 | static int |
... | @@ -498,7 +498,7 @@ mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator) | ... | @@ -498,7 +498,7 @@ mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator) |
498 | mu_iterator_set_next (iterator, next); | 498 | mu_iterator_set_next (iterator, next); |
499 | mu_iterator_set_getitem (iterator, getitem); | 499 | mu_iterator_set_getitem (iterator, getitem); |
500 | mu_iterator_set_finished_p (iterator, finished_p); | 500 | mu_iterator_set_finished_p (iterator, finished_p); |
501 | mu_iterator_set_curitem_p (iterator, curitem_p); | 501 | mu_iterator_set_delitem (iterator, delitem); |
502 | mu_iterator_set_destroy (iterator, destroy); | 502 | mu_iterator_set_destroy (iterator, destroy); |
503 | mu_iterator_set_dup (iterator, assoc_data_dup); | 503 | mu_iterator_set_dup (iterator, assoc_data_dup); |
504 | 504 | ... | ... |
... | @@ -81,12 +81,12 @@ mu_iterator_set_finished_p (mu_iterator_t itr, int (*finished_p) (void *)) | ... | @@ -81,12 +81,12 @@ mu_iterator_set_finished_p (mu_iterator_t itr, int (*finished_p) (void *)) |
81 | } | 81 | } |
82 | 82 | ||
83 | int | 83 | int |
84 | mu_iterator_set_curitem_p (mu_iterator_t itr, | 84 | mu_iterator_set_delitem (mu_iterator_t itr, |
85 | int (*curitem_p) (void *, void *)) | 85 | int (*delitem) (void *, void *)) |
86 | { | 86 | { |
87 | if (!itr) | 87 | if (!itr) |
88 | return EINVAL; | 88 | return EINVAL; |
89 | itr->curitem_p = curitem_p; | 89 | itr->delitem = delitem; |
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
... | @@ -158,7 +158,7 @@ mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig) | ... | @@ -158,7 +158,7 @@ mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig) |
158 | iterator->first = orig->first; | 158 | iterator->first = orig->first; |
159 | iterator->next = orig->next; | 159 | iterator->next = orig->next; |
160 | iterator->getitem = orig->getitem; | 160 | iterator->getitem = orig->getitem; |
161 | iterator->curitem_p = orig->curitem_p; | 161 | iterator->delitem = orig->delitem; |
162 | iterator->finished_p = orig->finished_p; | 162 | iterator->finished_p = orig->finished_p; |
163 | iterator->itrctl = orig->itrctl; | 163 | iterator->itrctl = orig->itrctl; |
164 | 164 | ||
... | @@ -250,14 +250,19 @@ iterator_get_owner (mu_iterator_t iterator, void **powner) | ... | @@ -250,14 +250,19 @@ iterator_get_owner (mu_iterator_t iterator, void **powner) |
250 | } | 250 | } |
251 | 251 | ||
252 | void | 252 | void |
253 | mu_iterator_advance (mu_iterator_t iterator, void *e) | 253 | mu_iterator_delitem (mu_iterator_t iterator, void *itm) |
254 | { | 254 | { |
255 | for (; iterator; iterator = iterator->next_itr) | 255 | for (; iterator; iterator = iterator->next_itr) |
256 | { | 256 | { |
257 | if (iterator->curitem_p (iterator->owner, e)) | 257 | if (iterator->delitem) |
258 | { | 258 | { |
259 | iterator->next (iterator->owner); | 259 | switch (iterator->delitem (iterator->owner, itm)) |
260 | iterator->is_advanced++; | 260 | { |
261 | case MU_ITR_DELITEM_NEXT: | ||
262 | iterator->next (iterator->owner); | ||
263 | case MU_ITR_DELITEM_ADVANCE: | ||
264 | iterator->is_advanced++; | ||
265 | } | ||
261 | } | 266 | } |
262 | } | 267 | } |
263 | } | 268 | } | ... | ... |
... | @@ -384,10 +384,11 @@ opitr_finished_p (void *owner) | ... | @@ -384,10 +384,11 @@ opitr_finished_p (void *owner) |
384 | } | 384 | } |
385 | 385 | ||
386 | static int | 386 | static int |
387 | opitr_curitem_p (void *owner, void *item) | 387 | opitr_delitem (void *owner, void *item) |
388 | { | 388 | { |
389 | struct opool_iterator *itr = owner; | 389 | struct opool_iterator *itr = owner; |
390 | return itr->cur && itr->cur->buf == item; | 390 | return (itr->cur && itr->cur->buf == item) ? |
391 | MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; | ||
391 | } | 392 | } |
392 | 393 | ||
393 | static int | 394 | static int |
... | @@ -446,7 +447,7 @@ mu_opool_get_iterator (mu_opool_t opool, mu_iterator_t *piterator) | ... | @@ -446,7 +447,7 @@ mu_opool_get_iterator (mu_opool_t opool, mu_iterator_t *piterator) |
446 | mu_iterator_set_next (iterator, opitr_next); | 447 | mu_iterator_set_next (iterator, opitr_next); |
447 | mu_iterator_set_getitem (iterator, opitr_getitem); | 448 | mu_iterator_set_getitem (iterator, opitr_getitem); |
448 | mu_iterator_set_finished_p (iterator, opitr_finished_p); | 449 | mu_iterator_set_finished_p (iterator, opitr_finished_p); |
449 | mu_iterator_set_curitem_p (iterator, opitr_curitem_p); | 450 | mu_iterator_set_delitem (iterator, opitr_delitem); |
450 | mu_iterator_set_destroy (iterator, opitr_destroy); | 451 | mu_iterator_set_destroy (iterator, opitr_destroy); |
451 | mu_iterator_set_dup (iterator, opitr_data_dup); | 452 | mu_iterator_set_dup (iterator, opitr_data_dup); |
452 | 453 | ... | ... |
... | @@ -572,10 +572,11 @@ finished_p (void *owner) | ... | @@ -572,10 +572,11 @@ finished_p (void *owner) |
572 | } | 572 | } |
573 | 573 | ||
574 | static int | 574 | static int |
575 | curitem_p (void *owner, void *item) | 575 | delitem (void *owner, void *item) |
576 | { | 576 | { |
577 | struct debug_iterator *itr = owner; | 577 | struct debug_iterator *itr = owner; |
578 | return mu_c_strcasecmp (cattab[itr->pos].name, (char *) item) == 0; | 578 | return mu_c_strcasecmp (cattab[itr->pos].name, (char *) item) == 0 ? |
579 | MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; | ||
579 | } | 580 | } |
580 | 581 | ||
581 | static int | 582 | static int |
... | @@ -659,7 +660,7 @@ mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset) | ... | @@ -659,7 +660,7 @@ mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset) |
659 | mu_iterator_set_next (iterator, next); | 660 | mu_iterator_set_next (iterator, next); |
660 | mu_iterator_set_getitem (iterator, getitem); | 661 | mu_iterator_set_getitem (iterator, getitem); |
661 | mu_iterator_set_finished_p (iterator, finished_p); | 662 | mu_iterator_set_finished_p (iterator, finished_p); |
662 | mu_iterator_set_curitem_p (iterator, curitem_p); | 663 | mu_iterator_set_delitem (iterator, delitem); |
663 | mu_iterator_set_dup (iterator, list_data_dup); | 664 | mu_iterator_set_dup (iterator, list_data_dup); |
664 | mu_iterator_set_itrctl (iterator, list_itrctl); | 665 | mu_iterator_set_itrctl (iterator, list_itrctl); |
665 | 666 | ... | ... |
... | @@ -84,10 +84,10 @@ destroy (mu_iterator_t iterator, void *data) | ... | @@ -84,10 +84,10 @@ destroy (mu_iterator_t iterator, void *data) |
84 | } | 84 | } |
85 | 85 | ||
86 | static int | 86 | static int |
87 | curitem_p (void *owner, void *item) | 87 | delitem (void *owner, void *item) |
88 | { | 88 | { |
89 | struct list_iterator *itr = owner; | 89 | struct list_iterator *itr = owner; |
90 | return itr->cur == item; | 90 | return itr->cur == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int | 93 | static int |
... | @@ -142,7 +142,7 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg) | ... | @@ -142,7 +142,7 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg) |
142 | ptr = itr->cur; | 142 | ptr = itr->cur; |
143 | prev = ptr->prev; | 143 | prev = ptr->prev; |
144 | 144 | ||
145 | mu_iterator_advance (list->itr, ptr); | 145 | mu_iterator_delitem (list->itr, ptr); |
146 | prev->next = ptr->next; | 146 | prev->next = ptr->next; |
147 | ptr->next->prev = prev; | 147 | ptr->next->prev = prev; |
148 | if (req == mu_itrctl_delete) | 148 | if (req == mu_itrctl_delete) |
... | @@ -238,7 +238,7 @@ mu_list_get_iterator (mu_list_t list, mu_iterator_t *piterator) | ... | @@ -238,7 +238,7 @@ mu_list_get_iterator (mu_list_t list, mu_iterator_t *piterator) |
238 | mu_iterator_set_next (iterator, next); | 238 | mu_iterator_set_next (iterator, next); |
239 | mu_iterator_set_getitem (iterator, getitem); | 239 | mu_iterator_set_getitem (iterator, getitem); |
240 | mu_iterator_set_finished_p (iterator, finished_p); | 240 | mu_iterator_set_finished_p (iterator, finished_p); |
241 | mu_iterator_set_curitem_p (iterator, curitem_p); | 241 | mu_iterator_set_delitem (iterator, delitem); |
242 | mu_iterator_set_destroy (iterator, destroy); | 242 | mu_iterator_set_destroy (iterator, destroy); |
243 | mu_iterator_set_dup (iterator, list_data_dup); | 243 | mu_iterator_set_dup (iterator, list_data_dup); |
244 | mu_iterator_set_itrctl (iterator, list_itrctl); | 244 | mu_iterator_set_itrctl (iterator, list_itrctl); | ... | ... |
... | @@ -35,7 +35,7 @@ mu_list_pop (mu_list_t list, void **item) | ... | @@ -35,7 +35,7 @@ mu_list_pop (mu_list_t list, void **item) |
35 | 35 | ||
36 | last = list->head.prev; | 36 | last = list->head.prev; |
37 | prev = last->prev; | 37 | prev = last->prev; |
38 | mu_iterator_advance (list->itr, last); | 38 | mu_iterator_delitem (list->itr, last); |
39 | prev->next = last->next; | 39 | prev->next = last->next; |
40 | prev->next->prev = prev; | 40 | prev->next->prev = prev; |
41 | if (item) | 41 | if (item) | ... | ... |
... | @@ -41,7 +41,7 @@ mu_list_remove (mu_list_t list, void *item) | ... | @@ -41,7 +41,7 @@ mu_list_remove (mu_list_t list, void *item) |
41 | { | 41 | { |
42 | struct list_data *previous = current->prev; | 42 | struct list_data *previous = current->prev; |
43 | 43 | ||
44 | mu_iterator_advance (list->itr, current); | 44 | mu_iterator_delitem (list->itr, current); |
45 | previous->next = current->next; | 45 | previous->next = current->next; |
46 | current->next->prev = previous; | 46 | current->next->prev = previous; |
47 | DESTROY_ITEM (list, current); | 47 | DESTROY_ITEM (list, current); | ... | ... |
... | @@ -26,7 +26,6 @@ int | ... | @@ -26,7 +26,6 @@ int |
26 | mu_list_remove_nth (mu_list_t list, size_t n) | 26 | mu_list_remove_nth (mu_list_t list, size_t n) |
27 | { | 27 | { |
28 | struct list_data *current; | 28 | struct list_data *current; |
29 | mu_list_comparator_t comp; | ||
30 | int status = MU_ERR_NOENT; | 29 | int status = MU_ERR_NOENT; |
31 | size_t i; | 30 | size_t i; |
32 | 31 | ||
... | @@ -42,7 +41,7 @@ mu_list_remove_nth (mu_list_t list, size_t n) | ... | @@ -42,7 +41,7 @@ mu_list_remove_nth (mu_list_t list, size_t n) |
42 | { | 41 | { |
43 | struct list_data *previous = current->prev; | 42 | struct list_data *previous = current->prev; |
44 | 43 | ||
45 | mu_iterator_advance (list->itr, current); | 44 | mu_iterator_delitem (list->itr, current); |
46 | previous->next = current->next; | 45 | previous->next = current->next; |
47 | current->next->prev = previous; | 46 | current->next->prev = previous; |
48 | DESTROY_ITEM (list, current); | 47 | DESTROY_ITEM (list, current); | ... | ... |
... | @@ -30,13 +30,20 @@ struct header_iterator | ... | @@ -30,13 +30,20 @@ struct header_iterator |
30 | { | 30 | { |
31 | mu_header_t header; | 31 | mu_header_t header; |
32 | size_t index; | 32 | size_t index; |
33 | int backwards; | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | static int | 36 | static int |
36 | hdr_first (void *owner) | 37 | hdr_first (void *owner) |
37 | { | 38 | { |
38 | struct header_iterator *itr = owner; | 39 | struct header_iterator *itr = owner; |
39 | itr->index = 1; | 40 | if (itr->backwards) |
41 | { | ||
42 | if (mu_header_get_field_count (itr->header, &itr->index)) | ||
43 | return 1; | ||
44 | } | ||
45 | else | ||
46 | itr->index = 1; | ||
40 | return 0; | 47 | return 0; |
41 | } | 48 | } |
42 | 49 | ||
... | @@ -44,7 +51,13 @@ static int | ... | @@ -44,7 +51,13 @@ static int |
44 | hdr_next (void *owner) | 51 | hdr_next (void *owner) |
45 | { | 52 | { |
46 | struct header_iterator *itr = owner; | 53 | struct header_iterator *itr = owner; |
47 | itr->index++; | 54 | if (itr->backwards) |
55 | { | ||
56 | if (itr->index != 0) | ||
57 | itr->index--; | ||
58 | } | ||
59 | else | ||
60 | itr->index++; | ||
48 | return 0; | 61 | return 0; |
49 | } | 62 | } |
50 | 63 | ||
... | @@ -58,16 +71,16 @@ hdr_getitem (void *owner, void **pret, const void **pkey) | ... | @@ -58,16 +71,16 @@ hdr_getitem (void *owner, void **pret, const void **pkey) |
58 | rc = mu_header_get_field_count (itr->header, &count); | 71 | rc = mu_header_get_field_count (itr->header, &count); |
59 | if (rc) | 72 | if (rc) |
60 | return rc; | 73 | return rc; |
61 | if (itr->index > count) | 74 | if (itr->index < 1 || itr->index > count) |
62 | return MU_ERR_NOENT; | 75 | return MU_ERR_NOENT; |
63 | 76 | ||
64 | rc = mu_header_sget_field_name (itr->header, itr->index, | 77 | rc = mu_header_sget_field_value (itr->header, itr->index, |
65 | (const char**) pkey); | 78 | (const char**) pret); |
66 | if (rc == 0) | 79 | if (rc == 0) |
67 | { | 80 | { |
68 | if (pkey) | 81 | if (pkey) |
69 | rc = mu_header_sget_field_value (itr->header, itr->index, | 82 | rc = mu_header_sget_field_name (itr->header, itr->index, |
70 | (const char**) pret); | 83 | (const char**) pkey); |
71 | } | 84 | } |
72 | return rc; | 85 | return rc; |
73 | } | 86 | } |
... | @@ -78,6 +91,9 @@ hdr_finished_p (void *owner) | ... | @@ -78,6 +91,9 @@ hdr_finished_p (void *owner) |
78 | struct header_iterator *itr = owner; | 91 | struct header_iterator *itr = owner; |
79 | size_t count; | 92 | size_t count; |
80 | 93 | ||
94 | if (itr->backwards) | ||
95 | return itr->index < 1; | ||
96 | |||
81 | if (mu_header_get_field_count (itr->header, &count)) | 97 | if (mu_header_get_field_count (itr->header, &count)) |
82 | return 1; | 98 | return 1; |
83 | return itr->index > count; | 99 | return itr->index > count; |
... | @@ -93,13 +109,16 @@ hdr_destroy (mu_iterator_t iterator, void *data) | ... | @@ -93,13 +109,16 @@ hdr_destroy (mu_iterator_t iterator, void *data) |
93 | } | 109 | } |
94 | 110 | ||
95 | static int | 111 | static int |
96 | hdr_curitem_p (void *owner, void *item) | 112 | hdr_delitem (void *owner, void *item) |
97 | { | 113 | { |
98 | void *ptr; | 114 | struct header_iterator *itr = owner; |
115 | const void *ptr; | ||
99 | 116 | ||
100 | if (hdr_getitem (owner, &ptr, NULL)) | 117 | if (mu_header_get_itemptr (itr->header, itr->index, &ptr)) |
101 | return 0; | 118 | return MU_ITR_DELITEM_NOTHING; |
102 | return ptr == item; | 119 | if (ptr == item && !itr->backwards) |
120 | return MU_ITR_DELITEM_ADVANCE; | ||
121 | return MU_ITR_DELITEM_NOTHING; | ||
103 | } | 122 | } |
104 | 123 | ||
105 | static int | 124 | static int |
... | @@ -115,6 +134,51 @@ hdr_data_dup (void **ptr, void *owner) | ... | @@ -115,6 +134,51 @@ hdr_data_dup (void **ptr, void *owner) |
115 | return 0; | 134 | return 0; |
116 | } | 135 | } |
117 | 136 | ||
137 | static int | ||
138 | hdr_itrctl (void *owner, enum mu_itrctl_req req, void *arg) | ||
139 | { | ||
140 | struct header_iterator *itr = owner; | ||
141 | |||
142 | switch (req) | ||
143 | { | ||
144 | case mu_itrctl_tell: | ||
145 | /* Return current position in the object */ | ||
146 | if (hdr_finished_p (owner)) | ||
147 | return MU_ERR_NOENT; | ||
148 | else | ||
149 | *(size_t*)arg = itr->index; | ||
150 | return 0; | ||
151 | break; | ||
152 | |||
153 | case mu_itrctl_delete: | ||
154 | /* Delete current element */ | ||
155 | if (hdr_finished_p (owner)) | ||
156 | return MU_ERR_NOENT; | ||
157 | else | ||
158 | return mu_header_remove (itr->header, NULL, itr->index); | ||
159 | break; | ||
160 | |||
161 | case mu_itrctl_qry_direction: | ||
162 | if (!arg) | ||
163 | return EINVAL; | ||
164 | else | ||
165 | *(int*)arg = itr->backwards; | ||
166 | break; | ||
167 | |||
168 | case mu_itrctl_set_direction: | ||
169 | if (!arg) | ||
170 | return EINVAL; | ||
171 | else | ||
172 | itr->backwards = !!*(int*)arg; | ||
173 | break; | ||
174 | |||
175 | default: | ||
176 | return ENOSYS; | ||
177 | } | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | |||
118 | int | 182 | int |
119 | mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator) | 183 | mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator) |
120 | { | 184 | { |
... | @@ -142,9 +206,10 @@ mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator) | ... | @@ -142,9 +206,10 @@ mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator) |
142 | mu_iterator_set_next (iterator, hdr_next); | 206 | mu_iterator_set_next (iterator, hdr_next); |
143 | mu_iterator_set_getitem (iterator, hdr_getitem); | 207 | mu_iterator_set_getitem (iterator, hdr_getitem); |
144 | mu_iterator_set_finished_p (iterator, hdr_finished_p); | 208 | mu_iterator_set_finished_p (iterator, hdr_finished_p); |
145 | mu_iterator_set_curitem_p (iterator, hdr_curitem_p); | 209 | mu_iterator_set_delitem (iterator, hdr_delitem); |
146 | mu_iterator_set_destroy (iterator, hdr_destroy); | 210 | mu_iterator_set_destroy (iterator, hdr_destroy); |
147 | mu_iterator_set_dup (iterator, hdr_data_dup); | 211 | mu_iterator_set_dup (iterator, hdr_data_dup); |
212 | mu_iterator_set_itrctl (iterator, hdr_itrctl); | ||
148 | 213 | ||
149 | mu_iterator_attach (&hdr->itr, iterator); | 214 | mu_iterator_attach (&hdr->itr, iterator); |
150 | 215 | ... | ... |
... | @@ -80,13 +80,15 @@ mu_hdrent_find (struct _mu_header *hdr, const char *name, int pos) | ... | @@ -80,13 +80,15 @@ mu_hdrent_find (struct _mu_header *hdr, const char *name, int pos) |
80 | if (pos > 0) | 80 | if (pos > 0) |
81 | { | 81 | { |
82 | for (p = hdr->head; p; p = p->next) | 82 | for (p = hdr->head; p; p = p->next) |
83 | if (mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0 && pos-- == 1) | 83 | if ((!name || mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0) && |
84 | pos-- == 1) | ||
84 | break; | 85 | break; |
85 | } | 86 | } |
86 | else if (pos < 0) | 87 | else if (pos < 0) |
87 | { | 88 | { |
88 | for (p = hdr->tail; p; p = p->prev) | 89 | for (p = hdr->tail; p; p = p->prev) |
89 | if (mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0 && ++pos == 0) | 90 | if ((!name || mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0) && |
91 | ++pos == 0) | ||
90 | break; | 92 | break; |
91 | } | 93 | } |
92 | else | 94 | else |
... | @@ -544,7 +546,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) | ... | @@ -544,7 +546,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) |
544 | int status; | 546 | int status; |
545 | struct mu_hdrent *ent; | 547 | struct mu_hdrent *ent; |
546 | 548 | ||
547 | if (header == NULL || fn == NULL) | 549 | if (header == NULL) |
548 | return EINVAL; | 550 | return EINVAL; |
549 | 551 | ||
550 | status = mu_header_fill (header); | 552 | status = mu_header_fill (header); |
... | @@ -555,6 +557,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) | ... | @@ -555,6 +557,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) |
555 | if (!ent) | 557 | if (!ent) |
556 | return MU_ERR_NOENT; | 558 | return MU_ERR_NOENT; |
557 | 559 | ||
560 | mu_iterator_delitem (header->itr, ent); | ||
558 | mu_hdrent_remove (header, ent); | 561 | mu_hdrent_remove (header, ent); |
559 | HEADER_SET_MODIFIED (header); | 562 | HEADER_SET_MODIFIED (header); |
560 | free (ent); | 563 | free (ent); |
... | @@ -782,6 +785,26 @@ mu_header_get_field_count (mu_header_t header, size_t *pcount) | ... | @@ -782,6 +785,26 @@ mu_header_get_field_count (mu_header_t header, size_t *pcount) |
782 | } | 785 | } |
783 | 786 | ||
784 | int | 787 | int |
788 | mu_header_get_itemptr (mu_header_t header, size_t num, const void **sptr) | ||
789 | { | ||
790 | int status; | ||
791 | |||
792 | if (header == NULL) | ||
793 | return EINVAL; | ||
794 | |||
795 | status = mu_header_fill (header); | ||
796 | if (status == 0) | ||
797 | { | ||
798 | struct mu_hdrent *ent = mu_hdrent_nth (header, num); | ||
799 | if (ent) | ||
800 | *sptr = ent; | ||
801 | else | ||
802 | status = MU_ERR_NOENT; | ||
803 | } | ||
804 | return status; | ||
805 | } | ||
806 | |||
807 | int | ||
785 | mu_header_sget_field_name (mu_header_t header, size_t num, const char **sptr) | 808 | mu_header_sget_field_name (mu_header_t header, size_t num, const char **sptr) |
786 | { | 809 | { |
787 | int status; | 810 | int status; | ... | ... |
... | @@ -52,7 +52,7 @@ mu_message_get_imapenvelope (mu_message_t msg, struct mu_imapenvelope **pimapenv | ... | @@ -52,7 +52,7 @@ mu_message_get_imapenvelope (mu_message_t msg, struct mu_imapenvelope **pimapenv |
52 | 52 | ||
53 | if (msg == NULL) | 53 | if (msg == NULL) |
54 | return EINVAL; | 54 | return EINVAL; |
55 | if (imapenvelope == NULL) | 55 | if (pimapenvelope == NULL) |
56 | return MU_ERR_OUT_PTR_NULL; | 56 | return MU_ERR_OUT_PTR_NULL; |
57 | if (msg->_imapenvelope) | 57 | if (msg->_imapenvelope) |
58 | return msg->_imapenvelope (msg, pimapenvelope); | 58 | return msg->_imapenvelope (msg, pimapenvelope); | ... | ... |
... | @@ -111,13 +111,14 @@ mbx_destroy (mu_iterator_t iterator, void *data) | ... | @@ -111,13 +111,14 @@ mbx_destroy (mu_iterator_t iterator, void *data) |
111 | } | 111 | } |
112 | 112 | ||
113 | static int | 113 | static int |
114 | mbx_curitem_p (void *owner, void *item) | 114 | mbx_delitem (void *owner, void *item) |
115 | { | 115 | { |
116 | void *ptr; | 116 | void *ptr; |
117 | 117 | ||
118 | if (mbx_getitem (owner, &ptr, NULL)) | 118 | if (mbx_getitem (owner, &ptr, NULL)) |
119 | return 0; | 119 | return 0; |
120 | return ptr == item;/* FIXME: Is it ok? */ | 120 | return ptr == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; |
121 | /* FIXME: is it ok? */ | ||
121 | } | 122 | } |
122 | 123 | ||
123 | static int | 124 | static int |
... | @@ -210,7 +211,7 @@ mu_mailbox_get_iterator (mu_mailbox_t mbx, mu_iterator_t *piterator) | ... | @@ -210,7 +211,7 @@ mu_mailbox_get_iterator (mu_mailbox_t mbx, mu_iterator_t *piterator) |
210 | mu_iterator_set_next (iterator, mbx_next); | 211 | mu_iterator_set_next (iterator, mbx_next); |
211 | mu_iterator_set_getitem (iterator, mbx_getitem); | 212 | mu_iterator_set_getitem (iterator, mbx_getitem); |
212 | mu_iterator_set_finished_p (iterator, mbx_finished_p); | 213 | mu_iterator_set_finished_p (iterator, mbx_finished_p); |
213 | mu_iterator_set_curitem_p (iterator, mbx_curitem_p); | 214 | mu_iterator_set_delitem (iterator, mbx_delitem); |
214 | mu_iterator_set_destroy (iterator, mbx_destroy); | 215 | mu_iterator_set_destroy (iterator, mbx_destroy); |
215 | mu_iterator_set_dup (iterator, mbx_data_dup); | 216 | mu_iterator_set_dup (iterator, mbx_data_dup); |
216 | mu_iterator_set_itrctl (iterator, mbx_itrctl); | 217 | mu_iterator_set_itrctl (iterator, mbx_itrctl); | ... | ... |
libmu_sieve/extensions/editheader.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2012 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public | ||
15 | License along with GNU Mailutils. If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | /* This module implements the Editheader Extension (RFC 5293) */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <mailutils/types.h> | ||
25 | #include <mailutils/message.h> | ||
26 | #include <mailutils/header.h> | ||
27 | #include <mailutils/error.h> | ||
28 | #include <mailutils/errno.h> | ||
29 | #include <mailutils/sieve.h> | ||
30 | |||
31 | /* Syntax: addheader [:last] <field-name: string> <value: string> | ||
32 | */ | ||
33 | int | ||
34 | sieve_addheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) | ||
35 | { | ||
36 | mu_sieve_value_t *val; | ||
37 | const char *field_name; | ||
38 | const char *field_value; | ||
39 | mu_message_t msg; | ||
40 | mu_header_t hdr; | ||
41 | int rc; | ||
42 | |||
43 | val = mu_sieve_value_get (args, 0); | ||
44 | if (!val) | ||
45 | { | ||
46 | mu_sieve_error (mach, "%lu: %s", | ||
47 | (unsigned long) mu_sieve_get_message_num (mach), | ||
48 | _("cannot get field name")); | ||
49 | mu_sieve_abort (mach); | ||
50 | } | ||
51 | field_name = val->v.string; | ||
52 | |||
53 | val = mu_sieve_value_get (args, 1); | ||
54 | if (!val) | ||
55 | { | ||
56 | mu_sieve_error (mach, "%lu: %s", | ||
57 | (unsigned long) mu_sieve_get_message_num (mach), | ||
58 | _("cannot get field value")); | ||
59 | mu_sieve_abort (mach); | ||
60 | } | ||
61 | field_value = val->v.string; | ||
62 | |||
63 | mu_sieve_log_action (mach, "ADDHEADER", "%s: %s", field_name, field_value); | ||
64 | |||
65 | if (mu_sieve_is_dry_run (mach)) | ||
66 | return 0; | ||
67 | |||
68 | msg = mu_sieve_get_message (mach); | ||
69 | rc = mu_message_get_header (msg, &hdr); | ||
70 | if (rc) | ||
71 | { | ||
72 | mu_sieve_error (mach, "%lu: %s: %s", | ||
73 | (unsigned long) mu_sieve_get_message_num (mach), | ||
74 | _("cannot get message header"), | ||
75 | mu_strerror (rc)); | ||
76 | mu_sieve_abort (mach); | ||
77 | } | ||
78 | |||
79 | rc = (mu_sieve_tag_lookup (tags, "last", NULL) ? | ||
80 | mu_header_append : mu_header_prepend) (hdr, field_name, field_value); | ||
81 | if (rc) | ||
82 | { | ||
83 | mu_sieve_error (mach, "%lu: %s: %s", | ||
84 | (unsigned long) mu_sieve_get_message_num (mach), | ||
85 | _("cannot append message header"), | ||
86 | mu_strerror (rc)); | ||
87 | mu_sieve_abort (mach); | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | /* Syntax: deleteheader [:index <fieldno: number> [:last]] | ||
93 | [COMPARATOR] [MATCH-TYPE] | ||
94 | <field-name: string> | ||
95 | [<value-patterns: string-list>] | ||
96 | */ | ||
97 | int | ||
98 | sieve_deleteheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) | ||
99 | { | ||
100 | mu_sieve_value_t *val; | ||
101 | const char *field_name; | ||
102 | const char *field_pattern; | ||
103 | mu_message_t msg; | ||
104 | mu_header_t hdr; | ||
105 | int rc; | ||
106 | mu_sieve_comparator_t comp; | ||
107 | mu_iterator_t itr; | ||
108 | unsigned long i, idx = 0; | ||
109 | |||
110 | val = mu_sieve_value_get (args, 0); | ||
111 | if (!val) | ||
112 | { | ||
113 | mu_sieve_error (mach, "%lu: %s", | ||
114 | (unsigned long) mu_sieve_get_message_num (mach), | ||
115 | _("cannot get field name")); | ||
116 | mu_sieve_abort (mach); | ||
117 | } | ||
118 | field_name = val->v.string; | ||
119 | |||
120 | val = mu_sieve_value_get (args, 1); | ||
121 | if (!val) | ||
122 | { | ||
123 | field_pattern = NULL; | ||
124 | mu_sieve_log_action (mach, "DELETEHEADER", "%s", field_name); | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | switch (val->type) | ||
129 | { | ||
130 | case SVT_STRING_LIST: | ||
131 | if (mu_list_get (val->v.list, 0, (void**)&field_pattern)) | ||
132 | { | ||
133 | mu_sieve_error (mach, "%lu: %s", | ||
134 | (unsigned long) mu_sieve_get_message_num (mach), | ||
135 | _("cannot get list item")); | ||
136 | mu_sieve_abort (mach); | ||
137 | } | ||
138 | mu_sieve_log_action (mach, "DELETEHEADER", "%s: (regexp)", | ||
139 | field_name); | ||
140 | break; | ||
141 | |||
142 | case SVT_STRING: | ||
143 | field_pattern = val->v.string; | ||
144 | mu_sieve_log_action (mach, "DELETEHEADER", "%s: %s", field_name, | ||
145 | field_pattern); | ||
146 | break; | ||
147 | |||
148 | default: | ||
149 | mu_sieve_error (mach, "%lu: %s: %d", | ||
150 | (unsigned long) mu_sieve_get_message_num (mach), | ||
151 | _("unexpected value type"), val->type); | ||
152 | mu_sieve_abort (mach); | ||
153 | |||
154 | } | ||
155 | } | ||
156 | |||
157 | if (mu_sieve_is_dry_run (mach)) | ||
158 | return 0; | ||
159 | |||
160 | msg = mu_sieve_get_message (mach); | ||
161 | rc = mu_message_get_header (msg, &hdr); | ||
162 | if (rc) | ||
163 | { | ||
164 | mu_sieve_error (mach, "%lu: %s: %s", | ||
165 | (unsigned long) mu_sieve_get_message_num (mach), | ||
166 | _("cannot get message header"), | ||
167 | mu_strerror (rc)); | ||
168 | mu_sieve_abort (mach); | ||
169 | } | ||
170 | |||
171 | mu_header_get_iterator (hdr, &itr); | ||
172 | if (mu_sieve_tag_lookup (tags, "last", NULL)) | ||
173 | { | ||
174 | int backwards = 1; | ||
175 | mu_iterator_ctl (itr, mu_itrctl_set_direction, &backwards); | ||
176 | } | ||
177 | comp = mu_sieve_get_comparator (mach, tags); | ||
178 | |||
179 | if (mu_sieve_tag_lookup (tags, "index", &val)) | ||
180 | idx = val->v.number; | ||
181 | |||
182 | for (i = 0, mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
183 | mu_iterator_next (itr)) | ||
184 | { | ||
185 | const char *fn, *fv; | ||
186 | |||
187 | mu_iterator_current_kv (itr, (const void **)&fn, (void **)&fv); | ||
188 | if (strcmp (field_name, fn)) | ||
189 | continue; | ||
190 | if (idx && ++i < idx) | ||
191 | continue; | ||
192 | |||
193 | if (field_pattern) | ||
194 | { | ||
195 | if (comp (field_pattern, fv)) | ||
196 | mu_iterator_ctl (itr, mu_itrctl_delete, NULL); | ||
197 | } | ||
198 | else | ||
199 | mu_iterator_ctl (itr, mu_itrctl_delete, NULL); | ||
200 | |||
201 | if (idx) | ||
202 | break; | ||
203 | } | ||
204 | mu_iterator_destroy (&itr); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | |||
209 | /* addheader tagged arguments: */ | ||
210 | static mu_sieve_tag_def_t addheader_tags[] = { | ||
211 | { "last", SVT_VOID }, | ||
212 | { NULL } | ||
213 | }; | ||
214 | |||
215 | static mu_sieve_tag_group_t addheader_tag_groups[] = { | ||
216 | { addheader_tags, NULL }, | ||
217 | { NULL } | ||
218 | }; | ||
219 | |||
220 | /* addheader required arguments: */ | ||
221 | static mu_sieve_data_type addheader_args[] = { | ||
222 | SVT_STRING, /* field name */ | ||
223 | SVT_STRING, /* field value */ | ||
224 | SVT_VOID | ||
225 | }; | ||
226 | |||
227 | #if 0 | ||
228 | /* FIXME: The checker interface should be redone. Until then this function | ||
229 | is commented out. Problems: | ||
230 | |||
231 | 1. Checkers are called per group, there's no way to call them per tag. | ||
232 | 2. See FIXMEs in the code. | ||
233 | */ | ||
234 | static int | ||
235 | index_checker (const char *name, mu_list_t tags, mu_list_t args) | ||
236 | { | ||
237 | mu_iterator_t itr; | ||
238 | mu_sieve_runtime_tag_t *match = NULL; | ||
239 | int err; | ||
240 | |||
241 | if (!tags || mu_list_get_iterator (tags, &itr)) | ||
242 | return 0; | ||
243 | |||
244 | err = 0; | ||
245 | for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr); | ||
246 | mu_iterator_next (itr)) | ||
247 | { | ||
248 | mu_sieve_runtime_tag_t *t; | ||
249 | mu_iterator_current (itr, (void **)&t); | ||
250 | |||
251 | if (strcmp (t->tag, "index") == 0) | ||
252 | { | ||
253 | if (match) | ||
254 | { | ||
255 | /* FIXME: 1. This function must be public. | ||
256 | 2. locus should be included in t | ||
257 | */ | ||
258 | mu_sv_compile_error (&mu_sieve_locus, | ||
259 | _("index specified twice in call to `%s'"), | ||
260 | name); | ||
261 | err = 1; | ||
262 | break; | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | mu_iterator_destroy (&itr); | ||
268 | |||
269 | if (err) | ||
270 | return 1; | ||
271 | |||
272 | if (match) | ||
273 | { | ||
274 | if (match->arg->v.number < 1) | ||
275 | { | ||
276 | // See FIXME above | ||
277 | mu_sv_compile_error (&mu_sieve_locus, | ||
278 | _("invalid index value: %s"), | ||
279 | match->arg->v.string); | ||
280 | return 1; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | #endif | ||
287 | |||
288 | static mu_sieve_tag_def_t match_part_tags[] = { | ||
289 | { "is", SVT_VOID }, | ||
290 | { "contains", SVT_VOID }, | ||
291 | { "matches", SVT_VOID }, | ||
292 | { "regex", SVT_VOID }, | ||
293 | { "count", SVT_STRING }, | ||
294 | { "value", SVT_STRING }, | ||
295 | { "comparator", SVT_STRING }, | ||
296 | { NULL } | ||
297 | }; | ||
298 | |||
299 | /* deleteheader tagged arguments: */ | ||
300 | static mu_sieve_tag_def_t deleteheader_tags[] = { | ||
301 | { "last", SVT_VOID }, | ||
302 | { "index", SVT_NUMBER }, | ||
303 | { NULL } | ||
304 | }; | ||
305 | |||
306 | static mu_sieve_tag_group_t deleteheader_tag_groups[] = { | ||
307 | { deleteheader_tags, NULL }, | ||
308 | { match_part_tags, mu_sieve_match_part_checker }, | ||
309 | { NULL } | ||
310 | }; | ||
311 | |||
312 | /* deleteheader required arguments: */ | ||
313 | static mu_sieve_data_type deleteheader_args[] = { | ||
314 | SVT_STRING, /* field name or value pattern */ | ||
315 | SVT_VOID | ||
316 | }; | ||
317 | |||
318 | int | ||
319 | SIEVE_EXPORT (editheader, init) (mu_sieve_machine_t mach) | ||
320 | { | ||
321 | int rc; | ||
322 | |||
323 | /* This dummy record is required by libmu_sieve */ | ||
324 | rc = mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1); | ||
325 | if (rc) | ||
326 | return rc; | ||
327 | rc = mu_sieve_register_action (mach, "addheader", sieve_addheader, | ||
328 | addheader_args, addheader_tag_groups, 1); | ||
329 | if (rc) | ||
330 | return rc; | ||
331 | rc = mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader, | ||
332 | deleteheader_args, deleteheader_args, | ||
333 | deleteheader_tag_groups, | ||
334 | 1); | ||
335 | if (rc) | ||
336 | return rc; | ||
337 | |||
338 | return rc; | ||
339 | } |
... | @@ -139,6 +139,7 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t arglist) | ... | @@ -139,6 +139,7 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t arglist) |
139 | mu_list_t tag_list = NULL; | 139 | mu_list_t tag_list = NULL; |
140 | mu_list_t chk_list = NULL; | 140 | mu_list_t chk_list = NULL; |
141 | mu_sieve_data_type *exp_arg; | 141 | mu_sieve_data_type *exp_arg; |
142 | int opt_args = 0; | ||
142 | int rc, err = 0; | 143 | int rc, err = 0; |
143 | static mu_sieve_data_type empty[] = { SVT_VOID }; | 144 | static mu_sieve_data_type empty[] = { SVT_VOID }; |
144 | 145 | ||
... | @@ -237,16 +238,25 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t arglist) | ... | @@ -237,16 +238,25 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t arglist) |
237 | mu_list_append (chk_list, cf); | 238 | mu_list_append (chk_list, cf); |
238 | } | 239 | } |
239 | } | 240 | } |
240 | else if (*exp_arg == SVT_VOID) | ||
241 | { | ||
242 | mu_sv_compile_error (&mu_sieve_locus, | ||
243 | _("too many arguments in call to `%s'"), | ||
244 | reg->name); | ||
245 | err = 1; | ||
246 | break; | ||
247 | } | ||
248 | else | 241 | else |
249 | { | 242 | { |
243 | if (*exp_arg == SVT_VOID) | ||
244 | { | ||
245 | if (reg->opt_args) | ||
246 | { | ||
247 | exp_arg = reg->opt_args; | ||
248 | opt_args = 1; | ||
249 | } | ||
250 | else | ||
251 | { | ||
252 | mu_sv_compile_error (&mu_sieve_locus, | ||
253 | _("too many arguments in call to `%s'"), | ||
254 | reg->name); | ||
255 | err = 1; | ||
256 | break; | ||
257 | } | ||
258 | } | ||
259 | |||
250 | if (*exp_arg != val->type) | 260 | if (*exp_arg != val->type) |
251 | { | 261 | { |
252 | if (*exp_arg == SVT_STRING_LIST && val->type == SVT_STRING) | 262 | if (*exp_arg == SVT_STRING_LIST && val->type == SVT_STRING) |
... | @@ -291,7 +301,7 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t arglist) | ... | @@ -291,7 +301,7 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t arglist) |
291 | 301 | ||
292 | if (!err) | 302 | if (!err) |
293 | { | 303 | { |
294 | if (*exp_arg != SVT_VOID) | 304 | if (!opt_args && *exp_arg != SVT_VOID) |
295 | { | 305 | { |
296 | mu_sv_compile_error (&mu_sieve_locus, | 306 | mu_sv_compile_error (&mu_sieve_locus, |
297 | _("too few arguments in call to `%s'"), | 307 | _("too few arguments in call to `%s'"), | ... | ... |
... | @@ -50,13 +50,15 @@ reg_lookup (mu_list_t list, const char *name) | ... | @@ -50,13 +50,15 @@ reg_lookup (mu_list_t list, const char *name) |
50 | mu_sieve_register_t * | 50 | mu_sieve_register_t * |
51 | mu_sieve_test_lookup (mu_sieve_machine_t mach, const char *name) | 51 | mu_sieve_test_lookup (mu_sieve_machine_t mach, const char *name) |
52 | { | 52 | { |
53 | return reg_lookup (mach->test_list, name); | 53 | mu_sieve_register_t *reg = reg_lookup (mach->test_list, name); |
54 | return (reg && reg->handler) ? reg : NULL; | ||
54 | } | 55 | } |
55 | 56 | ||
56 | mu_sieve_register_t * | 57 | mu_sieve_register_t * |
57 | mu_sieve_action_lookup (mu_sieve_machine_t mach, const char *name) | 58 | mu_sieve_action_lookup (mu_sieve_machine_t mach, const char *name) |
58 | { | 59 | { |
59 | return reg_lookup (mach->action_list, name); | 60 | mu_sieve_register_t *reg = reg_lookup (mach->action_list, name); |
61 | return (reg && reg->handler) ? reg : NULL; | ||
60 | } | 62 | } |
61 | 63 | ||
62 | static int | 64 | static int |
... | @@ -90,7 +92,8 @@ static int | ... | @@ -90,7 +92,8 @@ static int |
90 | sieve_register (mu_list_t *pool, | 92 | sieve_register (mu_list_t *pool, |
91 | mu_list_t *list, | 93 | mu_list_t *list, |
92 | const char *name, mu_sieve_handler_t handler, | 94 | const char *name, mu_sieve_handler_t handler, |
93 | mu_sieve_data_type *arg_types, | 95 | mu_sieve_data_type *req_arg_types, |
96 | mu_sieve_data_type *opt_arg_types, | ||
94 | mu_sieve_tag_group_t *tags, int required) | 97 | mu_sieve_tag_group_t *tags, int required) |
95 | { | 98 | { |
96 | mu_sieve_register_t *reg = mu_sieve_palloc (pool, sizeof (*reg)); | 99 | mu_sieve_register_t *reg = mu_sieve_palloc (pool, sizeof (*reg)); |
... | @@ -100,7 +103,8 @@ sieve_register (mu_list_t *pool, | ... | @@ -100,7 +103,8 @@ sieve_register (mu_list_t *pool, |
100 | reg->name = name; | 103 | reg->name = name; |
101 | reg->handler = handler; | 104 | reg->handler = handler; |
102 | 105 | ||
103 | reg->req_args = arg_types; | 106 | reg->req_args = req_arg_types; |
107 | reg->opt_args = opt_arg_types; | ||
104 | reg->tags = tags; | 108 | reg->tags = tags; |
105 | reg->required = required; | 109 | reg->required = required; |
106 | 110 | ||
... | @@ -119,23 +123,49 @@ sieve_register (mu_list_t *pool, | ... | @@ -119,23 +123,49 @@ sieve_register (mu_list_t *pool, |
119 | 123 | ||
120 | 124 | ||
121 | int | 125 | int |
122 | mu_sieve_register_test (mu_sieve_machine_t mach, | 126 | mu_sieve_register_test_ext (mu_sieve_machine_t mach, |
123 | const char *name, mu_sieve_handler_t handler, | 127 | const char *name, mu_sieve_handler_t handler, |
124 | mu_sieve_data_type *arg_types, | 128 | mu_sieve_data_type *req_args, |
125 | mu_sieve_tag_group_t *tags, int required) | 129 | mu_sieve_data_type *opt_args, |
130 | mu_sieve_tag_group_t *tags, int required) | ||
126 | { | 131 | { |
127 | return sieve_register (&mach->memory_pool, | 132 | return sieve_register (&mach->memory_pool, |
128 | &mach->test_list, name, handler, | 133 | &mach->test_list, name, handler, |
129 | arg_types, tags, required); | 134 | req_args, opt_args, tags, required); |
130 | } | 135 | } |
131 | 136 | ||
132 | int | 137 | int |
133 | mu_sieve_register_action (mu_sieve_machine_t mach, | 138 | mu_sieve_register_test (mu_sieve_machine_t mach, |
134 | const char *name, mu_sieve_handler_t handler, | 139 | const char *name, mu_sieve_handler_t handler, |
135 | mu_sieve_data_type *arg_types, | 140 | mu_sieve_data_type *arg_types, |
136 | mu_sieve_tag_group_t *tags, int required) | 141 | mu_sieve_tag_group_t *tags, int required) |
142 | { | ||
143 | return mu_sieve_register_test_ext (mach, name, handler, | ||
144 | arg_types, NULL, | ||
145 | tags, | ||
146 | required); | ||
147 | } | ||
148 | |||
149 | int | ||
150 | mu_sieve_register_action_ext (mu_sieve_machine_t mach, | ||
151 | const char *name, mu_sieve_handler_t handler, | ||
152 | mu_sieve_data_type *req_args, | ||
153 | mu_sieve_data_type *opt_args, | ||
154 | mu_sieve_tag_group_t *tags, int required) | ||
137 | { | 155 | { |
138 | return sieve_register (&mach->memory_pool, | 156 | return sieve_register (&mach->memory_pool, |
139 | &mach->action_list, name, handler, | 157 | &mach->action_list, name, handler, |
140 | arg_types, tags, required); | 158 | req_args, opt_args, tags, required); |
159 | } | ||
160 | |||
161 | int | ||
162 | mu_sieve_register_action (mu_sieve_machine_t mach, | ||
163 | const char *name, mu_sieve_handler_t handler, | ||
164 | mu_sieve_data_type *arg_types, | ||
165 | mu_sieve_tag_group_t *tags, int required) | ||
166 | { | ||
167 | return mu_sieve_register_action_ext (mach, name, handler, | ||
168 | arg_types, NULL, | ||
169 | tags, | ||
170 | required); | ||
141 | } | 171 | } | ... | ... |
... | @@ -426,8 +426,10 @@ mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t ac, void *data) | ... | @@ -426,8 +426,10 @@ mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t ac, void *data) |
426 | case SVT_VALUE_LIST: | 426 | case SVT_VALUE_LIST: |
427 | case SVT_STRING_LIST: | 427 | case SVT_STRING_LIST: |
428 | return mu_list_foreach (val->v.list, ac, data); | 428 | return mu_list_foreach (val->v.list, ac, data); |
429 | 429 | case SVT_STRING: | |
430 | return ac (val->v.string, data); | ||
430 | default: | 431 | default: |
432 | mu_error ("mu_sieve_vlist_do: unexpected list type %d", val->type); | ||
431 | return EINVAL; | 433 | return EINVAL; |
432 | } | 434 | } |
433 | } | 435 | } | ... | ... |
... | @@ -35,7 +35,7 @@ static int pop3_itr_destroy (mu_iterator_t itr, void *owner); | ... | @@ -35,7 +35,7 @@ static int pop3_itr_destroy (mu_iterator_t itr, void *owner); |
35 | static int pop3_itr_first (void *owner); | 35 | static int pop3_itr_first (void *owner); |
36 | static int pop3_itr_next (void *woner); | 36 | static int pop3_itr_next (void *woner); |
37 | static int pop3_itr_getitem (void *owner, void **pret, const void **pkey); | 37 | static int pop3_itr_getitem (void *owner, void **pret, const void **pkey); |
38 | static int pop3_itr_curitem_p (void *owner, void *data); | 38 | static int pop3_itr_delitem (void *owner, void *data); |
39 | static int pop3_itr_finished_p (void *owner); | 39 | static int pop3_itr_finished_p (void *owner); |
40 | 40 | ||
41 | struct pop3_iterator | 41 | struct pop3_iterator |
... | @@ -81,7 +81,7 @@ mu_pop3_iterator_create (mu_pop3_t pop3, mu_iterator_t *piterator) | ... | @@ -81,7 +81,7 @@ mu_pop3_iterator_create (mu_pop3_t pop3, mu_iterator_t *piterator) |
81 | mu_iterator_set_next (iterator, pop3_itr_next); | 81 | mu_iterator_set_next (iterator, pop3_itr_next); |
82 | mu_iterator_set_getitem (iterator, pop3_itr_getitem); | 82 | mu_iterator_set_getitem (iterator, pop3_itr_getitem); |
83 | mu_iterator_set_finished_p (iterator, pop3_itr_finished_p); | 83 | mu_iterator_set_finished_p (iterator, pop3_itr_finished_p); |
84 | mu_iterator_set_curitem_p (iterator, pop3_itr_curitem_p); | 84 | mu_iterator_set_delitem (iterator, pop3_itr_delitem); |
85 | mu_iterator_set_destroy (iterator, pop3_itr_destroy); | 85 | mu_iterator_set_destroy (iterator, pop3_itr_destroy); |
86 | mu_iterator_set_dup (iterator, pop3_itr_dup); | 86 | mu_iterator_set_dup (iterator, pop3_itr_dup); |
87 | 87 | ||
... | @@ -183,9 +183,10 @@ pop3_itr_finished_p (void *owner) | ... | @@ -183,9 +183,10 @@ pop3_itr_finished_p (void *owner) |
183 | } | 183 | } |
184 | 184 | ||
185 | static int | 185 | static int |
186 | pop3_itr_curitem_p (void *owner, void *item) | 186 | pop3_itr_delitem (void *owner, void *item) |
187 | { | 187 | { |
188 | struct pop3_iterator *pop3_iterator = (struct pop3_iterator *)owner; | 188 | struct pop3_iterator *pop3_iterator = (struct pop3_iterator *)owner; |
189 | return *((char **)item) == pop3_iterator->item; | 189 | return *((char **)item) == pop3_iterator->item ? |
190 | MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; | ||
190 | } | 191 | } |
191 | 192 | ... | ... |
... | @@ -41,9 +41,11 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac | ... | @@ -41,9 +41,11 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac |
41 | 41 | ||
42 | TESTSUITE_AT = \ | 42 | TESTSUITE_AT = \ |
43 | action.at\ | 43 | action.at\ |
44 | addheader.at\ | ||
44 | address.at\ | 45 | address.at\ |
45 | allof.at\ | 46 | allof.at\ |
46 | anyof.at\ | 47 | anyof.at\ |
48 | delheader.at\ | ||
47 | compile.at\ | 49 | compile.at\ |
48 | envelope.at\ | 50 | envelope.at\ |
49 | exists.at\ | 51 | exists.at\ | ... | ... |
sieve/tests/addheader.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2012 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_BANNER([addheader]) | ||
18 | m4_pushdef([MUT_SIEVE_EXT_NAME],[addheader]) | ||
19 | |||
20 | MUT_SIEVE_EXT_TEST([prepend header],[addheader addheader00], | ||
21 | [require "editheader"; | ||
22 | addheader "X-Sieve-Filtered" "<kim@job.example.com>"; | ||
23 | ], | ||
24 | [MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox) | ||
25 | sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog | ||
26 | sed '/X-IMAPbase:/d;s/ *$//' mailbox | ||
27 | ], | ||
28 | [From coyote@desert.example.org Sun May 6 22:16:47 2001 | ||
29 | X-Sieve-Filtered: <kim@job.example.com> | ||
30 | From: coyote@desert.example.org | ||
31 | To: roadrunner@acme.example.com | ||
32 | Subject: I have a present for you | ||
33 | X-Caffeine: C8H10N4O2 | ||
34 | Status: | ||
35 | X-UID: 1 | ||
36 | |||
37 | Look, I'm sorry about the whole anvil thing, and I really | ||
38 | didn't mean to try and drop it on you from the top of the | ||
39 | cliff. I want to try to make it up to you. I've got some | ||
40 | great birdseed over here at my place--top of the line | ||
41 | stuff--and if you come by, I'll have it all wrapped up | ||
42 | for you. I'm really sorry for all the problems I've caused | ||
43 | for you over the years, but I know we can work this out. | ||
44 | |||
45 | -- | ||
46 | Wile E. Coyote "Super Genius" coyote@desert.example.org | ||
47 | |||
48 | From b1ff@de.res.example.com Sun May 6 22:17:15 2001 | ||
49 | X-Sieve-Filtered: <kim@job.example.com> | ||
50 | From: youcouldberich!@reply-by-postal-mail.invalid | ||
51 | To: rube@landru.example.edu | ||
52 | Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$ | ||
53 | Date: TBD | ||
54 | X-Number: 0015 | ||
55 | Status: | ||
56 | X-UID: 2 | ||
57 | |||
58 | YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT | ||
59 | IT! SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS! IT WILL | ||
60 | GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY! | ||
61 | MONEY! MONEY! COLD HARD CASH! YOU WILL RECEIVE OVER | ||
62 | $20,000 IN LESS THAN TWO MONTHS! AND IT'S LEGAL!!!!!!!!! | ||
63 | !!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1 JUST | ||
64 | SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW! | ||
65 | |||
66 | From bar@dontmailme.org Fri Dec 28 23:28:09 2001 | ||
67 | X-Sieve-Filtered: <kim@job.example.com> | ||
68 | Received: (from bar@dontmailme.org) | ||
69 | by dontmailme.org id fERKR9N16790 | ||
70 | for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200 | ||
71 | Date: Fri, 28 Dec 2001 23:28:08 +0200 | ||
72 | From: Bar <bar@dontmailme.org> | ||
73 | To: Foo Bar <foobar@nonexistent.net> | ||
74 | Message-Id: <200112232808.fERKR9N16790@dontmailme.org> | ||
75 | Subject: Coffee | ||
76 | Status: | ||
77 | X-UID: 3 | ||
78 | |||
79 | How about some coffee? | ||
80 | |||
81 | ], | ||
82 | [ADDHEADER on msg uid 1: X-Sieve-Filtered: <kim@job.example.com> | ||
83 | ADDHEADER on msg uid 2: X-Sieve-Filtered: <kim@job.example.com> | ||
84 | ADDHEADER on msg uid 3: X-Sieve-Filtered: <kim@job.example.com> | ||
85 | ]) | ||
86 | |||
87 | MUT_SIEVE_EXT_TEST([append header],[addheader addheader01], | ||
88 | [require "editheader"; | ||
89 | addheader :last "X-Sieve-Filtered" "<kim@job.example.com>"; | ||
90 | ], | ||
91 | [MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox) | ||
92 | sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog | ||
93 | sed '/X-IMAPbase:/d;s/ *$//' mailbox | ||
94 | ], | ||
95 | [From coyote@desert.example.org Sun May 6 22:16:47 2001 | ||
96 | From: coyote@desert.example.org | ||
97 | To: roadrunner@acme.example.com | ||
98 | Subject: I have a present for you | ||
99 | X-Caffeine: C8H10N4O2 | ||
100 | X-Sieve-Filtered: <kim@job.example.com> | ||
101 | Status: | ||
102 | X-UID: 1 | ||
103 | |||
104 | Look, I'm sorry about the whole anvil thing, and I really | ||
105 | didn't mean to try and drop it on you from the top of the | ||
106 | cliff. I want to try to make it up to you. I've got some | ||
107 | great birdseed over here at my place--top of the line | ||
108 | stuff--and if you come by, I'll have it all wrapped up | ||
109 | for you. I'm really sorry for all the problems I've caused | ||
110 | for you over the years, but I know we can work this out. | ||
111 | |||
112 | -- | ||
113 | Wile E. Coyote "Super Genius" coyote@desert.example.org | ||
114 | |||
115 | From b1ff@de.res.example.com Sun May 6 22:17:15 2001 | ||
116 | From: youcouldberich!@reply-by-postal-mail.invalid | ||
117 | To: rube@landru.example.edu | ||
118 | Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$ | ||
119 | Date: TBD | ||
120 | X-Number: 0015 | ||
121 | X-Sieve-Filtered: <kim@job.example.com> | ||
122 | Status: | ||
123 | X-UID: 2 | ||
124 | |||
125 | YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT | ||
126 | IT! SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS! IT WILL | ||
127 | GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY! | ||
128 | MONEY! MONEY! COLD HARD CASH! YOU WILL RECEIVE OVER | ||
129 | $20,000 IN LESS THAN TWO MONTHS! AND IT'S LEGAL!!!!!!!!! | ||
130 | !!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1 JUST | ||
131 | SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW! | ||
132 | |||
133 | From bar@dontmailme.org Fri Dec 28 23:28:09 2001 | ||
134 | Received: (from bar@dontmailme.org) | ||
135 | by dontmailme.org id fERKR9N16790 | ||
136 | for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200 | ||
137 | Date: Fri, 28 Dec 2001 23:28:08 +0200 | ||
138 | From: Bar <bar@dontmailme.org> | ||
139 | To: Foo Bar <foobar@nonexistent.net> | ||
140 | Message-Id: <200112232808.fERKR9N16790@dontmailme.org> | ||
141 | Subject: Coffee | ||
142 | X-Sieve-Filtered: <kim@job.example.com> | ||
143 | Status: | ||
144 | X-UID: 3 | ||
145 | |||
146 | How about some coffee? | ||
147 | |||
148 | ], | ||
149 | [ADDHEADER on msg uid 1: X-Sieve-Filtered: <kim@job.example.com> | ||
150 | ADDHEADER on msg uid 2: X-Sieve-Filtered: <kim@job.example.com> | ||
151 | ADDHEADER on msg uid 3: X-Sieve-Filtered: <kim@job.example.com> | ||
152 | ]) | ||
153 | |||
154 | m4_popdef([MUT_SIEVE_EXT_NAME]) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
sieve/tests/delheader.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2012 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_BANNER([deleteheader]) | ||
18 | m4_pushdef([MUT_SIEVE_EXT_NAME],[deleteheader]) | ||
19 | |||
20 | m4_define([mkmailbox],[ | ||
21 | AT_DATA([$1], | ||
22 | [From coyote@desert.example.org Sun May 6 22:16:47 2001 | ||
23 | From: coyote@desert.example.org | ||
24 | To: roadrunner@acme.example.com | ||
25 | X-Agent: Agent A | ||
26 | Received: (from bar@example.org) | ||
27 | by example.org id fERKR9N16790 | ||
28 | for roadrunner@example.com; Fri, 28 Dec 2001 22:18:08 +0200 | ||
29 | X-Agent: Agent 22 | ||
30 | X-Agent: Agent C | ||
31 | Subject: Ping | ||
32 | |||
33 | Test message, please discard. | ||
34 | |||
35 | ])]) | ||
36 | |||
37 | |||
38 | MUT_SIEVE_EXT_TEST([delete all],[deleteheader delheader delheader00], | ||
39 | [require "editheader"; | ||
40 | deleteheader "X-Agent"; | ||
41 | ], | ||
42 | [mkmailbox(mailbox) | ||
43 | sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog | ||
44 | sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox | ||
45 | ], | ||
46 | [From coyote@desert.example.org Sun May 6 22:16:47 2001 | ||
47 | From: coyote@desert.example.org | ||
48 | To: roadrunner@acme.example.com | ||
49 | Received: (from bar@example.org) | ||
50 | by example.org id fERKR9N16790 | ||
51 | for roadrunner@example.com; Fri, 28 Dec 2001 22:18:08 +0200 | ||
52 | Subject: Ping | ||
53 | |||
54 | Test message, please discard. | ||
55 | |||
56 | ], | ||
57 | [DELETEHEADER on msg uid 1: X-Agent | ||
58 | ]) | ||
59 | |||
60 | MUT_SIEVE_EXT_TEST([delete index],[deleteheader delheader delheader01], | ||
61 | [require "editheader"; | ||
62 | deleteheader :index 1 "X-Agent"; | ||
63 | ], | ||
64 | [mkmailbox(mailbox) | ||
65 | sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog | ||
66 | sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox | ||
67 | ], | ||
68 | [From coyote@desert.example.org Sun May 6 22:16:47 2001 | ||
69 | From: coyote@desert.example.org | ||
70 | To: roadrunner@acme.example.com | ||
71 | Received: (from bar@example.org) | ||
72 | by example.org id fERKR9N16790 | ||
73 | for roadrunner@example.com; Fri, 28 Dec 2001 22:18:08 +0200 | ||
74 | X-Agent: Agent 22 | ||
75 | X-Agent: Agent C | ||
76 | Subject: Ping | ||
77 | |||
78 | Test message, please discard. | ||
79 | |||
80 | ], | ||
81 | [DELETEHEADER on msg uid 1: X-Agent | ||
82 | ]) | ||
83 | |||
84 | MUT_SIEVE_EXT_TEST([delete index backwards],[deleteheader delheader delheader02], | ||
85 | [require "editheader"; | ||
86 | deleteheader :index 2 :last "X-Agent"; | ||
87 | ], | ||
88 | [mkmailbox(mailbox) | ||
89 | sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog | ||
90 | sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox | ||
91 | ], | ||
92 | [From coyote@desert.example.org Sun May 6 22:16:47 2001 | ||
93 | From: coyote@desert.example.org | ||
94 | To: roadrunner@acme.example.com | ||
95 | X-Agent: Agent A | ||
96 | Received: (from bar@example.org) | ||
97 | by example.org id fERKR9N16790 | ||
98 | for roadrunner@example.com; Fri, 28 Dec 2001 22:18:08 +0200 | ||
99 | X-Agent: Agent C | ||
100 | Subject: Ping | ||
101 | |||
102 | Test message, please discard. | ||
103 | |||
104 | ], | ||
105 | [DELETEHEADER on msg uid 1: X-Agent | ||
106 | ]) | ||
107 | |||
108 | MUT_SIEVE_EXT_TEST([delete regex],[deleteheader delheader delheader03], | ||
109 | [require "editheader"; | ||
110 | deleteheader :regex "X-Agent" "Agent [[A-Z]]"; | ||
111 | ], | ||
112 | [mkmailbox(mailbox) | ||
113 | sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog | ||
114 | sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox | ||
115 | ], | ||
116 | [From coyote@desert.example.org Sun May 6 22:16:47 2001 | ||
117 | From: coyote@desert.example.org | ||
118 | To: roadrunner@acme.example.com | ||
119 | Received: (from bar@example.org) | ||
120 | by example.org id fERKR9N16790 | ||
121 | for roadrunner@example.com; Fri, 28 Dec 2001 22:18:08 +0200 | ||
122 | X-Agent: Agent 22 | ||
123 | Subject: Ping | ||
124 | |||
125 | Test message, please discard. | ||
126 | |||
127 | ], | ||
128 | [DELETEHEADER on msg uid 1: X-Agent: (regexp) | ||
129 | ]) | ||
130 | |||
131 | m4_popdef([MUT_SIEVE_EXT_NAME]) |
... | @@ -147,6 +147,7 @@ m4_include([moderator.at]) | ... | @@ -147,6 +147,7 @@ m4_include([moderator.at]) |
147 | m4_include([pipeact.at]) | 147 | m4_include([pipeact.at]) |
148 | m4_include([pipetest.at]) | 148 | m4_include([pipetest.at]) |
149 | m4_include([list.at]) | 149 | m4_include([list.at]) |
150 | 150 | m4_include([addheader.at]) | |
151 | m4_include([delheader.at]) | ||
151 | 152 | ||
152 | 153 | ... | ... |
-
Please register or sign in to post a comment