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-516-gea01b2f


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-516-gea01b2f
Date: Sat, 10 Dec 2011 10:05:05 +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=ea01b2f9a46d6eb0666e613f1c536f9ee69dcf3e

The branch, master has been updated
       via  ea01b2f9a46d6eb0666e613f1c536f9ee69dcf3e (commit)
       via  cef5f35da5f0e9b326d4d9a56f6b62ad565ad643 (commit)
      from  f9a034c7af98b56f62114b4e390a9c7f5971db68 (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 ea01b2f9a46d6eb0666e613f1c536f9ee69dcf3e
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 10 12:02:55 2011 +0200

    imap4d: remove functions duplicated in the library
    
    * imap4d/imap4d.h (util_format_attribute_flags)
    (util_attribute_to_type): Remove. All uses changed to
    mu_imap_format_flags and mu_imap_flag_to_attribute, respectively.
    (util_type_to_attribute): Remove.

commit cef5f35da5f0e9b326d4d9a56f6b62ad565ad643
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 10 11:32:37 2011 +0200

    Redo message set parser in imap4d
    
    The new parser complies to RFC3501. Its output message sets are
    formatted as MU lists of non-overlapping contiguous message ranges,
    which reduces memory consumption and imposes less strain on CPU.
    The parser automatically translates message UIDs to sequence numbers
    and provides better error handling.
    
    * imap4d/imap4d.h (util_msgset): Remove.
    (util_parse_msgset): New proto.
    (imap4d_message_action_t): New typedef.
    (util_foreach_message): New proto.
    * imap4d/util.c  (util_msgset): Remove.
    (util_parse_msgset): New function.
    
    * imap4d/copy.c: Use util_parse_msgset to parse message set specs and
    util_foreach_message to iterate over the returned list.
    * imap4d/fetch.c: Likewise.
    * imap4d/search.c: Likewise.
    * imap4d/store.c: Likewise.
    * imap4d/tests/IDEF0955.at: Update the test.
    * include/mailutils/list.h (mu_list_action_t): Fix typedef.
    * libmailutils/list/foreach.c (mu_list_foreach)
    (mu_list_do): Update signatures.

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

Summary of changes:
 imap4d/append.c             |    8 +-
 imap4d/copy.c               |  193 ++++++++-------
 imap4d/fetch.c              |   76 +++----
 imap4d/imap4d.c             |    1 -
 imap4d/imap4d.h             |   14 +-
 imap4d/search.c             |   51 ++---
 imap4d/store.c              |  127 +++++-----
 imap4d/sync.c               |    2 +-
 imap4d/tests/IDEF0955.at    |    5 +
 imap4d/util.c               |  567 ++++++++++++++++++++++---------------------
 include/mailutils/list.h    |    6 +-
 libmailutils/list/foreach.c |    4 +-
 12 files changed, 520 insertions(+), 534 deletions(-)

diff --git a/imap4d/append.c b/imap4d/append.c
index 632333a..74aebef 100644
--- a/imap4d/append.c
+++ b/imap4d/append.c
@@ -220,13 +220,13 @@ imap4d_append (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
     {
       while (++i < argc)
        {
-         int type;
          char *arg = imap4d_tokbuf_getarg (tok, i);
          
-         if (!util_attribute_to_type (arg, &type))
-           flags |= type;
-         else if (arg[0] == ')')
+         if (arg[0] == ')')
            break;
+         if (mu_imap_flag_to_attribute (arg, &flags))
+           return io_completion_response (command, RESP_BAD,
+                                          "Unrecognized flag");
        }
       if (i == argc)
        return io_completion_response (command, RESP_BAD, 
diff --git a/imap4d/copy.c b/imap4d/copy.c
index 69715df..607c278 100644
--- a/imap4d/copy.c
+++ b/imap4d/copy.c
@@ -55,88 +55,111 @@ imap4d_copy (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
   return io_completion_response (command, rc, "%s", text);
 }
 
+struct copy_env
+{
+  mu_mailbox_t dst;
+  mu_mailbox_t src;
+  mu_off_t total;
+  int ret;
+  char **err_text;
+};
+
 static int
-copy_check_size (mu_mailbox_t mbox, size_t n, size_t *set, mu_off_t *size)
+size_sum (size_t msgno, void *data)
 {
-  int status;
-  size_t i;
-  mu_off_t total = 0;
+  struct copy_env *env = data;
+  mu_message_t msg = NULL;
+  int rc;
   
-  for (i = 0; i < n; i++)
+  rc = mu_mailbox_get_message (env->src, msgno, &msg);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL, rc);
+      env->ret = RESP_NO;
+      return MU_ERR_FAILURE;
+    }
+  else 
     {
-      mu_message_t msg = NULL;
-      size_t msgno = set[i];
-      if (msgno)
+      size_t size;
+      rc = mu_message_size (msg, &size);
+      if (rc)
        {
-         status = mu_mailbox_get_message (mbox, msgno, &msg);
-         if (status)
-           {
-             mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
-                              status);
-             return RESP_BAD;
-           }
-         else 
-           {
-             size_t size;
-             status = mu_message_size (msg, &size);
-             if (status)
-               {
-                 mu_diag_funcall (MU_DIAG_ERROR, "mu_message_size", NULL,
-                                  status);
-                 return RESP_BAD;
-               }
-             total += size;
-           }
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_message_size", NULL, rc);
+         env->ret = RESP_BAD;
+         return MU_ERR_FAILURE;
        }
+      env->total += size;
     }
-  *size = total;
-  return quota_check (total);
+  return 0;
 }
 
 static int
-try_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set)
+do_copy (size_t msgno, void *data)
 {
-  int result;
-  size_t i;
-  mu_off_t total;
-  
-  result = copy_check_size (src, n, set, &total);
-  if (result)
-    return result;
-  
-  for (i = 0; i < n; i++)
-    {
-      mu_message_t msg = NULL;
-      size_t msgno = set[i];
+  struct copy_env *env = data;
+  mu_message_t msg = NULL;
+  int status;
 
-      if (msgno)
-       {
-         int status = mu_mailbox_get_message (src, msgno, &msg);
-         if (status)
-           {
-             mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
-                              status);
-             return RESP_BAD;
-           }
+  status = mu_mailbox_get_message (env->src, msgno, &msg);
+  if (status)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
+                      status);
+      env->ret = RESP_BAD;
+      return MU_ERR_FAILURE;
+    }
 
-         imap4d_enter_critical ();
-         status = mu_mailbox_append_message (dst, msg);
-         imap4d_leave_critical ();
-         if (status)
-           {
-             mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_append_message",
-                              NULL,
-                              status);
-             return RESP_BAD;
-           }
-       }
+  imap4d_enter_critical ();
+  status = mu_mailbox_append_message (env->dst, msg);
+  imap4d_leave_critical ();
+  if (status)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_append_message", NULL,
+                      status);
+      env->ret = RESP_BAD;
+      return MU_ERR_FAILURE;
     }
-  quota_update (total);
-  return RESP_OK;
+
+  return 0;
 }
 
 static int
-safe_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set,
+try_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_list_t msglist,
+         char **err_text)
+{
+  int rc;
+  struct copy_env env;
+
+  env.dst = dst;
+  env.src = src;
+  env.total = 0;
+  env.ret = RESP_OK;
+  env.err_text = err_text;
+
+  *env.err_text = "Operation failed";
+
+  /* Check size */
+  rc = util_foreach_message (msglist, size_sum, &env);
+  if (rc)
+    return RESP_NO;
+  if (env.ret != RESP_OK)
+    return env.ret;
+  rc = quota_check (env.total);
+  if (rc)
+    {
+      *env.err_text = "Mailbox quota exceeded";
+      return RESP_NO;
+    }
+  env.total = 0;
+  rc = util_foreach_message (msglist, do_copy, &env);
+  quota_update (env.total);
+  if (rc)
+    return RESP_NO;
+  return env.ret;
+}
+  
+static int
+safe_copy (mu_mailbox_t dst, mu_mailbox_t src, mu_list_t msglist,
           char **err_text)
 {
   size_t nmesg;
@@ -151,16 +174,11 @@ safe_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, 
size_t *set,
       return RESP_NO;
     }
 
-  status = try_copy (dst, src, n, set);
-  if (status)
+  status = try_copy (dst, src, msglist, err_text);
+  if (status != RESP_OK)
     {
       size_t maxmesg;
 
-      if (status == RESP_NO)
-       *err_text = "Mailbox quota exceeded";
-      else
-       *err_text = "Operation failed";
-      
       /* If the COPY command is unsuccessful for any reason, server
         implementations MUST restore the destination mailbox to its state
         before the COPY attempt. */
@@ -211,11 +229,11 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
 {
   int status;
   char *msgset;
+  mu_list_t msglist;
   char *name;
   char *mailbox_name;
   const char *delim = "/";
-  size_t *set = NULL;
-  int n = 0;
+  char *end;
   mu_mailbox_t cmbox = NULL;
   int arg = IMAP4_ARG_1 + !!isuid;
   int ns;
@@ -230,23 +248,14 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
   msgset = imap4d_tokbuf_getarg (tok, arg);
   name = imap4d_tokbuf_getarg (tok, arg + 1);
   /* Get the message numbers in set[].  */
-  status = util_msgset (msgset, &set, &n, isuid);
-  if (status != 0)
+  status = util_parse_msgset (msgset, isuid, mbox, &msglist, &end);
+  if (status)
     {
-      /* See RFC 3501, section 6.4.8, and a comment to the equivalent code
-        in fetch.c */
-      *err_text = "Completed";
-      return RESP_OK;
+      *err_text = "Error parsing message set";
+      /* FIXME: print error location */
+      return RESP_BAD;
     }
 
-  if (isuid)
-    {
-      int i;
-      /* Fixup the message set. Perhaps util_msgset should do it itself? */
-      for (i = 0; i < n; i++)
-       set[i] = uid_to_msgno (set[i]);
-    }
-  
   mailbox_name = namespace_getfullpath (name, delim, &ns);
 
   if (!mailbox_name)
@@ -256,7 +265,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
     }
 
   /* If the destination mailbox does not exist, a server should return
-     an error.  */
+     an error. */
   status = mu_mailbox_create_default (&cmbox, mailbox_name);
   if (status == 0)
     {
@@ -264,13 +273,13 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
       status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mailbox_mode[ns]);
       if (status == 0)
        {
-         status = safe_copy (cmbox, mbox, n, set, err_text);
+         if (!mu_list_is_empty (msglist))
+           status = safe_copy (cmbox, mbox, msglist, err_text);
          mu_mailbox_close (cmbox);
        }
       mu_mailbox_destroy (&cmbox);
     }
-  free (set);
-  free (mailbox_name);
+  mu_list_destroy (&msglist);
 
   if (status == 0)
     {
diff --git a/imap4d/fetch.c b/imap4d/fetch.c
index 6e955c0..d1698b6 100644
--- a/imap4d/fetch.c
+++ b/imap4d/fetch.c
@@ -37,6 +37,8 @@ struct fetch_runtime_closure
   mu_message_t msg;    /* The message itself */
   mu_list_t msglist;   /* A list of referenced messages.  See KLUDGE below. */
   char *err_text;      /* On return: error description if failed. */
+
+  mu_list_t fnlist;
 };
 
 struct fetch_function_closure;
@@ -62,8 +64,7 @@ struct fetch_parse_closure
 {
   int isuid;
   mu_list_t fnlist;
-  size_t *set;
-  int count;
+  mu_list_t msgnumlist;
 };
 
 
@@ -1751,38 +1752,16 @@ fetch_thunk (imap4d_parsebuf_t pb)
 {
   int status;
   char *msgset;
+  char *end;
   struct fetch_parse_closure *pclos = imap4d_parsebuf_data (pb);
   
   msgset = imap4d_parsebuf_next (pb, 1);
 
-  /* Get the message numbers in set[].  */
-  status = util_msgset (msgset, &pclos->set, &pclos->count, pclos->isuid);
-  switch (status)
-    {
-    case 0:
-      /* Very good! */
-      break;
-      
-    case EINVAL:
-      /* RFC3501, section 6.4.8.
-        
-        A non-existent unique identifier is ignored without any error
-        message generated.  Thus, it is possible for a UID FETCH command
-        to return an OK without any data or a UID COPY or UID STORE to
-        return an OK without performing any operations.
-
-        Obviously the same holds true for non-existing message numbers
-        as well, although I did not find any explicit mention thereof
-        in the RFC.
-
-        FIXME: This code also causes imap4d to silently ignore erroneous
-        msgset specifications (e.g. FETCH foobar (FLAGS)), which should
-        be fixed.  */
-      return RESP_OK;
-
-    default:
-      imap4d_parsebuf_exit (pb, "Failed to parse message set");
-    }
+  /* Parse sequence numbers. */
+  status = util_parse_msgset (msgset, pclos->isuid, mbox,
+                             &pclos->msgnumlist, &end);
+  if (status)
+    imap4d_parsebuf_exit (pb, "Failed to parse message set");
 
   /* Compile the expression */
 
@@ -1797,6 +1776,23 @@ fetch_thunk (imap4d_parsebuf_t pb)
   return RESP_OK;
 }
 
+int
+_fetch_from_message (size_t msgno, void *data)
+{
+  int rc = 0;
+  struct fetch_runtime_closure *frc = data;
+
+  frc->msgno = msgno;
+  if (mu_mailbox_get_message (mbox, msgno, &frc->msg) == 0)
+    {
+      io_sendf ("* %lu FETCH (", (unsigned long) msgno);
+      frc->eltno = 0;
+      rc = mu_list_foreach (frc->fnlist, _do_fetch, frc);
+      io_sendf (")\n");
+    }
+  return rc;
+}
+
 /* Where the real implementation is.  It is here since UID command also
    calls FETCH.  */
 int
@@ -1823,32 +1819,20 @@ imap4d_fetch0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
 
   if (rc == RESP_OK)
     {
-      size_t i;
       struct fetch_runtime_closure frc;
 
       memset (&frc, 0, sizeof (frc));
+      frc.fnlist = pclos.fnlist;
       /* Prepare status code. It will be replaced if an error occurs in the
         loop below */
       frc.err_text = "Completed";
-  
-      for (i = 0; i < pclos.count && rc == RESP_OK; i++)
-       {
-         frc.msgno = (isuid) ? uid_to_msgno (pclos.set[i]) : pclos.set[i];
-         
-         if (frc.msgno &&
-             mu_mailbox_get_message (mbox, frc.msgno, &frc.msg) == 0)
-           {
-             io_sendf ("* %lu FETCH (", (unsigned long) frc.msgno);
-             frc.eltno = 0;
-             rc = mu_list_foreach (pclos.fnlist, _do_fetch, &frc);
-             io_sendf (")\n");
-           }
-       }
+
+      util_foreach_message (pclos.msgnumlist, _fetch_from_message, &frc);
       mu_list_destroy (&frc.msglist);
     }
   
   mu_list_destroy (&pclos.fnlist);
-  free (pclos.set);
+  mu_list_destroy (&pclos.msgnumlist);
   return rc;
 }
 
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index e27948f..3fbbf8f 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -554,7 +554,6 @@ imap4d_master_signal (int signo)
 }
 
 
-
 int
 main (int argc, char **argv)
 {
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index f74eba3..09e7f64 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -105,6 +105,7 @@
 #include <mailutils/cstr.h>
 #include <mailutils/io.h>
 #include <mailutils/prog.h>
+#include <mailutils/imapio.h>
 
 #include <mu_umaxtostr.h>
 #include <muaux.h>
@@ -368,10 +369,17 @@ extern int  util_getstate (void);
 extern int  util_do_command (imap4d_tokbuf_t);
 extern char *util_tilde_expansion (const char *, const char *);
 extern char *util_getfullpath (const char *, const char *);
-extern int  util_msgset (char *, size_t **, int *, int);
 extern struct imap4d_command *util_getcommand (char *, 
                                                struct imap4d_command []);
 
+extern int util_parse_msgset (char *s, int isuid, mu_mailbox_t mbx,
+                             mu_list_t *plist, char **end);
+
+typedef int (*imap4d_message_action_t) (size_t, void *);
+
+int util_foreach_message (mu_list_t list, imap4d_message_action_t action,
+                         void *data);
+
 enum datetime_parse_mode     /* how to parse date/time strings */
   {
     datetime_default,        /* default mode */
@@ -390,10 +398,8 @@ extern char *util_localname (void);
 
 extern int util_wcard_match (const char *string, const char *pattern,
                             const char *delim);
-int util_format_attribute_flags (mu_stream_t str, int flags);
+
 void util_print_flags (mu_attribute_t attr);
-int util_attribute_to_type (const char *item, int *type);
-int util_type_to_attribute (int type, char **attr_str);
 int util_attribute_matches_flag (mu_attribute_t attr, const char *item);
 int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp);
 
diff --git a/imap4d/search.c b/imap4d/search.c
index bb9656b..54c212e 100644
--- a/imap4d/search.c
+++ b/imap4d/search.c
@@ -62,11 +62,7 @@ struct value
     char *string;
     mu_off_t number;
     time_t date;
-    struct
-    {
-      int n;
-      size_t *set;
-    } msgset;
+    mu_list_t msgset;
   } v;
 };
 
@@ -168,7 +164,7 @@ struct cond condlist[] =
   { "SUBJECT",    "s",  cond_subject },
   { "TEXT",       "s",  cond_text },
   { "TO",         "s",  cond_to },
-  { "UID",        "m",  cond_uid },
+  { "UID",        "u",  cond_uid },
   { NULL }
 };
 
@@ -584,8 +580,6 @@ parse_simple_key (struct parsebuf *pb)
   struct search_node *node;
   struct cond *condp;
   time_t time;
-  size_t *set = NULL;
-  int n = 0;
   
   for (condp = condlist; condp->name && mu_c_strcasecmp (condp->name, 
pb->token);
        condp++)
@@ -593,13 +587,14 @@ parse_simple_key (struct parsebuf *pb)
 
   if (!condp->name)
     {
-      if (util_msgset (pb->token, &set, &n, 0) == 0) 
+      mu_list_t msglist;
+      
+      if (util_parse_msgset (pb->token, pb->isuid, mbox, &msglist, NULL) == 0) 
        {
          struct search_node *np = parse_alloc (pb, sizeof *np);
          np->type = node_value;
          np->v.value.type = value_msgset;
-         np->v.value.v.msgset.n = n;
-         np->v.value.v.msgset.set = parse_regmem (pb, set);
+         np->v.value.v.msgset = msglist;
          
          node = parse_alloc (pb, sizeof *node);
          node->type = node_call;
@@ -630,9 +625,7 @@ parse_simple_key (struct parsebuf *pb)
     {
       char *t = condp->argtypes;
       char *s;
-      int n;
       mu_off_t number;
-      size_t *set;
       struct search_node *arg;
       
       for (; *t; t++, parse_gettoken (pb, 0))
@@ -680,20 +673,20 @@ parse_simple_key (struct parsebuf *pb)
              arg->v.value.v.date = time;
              break;
              
-           case 'm': /* message set */
-             if (util_msgset (pb->token, &set, &n, 1)) /*FIXME: isuid?*/
+           case 'u': /* UID message set */
+             if (util_parse_msgset (pb->token, 0, NULL,
+                                    &arg->v.value.v.msgset, NULL)) 
                {
                  pb->err_mesg = "Bogus number set";
                  return NULL;
                }
              arg->v.value.type = value_msgset;
-             arg->v.value.v.msgset.n = n;
-             arg->v.value.v.msgset.set = parse_regmem (pb, set);
              break;
              
            default:
-             mu_diag_output (MU_DIAG_CRIT, _("%s:%d: INTERNAL ERROR (please 
report)"),
-                    __FILE__, __LINE__);
+             mu_diag_output (MU_DIAG_CRIT,
+                             _("%s:%d: INTERNAL ERROR (please report)"),
+                             __FILE__, __LINE__);
              abort (); /* should never happen */
            }
          node->v.key.arg[node->v.key.narg++] = arg;
@@ -860,15 +853,9 @@ static void
 cond_msgset (struct parsebuf *pb, struct search_node *node, struct value *arg,
             struct value *retval)
 {
-  int  n = arg[0].v.msgset.n;
-  size_t *set = arg[0].v.msgset.set;
-  int i, rc;
-  
-  for (i = rc = 0; rc == 0 && i < n; i++)
-    rc = set[i] == pb->msgno;
-      
+  int rc = mu_list_locate (arg[0].v.msgset, &pb->msgno, NULL);
   retval->type = value_number;
-  retval->v.number = rc;
+  retval->v.number = rc == 0;
 }
 
 static void
@@ -1084,16 +1071,12 @@ static void
 cond_uid (struct parsebuf *pb, struct search_node *node, struct value *arg,
          struct value *retval)
 {
-  int  n = arg[0].v.msgset.n;
-  size_t *set = arg[0].v.msgset.set;
+  int rc;
   size_t uid = 0;
-  int i, rc;
   
   mu_message_get_uid (pb->msg, &uid);
-  for (i = rc = 0; rc == 0 && i < n; i++)
-    rc = set[i] == uid;
-      
+  rc = mu_list_locate (arg[0].v.msgset, &pb->msgno, NULL);
   retval->type = value_number;
-  retval->v.number = rc;
+  retval->v.number = rc == 0;
 }                      
 
diff --git a/imap4d/store.c b/imap4d/store.c
index 7e9d9ad..17f853c 100644
--- a/imap4d/store.c
+++ b/imap4d/store.c
@@ -25,8 +25,7 @@ struct store_parse_closure
   int ack;
   int type;
   int isuid;
-  size_t *set;
-  int count;
+  mu_list_t msgnumlist;
 };
   
 static int
@@ -36,6 +35,7 @@ store_thunk (imap4d_parsebuf_t p)
   char *msgset;
   char *data;
   int status;
+  char *end;
   
   msgset = imap4d_parsebuf_next (p, 1);
   data = imap4d_parsebuf_next (p, 1);
@@ -70,43 +70,75 @@ store_thunk (imap4d_parsebuf_t p)
     }
 
   /* Get the message numbers in set[].  */
-  status = util_msgset (msgset, &pclos->set, &pclos->count, pclos->isuid);
-  switch (status)
-    {
-    case 0:
-      break;
-
-    case EINVAL:
-      /* See RFC 3501, section 6.4.8, and a comment to the equivalent code
-        in fetch.c */
-      return RESP_OK;
-
-    default:
-      imap4d_parsebuf_exit (p, "Failed to parse message set");
-    }      
+  status = util_parse_msgset (msgset, pclos->isuid, mbox,
+                             &pclos->msgnumlist, &end);
+  if (status)
+    imap4d_parsebuf_exit (p, "Failed to parse message set");
 
   if (p->token[0] != '(')
     imap4d_parsebuf_exit (p, "Syntax error");
   imap4d_parsebuf_next (p, 1);
   
   do
-    {
-      int t;
-      if (util_attribute_to_type (p->token, &t))
-       imap4d_parsebuf_exit (p, "Failed to parse flags");
-      else
-       pclos->type |= t;
-    }
+    if (mu_imap_flag_to_attribute (p->token, &pclos->type))
+      imap4d_parsebuf_exit (p, "Unrecognized flag");
   while (imap4d_parsebuf_next (p, 1) && p->token[0] != ')');
   return RESP_OK;
 }
 
+static int
+_do_store (size_t msgno, void *data)
+{
+  struct store_parse_closure *pclos = data;
+  mu_message_t msg = NULL;
+  mu_attribute_t attr = NULL;
+      
+  mu_mailbox_get_message (mbox, msgno, &msg);
+  mu_message_get_attribute (msg, &attr);
+             
+  switch (pclos->how)
+    {
+    case STORE_ADD:
+      mu_attribute_set_flags (attr, pclos->type);
+      break;
+      
+    case STORE_UNSET:
+      mu_attribute_unset_flags (attr, pclos->type);
+      break;
+      
+    case STORE_SET:
+      mu_attribute_unset_flags (attr, 0xffffffff); /* FIXME */
+      mu_attribute_set_flags (attr, pclos->type);
+    }
+
+         
+  if (pclos->ack)
+    {
+      io_sendf ("* %lu FETCH (", (unsigned long) msgno);
+      
+      if (pclos->isuid)
+       {
+         size_t uid;
+         int rc = mu_mailbox_translate (mbox, MU_MAILBOX_UID_TO_MSGNO,
+                                        msgno, &uid);
+         if (rc == 0)
+           io_sendf ("UID %lu ", (unsigned long) uid);
+       }
+      io_sendf ("FLAGS (");
+      util_print_flags (attr);
+      io_sendf ("))\n");
+    }
+  /* Update the flags of uid table.  */
+  imap4d_sync_flags (msgno);
+  return 0;
+}
+
 int
 imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext)
 {
   int rc;
   struct store_parse_closure pclos;
-
+  
   memset (&pclos, 0, sizeof pclos);
   pclos.ack = 1;
   pclos.isuid = isuid;
@@ -118,53 +150,12 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char 
**ptext)
                             ptext);
   if (rc == RESP_OK)
     {
-      size_t i;
-      
-      for (i = 0; i < pclos.count; i++)
-       {
-         mu_message_t msg = NULL;
-         mu_attribute_t attr = NULL;
-         size_t msgno = isuid ? uid_to_msgno (pclos.set[i]) : pclos.set[i];
-      
-         if (msgno)
-           {
-             mu_mailbox_get_message (mbox, msgno, &msg);
-             mu_message_get_attribute (msg, &attr);
-             
-             switch (pclos.how)
-               {
-               case STORE_ADD:
-                 mu_attribute_set_flags (attr, pclos.type);
-                 break;
-                 
-               case STORE_UNSET:
-                 mu_attribute_unset_flags (attr, pclos.type);
-                 break;
-      
-               case STORE_SET:
-                 mu_attribute_unset_flags (attr, 0xffffffff); /* FIXME */
-                 mu_attribute_set_flags (attr, pclos.type);
-               }
-           }
-         
-         if (pclos.ack)
-           {
-             io_sendf ("* %lu FETCH (", (unsigned long) msgno);
-             
-             if (isuid)
-               io_sendf ("UID %lu ", (unsigned long) msgno);
-             io_sendf ("FLAGS (");
-             util_print_flags (attr);
-             io_sendf ("))\n");
-           }
-         /* Update the flags of uid table.  */
-         imap4d_sync_flags (pclos.set[i]);
-       }
-
+      util_foreach_message (pclos.msgnumlist, _do_store, &pclos);
+    
       *ptext = "Completed";
     }
   
-  free (pclos.set);
+  mu_list_destroy (&pclos.msgnumlist);
   
   return rc;
 }
diff --git a/imap4d/sync.c b/imap4d/sync.c
index 1a5d0c5..e14b015 100644
--- a/imap4d/sync.c
+++ b/imap4d/sync.c
@@ -100,7 +100,7 @@ notify (void)
              if (nflags != attr_table[i-1])
                {
                  io_sendf ("* %lu FETCH FLAGS (",  (unsigned long) i);
-                 util_format_attribute_flags (iostream, nflags);
+                 mu_imap_format_flags (iostream, nflags);
                  io_sendf (")\n");
                  attr_table[i-1] = nflags;
                }
diff --git a/imap4d/tests/IDEF0955.at b/imap4d/tests/IDEF0955.at
index 63fd765..19fe99c 100644
--- a/imap4d/tests/IDEF0955.at
+++ b/imap4d/tests/IDEF0955.at
@@ -39,6 +39,11 @@ imap4d IMAP4D_OPTIONS < input | remove_uidvalidity | tr -d 
'\r'
 * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
 * OK [[PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft)]] Permanent 
flags
 1 OK [[READ-WRITE]] SELECT Completed
+* 1 FETCH (FLAGS (\Recent))
+* 2 FETCH (FLAGS (\Recent))
+* 3 FETCH (FLAGS (\Recent))
+* 4 FETCH (FLAGS (\Recent))
+* 5 FETCH (FLAGS (\Recent))
 2 OK FETCH Completed
 * 1 FETCH (UID 1 FLAGS (\Recent))
 * 2 FETCH (UID 2 FLAGS (\Recent))
diff --git a/imap4d/util.c b/imap4d/util.c
index 4165f42..a017cd8 100644
--- a/imap4d/util.c
+++ b/imap4d/util.c
@@ -17,10 +17,8 @@
 
 #include "imap4d.h"
 
-static int add2set (size_t **, int *, unsigned long);
-
 /* NOTE: Allocates Memory.  */
-/* Expand: ~ --> /home/user and to ~guest --> /home/guest.  */
+/* Expand: ~ --> /home/user, and ~guest --> /home/guest.  */
 char *
 util_tilde_expansion (const char *ref, const char *delim)
 {
@@ -32,29 +30,23 @@ util_tilde_expansion (const char *ref, const char *delim)
 char *
 util_getfullpath (const char *name, const char *delim)
 {
-  char *p = util_tilde_expansion (name, delim);
-  if (*p != delim[0])
+  char *exp = util_tilde_expansion (name, delim);
+  if (*exp != delim[0])
     {
-      char *s =
-       calloc (strlen (imap4d_homedir) + strlen (delim) + strlen (p) + 1, 1);
-      sprintf (s, "%s%s%s", imap4d_homedir, delim, p);
-      free (p);
-      p = s;
+      char *p, *s =
+       malloc (strlen (imap4d_homedir) + strlen (delim) + strlen (exp) + 1);
+      if (!s)
+       imap4d_bye (ERR_NO_MEM);
+      p = strcpy (s, imap4d_homedir);
+      p = mu_stpcpy (p, (char*) delim);
+      strcpy (p, exp);
+      free (exp);
+      exp = s;
     }
-  return mu_normalize_path (p);
-}
-
-static int
-comp_int (const void *a, const void *b)
-{
-  return *(int *) a - *(int *) b;
+  return mu_normalize_path (exp);
 }
-
-/* Parse the message set specification from S. Store message numbers
-   in SET, store number of element in the SET into the memory pointed to
-   by N.
-
-   A message set is defined as:
+
+/* A message set is defined as:
 
    set ::= sequence_num / (sequence_num ":" sequence_num) / (set "," set)
    sequence_num    ::= nz_number / "*"
@@ -65,204 +57,301 @@ comp_int (const void *a, const void *b)
    ;; the mailbox.
    nz_number       ::= digit_nz *digit
 
-   FIXME: The message sets like <,,,> or <:12> or <20:10> are not considered
-   an error */
-int
-util_msgset (char *s, size_t ** set, int *n, int isuid)
+   Non-existing sequence numbers are ignored, except when they form part
+   of a message range (sequence_num ":" sequence_num), in which case they
+   are treated as minimal or maximal sequence numbers (uids) available in
+   the mailbox depending on whether they appear to the left or to the right
+   of ":".
+*/
+
+/* Message set is a list of non-overlapping msgranges, in ascending
+   order.  No matter what command flavor is used, msg_beg and msg_end are
+   treated as sequence numbers (not UIDs). */
+struct msgrange
+{
+  size_t msg_beg;           /* beginning message number */
+  size_t msg_end;           /* ending message number */
+};
+
+/* Comparator function used to sort the message set list. */
+static int
+compare_msgrange (const void *a, const void *b)
+{
+  struct msgrange const *sa = a;
+  struct msgrange const *sb = b;
+  
+  if (sa->msg_beg < sb->msg_beg)
+    return -1;
+  if (sa->msg_beg > sb->msg_beg)
+    return 1;
+  if (sa->msg_end < sb->msg_end)
+    return -1;
+  if (sa->msg_end > sb->msg_end)
+    return 1;
+  return 0;
+}
+
+/* Comparator function used to locate a message in the list.  Second argument
+   (b) is a pointer to the message number. */
+static int
+compare_msgnum (const void *a, const void *b)
+{
+  struct msgrange const *range = a;
+  size_t msgno = *(size_t*)b;
+
+  if (range->msg_beg <= msgno && msgno <= range->msg_end)
+    return 0;
+  return 1;
+}
+
+/* This structure keeps parser state while parsing message set. */
+struct parse_msgnum_env
+{
+  char *s;               /* Current position in string */
+  size_t minval;         /* Min. sequence number or UID */
+  size_t maxval;         /* Max. sequence number or UID */
+  mu_list_t list;        /* List being built. */
+  int isuid:1;           /* True, if parsing an UID command. */
+  mu_mailbox_t mailbox;  /* Reference mailbox (can be NULL). */
+};
+
+/* Get a single message number/UID from env->s and store it into *PN.
+   Return 0 on success and error code on error.
+
+   Advance env->s to the point past the parsed message number.
+ */
+static int
+get_msgnum (struct parse_msgnum_env *env, size_t *pn)
 {
-  unsigned long val = 0;
-  unsigned long low = 0;
-  int done = 0;
-  int status = 0;
-  size_t max = 0;
-  size_t *tmp;
-  int i, j;
-  unsigned long invalid_uid = 0; /* For UID mode only: have we 
-                                   encountered an uid > max uid? */
+  size_t msgnum;
+  char *p;
   
-  status = mu_mailbox_messages_count (mbox, &max);
-  if (status != 0)
-    return status;
-  /* If it is a uid sequence, override max with the UID.  */
-  if (isuid)
+  errno = 0;
+  msgnum = strtoul (env->s, &p, 10);
+  if (msgnum == ULONG_MAX && errno == ERANGE)
+    return MU_ERR_PARSE;
+  env->s = p;
+  if (msgnum > env->maxval)
+    msgnum = env->maxval;
+  *pn = msgnum;
+  return 0;
+}
+
+/* Parse a single message range (A:B). Treat '*' as the largest number/UID
+   in use. */
+static int
+parse_msgrange (struct parse_msgnum_env *env)
+{
+  int rc;
+  struct msgrange msgrange, *mp;
+  
+  if (*env->s == '*')
     {
-      mu_message_t msg = NULL;
-      mu_mailbox_get_message (mbox, max, &msg);
-      mu_message_get_uid (msg, &max);
+      msgrange.msg_beg = env->maxval;
+      env->s++;
     }
+  else if ((rc = get_msgnum (env, &msgrange.msg_beg)))
+    return rc;
 
-  *n = 0;
-  *set = NULL;
-  while (*s)
+  if (*env->s == ':')
     {
-      switch (*s)
+      if (*++env->s == '*')
        {
-         /* isdigit */
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-         {
-           errno = 0;
-           val = strtoul (s, &s, 10);
-           if (val == ULONG_MAX && errno == ERANGE)
-             {
-               if (*set)
-                 free (*set);
-               *set = NULL;
-               *n = 0;
-               return EINVAL;
-             }
-           else if (val > max)
-             {
-               if (isuid)
-                 {
-                   invalid_uid = 1;
-                   continue;
-                 }
-               if (*set)
-                 free (*set);
-               *set = NULL;
-               *n = 0;
-               return EINVAL;
-             }
-           
-           if (low)
-             {
-               /* Reverse it. */
-               if (low > val)
-                 {
-                   long tmp = low;
-                   tmp -= 2;
-                   if (tmp < 0 || val == 0)
-                     {
-                       free (*set);
-                       *set = NULL;
-                       *n = 0;
-                       return EINVAL;
-                     }
-                   low = val;
-                   val = tmp;
-                 }
-               for (; low && low <= val; low++)
-                 {
-                   status = add2set (set, n, low);
-                   if (status != 0)
-                     return status;
-                 }
-               low = 0;
-             }
-           else
-             {
-               status = add2set (set, n, val);
-               if (status != 0)
-                 return status;
-             }
-           break;
-         }
-
-         /* A pair of numbers separated by a ':' character indicates a
-            contiguous set of mesages ranging from the first number to the
-            second:
-            3:5  --> 3 4 5
-          */
-       case ':':
-         low = val + 1;
-         s++;
-         break;
-
-         /* As a convenience. '*' is provided to refer to the highest
-            message number int the mailbox:
-            5:*  --> 5 6 7 8
-          */
-       case '*':
-         {
-           val = max;
-           s++;
-           status = add2set (set, n, val);
-           if (status != 0)
-             return status;
-         }
-         break;
-
-         /* IMAP also allows a set of noncontiguous numbers to be specified
-            with the ',' character:
-            1,3,5,7  --> 1 3 5 7
-          */
-       case ',':
-         s++;
-         break;
+         msgrange.msg_end = env->maxval;
+         ++env->s;
+       }
+      else if (*env->s == 0)
+       return MU_ERR_PARSE;
+      else if ((rc = get_msgnum (env, &msgrange.msg_end)))
+       return rc;
+    }
+  else
+    msgrange.msg_end = msgrange.msg_beg;
 
-       default:
-         done = 1;
-         if (*set)
-           free (*set);
-         *set = NULL;
-         *n = 0;
-         return EINVAL;
+  if (msgrange.msg_end < msgrange.msg_beg)
+    {
+      size_t tmp = msgrange.msg_end;
+      msgrange.msg_end = msgrange.msg_beg;
+      msgrange.msg_beg = tmp;
+    }
 
-       }                       /* switch */
+  if (env->isuid && env->mailbox)
+    {
+      int rc;
+
+      rc = mu_mailbox_translate (env->mailbox,
+                                MU_MAILBOX_UID_TO_MSGNO,
+                                msgrange.msg_beg, &msgrange.msg_beg);
+      if (rc == MU_ERR_NOENT)
+       msgrange.msg_beg = env->minval;
+      else if (rc)
+       return rc;
+      
+      rc = mu_mailbox_translate (env->mailbox,
+                                MU_MAILBOX_UID_TO_MSGNO,
+                                msgrange.msg_end, &msgrange.msg_end);
+      if (rc == MU_ERR_NOENT)
+       msgrange.msg_end = env->maxval;
+      else if (rc)
+       return rc;
+    }      
+
+  mp = malloc (sizeof (*mp));
+  if (!mp)
+    return ENOMEM;
+
+  *mp = msgrange;
+
+  rc = mu_list_append (env->list, mp);
+  if (rc)
+    free (mp);
+  return rc;
+}
 
-      if (done)
-       break;
-    }                          /* while */
+/* Parse message set specification S. ISUID indicates if the set is supposed
+   to contain UIDs (they will be translated to message sequence numbers).
+   MBX is a reference mailbox or NULL.
 
-  if (*n == 0)
-    return 0;
+   On success, return 0 and place the resulting set into *PLIST. On error,
+   return error code and point END to the position in the input string where
+   the parsing failed. */
+int
+util_parse_msgset (char *s, int isuid, mu_mailbox_t mbx,
+                  mu_list_t *plist, char **end)
+{
+  int rc;
+  struct parse_msgnum_env env;
+  size_t n;
   
-  /* For message sets in form X:Y where Y is a not-existing UID greater
-     than max UID, replace Y with the max UID in the mailbox */
-  if (*n == 1 && invalid_uid)
+  if (!s)
+    return EINVAL;
+  if (!*s)
+    return MU_ERR_PARSE;
+
+  memset (&env, 0, sizeof (env));
+  env.s = s;
+  if (mbox)
     {
-      val = max;
-      status = add2set (set, n, val);
-      if (status != 0)
-       return status;
+      size_t lastmsgno;      /* Max. sequence number. */
+
+      rc = mu_mailbox_messages_count (mbx, &lastmsgno);
+      if (rc == 0)
+       {
+         if (isuid)
+           {
+             rc = mu_mailbox_translate (mbox, MU_MAILBOX_MSGNO_TO_UID,
+                                        lastmsgno, &env.maxval);
+             if (rc == 0)
+               rc = mu_mailbox_translate (mbox, MU_MAILBOX_MSGNO_TO_UID,
+                                          1, &env.minval);
+           }
+         else
+           env.maxval = lastmsgno;
+       }
+      if (rc)
+       return rc;
     }
+  rc = mu_list_create (&env.list);
+  if (rc)
+    return rc;
+  mu_list_set_destroy_item (env.list, mu_list_free_item);
+  
+  env.isuid = isuid;
+  env.mailbox = mbx;
   
-  if (low)
+  while ((rc = parse_msgrange (&env)) == 0 && *env.s)
     {
-      /* Reverse it. */
-      if (low > val)
+      if (*env.s != ',' || *++env.s == 0)
        {
-         long tmp = low;
-         tmp -= 2;
-         if (tmp < 0 || val == 0)
-           {
-             free (*set);
-             *set = NULL;
-             *n = 0;
-             return EINVAL;
-           }
-         low = val;
-         val = tmp;
+         rc = MU_ERR_PARSE;
+         break;
        }
-      for (; low && low <= val; low++)
+    }
+
+  if (end)
+    *end = env.s;
+  if (rc)
+    {
+      mu_list_destroy (&env.list);
+      return rc;
+    }
+
+  mu_list_count (env.list, &n);
+  if (n > 1)
+    {
+      mu_iterator_t itr;
+      struct msgrange *last = NULL;
+
+      /* Sort the list and coalesce overlapping message ranges. */
+      mu_list_sort (env.list, compare_msgrange);
+
+      mu_list_get_iterator (env.list, &itr);
+      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+          mu_iterator_next (itr))
        {
-         status = add2set (set, n, low);
-         if (status != 0)
-           return status;
+         struct msgrange *msgrange;
+
+         mu_iterator_current (itr, (void**)&msgrange);
+         if (last)
+           {
+             if (last->msg_beg <= msgrange->msg_beg &&
+                 msgrange->msg_beg <= last->msg_end)
+               {
+                 if (msgrange->msg_end > last->msg_end)
+                   last->msg_end = msgrange->msg_end;
+                 mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
+                 continue;
+               }
+                 
+           }
+         last = msgrange;
        }
+      mu_iterator_destroy (&itr);
     }
 
-  /* Sort the resulting message set */
-  qsort (*set, *n, sizeof (**set), comp_int);
+  if (rc == 0)
+    {
+      mu_list_set_comparator (env.list, compare_msgnum);
+      *plist = env.list;
+    }
+  else
+    mu_list_destroy (&env.list);
+  return rc;
+}
+
+struct action_closure
+{
+  imap4d_message_action_t action;
+  void *data;
+};
+
+static int
+procrange (void *item, void *data)
+{
+  struct msgrange *mp = item;
+  struct action_closure *clos = data;
+  size_t i;
 
-  /* Remove duplicates. tmp serves to avoid extra dereferences */
-  tmp = *set;
-  for (i = 0, j = 1; i < *n; i++)
-    if (tmp[j - 1] != tmp[i])
-      tmp[j++] = tmp[i];
-  *n = j;
+  for (i = mp->msg_beg; i <= mp->msg_end; i++)
+    {
+      int rc = clos->action (i, clos->data);
+      if (rc)
+       return rc;
+    }
   return 0;
 }
 
+/* Apply ACTION to each message number from LIST. */
+int
+util_foreach_message (mu_list_t list, imap4d_message_action_t action,
+                     void *data)
+{
+  struct action_closure clos;
+  clos.action = action;
+  clos.data = data;
+  return mu_list_foreach (list, procrange, &clos);
+}
+
 int
 util_do_command (imap4d_tokbuf_t tok)
 {
@@ -317,26 +406,9 @@ util_getcommand (char *cmd, struct imap4d_command 
command_table[])
   return NULL;
 }
 
-static int
-add2set (size_t ** set, int *n, unsigned long val)
-{
-  size_t *tmp;
-  tmp = realloc (*set, (*n + 1) * sizeof (**set));
-  if (tmp == NULL)
-    {
-      if (*set)
-       free (*set);
-      *n = 0;
-      return ENOMEM;
-    }
-  *set = tmp;
-  (*set)[*n] = val;
-  (*n)++;
-  return 0;
-}
-
 static void
-adjust_tm (struct tm *tm, struct mu_timezone *tz, enum datetime_parse_mode 
flag)
+adjust_tm (struct tm *tm, struct mu_timezone *tz,
+          enum datetime_parse_mode flag)
 {
   switch (flag)
     {
@@ -428,76 +500,13 @@ util_strcasestr (const char *haystack, const char *needle)
   return mu_c_strcasestr (haystack, needle);
 }
 
-struct
-{
-  char *name;
-  int flag;
-}
-_imap4d_attrlist[] =
-{
-  { "\\Answered", MU_ATTRIBUTE_ANSWERED },
-  { "\\Flagged", MU_ATTRIBUTE_FLAGGED },
-  { "\\Deleted", MU_ATTRIBUTE_DELETED },
-  { "\\Draft", MU_ATTRIBUTE_DRAFT },
-  { "\\Seen", MU_ATTRIBUTE_SEEN|MU_ATTRIBUTE_READ },
-};
-
-#define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0])
-
-int _imap4d_nattr = NATTR;
-
-int
-util_attribute_to_type (const char *item, int *type)
-{
-  int i;
-
-  if (mu_c_strcasecmp (item, "\\Recent") == 0)
-    {
-      *type = MU_ATTRIBUTE_RECENT;
-      return 0;
-    }
-  
-  for (i = 0; i < _imap4d_nattr; i++)
-    if (mu_c_strcasecmp (item, _imap4d_attrlist[i].name) == 0)
-      {
-       *type = _imap4d_attrlist[i].flag;
-       return 0;
-      }
-  return 1;
-}
-
-int
-util_format_attribute_flags (mu_stream_t str, int flags)
-{
-  int i;
-  int delim = 0;
-  
-  for (i = 0; i < _imap4d_nattr; i++)
-    if (flags & _imap4d_attrlist[i].flag)
-      {
-       if (delim)
-         mu_stream_printf (str, " ");
-       mu_stream_printf (str, "%s", _imap4d_attrlist[i].name);
-       delim = 1;
-      }
-
-  if (MU_ATTRIBUTE_IS_UNSEEN (flags))
-    {
-      if (delim)
-       mu_stream_printf (str, " ");
-      mu_stream_printf (str, "\\Recent");
-    }
-  
-  return 0;
-}
-
 void
 util_print_flags (mu_attribute_t attr)
 {
   int flags = 0;
 
   mu_attribute_get_flags (attr, &flags);
-  util_format_attribute_flags (iostream, flags);
+  mu_imap_format_flags (iostream, flags);
 }
 
 int
@@ -506,7 +515,7 @@ util_attribute_matches_flag (mu_attribute_t attr, const 
char *item)
   int flags = 0, mask = 0;
 
   mu_attribute_get_flags (attr, &flags);
-  util_attribute_to_type (item, &mask);
+  mu_imap_flag_to_attribute (item, &mask);
   if (mask == MU_ATTRIBUTE_RECENT)
     return MU_ATTRIBUTE_IS_UNSEEN (flags);
 
diff --git a/include/mailutils/list.h b/include/mailutils/list.h
index 7934aa2..184c7ec 100644
--- a/include/mailutils/list.h
+++ b/include/mailutils/list.h
@@ -141,13 +141,13 @@ int mu_list_get_iterator (mu_list_t _list, mu_iterator_t 
*_pitr);
 
   /* A general-purpose iteration function.  When called, _item points to
      the item currently visited and _data points to call-specific data. */
-typedef int mu_list_action_t (void *_item, void *_data);
+typedef int (*mu_list_action_t) (void *_item, void *_data);
 
   /* Execute _action for each element in _list.  Use _data as the call-specific
      data. */
-int mu_list_foreach (mu_list_t _list, mu_list_action_t *_action, void *_data);
+int mu_list_foreach (mu_list_t _list, mu_list_action_t _action, void *_data);
   /* A historical alias to the above. */
-int mu_list_do (mu_list_t, mu_list_action_t *, void *) MU_DEPRECATED;
+int mu_list_do (mu_list_t, mu_list_action_t, void *) MU_DEPRECATED;
 
   /* ************************************************* */
   /* Functions for combining two lists.                */
diff --git a/libmailutils/list/foreach.c b/libmailutils/list/foreach.c
index 131f587..8c0d2a3 100644
--- a/libmailutils/list/foreach.c
+++ b/libmailutils/list/foreach.c
@@ -24,7 +24,7 @@
 #include <mailutils/errno.h>
 
 int
-mu_list_foreach (mu_list_t list, mu_list_action_t *action, void *cbdata)
+mu_list_foreach (mu_list_t list, mu_list_action_t action, void *cbdata)
 {
   mu_iterator_t itr;
   int status = 0;
@@ -49,7 +49,7 @@ mu_list_foreach (mu_list_t list, mu_list_action_t *action, 
void *cbdata)
 /* Retained for compatibility with previous versions.
    In the future it will be removed, or changed to a define or weak alias. */
 int
-mu_list_do (mu_list_t list, mu_list_action_t *action, void *cbdata)
+mu_list_do (mu_list_t list, mu_list_action_t action, void *cbdata)
 {
   return mu_list_foreach (list, action, cbdata);
 }


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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