commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-633-g6fad8e1


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-633-g6fad8e1
Date: Mon, 12 Nov 2012 18:16:55 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=6fad8e1734a83c273f6283436775a6548f9c941f

The branch, master has been updated
       via  6fad8e1734a83c273f6283436775a6548f9c941f (commit)
      from  a7a174d51ca7845f9eda854709258d64e5d0077e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6fad8e1734a83c273f6283436775a6548f9c941f
Author: Sergey Poznyakoff <address@hidden>
Date:   Mon Nov 12 19:59:26 2012 +0200

    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.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                |    6 +-
 doc/rfc/README                      |    1 +
 include/mailutils/header.h          |    2 +
 include/mailutils/iterator.h        |   13 +-
 include/mailutils/sieve.h           |   12 ++
 include/mailutils/sys/iterator.h    |    2 +-
 libmailutils/base/assoc.c           |    6 +-
 libmailutils/base/iterator.c        |   21 ++-
 libmailutils/base/opool.c           |    7 +-
 libmailutils/diag/debug.c           |    7 +-
 libmailutils/list/iterator.c        |    8 +-
 libmailutils/list/pop.c             |    2 +-
 libmailutils/list/remove.c          |    2 +-
 libmailutils/list/removenth.c       |    3 +-
 libmailutils/mailbox/hdritr.c       |   91 ++++++++--
 libmailutils/mailbox/header.c       |   29 +++-
 libmailutils/mailbox/imapenv.c      |    2 +-
 libmailutils/mailbox/mbxitr.c       |    7 +-
 libmu_sieve/extensions/Makefile.am  |    1 +
 libmu_sieve/extensions/editheader.c |  339 +++++++++++++++++++++++++++++++++++
 libmu_sieve/prog.c                  |   28 ++-
 libmu_sieve/register.c              |   58 +++++--
 libmu_sieve/util.c                  |    4 +-
 libproto/pop/pop3_iterator.c        |    9 +-
 sieve/tests/Makefile.am             |    2 +
 sieve/tests/addheader.at            |  154 ++++++++++++++++
 sieve/tests/delheader.at            |  131 ++++++++++++++
 sieve/tests/testsuite.at            |    3 +-
 28 files changed, 870 insertions(+), 80 deletions(-)
 create mode 100644 libmu_sieve/extensions/editheader.c
 create mode 100644 sieve/tests/addheader.at
 create mode 100644 sieve/tests/delheader.at

diff --git a/NEWS b/NEWS
index ac7dbdf..94cc1b7 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 38d0abb..593ec69 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 8e50cb6..079f679 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 84d469f..867f775 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 f9ef9db..ffe5db3 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 73a4926..7f007af 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 c34b6af..ecef8a3 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 8e88c68..118de72 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 51c8e91..00a6582 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 897062c..d9b5178 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 26cc364..f517a80 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 c25c2ae..6a504eb 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 5ebd312..f563403 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 80550ee..f589b51 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 a2504d5..d516b72 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 1c76421..2745963 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 847a6f7..aa8a865 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 72c7a7d..0ea8856 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 9ac82b1..d538ca6 100644
--- a/libmu_sieve/extensions/Makefile.am
+++ b/libmu_sieve/extensions/Makefile.am
@@ -16,6 +16,7 @@
 
 address@hidden@
 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 0000000..89ae6ea
--- /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))
+           {
+             mu_sieve_error (mach, "%lu: %s",
+                             (unsigned long) mu_sieve_get_message_num (mach),
+                             _("cannot get list item"));
+             mu_sieve_abort (mach);
+           }
+         mu_sieve_log_action (mach, "DELETEHEADER", "%s: (regexp)",
+                              field_name);
+         break;
+         
+       case SVT_STRING:
+         field_pattern = val->v.string;
+         mu_sieve_log_action (mach, "DELETEHEADER", "%s: %s", field_name,
+                              field_pattern);
+         break;
+
+       default:
+         mu_sieve_error (mach, "%lu: %s: %d",
+                         (unsigned long) mu_sieve_get_message_num (mach),
+                         _("unexpected value type"), val->type);
+         mu_sieve_abort (mach);
+         
+       }
+    }
+  
+  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);
+    }
+
+  mu_header_get_iterator (hdr, &itr);
+  if (mu_sieve_tag_lookup (tags, "last", NULL))
+    {
+      int backwards = 1;
+      mu_iterator_ctl (itr, mu_itrctl_set_direction, &backwards);
+    }
+  comp = mu_sieve_get_comparator (mach, tags);
+
+  if (mu_sieve_tag_lookup (tags, "index", &val))
+    idx = val->v.number;
+  
+  for (i = 0, mu_iterator_first (itr); !mu_iterator_is_done (itr);
+       mu_iterator_next (itr))
+    {
+      const char *fn, *fv;
+
+      mu_iterator_current_kv (itr, (const void **)&fn, (void **)&fv);
+      if (strcmp (field_name, fn))
+       continue;
+      if (idx && ++i < idx)
+       continue;
+         
+      if (field_pattern)
+       {
+         if (comp (field_pattern, fv))
+           mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
+       }
+      else
+       mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
+
+      if (idx)
+       break;
+    }
+  mu_iterator_destroy (&itr);
+  return 0;
+}
+
+
+/* addheader tagged arguments: */
+static mu_sieve_tag_def_t addheader_tags[] = {
+  { "last", SVT_VOID },
+  { NULL }
+};
+
+static mu_sieve_tag_group_t addheader_tag_groups[] = {
+  { addheader_tags, NULL },
+  { NULL }
+};
+
+/* addheader required arguments: */
+static mu_sieve_data_type addheader_args[] = {
+  SVT_STRING,                  /* field name */
+  SVT_STRING,                   /* field value */ 
+  SVT_VOID
+};
+
+#if 0
+/* FIXME: The checker interface should be redone. Until then this function
+   is commented out.  Problems:
+
+   1. Checkers are called per group, there's no way to call them per tag.
+   2. See FIXMEs in the code.
+*/
+static int
+index_checker (const char *name, mu_list_t tags, mu_list_t args)
+{
+  mu_iterator_t itr;
+  mu_sieve_runtime_tag_t *match = NULL;
+  int err;
+  
+  if (!tags || mu_list_get_iterator (tags, &itr))
+    return 0;
+
+  err = 0;
+  for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr);
+       mu_iterator_next (itr))
+    {
+      mu_sieve_runtime_tag_t *t;
+      mu_iterator_current (itr, (void **)&t);
+      
+      if (strcmp (t->tag, "index") == 0)
+       {
+         if (match)
+           {
+             /* FIXME: 1. This function must be public.
+                       2. locus should be included in t
+             */
+             mu_sv_compile_error (&mu_sieve_locus, 
+                             _("index specified twice in call to `%s'"),
+                                  name);
+             err = 1;
+             break;
+           }    
+       }
+    }
+
+  mu_iterator_destroy (&itr);
+
+  if (err)
+    return 1;
+
+  if (match)
+    {
+      if (match->arg->v.number < 1)
+       {
+       // See FIXME above 
+         mu_sv_compile_error (&mu_sieve_locus, 
+                              _("invalid index value: %s"),
+                              match->arg->v.string);
+         return 1;
+       }
+    }
+  
+  return 0;
+}
+#endif
+
+static mu_sieve_tag_def_t match_part_tags[] = {
+  { "is", SVT_VOID },
+  { "contains", SVT_VOID },
+  { "matches", SVT_VOID },
+  { "regex", SVT_VOID },
+  { "count", SVT_STRING },
+  { "value", SVT_STRING },
+  { "comparator", SVT_STRING },
+  { NULL }
+};
+
+/* deleteheader tagged arguments: */
+static mu_sieve_tag_def_t deleteheader_tags[] = {
+  { "last", SVT_VOID },
+  { "index", SVT_NUMBER },
+  { NULL }
+};
+
+static mu_sieve_tag_group_t deleteheader_tag_groups[] = {
+  { deleteheader_tags, NULL },
+  { match_part_tags, mu_sieve_match_part_checker },
+  { NULL }
+};
+
+/* deleteheader required arguments: */
+static mu_sieve_data_type deleteheader_args[] = {
+  SVT_STRING,                  /* field name or value pattern */
+  SVT_VOID
+};
+
+int
+SIEVE_EXPORT (editheader, init) (mu_sieve_machine_t mach)
+{
+  int rc;
+
+  /* This dummy record is required by libmu_sieve  */
+  rc = mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1);
+  if (rc)
+    return rc;
+  rc = mu_sieve_register_action (mach, "addheader", sieve_addheader,
+                                addheader_args, addheader_tag_groups, 1);
+  if (rc)
+    return rc;
+  rc = mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader,
+                                    deleteheader_args, deleteheader_args,
+                                    deleteheader_tag_groups,
+                                    1);
+  if (rc)
+    return rc;
+
+  return rc;
+}
diff --git a/libmu_sieve/prog.c b/libmu_sieve/prog.c
index 7ea7af0..74b92bc 100644
--- a/libmu_sieve/prog.c
+++ b/libmu_sieve/prog.c
@@ -139,6 +139,7 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t 
arglist)
   mu_list_t tag_list = NULL;
   mu_list_t chk_list = NULL;
   mu_sieve_data_type *exp_arg;
+  int opt_args = 0;
   int rc, err = 0;
   static mu_sieve_data_type empty[] = { SVT_VOID };
   
@@ -237,16 +238,25 @@ mu_sv_code_command (mu_sieve_register_t *reg, mu_list_t 
arglist)
                    mu_list_append (chk_list, cf);
                }
            }
-         else if (*exp_arg == SVT_VOID)
-           {
-             mu_sv_compile_error (&mu_sieve_locus, 
-                                   _("too many arguments in call to `%s'"),
-                                  reg->name);
-             err = 1;
-             break;
-           }
          else
            {
+             if (*exp_arg == SVT_VOID)
+               {
+                 if (reg->opt_args)
+                   {
+                     exp_arg = reg->opt_args;
+                     opt_args = 1;
+                   }
+                 else
+                   {
+                     mu_sv_compile_error (&mu_sieve_locus, 
+                                     _("too many arguments in call to `%s'"),
+                                          reg->name);
+                     err = 1;
+                     break;
+                   }
+               }
+             
              if (*exp_arg != val->type)
                {
                  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)
 
   if (!err)
     {
-      if (*exp_arg != SVT_VOID)
+      if (!opt_args && *exp_arg != SVT_VOID)
        {
          mu_sv_compile_error (&mu_sieve_locus, 
                                _("too few arguments in call to `%s'"),
diff --git a/libmu_sieve/register.c b/libmu_sieve/register.c
index 72106d2..e1bad6a 100644
--- a/libmu_sieve/register.c
+++ b/libmu_sieve/register.c
@@ -50,13 +50,15 @@ reg_lookup (mu_list_t list, const char *name)
 mu_sieve_register_t *
 mu_sieve_test_lookup (mu_sieve_machine_t mach, const char *name)
 {
-  return reg_lookup (mach->test_list, name);
+  mu_sieve_register_t *reg = reg_lookup (mach->test_list, name);
+  return (reg && reg->handler) ? reg : NULL;
 }
 
 mu_sieve_register_t *
 mu_sieve_action_lookup (mu_sieve_machine_t mach, const char *name)
 {
-  return reg_lookup (mach->action_list, name);
+  mu_sieve_register_t *reg = reg_lookup (mach->action_list, name);
+  return (reg && reg->handler) ? reg : NULL;
 }
 
 static int
@@ -90,7 +92,8 @@ static int
 sieve_register (mu_list_t *pool,
                mu_list_t *list,
                const char *name, mu_sieve_handler_t handler,
-               mu_sieve_data_type *arg_types,
+               mu_sieve_data_type *req_arg_types,
+               mu_sieve_data_type *opt_arg_types,
                mu_sieve_tag_group_t *tags, int required)
 {
   mu_sieve_register_t *reg = mu_sieve_palloc (pool, sizeof (*reg));
@@ -100,7 +103,8 @@ sieve_register (mu_list_t *pool,
   reg->name = name;
   reg->handler = handler;
 
-  reg->req_args = arg_types;
+  reg->req_args = req_arg_types;
+  reg->opt_args = opt_arg_types;
   reg->tags = tags;
   reg->required = required;
   
@@ -119,23 +123,49 @@ sieve_register (mu_list_t *pool,
 
 
 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)
+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)
 {
   return sieve_register (&mach->memory_pool,
                         &mach->test_list, name, handler,
-                        arg_types, tags, required);
+                        req_args, opt_args, tags, 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,
-                      mu_sieve_tag_group_t *tags, int required)
+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)
+{
+  return mu_sieve_register_test_ext (mach, name, handler,
+                                    arg_types, NULL,
+                                    tags,
+                                    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)
 {
   return sieve_register (&mach->memory_pool,
                         &mach->action_list, name, handler,
-                        arg_types, tags, required);
+                        req_args, opt_args, tags, 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,
+                         mu_sieve_tag_group_t *tags, int required)
+{
+  return mu_sieve_register_action_ext (mach, name, handler,
+                                      arg_types, NULL,
+                                      tags,
+                                      required);
 }
diff --git a/libmu_sieve/util.c b/libmu_sieve/util.c
index b487fab..17f7da5 100644
--- a/libmu_sieve/util.c
+++ b/libmu_sieve/util.c
@@ -426,8 +426,10 @@ mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t 
ac, void *data)
     case SVT_VALUE_LIST:
     case SVT_STRING_LIST:
       return mu_list_foreach (val->v.list, ac, data);
-      
+    case SVT_STRING:
+      return ac (val->v.string, data);
     default:
+      mu_error ("mu_sieve_vlist_do: unexpected list type %d", val->type);
       return EINVAL;
     }
 }
diff --git a/libproto/pop/pop3_iterator.c b/libproto/pop/pop3_iterator.c
index 2a9159c..44a1b22 100644
--- a/libproto/pop/pop3_iterator.c
+++ b/libproto/pop/pop3_iterator.c
@@ -35,7 +35,7 @@ static int  pop3_itr_destroy (mu_iterator_t itr, void *owner);
 static int  pop3_itr_first   (void *owner);
 static int  pop3_itr_next    (void *woner);
 static int  pop3_itr_getitem (void *owner, void **pret, const void **pkey);
-static int  pop3_itr_curitem_p (void *owner, void *data);
+static int  pop3_itr_delitem (void *owner, void *data);
 static int  pop3_itr_finished_p (void *owner);
 
 struct pop3_iterator
@@ -81,7 +81,7 @@ mu_pop3_iterator_create (mu_pop3_t pop3, mu_iterator_t 
*piterator)
   mu_iterator_set_next (iterator, pop3_itr_next);
   mu_iterator_set_getitem (iterator, pop3_itr_getitem);
   mu_iterator_set_finished_p (iterator, pop3_itr_finished_p);
-  mu_iterator_set_curitem_p (iterator, pop3_itr_curitem_p);
+  mu_iterator_set_delitem (iterator, pop3_itr_delitem);
   mu_iterator_set_destroy (iterator, pop3_itr_destroy);
   mu_iterator_set_dup (iterator, pop3_itr_dup);
 
@@ -183,9 +183,10 @@ pop3_itr_finished_p (void *owner)
 }
 
 static int
-pop3_itr_curitem_p (void *owner, void *item)
+pop3_itr_delitem (void *owner, void *item)
 {
   struct pop3_iterator *pop3_iterator = (struct pop3_iterator *)owner;
-  return *((char **)item) == pop3_iterator->item;
+  return *((char **)item) == pop3_iterator->item ? 
+    MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
 }
 
diff --git a/sieve/tests/Makefile.am b/sieve/tests/Makefile.am
index 760a6a2..8b46d47 100644
--- a/sieve/tests/Makefile.am
+++ b/sieve/tests/Makefile.am
@@ -41,9 +41,11 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
 
 TESTSUITE_AT = \
   action.at\
+  addheader.at\
   address.at\
   allof.at\
   anyof.at\
+  delheader.at\
   compile.at\
   envelope.at\
   exists.at\
diff --git a/sieve/tests/addheader.at b/sieve/tests/addheader.at
new file mode 100644
index 0000000..e10abd1
--- /dev/null
+++ b/sieve/tests/addheader.at
@@ -0,0 +1,154 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# 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 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+
+AT_BANNER([addheader])
+m4_pushdef([MUT_SIEVE_EXT_NAME],[addheader])
+
+MUT_SIEVE_EXT_TEST([prepend header],[addheader addheader00],
+[require "editheader";
+addheader "X-Sieve-Filtered" "<address@hidden>";
+],
+[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
+sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
+sed '/X-IMAPbase:/d;s/ *$//' mailbox
+],
+[From address@hidden Sun May  6 22:16:47 2001
+X-Sieve-Filtered: <address@hidden>
+From: address@hidden
+To: address@hidden
+Subject: I have a present for you
+X-Caffeine: C8H10N4O2
+Status: 
+X-UID: 1
+
+Look, I'm sorry about the whole anvil thing, and I really
+didn't mean to try and drop it on you from the top of the
+cliff.  I want to try to make it up to you.  I've got some
+great birdseed over here at my place--top of the line
+stuff--and if you come by, I'll have it all wrapped up
+for you.  I'm really sorry for all the problems I've caused
+for you over the years, but I know we can work this out.
+
+--
+Wile E. Coyote   "Super Genius"   address@hidden
+
+From address@hidden Sun May  6 22:17:15 2001
+X-Sieve-Filtered: <address@hidden>
+From: address@hidden
+To: address@hidden
+Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$
+Date: TBD
+X-Number: 0015
+Status: 
+X-UID: 2
+
+YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT
+IT!  SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS!  IT WILL
+GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY!
+MONEY! MONEY! COLD HARD CASH!  YOU WILL RECEIVE OVER
+$20,000 IN LESS THAN TWO MONTHS!  AND IT'S LEGAL!!!!!!!!!
+!!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1  JUST
+SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW!
+
+From address@hidden  Fri Dec 28 23:28:09 2001
+X-Sieve-Filtered: <address@hidden>
+Received: (from address@hidden)
+       by dontmailme.org id fERKR9N16790
+       for address@hidden; Fri, 28 Dec 2001 22:18:08 +0200
+Date: Fri, 28 Dec 2001 23:28:08 +0200
+From: Bar <address@hidden>
+To: Foo Bar <address@hidden>
+Message-Id: <address@hidden>
+Subject: Coffee
+Status: 
+X-UID: 3
+
+How about some coffee?
+
+],
+[ADDHEADER on msg uid 1: X-Sieve-Filtered: <address@hidden>
+ADDHEADER on msg uid 2: X-Sieve-Filtered: <address@hidden>
+ADDHEADER on msg uid 3: X-Sieve-Filtered: <address@hidden>
+])
+
+MUT_SIEVE_EXT_TEST([append header],[addheader addheader01],
+[require "editheader";
+addheader :last "X-Sieve-Filtered" "<address@hidden>";
+],
+[MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
+sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
+sed '/X-IMAPbase:/d;s/ *$//' mailbox
+],
+[From address@hidden Sun May  6 22:16:47 2001
+From: address@hidden
+To: address@hidden
+Subject: I have a present for you
+X-Caffeine: C8H10N4O2
+X-Sieve-Filtered: <address@hidden>
+Status: 
+X-UID: 1
+
+Look, I'm sorry about the whole anvil thing, and I really
+didn't mean to try and drop it on you from the top of the
+cliff.  I want to try to make it up to you.  I've got some
+great birdseed over here at my place--top of the line
+stuff--and if you come by, I'll have it all wrapped up
+for you.  I'm really sorry for all the problems I've caused
+for you over the years, but I know we can work this out.
+
+--
+Wile E. Coyote   "Super Genius"   address@hidden
+
+From address@hidden Sun May  6 22:17:15 2001
+From: address@hidden
+To: address@hidden
+Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$
+Date: TBD
+X-Number: 0015
+X-Sieve-Filtered: <address@hidden>
+Status: 
+X-UID: 2
+
+YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT
+IT!  SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS!  IT WILL
+GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY!
+MONEY! MONEY! COLD HARD CASH!  YOU WILL RECEIVE OVER
+$20,000 IN LESS THAN TWO MONTHS!  AND IT'S LEGAL!!!!!!!!!
+!!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1  JUST
+SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW!
+
+From address@hidden  Fri Dec 28 23:28:09 2001
+Received: (from address@hidden)
+       by dontmailme.org id fERKR9N16790
+       for address@hidden; Fri, 28 Dec 2001 22:18:08 +0200
+Date: Fri, 28 Dec 2001 23:28:08 +0200
+From: Bar <address@hidden>
+To: Foo Bar <address@hidden>
+Message-Id: <address@hidden>
+Subject: Coffee
+X-Sieve-Filtered: <address@hidden>
+Status: 
+X-UID: 3
+
+How about some coffee?
+
+],
+[ADDHEADER on msg uid 1: X-Sieve-Filtered: <address@hidden>
+ADDHEADER on msg uid 2: X-Sieve-Filtered: <address@hidden>
+ADDHEADER on msg uid 3: X-Sieve-Filtered: <address@hidden>
+])
+
+m4_popdef([MUT_SIEVE_EXT_NAME])
\ No newline at end of file
diff --git a/sieve/tests/delheader.at b/sieve/tests/delheader.at
new file mode 100644
index 0000000..fa315ba
--- /dev/null
+++ b/sieve/tests/delheader.at
@@ -0,0 +1,131 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# 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 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
+
+AT_BANNER([deleteheader])
+m4_pushdef([MUT_SIEVE_EXT_NAME],[deleteheader])
+
+m4_define([mkmailbox],[
+AT_DATA([$1],
+[From address@hidden Sun May  6 22:16:47 2001
+From: address@hidden
+To: address@hidden
+X-Agent: Agent A
+Received: (from address@hidden)
+       by example.org id fERKR9N16790
+       for address@hidden; Fri, 28 Dec 2001 22:18:08 +0200
+X-Agent: Agent 22
+X-Agent: Agent C
+Subject: Ping
+
+Test message, please discard.
+
+])])
+
+
+MUT_SIEVE_EXT_TEST([delete all],[deleteheader delheader delheader00],
+[require "editheader";
+deleteheader "X-Agent";
+],
+[mkmailbox(mailbox)
+sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
+sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox
+],
+[From address@hidden Sun May  6 22:16:47 2001
+From: address@hidden
+To: address@hidden
+Received: (from address@hidden)
+       by example.org id fERKR9N16790
+       for address@hidden; Fri, 28 Dec 2001 22:18:08 +0200
+Subject: Ping
+
+Test message, please discard.
+
+],
+[DELETEHEADER on msg uid 1: X-Agent
+])
+
+MUT_SIEVE_EXT_TEST([delete index],[deleteheader delheader delheader01],
+[require "editheader";
+deleteheader :index 1 "X-Agent";
+],
+[mkmailbox(mailbox)
+sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
+sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox
+],
+[From address@hidden Sun May  6 22:16:47 2001
+From: address@hidden
+To: address@hidden
+Received: (from address@hidden)
+       by example.org id fERKR9N16790
+       for address@hidden; Fri, 28 Dec 2001 22:18:08 +0200
+X-Agent: Agent 22
+X-Agent: Agent C
+Subject: Ping
+
+Test message, please discard.
+
+],
+[DELETEHEADER on msg uid 1: X-Agent
+])
+
+MUT_SIEVE_EXT_TEST([delete index backwards],[deleteheader delheader 
delheader02],
+[require "editheader";
+deleteheader :index 2 :last "X-Agent";
+],
+[mkmailbox(mailbox)
+sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
+sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox
+],
+[From address@hidden Sun May  6 22:16:47 2001
+From: address@hidden
+To: address@hidden
+X-Agent: Agent A
+Received: (from address@hidden)
+       by example.org id fERKR9N16790
+       for address@hidden; Fri, 28 Dec 2001 22:18:08 +0200
+X-Agent: Agent C
+Subject: Ping
+
+Test message, please discard.
+
+],
+[DELETEHEADER on msg uid 1: X-Agent
+])
+
+MUT_SIEVE_EXT_TEST([delete regex],[deleteheader delheader delheader03],
+[require "editheader";
+deleteheader :regex "X-Agent" "Agent [[A-Z]]";
+],
+[mkmailbox(mailbox)
+sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog
+sed '/^X-IMAPbase:/d;/^Status:/d;/^X-UID:/d;s/ *$//' mailbox
+],
+[From address@hidden Sun May  6 22:16:47 2001
+From: address@hidden
+To: address@hidden
+Received: (from address@hidden)
+       by example.org id fERKR9N16790
+       for address@hidden; Fri, 28 Dec 2001 22:18:08 +0200
+X-Agent: Agent 22
+Subject: Ping
+
+Test message, please discard.
+
+],
+[DELETEHEADER on msg uid 1: X-Agent: (regexp)
+])
+
+m4_popdef([MUT_SIEVE_EXT_NAME])
diff --git a/sieve/tests/testsuite.at b/sieve/tests/testsuite.at
index b78f7de..7525816 100644
--- a/sieve/tests/testsuite.at
+++ b/sieve/tests/testsuite.at
@@ -147,6 +147,7 @@ m4_include([moderator.at])
 m4_include([pipeact.at])
 m4_include([pipetest.at])
 m4_include([list.at])
-
+m4_include([addheader.at])
+m4_include([delheader.at])
 
 


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]