summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-11-12 19:59:26 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2012-11-12 20:17:19 +0200
commit6fad8e1734a83c273f6283436775a6548f9c941f (patch)
tree1816552b9058bda515d6e521fd16ef2cbd95332d
parenta7a174d51ca7845f9eda854709258d64e5d0077e (diff)
downloadmailutils-6fad8e1734a83c273f6283436775a6548f9c941f.tar.gz
mailutils-6fad8e1734a83c273f6283436775a6548f9c941f.tar.bz2
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.
-rw-r--r--NEWS6
-rw-r--r--doc/rfc/README1
-rw-r--r--include/mailutils/header.h2
-rw-r--r--include/mailutils/iterator.h13
-rw-r--r--include/mailutils/sieve.h12
-rw-r--r--include/mailutils/sys/iterator.h2
-rw-r--r--libmailutils/base/assoc.c6
-rw-r--r--libmailutils/base/iterator.c21
-rw-r--r--libmailutils/base/opool.c7
-rw-r--r--libmailutils/diag/debug.c7
-rw-r--r--libmailutils/list/iterator.c8
-rw-r--r--libmailutils/list/pop.c2
-rw-r--r--libmailutils/list/remove.c2
-rw-r--r--libmailutils/list/removenth.c3
-rw-r--r--libmailutils/mailbox/hdritr.c91
-rw-r--r--libmailutils/mailbox/header.c29
-rw-r--r--libmailutils/mailbox/imapenv.c2
-rw-r--r--libmailutils/mailbox/mbxitr.c7
-rw-r--r--libmu_sieve/extensions/Makefile.am1
-rw-r--r--libmu_sieve/extensions/editheader.c339
-rw-r--r--libmu_sieve/prog.c28
-rw-r--r--libmu_sieve/register.c58
-rw-r--r--libmu_sieve/util.c4
-rw-r--r--libproto/pop/pop3_iterator.c9
-rw-r--r--sieve/tests/Makefile.am2
-rw-r--r--sieve/tests/addheader.at154
-rw-r--r--sieve/tests/delheader.at131
-rw-r--r--sieve/tests/testsuite.at3
28 files changed, 870 insertions, 80 deletions
diff --git a/NEWS b/NEWS
index ac7dbdf00..94cc1b71f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2012-08-07
+GNU mailutils NEWS -- history of user-visible changes. 2012-11-12
Copyright (C) 2002-2012 Free Software Foundation, Inc.
See the end of file for copying conditions.
@@ -114,6 +114,10 @@ header field with the given date.
See <http://mailutils.org/wiki/Timestamp_(Sieve_test)>.
+Implemented the Editheader extension: `addheader' and `delheader' actions.
+
+See <http://tools.ietf.org/html/rfc5293>.
+
** mail: sending attachments
The mail[x] utility now allows for sending attachments. Any number of
diff --git a/doc/rfc/README b/doc/rfc/README
index 38d0abbef..593ec69b0 100644
--- a/doc/rfc/README
+++ b/doc/rfc/README
@@ -53,3 +53,4 @@ the actual RFC number.
3501 INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1
3691 Internet Message Access Protocol (IMAP) UNSELECT command
4314 IMAP4 Access Control List (ACL) Extension
+5293 Sieve Email Filtering: Editheader Extension
diff --git a/include/mailutils/header.h b/include/mailutils/header.h
index 8e50cb601..079f679d9 100644
--- a/include/mailutils/header.h
+++ b/include/mailutils/header.h
@@ -169,6 +169,8 @@ extern int mu_header_set_fill (mu_header_t,
int (*_fill) (void *data, char **, size_t *),
void *data);
+extern int mu_header_get_itemptr (mu_header_t header, size_t num,
+ const void **sptr);
#ifdef __cplusplus
}
diff --git a/include/mailutils/iterator.h b/include/mailutils/iterator.h
index 84d469f96..867f77537 100644
--- a/include/mailutils/iterator.h
+++ b/include/mailutils/iterator.h
@@ -37,7 +37,7 @@ enum mu_itrctl_req
mu_itrctl_qry_direction, /* Query iteration direction */
mu_itrctl_set_direction /* Set iteration direction */
};
-
+
extern int mu_iterator_create (mu_iterator_t *, void *);
extern int mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig);
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 *);
extern int mu_iterator_attach (mu_iterator_t *root, mu_iterator_t iterator);
extern int mu_iterator_detach (mu_iterator_t *root, mu_iterator_t iterator);
-extern void mu_iterator_advance (mu_iterator_t iterator, void *e);
+extern void mu_iterator_delitem (mu_iterator_t iterator, void *e);
extern int mu_iterator_set_first (mu_iterator_t, int (*first) (void *));
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,
int (*dup) (void **ptr, void *data));
extern int mu_iterator_set_destroy (mu_iterator_t itr,
int (*destroy) (mu_iterator_t, void *data));
-extern int mu_iterator_set_curitem_p (mu_iterator_t itr,
- int (*curitem_p) (void *, void *));
+
+#define MU_ITR_DELITEM_NOTHING 0
+#define MU_ITR_DELITEM_NEXT 1
+#define MU_ITR_DELITEM_ADVANCE 2
+
+extern int mu_iterator_set_delitem (mu_iterator_t itr,
+ int (*delitem) (void *, void *));
extern int mu_iterator_set_itrctl (mu_iterator_t itr,
int (*itrctl) (void *,
enum mu_itrctl_req,
diff --git a/include/mailutils/sieve.h b/include/mailutils/sieve.h
index f9ef9dbf6..ffe5db347 100644
--- a/include/mailutils/sieve.h
+++ b/include/mailutils/sieve.h
@@ -100,6 +100,7 @@ typedef struct
int required;
mu_sieve_handler_t handler;
mu_sieve_data_type *req_args;
+ mu_sieve_data_type *opt_args;
mu_sieve_tag_group_t *tags;
} mu_sieve_register_t;
@@ -146,10 +147,21 @@ mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach,
const char *name);
mu_sieve_register_t *mu_sieve_action_lookup (mu_sieve_machine_t mach,
const char *name);
+int mu_sieve_register_test_ext (mu_sieve_machine_t mach,
+ const char *name, mu_sieve_handler_t handler,
+ mu_sieve_data_type *req_args,
+ mu_sieve_data_type *opt_args,
+ mu_sieve_tag_group_t *tags, int required);
int mu_sieve_register_test (mu_sieve_machine_t mach,
const char *name, mu_sieve_handler_t handler,
mu_sieve_data_type * arg_types,
mu_sieve_tag_group_t * tags, int required);
+
+int mu_sieve_register_action_ext (mu_sieve_machine_t mach,
+ const char *name, mu_sieve_handler_t handler,
+ mu_sieve_data_type *req_args,
+ mu_sieve_data_type *opt_args,
+ mu_sieve_tag_group_t *tags, int required);
int mu_sieve_register_action (mu_sieve_machine_t mach,
const char *name, mu_sieve_handler_t handler,
mu_sieve_data_type * arg_types,
diff --git a/include/mailutils/sys/iterator.h b/include/mailutils/sys/iterator.h
index 73a4926f5..7f007afe3 100644
--- a/include/mailutils/sys/iterator.h
+++ b/include/mailutils/sys/iterator.h
@@ -36,7 +36,7 @@ struct _mu_iterator
int (*first) (void *owner);
int (*next) (void *owner);
int (*getitem) (void *owner, void **pret, const void **pkey);
- int (*curitem_p) (void *owner, void *item);
+ int (*delitem) (void *owner, void *item);
int (*finished_p) (void *owner);
int (*itrctl) (void *owner, enum mu_itrctl_req req, void *arg);
void *(*dataptr) (void *);
diff --git a/libmailutils/base/assoc.c b/libmailutils/base/assoc.c
index c34b6af0f..ecef8a320 100644
--- a/libmailutils/base/assoc.c
+++ b/libmailutils/base/assoc.c
@@ -452,13 +452,13 @@ destroy (mu_iterator_t iterator, void *data)
}
static int
-curitem_p (void *owner, void *item)
+delitem (void *owner, void *item)
{
struct assoc_iterator *itr = owner;
mu_assoc_t assoc = itr->assoc;
struct _mu_assoc_elem *elem = ASSOC_ELEM (assoc, itr->index);
- return elem == item;
+ return elem == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
}
static int
@@ -498,7 +498,7 @@ mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator)
mu_iterator_set_next (iterator, next);
mu_iterator_set_getitem (iterator, getitem);
mu_iterator_set_finished_p (iterator, finished_p);
- mu_iterator_set_curitem_p (iterator, curitem_p);
+ mu_iterator_set_delitem (iterator, delitem);
mu_iterator_set_destroy (iterator, destroy);
mu_iterator_set_dup (iterator, assoc_data_dup);
diff --git a/libmailutils/base/iterator.c b/libmailutils/base/iterator.c
index 8e88c68ca..118de726b 100644
--- a/libmailutils/base/iterator.c
+++ b/libmailutils/base/iterator.c
@@ -81,12 +81,12 @@ mu_iterator_set_finished_p (mu_iterator_t itr, int (*finished_p) (void *))
}
int
-mu_iterator_set_curitem_p (mu_iterator_t itr,
- int (*curitem_p) (void *, void *))
+mu_iterator_set_delitem (mu_iterator_t itr,
+ int (*delitem) (void *, void *))
{
if (!itr)
return EINVAL;
- itr->curitem_p = curitem_p;
+ itr->delitem = delitem;
return 0;
}
@@ -158,7 +158,7 @@ mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig)
iterator->first = orig->first;
iterator->next = orig->next;
iterator->getitem = orig->getitem;
- iterator->curitem_p = orig->curitem_p;
+ iterator->delitem = orig->delitem;
iterator->finished_p = orig->finished_p;
iterator->itrctl = orig->itrctl;
@@ -250,14 +250,19 @@ iterator_get_owner (mu_iterator_t iterator, void **powner)
}
void
-mu_iterator_advance (mu_iterator_t iterator, void *e)
+mu_iterator_delitem (mu_iterator_t iterator, void *itm)
{
for (; iterator; iterator = iterator->next_itr)
{
- if (iterator->curitem_p (iterator->owner, e))
+ if (iterator->delitem)
{
- iterator->next (iterator->owner);
- iterator->is_advanced++;
+ switch (iterator->delitem (iterator->owner, itm))
+ {
+ case MU_ITR_DELITEM_NEXT:
+ iterator->next (iterator->owner);
+ case MU_ITR_DELITEM_ADVANCE:
+ iterator->is_advanced++;
+ }
}
}
}
diff --git a/libmailutils/base/opool.c b/libmailutils/base/opool.c
index 51c8e91e0..00a65824b 100644
--- a/libmailutils/base/opool.c
+++ b/libmailutils/base/opool.c
@@ -384,10 +384,11 @@ opitr_finished_p (void *owner)
}
static int
-opitr_curitem_p (void *owner, void *item)
+opitr_delitem (void *owner, void *item)
{
struct opool_iterator *itr = owner;
- return itr->cur && itr->cur->buf == item;
+ return (itr->cur && itr->cur->buf == item) ?
+ MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
}
static int
@@ -446,7 +447,7 @@ mu_opool_get_iterator (mu_opool_t opool, mu_iterator_t *piterator)
mu_iterator_set_next (iterator, opitr_next);
mu_iterator_set_getitem (iterator, opitr_getitem);
mu_iterator_set_finished_p (iterator, opitr_finished_p);
- mu_iterator_set_curitem_p (iterator, opitr_curitem_p);
+ mu_iterator_set_delitem (iterator, opitr_delitem);
mu_iterator_set_destroy (iterator, opitr_destroy);
mu_iterator_set_dup (iterator, opitr_data_dup);
diff --git a/libmailutils/diag/debug.c b/libmailutils/diag/debug.c
index 897062cfe..d9b5178b8 100644
--- a/libmailutils/diag/debug.c
+++ b/libmailutils/diag/debug.c
@@ -572,10 +572,11 @@ finished_p (void *owner)
}
static int
-curitem_p (void *owner, void *item)
+delitem (void *owner, void *item)
{
struct debug_iterator *itr = owner;
- return mu_c_strcasecmp (cattab[itr->pos].name, (char *) item) == 0;
+ return mu_c_strcasecmp (cattab[itr->pos].name, (char *) item) == 0 ?
+ MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
}
static int
@@ -659,7 +660,7 @@ mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset)
mu_iterator_set_next (iterator, next);
mu_iterator_set_getitem (iterator, getitem);
mu_iterator_set_finished_p (iterator, finished_p);
- mu_iterator_set_curitem_p (iterator, curitem_p);
+ mu_iterator_set_delitem (iterator, delitem);
mu_iterator_set_dup (iterator, list_data_dup);
mu_iterator_set_itrctl (iterator, list_itrctl);
diff --git a/libmailutils/list/iterator.c b/libmailutils/list/iterator.c
index 26cc364e0..f517a8093 100644
--- a/libmailutils/list/iterator.c
+++ b/libmailutils/list/iterator.c
@@ -84,10 +84,10 @@ destroy (mu_iterator_t iterator, void *data)
}
static int
-curitem_p (void *owner, void *item)
+delitem (void *owner, void *item)
{
struct list_iterator *itr = owner;
- return itr->cur == item;
+ return itr->cur == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
}
static int
@@ -142,7 +142,7 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
ptr = itr->cur;
prev = ptr->prev;
- mu_iterator_advance (list->itr, ptr);
+ mu_iterator_delitem (list->itr, ptr);
prev->next = ptr->next;
ptr->next->prev = prev;
if (req == mu_itrctl_delete)
@@ -238,7 +238,7 @@ mu_list_get_iterator (mu_list_t list, mu_iterator_t *piterator)
mu_iterator_set_next (iterator, next);
mu_iterator_set_getitem (iterator, getitem);
mu_iterator_set_finished_p (iterator, finished_p);
- mu_iterator_set_curitem_p (iterator, curitem_p);
+ mu_iterator_set_delitem (iterator, delitem);
mu_iterator_set_destroy (iterator, destroy);
mu_iterator_set_dup (iterator, list_data_dup);
mu_iterator_set_itrctl (iterator, list_itrctl);
diff --git a/libmailutils/list/pop.c b/libmailutils/list/pop.c
index c25c2aed8..6a504eb73 100644
--- a/libmailutils/list/pop.c
+++ b/libmailutils/list/pop.c
@@ -35,7 +35,7 @@ mu_list_pop (mu_list_t list, void **item)
last = list->head.prev;
prev = last->prev;
- mu_iterator_advance (list->itr, last);
+ mu_iterator_delitem (list->itr, last);
prev->next = last->next;
prev->next->prev = prev;
if (item)
diff --git a/libmailutils/list/remove.c b/libmailutils/list/remove.c
index 5ebd31235..f56340390 100644
--- a/libmailutils/list/remove.c
+++ b/libmailutils/list/remove.c
@@ -41,7 +41,7 @@ mu_list_remove (mu_list_t list, void *item)
{
struct list_data *previous = current->prev;
- mu_iterator_advance (list->itr, current);
+ mu_iterator_delitem (list->itr, current);
previous->next = current->next;
current->next->prev = previous;
DESTROY_ITEM (list, current);
diff --git a/libmailutils/list/removenth.c b/libmailutils/list/removenth.c
index 80550eeb7..f589b51e1 100644
--- a/libmailutils/list/removenth.c
+++ b/libmailutils/list/removenth.c
@@ -26,7 +26,6 @@ int
mu_list_remove_nth (mu_list_t list, size_t n)
{
struct list_data *current;
- mu_list_comparator_t comp;
int status = MU_ERR_NOENT;
size_t i;
@@ -42,7 +41,7 @@ mu_list_remove_nth (mu_list_t list, size_t n)
{
struct list_data *previous = current->prev;
- mu_iterator_advance (list->itr, current);
+ mu_iterator_delitem (list->itr, current);
previous->next = current->next;
current->next->prev = previous;
DESTROY_ITEM (list, current);
diff --git a/libmailutils/mailbox/hdritr.c b/libmailutils/mailbox/hdritr.c
index a2504d5fb..d516b7259 100644
--- a/libmailutils/mailbox/hdritr.c
+++ b/libmailutils/mailbox/hdritr.c
@@ -30,13 +30,20 @@ struct header_iterator
{
mu_header_t header;
size_t index;
+ int backwards;
};
static int
hdr_first (void *owner)
{
struct header_iterator *itr = owner;
- itr->index = 1;
+ if (itr->backwards)
+ {
+ if (mu_header_get_field_count (itr->header, &itr->index))
+ return 1;
+ }
+ else
+ itr->index = 1;
return 0;
}
@@ -44,7 +51,13 @@ static int
hdr_next (void *owner)
{
struct header_iterator *itr = owner;
- itr->index++;
+ if (itr->backwards)
+ {
+ if (itr->index != 0)
+ itr->index--;
+ }
+ else
+ itr->index++;
return 0;
}
@@ -58,16 +71,16 @@ hdr_getitem (void *owner, void **pret, const void **pkey)
rc = mu_header_get_field_count (itr->header, &count);
if (rc)
return rc;
- if (itr->index > count)
+ if (itr->index < 1 || itr->index > count)
return MU_ERR_NOENT;
- rc = mu_header_sget_field_name (itr->header, itr->index,
- (const char**) pkey);
+ rc = mu_header_sget_field_value (itr->header, itr->index,
+ (const char**) pret);
if (rc == 0)
{
if (pkey)
- rc = mu_header_sget_field_value (itr->header, itr->index,
- (const char**) pret);
+ rc = mu_header_sget_field_name (itr->header, itr->index,
+ (const char**) pkey);
}
return rc;
}
@@ -78,6 +91,9 @@ hdr_finished_p (void *owner)
struct header_iterator *itr = owner;
size_t count;
+ if (itr->backwards)
+ return itr->index < 1;
+
if (mu_header_get_field_count (itr->header, &count))
return 1;
return itr->index > count;
@@ -93,13 +109,16 @@ hdr_destroy (mu_iterator_t iterator, void *data)
}
static int
-hdr_curitem_p (void *owner, void *item)
+hdr_delitem (void *owner, void *item)
{
- void *ptr;
+ struct header_iterator *itr = owner;
+ const void *ptr;
- if (hdr_getitem (owner, &ptr, NULL))
- return 0;
- return ptr == item;
+ if (mu_header_get_itemptr (itr->header, itr->index, &ptr))
+ return MU_ITR_DELITEM_NOTHING;
+ if (ptr == item && !itr->backwards)
+ return MU_ITR_DELITEM_ADVANCE;
+ return MU_ITR_DELITEM_NOTHING;
}
static int
@@ -115,6 +134,51 @@ hdr_data_dup (void **ptr, void *owner)
return 0;
}
+static int
+hdr_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
+{
+ struct header_iterator *itr = owner;
+
+ switch (req)
+ {
+ case mu_itrctl_tell:
+ /* Return current position in the object */
+ if (hdr_finished_p (owner))
+ return MU_ERR_NOENT;
+ else
+ *(size_t*)arg = itr->index;
+ return 0;
+ break;
+
+ case mu_itrctl_delete:
+ /* Delete current element */
+ if (hdr_finished_p (owner))
+ return MU_ERR_NOENT;
+ else
+ return mu_header_remove (itr->header, NULL, itr->index);
+ break;
+
+ case mu_itrctl_qry_direction:
+ if (!arg)
+ return EINVAL;
+ else
+ *(int*)arg = itr->backwards;
+ break;
+
+ case mu_itrctl_set_direction:
+ if (!arg)
+ return EINVAL;
+ else
+ itr->backwards = !!*(int*)arg;
+ break;
+
+ default:
+ return ENOSYS;
+ }
+ return 0;
+}
+
+
int
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)
mu_iterator_set_next (iterator, hdr_next);
mu_iterator_set_getitem (iterator, hdr_getitem);
mu_iterator_set_finished_p (iterator, hdr_finished_p);
- mu_iterator_set_curitem_p (iterator, hdr_curitem_p);
+ mu_iterator_set_delitem (iterator, hdr_delitem);
mu_iterator_set_destroy (iterator, hdr_destroy);
mu_iterator_set_dup (iterator, hdr_data_dup);
+ mu_iterator_set_itrctl (iterator, hdr_itrctl);
mu_iterator_attach (&hdr->itr, iterator);
diff --git a/libmailutils/mailbox/header.c b/libmailutils/mailbox/header.c
index 1c7642183..2745963b9 100644
--- a/libmailutils/mailbox/header.c
+++ b/libmailutils/mailbox/header.c
@@ -80,13 +80,15 @@ mu_hdrent_find (struct _mu_header *hdr, const char *name, int pos)
if (pos > 0)
{
for (p = hdr->head; p; p = p->next)
- if (mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0 && pos-- == 1)
+ if ((!name || mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0) &&
+ pos-- == 1)
break;
}
else if (pos < 0)
{
for (p = hdr->tail; p; p = p->prev)
- if (mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0 && ++pos == 0)
+ if ((!name || mu_c_strcasecmp (MU_HDRENT_NAME (hdr,p), name) == 0) &&
+ ++pos == 0)
break;
}
else
@@ -544,7 +546,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n)
int status;
struct mu_hdrent *ent;
- if (header == NULL || fn == NULL)
+ if (header == NULL)
return EINVAL;
status = mu_header_fill (header);
@@ -555,6 +557,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n)
if (!ent)
return MU_ERR_NOENT;
+ mu_iterator_delitem (header->itr, ent);
mu_hdrent_remove (header, ent);
HEADER_SET_MODIFIED (header);
free (ent);
@@ -782,6 +785,26 @@ mu_header_get_field_count (mu_header_t header, size_t *pcount)
}
int
+mu_header_get_itemptr (mu_header_t header, size_t num, const void **sptr)
+{
+ int status;
+
+ if (header == NULL)
+ return EINVAL;
+
+ status = mu_header_fill (header);
+ if (status == 0)
+ {
+ struct mu_hdrent *ent = mu_hdrent_nth (header, num);
+ if (ent)
+ *sptr = ent;
+ else
+ status = MU_ERR_NOENT;
+ }
+ return status;
+}
+
+int
mu_header_sget_field_name (mu_header_t header, size_t num, const char **sptr)
{
int status;
diff --git a/libmailutils/mailbox/imapenv.c b/libmailutils/mailbox/imapenv.c
index 847a6f762..aa8a865af 100644
--- a/libmailutils/mailbox/imapenv.c
+++ b/libmailutils/mailbox/imapenv.c
@@ -52,7 +52,7 @@ mu_message_get_imapenvelope (mu_message_t msg, struct mu_imapenvelope **pimapenv
if (msg == NULL)
return EINVAL;
- if (imapenvelope == NULL)
+ if (pimapenvelope == NULL)
return MU_ERR_OUT_PTR_NULL;
if (msg->_imapenvelope)
return msg->_imapenvelope (msg, pimapenvelope);
diff --git a/libmailutils/mailbox/mbxitr.c b/libmailutils/mailbox/mbxitr.c
index 72c7a7dfb..0ea8856aa 100644
--- a/libmailutils/mailbox/mbxitr.c
+++ b/libmailutils/mailbox/mbxitr.c
@@ -111,13 +111,14 @@ mbx_destroy (mu_iterator_t iterator, void *data)
}
static int
-mbx_curitem_p (void *owner, void *item)
+mbx_delitem (void *owner, void *item)
{
void *ptr;
if (mbx_getitem (owner, &ptr, NULL))
return 0;
- return ptr == item;/* FIXME: Is it ok? */
+ return ptr == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
+ /* FIXME: is it ok? */
}
static int
@@ -210,7 +211,7 @@ mu_mailbox_get_iterator (mu_mailbox_t mbx, mu_iterator_t *piterator)
mu_iterator_set_next (iterator, mbx_next);
mu_iterator_set_getitem (iterator, mbx_getitem);
mu_iterator_set_finished_p (iterator, mbx_finished_p);
- mu_iterator_set_curitem_p (iterator, mbx_curitem_p);
+ mu_iterator_set_delitem (iterator, mbx_delitem);
mu_iterator_set_destroy (iterator, mbx_destroy);
mu_iterator_set_dup (iterator, mbx_data_dup);
mu_iterator_set_itrctl (iterator, mbx_itrctl);
diff --git a/libmu_sieve/extensions/Makefile.am b/libmu_sieve/extensions/Makefile.am
index 9ac82b175..d538ca6b1 100644
--- a/libmu_sieve/extensions/Makefile.am
+++ b/libmu_sieve/extensions/Makefile.am
@@ -16,6 +16,7 @@
moddir=@MU_SIEVE_MODDIR@
mod_LTLIBRARIES = \
+ editheader.la\
list.la\
moderator.la\
pipe.la\
diff --git a/libmu_sieve/extensions/editheader.c b/libmu_sieve/extensions/editheader.c
new file mode 100644
index 000000000..89ae6ea43
--- /dev/null
+++ b/libmu_sieve/extensions/editheader.c
@@ -0,0 +1,339 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with GNU Mailutils. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This module implements the Editheader Extension (RFC 5293) */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <mailutils/types.h>
+#include <mailutils/message.h>
+#include <mailutils/header.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/sieve.h>
+
+/* Syntax: addheader [:last] <field-name: string> <value: string>
+ */
+int
+sieve_addheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
+{
+ mu_sieve_value_t *val;
+ const char *field_name;
+ const char *field_value;
+ mu_message_t msg;
+ mu_header_t hdr;
+ int rc;
+
+ val = mu_sieve_value_get (args, 0);
+ if (!val)
+ {
+ mu_sieve_error (mach, "%lu: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ _("cannot get field name"));
+ mu_sieve_abort (mach);
+ }
+ field_name = val->v.string;
+
+ val = mu_sieve_value_get (args, 1);
+ if (!val)
+ {
+ mu_sieve_error (mach, "%lu: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ _("cannot get field value"));
+ mu_sieve_abort (mach);
+ }
+ field_value = val->v.string;
+
+ mu_sieve_log_action (mach, "ADDHEADER", "%s: %s", field_name, field_value);
+
+ if (mu_sieve_is_dry_run (mach))
+ return 0;
+
+ msg = mu_sieve_get_message (mach);
+ rc = mu_message_get_header (msg, &hdr);
+ if (rc)
+ {
+ mu_sieve_error (mach, "%lu: %s: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ _("cannot get message header"),
+ mu_strerror (rc));
+ mu_sieve_abort (mach);
+ }
+
+ rc = (mu_sieve_tag_lookup (tags, "last", NULL) ?
+ mu_header_append : mu_header_prepend) (hdr, field_name, field_value);
+ if (rc)
+ {
+ mu_sieve_error (mach, "%lu: %s: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ _("cannot append message header"),
+ mu_strerror (rc));
+ mu_sieve_abort (mach);
+ }
+ return 0;
+}
+
+/* Syntax: deleteheader [:index <fieldno: number> [:last]]
+ [COMPARATOR] [MATCH-TYPE]
+ <field-name: string>
+ [<value-patterns: string-list>]
+ */
+int
+sieve_deleteheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
+{
+ mu_sieve_value_t *val;
+ const char *field_name;
+ const char *field_pattern;
+ mu_message_t msg;
+ mu_header_t hdr;
+ int rc;
+ mu_sieve_comparator_t comp;
+ mu_iterator_t itr;
+ unsigned long i, idx = 0;
+
+ val = mu_sieve_value_get (args, 0);
+ if (!val)
+ {
+ mu_sieve_error (mach, "%lu: %s",
+ (unsigned long) mu_sieve_get_message_num (mach),
+ _("cannot get field name"));
+ mu_sieve_abort (mach);
+ }
+ field_name = val->v.string;
+
+ val = mu_sieve_value_get (args, 1);
+ if (!val)
+ {
+ field_pattern = NULL;
+ mu_sieve_log_action (mach, "DELETEHEADER", "%s", field_name);
+ }
+ else
+ {
+ switch (val->type)
+ {
+ case SVT_STRING_LIST:
+ if (mu_list_get (val->v.list, 0, (void**)&field_pattern))