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-532-gfa42589


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-532-gfa42589
Date: Thu, 15 Dec 2011 16:47:43 +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=fa42589cef090379bda4ea4e0838474520f9f4f6

The branch, master has been updated
       via  fa42589cef090379bda4ea4e0838474520f9f4f6 (commit)
      from  0e8ae1c37611759936ce66eefff2ef392c3b8de0 (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 fa42589cef090379bda4ea4e0838474520f9f4f6
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Dec 15 10:20:07 2011 +0200

    imap client: implement folder API.
    
    * libmailutils/list/listlist.c (mu_list_append_list): Do nothing if the
    source list is empty.
    
    * include/mailutils/sys/imap.h (_mu_imap_url_init)
    (_mu_imaps_url_init): New protos.
    * libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Restore url.c
    * libproto/imap/mbox.c: Deleted
    * libproto/imap/url.c: Rewrite.
    * libproto/imap/folder.c: Rewrite from scratch.
    * configure.ac: Build libproto/imap/tests/Makefile
    * include/mailutils/imap.h (mu_imap_session_state)
    (mu_imap_iserror, mu_imap_clearerr)
    (mu_imap_login_secret): New protos.
    * include/mailutils/sys/imap.h (_mu_imap_list_element_is_nil): New proto.
    
    * libmailutils/mailbox/folder.c (mu_folder_list): Pass
    MU_FOLDER_ATTRIBUTE_ALL.
    * libproto/imap/fake-folder.c: Remove.
    * libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Remove fake-folder.c
    Add url.c and folder.c
    * libproto/imap/create.c (mu_imap_session_state)
    (mu_imap_iserror, mu_imap_clearerr): New functions.
    * libproto/imap/delete.c: Check input parameters.
    
    * libproto/imap/fetch.c: Use _mu_imap_list_element_is_nil to check for
    empty lists.
    * libproto/imap/genlist.c: Likewise.
    * libproto/imap/rename.c: Likewise.
    * libproto/imap/subscribe.c: Likewise.
    * libproto/imap/unsubscribe.c: Likewise.
    
    * libproto/imap/resplist.c: Treat NIL and () equally.
    * libproto/imap/login.c (mu_imap_login_secret): New function.
    
    * mu/imap.c: Fix a typo.

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

Summary of changes:
 configure.ac                              |    1 +
 include/mailutils/imap.h                  |    6 +
 include/mailutils/sys/imap.h              |   15 +-
 libmailutils/list/listlist.c              |    4 +-
 libmailutils/mailbox/folder.c             |    3 +-
 libproto/imap/Makefile.am                 |   13 +-
 libproto/imap/create.c                    |   27 +
 libproto/imap/delete.c                    |    3 +
 libproto/imap/fake-folder.c               |    7 -
 libproto/imap/fetch.c                     |   25 +-
 libproto/imap/folder.c                    | 2916 +++++------------------------
 libproto/imap/genlist.c                   |    9 +-
 libproto/imap/login.c                     |   10 +
 libproto/imap/mbox.c                      | 2142 ---------------------
 libproto/imap/rename.c                    |    3 +
 libproto/imap/resplist.c                  |   18 +
 libproto/imap/subscribe.c                 |    4 +
 libproto/imap/tests/.gitignore            |    1 +
 libproto/{mbox => imap/tests}/Makefile.am |   20 +-
 libproto/imap/tests/imapfolder.c          |  242 +++
 libproto/imap/unsubscribe.c               |    4 +
 libproto/imap/url.c                       |   12 +-
 mu/imap.c                                 |    4 +-
 23 files changed, 819 insertions(+), 4670 deletions(-)
 delete mode 100644 libproto/imap/fake-folder.c
 delete mode 100644 libproto/imap/mbox.c
 create mode 100644 libproto/imap/tests/.gitignore
 copy libproto/{mbox => imap/tests}/Makefile.am (77%)
 create mode 100644 libproto/imap/tests/imapfolder.c

diff --git a/configure.ac b/configure.ac
index dfacf09..4edf484 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1460,6 +1460,7 @@ AC_CONFIG_FILES([
  libproto/pop/Makefile
  libproto/nntp/Makefile
  libproto/imap/Makefile
+ libproto/imap/tests/Makefile
  libmu_compat/Makefile
  maidag/Makefile
  mail/Makefile
diff --git a/include/mailutils/imap.h b/include/mailutils/imap.h
index 88a7207..ab20716 100644
--- a/include/mailutils/imap.h
+++ b/include/mailutils/imap.h
@@ -47,6 +47,10 @@ void mu_imap_destroy (mu_imap_t *pimap);
 int mu_imap_connect (mu_imap_t imap);
 int mu_imap_disconnect (mu_imap_t imap);
 
+int mu_imap_session_state (mu_imap_t imap);
+int mu_imap_iserror (mu_imap_t imap);
+void mu_imap_clearerr (mu_imap_t imap);
+  
 int mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter);
 int mu_imap_capability_test (mu_imap_t imap, const char *name,
                             const char **pret);
@@ -54,6 +58,8 @@ int mu_imap_capability_test (mu_imap_t imap, const char *name,
 int mu_imap_starttls (mu_imap_t imap);
   
 int mu_imap_login (mu_imap_t imap, const char *user, const char *pass);
+int mu_imap_login_secret (mu_imap_t imap, const char *user,
+                         mu_secret_t secret);
 int mu_imap_logout (mu_imap_t imap);
 
 int mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc);
diff --git a/include/mailutils/sys/imap.h b/include/mailutils/sys/imap.h
index 0063a27..68bdf06 100644
--- a/include/mailutils/sys/imap.h
+++ b/include/mailutils/sys/imap.h
@@ -215,6 +215,8 @@ int _mu_imap_response (mu_imap_t imap, 
mu_imap_response_action_t fun,
   
 int _mu_imap_list_element_is_string (struct imap_list_element *elt,
                                     const char *str);
+int _mu_imap_list_element_is_nil (struct imap_list_element *elt);
+
 int _mu_imap_list_nth_element_is_string (mu_list_t list, size_t n,
                                         const char *str);
   
@@ -225,7 +227,18 @@ struct imap_list_element *_mu_imap_list_at (mu_list_t 
list, int idx);
 int _mu_imap_parse_fetch_response (mu_list_t resp, mu_list_t *result_list);
 
 void _mu_close_handler (mu_imap_t imap);
-  
+
+/* ----------------------------- */
+/* URL Auxiliaries               */
+/* ----------------------------- */
+int _mu_imap_url_init (mu_url_t url);
+int _mu_imaps_url_init (mu_url_t url);
+
+/* ----------------------------- */
+/* Folder interface              */
+/* ----------------------------- */
+
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/libmailutils/list/listlist.c b/libmailutils/list/listlist.c
index 38bd588..cfd5eaa 100644
--- a/libmailutils/list/listlist.c
+++ b/libmailutils/list/listlist.c
@@ -99,7 +99,9 @@ mu_list_insert_list (mu_list_t list, void *item, mu_list_t 
new_list,
 void
 mu_list_append_list (mu_list_t list, mu_list_t new_list)
 {
-  if (list->count == 0)
+  if (new_list->count == 0)
+    return;
+  else if (list->count == 0)
     {
       list->head = new_list->head;
       list->head.next->prev = list->head.prev->next = &list->head;
diff --git a/libmailutils/mailbox/folder.c b/libmailutils/mailbox/folder.c
index 86ad0a5..3314fcd 100644
--- a/libmailutils/mailbox/folder.c
+++ b/libmailutils/mailbox/folder.c
@@ -368,7 +368,8 @@ mu_folder_list (mu_folder_t folder, const char *dirname, 
void *pattern,
                size_t max_level,
                mu_list_t *pflist)
 {
-  return mu_folder_enumerate (folder, dirname, pattern, 0, max_level,
+  return mu_folder_enumerate (folder, dirname, pattern,
+                             MU_FOLDER_ATTRIBUTE_ALL, max_level,
                              pflist, NULL, NULL);
 }
 
diff --git a/libproto/imap/Makefile.am b/libproto/imap/Makefile.am
index 82c7c87..181ac35 100644
--- a/libproto/imap/Makefile.am
+++ b/libproto/imap/Makefile.am
@@ -21,16 +21,14 @@ lib_LTLIBRARIES = libmu_imap.la
 libmu_imap_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
 libmu_imap_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@ 
 
-# FIXME: Put these back when ready
+SUBDIRS = . tests
 
-#  folder.c\
-#  mbox.c\
-#  url.c
+# FIXME: Put this back when ready
+#  mbox.c
 libmu_imap_la_SOURCES = \
  appmsg.c\
  appstr.c\
  appstrsiz.c\
- fake-folder.c\
  fetch.c\
  gencom.c\
  genlist.c\
@@ -68,5 +66,6 @@ libmu_imap_la_SOURCES = \
  tag.c\
  trace.c\
  unselect.c\
- unsubscribe.c
-
+ unsubscribe.c\
+ folder.c\
+ url.c
diff --git a/libproto/imap/create.c b/libproto/imap/create.c
index 9ae92eb..5aebcae 100644
--- a/libproto/imap/create.c
+++ b/libproto/imap/create.c
@@ -64,3 +64,30 @@ _mu_imap_init (mu_imap_t imap)
   imap->session_state = MU_IMAP_SESSION_INIT;
   return 0;
 }
+
+int
+mu_imap_session_state (mu_imap_t imap)
+{
+  if (!imap)
+    return -1;
+  return imap->session_state;
+}
+
+int
+mu_imap_iserror (mu_imap_t imap)
+{
+  if (!imap)
+    return -1;
+  return imap->client_state == MU_IMAP_CLIENT_ERROR;
+}
+
+void
+mu_imap_clearerr (mu_imap_t imap)
+{
+  if (imap)
+    {
+      imap->client_state = MU_IMAP_CLIENT_READY;
+      if (imap->io)
+       mu_imapio_clearerr (imap->io);
+    }
+}
diff --git a/libproto/imap/delete.c b/libproto/imap/delete.c
index 0818c4b..5a605d0 100644
--- a/libproto/imap/delete.c
+++ b/libproto/imap/delete.c
@@ -31,6 +31,9 @@ mu_imap_delete (mu_imap_t imap, const char *mailbox)
   char const *argv[2];
   static struct imap_command com;
 
+  if (!mailbox)
+    return EINVAL;
+  
   argv[0] = "DELETE";
   argv[1] = mailbox;
 
diff --git a/libproto/imap/fake-folder.c b/libproto/imap/fake-folder.c
deleted file mode 100644
index fb59c49..0000000
--- a/libproto/imap/fake-folder.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <mailutils/mailutils.h>
-
-mu_record_t mu_imap_record = NULL;
-mu_record_t mu_imaps_record = NULL;
diff --git a/libproto/imap/fetch.c b/libproto/imap/fetch.c
index f32ed3a..b1994ae 100644
--- a/libproto/imap/fetch.c
+++ b/libproto/imap/fetch.c
@@ -354,11 +354,11 @@ static int
 elt_to_string (struct imap_list_element *elt, char **pstr)
 {
   char *p;
-  
-  if (elt->type != imap_eltype_string)
-    return EINVAL;
-  if (mu_c_strcasecmp (elt->v.string, "NIL") == 0)
+
+  if (_mu_imap_list_element_is_nil (elt))
     p = NULL;
+  else if (elt->type != imap_eltype_string)
+    return EINVAL;
   else
     {
       p = strdup (elt->v.string);
@@ -386,13 +386,13 @@ _fill_subaddr (void *item, void *data)
     return 0;
   
   arg = _mu_imap_list_at (elt->v.list, 0);
-  if (arg && arg->type == imap_eltype_string && strcmp (arg->v.string, "NIL"))
+  if (arg && arg->type == imap_eltype_string)
     personal = arg->v.string;
   arg = _mu_imap_list_at (elt->v.list, 2);
-  if (arg && arg->type == imap_eltype_string && strcmp (arg->v.string, "NIL"))
+  if (arg && arg->type == imap_eltype_string)
     local = arg->v.string;
   arg = _mu_imap_list_at (elt->v.list, 3);
-  if (arg && arg->type == imap_eltype_string && strcmp (arg->v.string, "NIL"))
+  if (arg && arg->type == imap_eltype_string)
     domain = arg->v.string;
 
   if (domain && local)
@@ -414,13 +414,10 @@ _fill_subaddr (void *item, void *data)
 static int
 elt_to_address (struct imap_list_element *elt, mu_address_t *paddr)
 {
-  if (elt->type != imap_eltype_list)
-    {
-      if (mu_c_strcasecmp (elt->v.string, "NIL") == 0)
-       *paddr = NULL;
-      else
-       return EINVAL;
-    }
+  if (_mu_imap_list_element_is_nil (elt))
+    *paddr = NULL;
+  else if (elt->type != imap_eltype_list)
+    return EINVAL;
   else
     {
       struct addr_env addr_env;
diff --git a/libproto/imap/folder.c b/libproto/imap/folder.c
index 828f2a2..1bf637f 100644
--- a/libproto/imap/folder.c
+++ b/libproto/imap/folder.c
@@ -1,6 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2009,
-   2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2011 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -20,352 +19,395 @@
 # include <config.h>
 #endif
 
-#ifdef ENABLE_IMAP
-
 #include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
 #include <string.h>
-#include <assert.h>
-#include <fnmatch.h>
-
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#include <mailutils/sys/imap.h>
-#include <mailutils/sys/url.h>
+#include <netinet/in.h>
 
-#include <mailutils/auth.h>
-#include <mailutils/attribute.h>
+#include <mailutils/imap.h>
+#include <mailutils/diag.h>
 #include <mailutils/debug.h>
 #include <mailutils/error.h>
 #include <mailutils/errno.h>
-#include <mailutils/header.h>
-#include <mailutils/observer.h>
-#include <mailutils/stream.h>
-#include <mailutils/iterator.h>
-#include <mailutils/argcv.h>
-#include <mailutils/tls.h>
 #include <mailutils/nls.h>
+#include <mailutils/tls.h>
+#include <mailutils/url.h>
+#include <mailutils/list.h>
 #include <mailutils/secret.h>
-#include <mailutils/util.h>
-#include <mailutils/cctype.h>
 #include <mailutils/cstr.h>
+#include <mailutils/sockaddr.h>
+#include <mailutils/wordsplit.h>
+#include <mailutils/sys/imap.h>
+#include <mailutils/sys/folder.h>
 
-/* For dbg purposes set to one to see different level of traffic.  */
-/* Print to stderr the command sent to the IMAP server.  */
-#define DEBUG_SHOW_COMMAND 0
-/* Print to stderr the responses received from the IMAP server.  */
-#define DEBUG_SHOW_RESPONSE 0
-/* Print to stderr the literal/quoted string received from the IMAP server.  */
-#define DEBUG_SHOW_DATA 0
+/* Placeholders. */
+#define _mu_imap_mailbox_init NULL
+#define _mu_imaps_mailbox_init NULL
 
-/* Variable use for the registrar.  */
-static struct _mu_record _imap_record =
+
+static void
+_mu_imap_folder_destroy (mu_folder_t folder)
 {
-  MU_IMAP_PRIO,
-  MU_IMAP_SCHEME,
-  MU_RECORD_DEFAULT,
-  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
-  MU_URL_HOST,
-  _url_imap_init,     /* url entry.  */
-  _mailbox_imap_init, /* Mailbox entry.  */
-  NULL,               /* Mailer entry.  */
-  _folder_imap_init,  /* Folder entry.  */
-  NULL, /* No need for a back pointer.  */
-  NULL, /* _is_scheme method.  */
-  NULL, /* _get_url method.  */
-  NULL, /* _get_mailbox method.  */
-  NULL, /* _get_mailer method.  */
-  NULL  /* _get_folder method.  */
-};
+  mu_imap_t imap = folder->data;
+  if (imap)
+    {
+      /*
+       mu_imap_logout (imap);
+       mu_imap_disconnect (imap);
+      */
+      mu_imap_destroy (&imap);
+      folder->data = imap;
+    }
+}
+
+/* Imap callbacks */
+static void
+_mu_folder_preauth_callback (void *data, int code, size_t sdat, void *pdat)
+{
+  /*  mu_folder_t folder = data;*/
+  const char *text = pdat;
+  mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_TRACE1,
+           (_("IMAP server opened in preauth mode: %s"), text));
+}
 
-/* We export this variable: url parsing and the initialisation of the mailbox,
-   via the register entry/record.  */
-mu_record_t mu_imap_record = &_imap_record;
+static void
+_mu_folder_bye_callback (void *data, int code, size_t sdat, void *pdat)
+{
+  mu_folder_t folder = data;
+  const char *text = pdat;
+  mu_imap_t imap = folder->data;
+  mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_TRACE1,
+           (_("IMAP server closing connection: %s"), text));
+  /*FIXME:  mu_imap_disconnect (imap);*/
+}
 
-#ifdef WITH_TLS
-static struct _mu_record _imaps_record =
+static void
+_mu_folder_bad_callback (void *data, int code, size_t sdat, void *pdat)
 {
-  MU_IMAP_PRIO,
-  MU_IMAPS_SCHEME,
-  MU_RECORD_DEFAULT,
-  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
-  MU_URL_HOST,
-  _url_imaps_init,     /* url entry.  */
-  _mailbox_imaps_init, /* Mailbox entry.  */
-  NULL,                /* Mailer entry.  */
-  _folder_imap_init,   /* Folder entry.  */
-  NULL, /* No need for a back pointer.  */
-  NULL, /* _is_scheme method.  */
-  NULL, /* _get_url method.  */
-  NULL, /* _get_mailbox method.  */
-  NULL, /* _get_mailer method.  */
-  NULL  /* _get_folder method.  */
-};
-mu_record_t mu_imaps_record = &_imaps_record;
-#else
-mu_record_t mu_imaps_record = NULL;
-#endif /* WITH_TLS */
+  /*  mu_folder_t folder = data;*/
+  const char *text = pdat;
 
-#ifndef HAVE_STRTOK_R
-char *strtok_r                      (char *, const char *, char **);
+  mu_error (_("IMAP server complains: %s"), text);
+  mu_error (_("This probably indicates a bug in Mailutils client code."));
+  mu_error (_("Please, report that to <%s>."), PACKAGE_BUGREPORT);
+}
+#if 0
+static void
+_mu_folder_fetch_callback (void *data, int code, size_t sdat, void *pdat)
+{
+  mu_folder_t folder = data;
+}
 #endif
+
+/* Set up an IMAP(S) connection for this folder */
+static int
+_mu_imap_folder_open (mu_folder_t folder, int flags)
+{
+  int rc;
+  mu_imap_t imap = folder->data;
+  struct mu_sockaddr *sa;
+  struct mu_sockaddr_hints hints;
+  char const *s;
+  int tls;
+  mu_stream_t transport;
 
-/* Concrete mu_folder_t IMAP implementation.  */
-static int  folder_imap_open        (mu_folder_t, int);
-static int  folder_imap_close       (mu_folder_t);
-static void folder_imap_destroy     (mu_folder_t);
-static int  folder_imap_delete      (mu_folder_t, const char *);
-static int  folder_imap_list        (mu_folder_t, const char *, void *,
-                                    int, size_t,
-                                    mu_list_t,
-                                    mu_folder_enumerate_fp efp, void *edp);
-static int  folder_imap_lsub        (mu_folder_t, const char *, const char *,
-                                    mu_list_t);
-static int  folder_imap_rename      (mu_folder_t, const char *,
-                                    const char *);
-static int  folder_imap_subscribe   (mu_folder_t, const char *);
-static int  folder_imap_unsubscribe (mu_folder_t, const char *);
-static int  folder_imap_get_authority (mu_folder_t, mu_authority_t *);
+  /* FIXME: This monitor business is suspicious */
+  mu_monitor_wrlock (folder->monitor);
+  rc = mu_imap_session_state (imap);
+  mu_monitor_unlock (folder->monitor);
+  if (rc != MU_IMAP_SESSION_INIT)
+    return 0;
 
-/* FETCH  */
-static int  imap_fetch              (f_imap_t);
-static int  imap_rfc822             (f_imap_t, char **);
-static int  imap_rfc822_size        (f_imap_t, char **);
-static int  imap_rfc822_header      (f_imap_t, char **);
-static int  imap_rfc822_text        (f_imap_t, char **);
-static int  imap_fetch_flags        (f_imap_t, char **);
-static int  imap_permanentflags     (f_imap_t, char **);
-static int  imap_flags              (char **, int *);
-static int  imap_bodystructure      (f_imap_t, char **);
-static int  imap_body               (f_imap_t, char **);
-static int  imap_internaldate       (f_imap_t, char **);
+  mu_url_sget_scheme (folder->url, &s);
+  tls = strcmp (s, "imaps") == 0;
 
-static int  imap_uid                (f_imap_t, char **);
-static int  imap_status             (f_imap_t);
-static int  imap_expunge            (f_imap_t, unsigned int);
-static int  imap_search             (f_imap_t);
+  memset (&hints, 0, sizeof (hints));
+  hints.flags = MU_AH_DETECT_FAMILY;
+  hints.port = tls ? MU_IMAP_DEFAULT_SSL_PORT : MU_IMAP_DEFAULT_PORT;
+  hints.protocol = IPPROTO_TCP;
+  hints.socktype = SOCK_STREAM;
 
-/* String.  */
-static int  imap_literal_string     (f_imap_t, char **);
-static int  imap_string             (f_imap_t, char **);
-static int  imap_quoted_string      (f_imap_t, char **);
-static int  imap_mailbox_name_match (const char* pattern, const char* mailbox);
+  rc = mu_sockaddr_from_url (&sa, folder->url, &hints);
+  if (rc)
+    {
+      s = mu_url_to_string (folder->url);
+      mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+               (_("cannot create sockaddr from URL %s: %s"),
+                s, mu_strerror (rc)));
+      return rc;
+    }
 
-static int  imap_token              (char *, size_t, char **);
+  rc = mu_tcp_stream_create_from_sa (&transport, sa, NULL, 0);
+  if (rc)
+    {
+      s = mu_url_to_string (folder->url);
+      mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+               (_("cannot create stream from URL %s: %s"),
+                s, mu_strerror (rc)));
+      mu_sockaddr_free (sa);
+      return rc;
+    }
+  
+#ifdef WITH_TLS
+  if (tls)
+    {
+      mu_stream_t tlsstream;
+             
+      rc = mu_tls_client_stream_create (&tlsstream, transport, transport, 0);
+      mu_stream_unref (transport);
+      if (rc)
+       {
+         mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+                   (_("cannot create TLS stream: %s"),
+                    mu_strerror (rc)));
+         return rc;
+       }
+      transport = tlsstream;
+    }
+#endif
 
-/* Capability */
-static int  parse_capa              (f_imap_t f_imap, char *str);
-static int  read_capa               (f_imap_t f_imap, int force);
-static int  check_capa              (f_imap_t f_imap, char *capa);
+  mu_imap_set_carrier (imap, transport);
+
+  if (mu_debug_level_p (MU_DEBCAT_FOLDER, MU_DEBUG_PROT) ||
+      mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_PROT))
+    mu_imap_trace (imap, MU_IMAP_TRACE_SET);
+  if (mu_debug_level_p (MU_DEBCAT_FOLDER, MU_DEBUG_TRACE6) ||
+      mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE6))
+    mu_imap_trace_mask (imap, MU_IMAP_TRACE_SET, MU_XSCRIPT_SECURE);
+  if (mu_debug_level_p (MU_DEBCAT_FOLDER, MU_DEBUG_TRACE7) ||
+      mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE7))
+    mu_imap_trace_mask (imap, MU_IMAP_TRACE_SET, MU_XSCRIPT_PAYLOAD);
+
+  /* Set callbacks */
+  mu_imap_register_callback_function (imap, MU_IMAP_CB_PREAUTH,
+                                     _mu_folder_preauth_callback,
+                                     folder);
+  mu_imap_register_callback_function (imap, MU_IMAP_CB_BYE,
+                                     _mu_folder_bye_callback,
+                                     folder);
+  mu_imap_register_callback_function (imap, MU_IMAP_CB_BAD,
+                                     _mu_folder_bad_callback,
+                                     folder);
+#if 0
+  mu_imap_register_callback_function (imap, MU_IMAP_CB_FETCH,
+                                     _mu_folder_fetch_callback,
+                                     folder);
+#endif
+  rc = mu_imap_connect (imap);
+  if (rc)
+    {
+      s = mu_url_to_string (folder->url);
+      mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+               (_("failed to connect to %s: %s"),
+                s, mu_strerror (rc)));
+      if (mu_imap_strerror (imap, &s))
+       mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+                 (_("server response: %s"), s));
+      mu_imap_destroy (&imap);
+      return rc;
+    }
 
+  if (mu_imap_session_state (imap) == MU_IMAP_SESSION_NONAUTH)
+    {
+      rc = mu_authority_authenticate (folder->authority);
+      if (rc)
+       {
+         mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+                   (_("IMAP authentication: %s"),
+                    mu_strerror (rc)));
+         mu_folder_close (folder);
+       }
+    }
+  
+  return rc;
+}
 
-/* Authentication methods */
-
-typedef int (*auth_method_t) (mu_authority_t);
-
-/* Simple User/pass authentication for imap.  */
+/* Close existing connection */
 static int
-authenticate_imap_login (mu_authority_t auth)
+_mu_imap_folder_close (mu_folder_t folder)
 {
-  mu_folder_t folder = mu_authority_get_owner (auth);
-  f_imap_t f_imap = folder->data;
-  mu_ticket_t ticket;
-  int status = 0;
+  mu_imap_t imap = folder->data;
 
-  if (check_capa (f_imap, "LOGINDISABLED") == 0)
+  if (mu_imap_session_state (imap) > MU_IMAP_SESSION_INIT)
     {
-      MU_DEBUG (folder->debug, MU_DEBUG_TRACE, "LOGIN command disabled\n");
-      return ENOSYS;
+      mu_imap_clearerr (imap);
+      mu_imap_logout (imap);
+      mu_imap_disconnect (imap);
     }
   
-  switch (f_imap->state)
-    {
-    case IMAP_AUTH:
-      {
-       /* Grab the User and Passwd information.  */
-       mu_authority_get_ticket (auth, &ticket);
-       if (f_imap->user)
-         free (f_imap->user);
-       /* Was it in the URL?  */
-       status = mu_url_aget_user (folder->url, &f_imap->user);
-        if (status == MU_ERR_NOENT)
-         status = mu_ticket_get_cred (ticket, folder->url,
-                                      "Imap User: ", &f_imap->user, NULL);
-       if (status == MU_ERR_NOENT || f_imap->user == NULL)
-         return MU_ERR_NOUSERNAME;
-       else if (status)
-         return status;
-
-       status = mu_url_get_secret (folder->url, &f_imap->secret);
-        if (status == MU_ERR_NOENT)
-         status = mu_ticket_get_cred (ticket, folder->url,
-                                      "Imap Passwd: ",
-                                      NULL, &f_imap->secret);
-       
-       if (status == MU_ERR_NOENT || !f_imap->secret)
-         /* FIXME: Is this always right? The user might legitimately have
-            no password */
-         return MU_ERR_NOPASSWORD;
-       else if (status)
-         return status;
-       
-       status = imap_writeline (f_imap, "g%lu LOGIN \"%s\" \"%s\"\r\n",
-                                (unsigned long) f_imap->seq, f_imap->user,
-                                mu_secret_password (f_imap->secret));
-       mu_secret_password_unref (f_imap->secret);
-       mu_secret_unref (f_imap->secret);
-       f_imap->secret = NULL;
-       CHECK_ERROR_CLOSE (folder, f_imap, status);
-       MU_DEBUG2 (folder->debug, MU_DEBUG_TRACE, "g%lu LOGIN %s *\n",
-                  (unsigned long) f_imap->seq, f_imap->user);
-       f_imap->seq++;
-       free (f_imap->user);
-       f_imap->user = NULL;
-       f_imap->secret = NULL;
-       f_imap->state = IMAP_LOGIN;
-      }
-
-    case IMAP_LOGIN:
-      /* Send it across.  */
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      /* Clear the buffer it contains the passwd. */
-      memset (f_imap->buffer, '\0', f_imap->buflen);
-      f_imap->state = IMAP_LOGIN_ACK;
-
-    case IMAP_LOGIN_ACK:
-      /* Get the login ack.  */
-      status = imap_parse (f_imap);
-      if (status)
-       return status;
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_AUTH_DONE;
-
-    default:
-      break;  /* We're outta here.  */
-    }
-  CLEAR_STATE (f_imap);
   return 0;
 }
+
+struct enumerate_closure
+{
+  mu_folder_t folder;
+  mu_folder_enumerate_fp fun;
+  void *data;
+};
 
-/*
-  The anonymous SASL mechanism is defined in rfc2245.txt as a single
-  message from client to server:
-
-  message         = [email / token]
-
-  So the message is optional.
-
-  The command is:
-
-  C: <tag> authenticate anonymous
-
-  The server responds with a request for continuation data (the "message"
-  in the SASL syntax). We respond with no data, which is legal.
+static int
+_enumerate_helper (void *item, void *data)
+{
+  struct mu_list_response *rp = item;
+  struct enumerate_closure *clos = data;
 
-  S: +
-  C:
+  return clos->fun (clos->folder, rp, clos->data);
+}
 
-  The server should then respond with OK on success, or else a failure
-  code (NO or BAD).
+static int
+_mu_imap_folder_list (mu_folder_t folder, const char *ref, void *name,
+                     int flags, size_t max_level,
+                     mu_list_t flist,
+                     mu_folder_enumerate_fp efp, void *edp)
+{
+  mu_imap_t imap = folder->data;
+  mu_list_t list;
+  int rc = mu_imap_list_new (imap, ref, name, &list);
 
-  If OK, then we are authenticated!
+  if (rc)
+    return rc;
 
-  So, states are:
+  if (max_level ||
+      (flags & MU_FOLDER_ATTRIBUTE_ALL) != MU_FOLDER_ATTRIBUTE_ALL)
+    {
+      /* Filter out the list, eliminating non-matching entries */
+      mu_iterator_t itr;
 
-  AUTH_ANON_REQ
+      rc = mu_list_get_iterator (list, &itr);
+      if (rc)
+       {
+         mu_list_destroy (&list);
+         return rc;
+       }
 
-  > g%u AUTHENTICATE ANONYMOUS
+      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+          mu_iterator_next (itr))
+       {
+         struct mu_list_response *rp;
 
-  AUTH_ANON_WAIT_CONT
+         mu_iterator_current (itr, (void**) &rp);
+         if (!(rp->type & flags) || (max_level && rp->level > max_level))
+           mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
+       }
+      mu_iterator_destroy (&itr);
+    }
 
-  < +
+  if (efp)
+    {
+      struct enumerate_closure clos;
 
-  AUTH_ANON_MSG
+      clos.folder = folder;
+      clos.fun = efp;
+      clos.data = edp;
 
-  >
+      rc = mu_list_foreach (list, _enumerate_helper, &clos);
+    }
 
-  AUTH_ANON_WAIT_RESP
+  if (flist)
+    mu_list_append_list (flist, list);
 
-  < NO/BAD/OK
+  mu_list_destroy (&list);
 
-*/
+  return rc;
+}
+
+static int
+_mu_imap_folder_lsub (mu_folder_t folder, const char *ref, const char *name,
+                     mu_list_t flist)
+{
+  mu_imap_t imap = folder->data;
+  return mu_imap_lsub (imap, ref, name, flist);
+}
+
+/* Subscribe to the named mailbox. */
+static int
+_mu_imap_folder_subscribe (mu_folder_t folder, const char *name)
+{
+  mu_imap_t imap = folder->data;
+  return mu_imap_subscribe (imap, name);
+}
+/* Unsubscribe from the mailbox. */
+static int
+_mu_imap_folder_unsubscribe (mu_folder_t folder, const char *name)
+{
+  mu_imap_t imap = folder->data;
+  return mu_imap_unsubscribe (imap, name);
+}
+
+/* Remove a mailbox.  */
+static int
+_mu_imap_folder_delete (mu_folder_t folder, const char *name)
+{
+  mu_imap_t imap = folder->data;
+  return mu_imap_delete (imap, name);
+}
+
+/* Rename OLDPATH to NEWPATH */
+static int
+_mu_imap_folder_rename (mu_folder_t folder, const char *oldpath,
+                       const char *newpath)
+{
+  mu_imap_t imap = folder->data;
+  return mu_imap_rename (imap, oldpath, newpath);
+}
+
+typedef int (*auth_method_t) (mu_authority_t);
 
 static int
-authenticate_imap_sasl_anon (mu_authority_t auth)
+authenticate_imap_login (mu_authority_t auth)
 {
   mu_folder_t folder = mu_authority_get_owner (auth);
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-
-  assert (f_imap->state == IMAP_AUTH);
-
-  if (check_capa (f_imap, "AUTH=ANONYMOUS"))
+  mu_imap_t imap = folder->data;
+  mu_ticket_t ticket;
+  char *user;
+  int rc;
+  mu_secret_t secret;
+  
+  rc = mu_imap_capability_test (imap, "LOGINDISABLED", NULL);
+  if (rc == 0)
+    {
+      mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+               (_("IMAP LOGIN disabled")));
+      return rc;
+    }
+  else if (rc != MU_ERR_NOENT)
+    {
+      mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+               (_("cannot test server capabilities (%s), continuing anyway"),
+                mu_strerror (rc)));
+      return rc;
+    }
+
+  /* Grab the User and Passwd information.  */
+  mu_authority_get_ticket (auth, &ticket);
+  /* Was it in the URL?  */
+  rc = mu_url_aget_user (folder->url, &user);
+  if (rc == MU_ERR_NOENT)
+    rc = mu_ticket_get_cred (ticket, folder->url, "Imap User: ", &user, NULL);
+  if (rc == MU_ERR_NOENT || user == NULL)
+    return MU_ERR_NOUSERNAME;
+  else if (rc)
+    return rc;
+
+  rc = mu_url_get_secret (folder->url, &secret);
+  if (rc == MU_ERR_NOENT)
+    rc = mu_ticket_get_cred (ticket, folder->url,
+                            "Imap Passwd: ", NULL, &secret);
+       
+  if (rc == MU_ERR_NOENT || !secret)
     {
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT,
-               "ANONYMOUS capability not present\n");
-      return ENOSYS;
+      /* FIXME: Is this always right? The user might legitimately have
+        no password */
+      free (user);
+      return MU_ERR_NOPASSWORD;
     }
-
-  /* FIXME: auth_state is never set explicitely before this function */
-  switch (f_imap->auth_state)
+  else if (rc)
     {
-    case IMAP_AUTH_ANON_REQ_WRITE:
-      {
-       MU_DEBUG1 (folder->debug, MU_DEBUG_PROT, 
-                   "g%lu AUTHENTICATE ANONYMOUS\n",
-                  (unsigned long) f_imap->seq);
-       status = imap_writeline (f_imap, "g%lu AUTHENTICATE ANONYMOUS\r\n",
-                                (unsigned long) f_imap->seq);
-       f_imap->seq++;
-       CHECK_ERROR_CLOSE (folder, f_imap, status);
-       f_imap->auth_state = IMAP_AUTH_ANON_REQ_SEND;
-      }
-
-    case IMAP_AUTH_ANON_REQ_SEND:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->auth_state = IMAP_AUTH_ANON_WAIT_CONT;
-
-    case IMAP_AUTH_ANON_WAIT_CONT:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      if (strncmp ("+", f_imap->buffer, 2) == 0)
-       {
-         f_imap->auth_state = IMAP_AUTH_ANON_MSG;
-       }
-      else
-       {
-         /* Something is wrong! */
-       }
-      f_imap->auth_state = IMAP_AUTH_ANON_MSG;
-
-    case IMAP_AUTH_ANON_MSG:
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, "\n");
-      status = imap_writeline (f_imap, "\r\n");
-      CHECK_ERROR_CLOSE (folder, f_imap, status);
-      f_imap->auth_state = IMAP_AUTH_ANON_MSG_SEND;
-
-    case IMAP_AUTH_ANON_MSG_SEND:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-
-      f_imap->auth_state = IMAP_AUTH_ANON_WAIT_RESP;
-
-    case IMAP_AUTH_ANON_WAIT_RESP:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;                   /* We're outta here.  */
+      free (user);
+      return rc;
     }
-  CLEAR_STATE (f_imap);
-  return 0;
+  rc = mu_imap_login_secret (imap, user, secret);
+  mu_secret_unref (secret);
+  return rc;
 }
 
 struct auth_tab
@@ -379,7 +421,7 @@ struct auth_tab
 
 static struct auth_tab auth_tab[] = {
   { "login", authenticate_imap_login },
-  { "anon", authenticate_imap_sasl_anon },
+  /*  { "anon",  authenticate_imap_sasl_anon },*/
   { NULL }
 };
 
@@ -398,74 +440,13 @@ find_auth_method (const char *name)
 static int
 authenticate_imap_select (mu_authority_t auth)
 {
-  mu_folder_t folder = mu_authority_get_owner (auth);
-  f_imap_t f_imap = folder->data;
   struct auth_tab *p;
-  int status = ENOSYS;
+  int rc = ENOSYS;
   
-  for (p = auth_tab; status == ENOSYS && p->name; p++)
-    {
-      f_imap->state = IMAP_AUTH;
-      status = p->method (auth);
-    }
-
-  return status;
-}
-
-
-
-
-/* Initialize the concrete IMAP mailbox: overload the folder functions  */
-int
-_folder_imap_init (mu_folder_t folder)
-{
-  int status;
-  f_imap_t f_imap;
-
-  /* Set the authority early:
-     (1) so we can check for errors.
-     (2) allow the client to get the authority for setting the ticket
-     before the open.  */
-  status = folder_imap_get_authority (folder, NULL);
-  if (status != 0)
-    return status;
-
-  f_imap = folder->data = calloc (1, sizeof (*f_imap));
-  if (f_imap == NULL)
-    return ENOMEM;
-
-  f_imap->folder = folder;
-  f_imap->state = IMAP_NO_STATE;
-
-  folder->_destroy = folder_imap_destroy;
+  for (p = auth_tab; rc == ENOSYS && p->name; p++)
+    rc = p->method (auth);
 
-  folder->_open = folder_imap_open;
-  folder->_close = folder_imap_close;
-
-  folder->_list = folder_imap_list;
-  folder->_lsub = folder_imap_lsub;
-  folder->_subscribe = folder_imap_subscribe;
-  folder->_unsubscribe = folder_imap_unsubscribe;
-  folder->_delete = folder_imap_delete;
-  folder->_rename = folder_imap_rename;
-
-  return 0;
-}
-
-/* Destroy the folder resources.  */
-static void
-folder_imap_destroy (mu_folder_t folder)
-{
-  if (folder->data)
-    {
-      f_imap_t f_imap = folder->data;
-      if (f_imap->buffer)
-       free (f_imap->buffer);
-      if (f_imap->capav)
-       mu_argcv_free (f_imap->capac, f_imap->capav);
-      free (f_imap);
-      folder->data = NULL;
-    }
+  return rc;
 }
 
 static int
@@ -473,2152 +454,139 @@ folder_set_auth_method (mu_folder_t folder, 
auth_method_t method)
 {
   if (!folder->authority)
     {
-      int status = mu_authority_create (&folder->authority, NULL, folder);
-      if (status)
-       return status;
+      int rc = mu_authority_create (&folder->authority, NULL, folder);
+      if (rc)
+       return rc;
     }
   return mu_authority_set_authenticate (folder->authority, method, folder);
 }
 
 static int
-folder_imap_get_authority (mu_folder_t folder, mu_authority_t *pauth)
+_imap_folder_setup_authority (mu_folder_t folder)
 {
-  int status = 0;
-  if (folder->authority == NULL)
+  int rc = 0;
+
+  if (!folder->authority)
     {
-      /* assert (folder->url); */
+      const char *auth;
       if (folder->url == NULL)
        return EINVAL;
 
-      if (folder->url->auth == NULL
-         || strcmp (folder->url->auth, "*") == 0)
-       {
-         status = folder_set_auth_method (folder, authenticate_imap_select);
-       }
+      if (mu_url_sget_auth (folder->url, &auth))
+       rc = folder_set_auth_method (folder, authenticate_imap_select);
+      else if (strcmp (auth, "*") == 0)
+       rc = folder_set_auth_method (folder, authenticate_imap_select);
       else 
        {
-         char *p, *sp;
+         struct mu_wordsplit ws;
 
-         for (p = strtok_r (folder->url->auth, ",", &sp);
-              status == 0 && p;
-              p = strtok_r (NULL, ",", &sp))
+         ws.ws_delim = ",";
+         if (mu_wordsplit (auth, &ws,
+                           MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
+                           MU_WRDSF_DELIM))
+           {
+             mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+                       (_("cannot split out auth part: %s"),
+                        mu_wordsplit_strerror (&ws)));
+             rc = MU_ERR_FAILURE;
+           }
+         else
            {
-             auth_method_t method = find_auth_method (p);
-             if (method)
-               status = folder_set_auth_method (folder, method);
-             else
-               status = MU_ERR_BAD_AUTH_SCHEME;
-           }             
+             int i;
+
+             for (i = 0; i < ws.ws_wordc; i++)
+               {
+                 auth_method_t method = find_auth_method (ws.ws_wordv[i]);
+                 if (method)
+                   rc = folder_set_auth_method (folder, method);
+                 else
+                   {
+                     mu_debug (MU_DEBCAT_FOLDER, MU_DEBUG_ERROR,
+                               (_("unrecognized AUTH scheme %s"),
+                                ws.ws_wordv[i]));
+                     rc = MU_ERR_BAD_AUTH_SCHEME;
+                   }
+               }
+             mu_wordsplit_free (&ws);
+           }
        }
     }
 
-  if (status)
-    return status;
-  
-  if (pauth)
-    *pauth = folder->authority;
-  return status;
+  return rc;
 }
-
 
-/* Capability handling */
-static int
-parse_capa (f_imap_t f_imap, char *str)
+int
+_mu_imap_folder_init (mu_folder_t folder)
 {
-  if (f_imap->capav)
-    mu_argcv_free (f_imap->capac, f_imap->capav);
-  return mu_argcv_get (str, "", NULL, &f_imap->capac, &f_imap->capav);
-}
+  mu_imap_t imap;
+  int rc;
 
-static int
-read_capa (f_imap_t f_imap, int force)
-{
-  int status = 0;
-  
-  if (force)
-    {
-      mu_argcv_free (f_imap->capac, f_imap->capav);
-      f_imap->capac = 0;
-      f_imap->capav = NULL;
-    }
+  rc = _imap_folder_setup_authority (folder);
+  if (rc)
+    return rc;
   
-  if (!f_imap->capav)
-    {
-      status = imap_writeline (f_imap, "g%lu CAPABILITY\r\n",
-                              (unsigned long) f_imap->seq++);
-      status = imap_send (f_imap);
-      status = imap_parse (f_imap);
-    }
-  return status;
-}
-
-static int
-check_capa (f_imap_t f_imap, char *capa)
-{
-  int i;
-
-  read_capa (f_imap, 0);
-  for (i = 0; i < f_imap->capac; i++)
-    if (mu_c_strcasecmp (f_imap->capav[i], capa) == 0)
-      return 0;
-  return 1;
-}
-
-
-static int
-imap_reader (void *iodata)
-{
-  f_imap_t iop = iodata;
-  int status = imap_parse (iop);
-  CHECK_EAGAIN (iop, status);
-  MU_DEBUG (iop->folder->debug, MU_DEBUG_PROT, iop->buffer);
-  return status;
-}
-
-static int
-imap_writer (void *iodata, char *buf)
-{
-  f_imap_t iop = iodata;
-  int status;
-    
-  MU_DEBUG2 (iop->folder->debug, MU_DEBUG_PROT, "g%lu %s\n",
-             (unsigned long)iop->seq, buf);
-  status = imap_writeline (iop, "g%lu %s\r\n",
-                          (unsigned long)iop->seq++, buf);
-  CHECK_ERROR (iop, status);
-  status = imap_send (iop);
-  CHECK_ERROR (iop, status);
-  return status;
-}
+  rc = mu_imap_create (&imap);
+  if (rc)
+    return rc;
 
-static void
-imap_stream_ctl (void *iodata, mu_stream_t *pold, mu_stream_t new)
-{
-  f_imap_t iop = iodata;
-  if (pold)
-    *pold = iop->folder->stream;
-  if (new)
-    iop->folder->stream = new;
-}  
+  folder->data = imap;
 
-static int
-tls (mu_folder_t folder)
-{
-#ifdef WITH_TLS
-  int status;
-  f_imap_t f_imap = folder->data;
-  char *keywords[] = { "STARTTLS", "CAPABILITY", NULL };
+  folder->_destroy = _mu_imap_folder_destroy;
 
-  if (!mu_tls_enable || check_capa (f_imap, "STARTTLS"))
-    return -1;
+  folder->_open = _mu_imap_folder_open;
+  folder->_close = _mu_imap_folder_close;
 
-  status = mu_tls_begin (f_imap, imap_reader, imap_writer,
-                        imap_stream_ctl, keywords);
+  folder->_list = _mu_imap_folder_list;
+  folder->_lsub = _mu_imap_folder_lsub;
 
-  MU_DEBUG1 (folder->debug, MU_DEBUG_PROT, "TLS negotiation %s\n",
-            status == 0 ? "succeeded" : "failed");
-  return status;
-#else
-  return -1;
-#endif /* WITH_TLS */
+  folder->_subscribe = _mu_imap_folder_subscribe;
+  folder->_unsubscribe = _mu_imap_folder_unsubscribe;
+  folder->_delete = _mu_imap_folder_delete;
+  folder->_rename = _mu_imap_folder_rename;
+  return 0;
 }
-
-/* Create/Open the stream for IMAP.  */
-static int
-folder_imap_open (mu_folder_t folder, int flags)
+
+static struct _mu_record _imap_record =
 {
-  f_imap_t f_imap = folder->data;
-  const char *host;
-  unsigned port = f_imap->imaps ? MU_IMAPS_PORT : MU_IMAP_PORT;
-  int status = 0;
-
-  /* If we are already open for business, noop.  */
-  mu_monitor_wrlock (folder->monitor);
-  if (f_imap->isopen)
-    {
-      mu_monitor_unlock (folder->monitor);
-      return 0;
-    }
-  mu_monitor_unlock (folder->monitor);
+  MU_IMAP_PRIO,
+  MU_IMAP_SCHEME,
+  MU_RECORD_DEFAULT,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH,
+  MU_URL_HOST,
+  _mu_imap_url_init,     /* url entry.  */
+  _mu_imap_mailbox_init, /* Mailbox entry.  */
+  NULL,                  /* Mailer entry.  */
+  _mu_imap_folder_init,  /* Folder entry.  */
+  NULL, /* No need for a back pointer.  */
+  NULL, /* _is_scheme method.  */
+  NULL, /* _get_url method.  */
+  NULL, /* _get_mailbox method.  */
+  NULL, /* _get_mailer method.  */
+  NULL  /* _get_folder method.  */
+};
 
-  /* Fetch the server name and the port in the mu_url_t.  */
-  status = mu_url_sget_host (folder->url, &host);
-  if (status != 0)
-    return status;
-  mu_url_get_port (folder->url, &port);
+mu_record_t mu_imap_record = &_imap_record;
 
-  folder->flags = flags;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      /* allocate working io buffer.  */
-      if (f_imap->buffer == NULL)
-        {
-         /* There is no particular limit on the length of a command/response
-            in IMAP. We start with 255, which is quite reasonnable and grow
-            as we go along.  */
-          f_imap->buflen = 255;
-          f_imap->buffer = calloc (f_imap->buflen + 1, 1);
-          if (f_imap->buffer == NULL)
-            {
-              CHECK_ERROR (f_imap, ENOMEM);
-            }
-         status = mu_memory_stream_create (&f_imap->string.stream, NULL, 
MU_STREAM_RDWR);
-          CHECK_ERROR (f_imap, status);
-        }
-      else
-        {
-         /* Clear from any residue.  */
-          memset (f_imap->buffer, '\0', f_imap->buflen);
-         mu_stream_truncate (f_imap->string.stream, 0);
-         f_imap->string.offset = 0;
-         f_imap->string.nleft = 0;
-        }
-      f_imap->ptr = f_imap->buffer;
-
-      /* Create the networking stack.  */
-      if (folder->stream == NULL)
-        {
-          status = mu_tcp_stream_create (&folder->stream, host, port, 
folder->flags);
-          CHECK_ERROR (f_imap, status);
-
-#ifdef WITH_TLS
-         if (f_imap->imaps)
-           {
-             mu_stream_t newstr;
-
-             status = mu_tls_client_stream_create (&newstr, 
-                                                   folder->stream,
-                                                   folder->stream, 0);
-             if (status != 0)
-               {
-                 mu_error ("folder_imap_open: mu_tls_client_stream_create: %s",
-                           mu_strerror (status));
-                 return status;
-               }
-             folder->stream = newstr;
-           }
-#endif /* WITH_TLS */
-
-         /* Ask for the stream internal buffering mechanism scheme.  */
-         mu_stream_setbufsiz (folder->stream, BUFSIZ);
-        }
-      else
-        mu_stream_close (folder->stream);
-      MU_DEBUG2 (folder->debug, MU_DEBUG_PROT, "imap_open (%s:%ld)\n",
-                host, port);
-      f_imap->state = IMAP_OPEN_CONNECTION;
-
-    case IMAP_OPEN_CONNECTION:
-      /* Establish the connection.  */
-      if (!mu_stream_is_open (folder->stream))
-        {
-          status = mu_stream_open (folder->stream);
-          CHECK_EAGAIN (f_imap, status);
-          /* Can't recover bailout.  */
-          CHECK_ERROR_CLOSE (folder, f_imap, status);
-        }
-      f_imap->state = IMAP_GREETINGS;
-
-    case IMAP_GREETINGS:
-      {
-        /* Swallow the greetings.  */
-        status = imap_readline (f_imap);
-        CHECK_EAGAIN (f_imap, status);
-       f_imap->ptr = f_imap->buffer;
-        MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-       /* Are they open for business ?  The server send an untagged response
-          for greeting. Tecnically it can be OK/PREAUTH/BYE.  The BYE is
-          the one that we do not want, server being unfriendly.  */
-       if (mu_c_strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0)
-         {
-           f_imap->state = IMAP_AUTH_DONE;
-         }
-       else
-         {
-            if (mu_c_strncasecmp (f_imap->buffer, "* OK", 4) != 0)
-              CHECK_ERROR_CLOSE (folder, f_imap, EACCES);
-            f_imap->state = IMAP_AUTH;
-         }
-      }
-      if (!f_imap->imaps)
-       tls (folder);
-      
-    case IMAP_AUTH:
-    case IMAP_LOGIN:
-    case IMAP_LOGIN_ACK:
-      assert (folder->authority);
-      {
-       status = mu_authority_authenticate (folder->authority);
-       if (status)
-         {
-           /* Fake folder_imap_close into closing the folder.
-              FIXME: The entire state machine should probably
-              be revised... */
-           f_imap->isopen++;
-           f_imap->state = IMAP_NO_STATE;
-           folder_imap_close (folder);
-           return status;
-         }
-      }
-
-    case IMAP_AUTH_DONE:
-    default:
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  mu_monitor_wrlock (folder->monitor);
-  f_imap->isopen++;
-  mu_monitor_unlock (folder->monitor);
-  return 0;
-}
-
-
-/* Shutdown the connection.  */
-static int
-folder_imap_close (mu_folder_t folder)
-{
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-
-  mu_monitor_wrlock (folder->monitor);
-  f_imap->isopen--;
-  if (f_imap->isopen)
-    {
-      mu_monitor_unlock (folder->monitor);
-      return 0;
-    }
-  mu_monitor_unlock (folder->monitor);
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu LOGOUT\r\n",
-                              (unsigned long) f_imap->seq++);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_LOGOUT;
-
-    case IMAP_LOGOUT:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_LOGOUT_ACK;
-
-    case IMAP_LOGOUT_ACK:
-      /* Check for "* Bye" from the imap server.  */
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      /* This is done when we received the BYE in the parser code.  */
-      /* mu_stream_close (folder->stream); */
-      /* f_imap->isopen = 0 ; */
-
-    default:
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  f_imap->selected = NULL;
-  return 0;
-}
-
-/* Remove a mailbox.  */
-static int
-folder_imap_delete (mu_folder_t folder, const char *name)
-{
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-
-  if (name == NULL)
-    return EINVAL;
-
-  status = mu_folder_open (folder, folder->flags);
-  if (status != 0)
-    return status;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu DELETE %s\r\n",
-                              (unsigned long) f_imap->seq++,
-                              name);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_DELETE;
-
-    case IMAP_DELETE:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_DELETE_ACK;
-
-    case IMAP_DELETE_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-void
-guess_level (struct mu_list_response *resp, size_t prefix_len)
-{
-  size_t lev = 0;
-
-  if (!resp->separator)
-    lev = 0;
-  else
-    {
-      char *p = resp->name + prefix_len;
-      if (p[0] == resp->separator)
-       for ( ; p; p = strchr (p + 1, resp->separator))
-         lev++;
-    }
-  resp->level = lev;
-}
-
-/* Moves all matching items from list DST to SRC.
-   Items are moved verbatim (i.e. pointers are moved). Non-matching
-   items are deleted. After calling this function, SRC must be
-   destroyed.
-
-   While moving, this function also computes the recursion level.
-   
-   Matching is determined based on PATTERN, by NAMECMP function,
-   and MAX_LEVEL. Both can be zero. */
-   
-static void
-list_copy (mu_list_t dst, mu_list_t src,
-          size_t prefix_len,
-          int (*namecmp) (const char* pattern, const char* mailbox),
-          const char *pattern, size_t max_level)
-{
-  mu_iterator_t itr;
-
-  if (!src)
-    return;
-  
-  mu_list_get_iterator (src, &itr);
-  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
-       mu_iterator_next (itr))
-    {
-      char *name;
-      struct mu_list_response *p;
-      mu_iterator_current (itr, (void **)&p);
-      guess_level (p, prefix_len);
-      name = p->name + prefix_len;
-      if (name[0] == p->separator && pattern[0] != p->separator)
-       name++;
-      if ((max_level == 0 || p->level <= max_level)
-         && (!namecmp || namecmp (pattern, name) == 0))
-       mu_list_append (dst, p);
-      else
-       free (p);
-    }
-  mu_iterator_destroy (&itr);
-  mu_list_set_destroy_item (src, NULL);
-}
-
-/* Convert glob(3)-style pattern to IMAP one
-   Rules:
-     Wildcard          Replace with
-     --------          ------------
-     *                 * for recursive searches, % otherwise
-     ?                 %
-     [..]              %
-
-   NOTE:
-    1. The '*' can be made more selective by taking into account the
-       required maximum recursion level and counting directory separators
-       ('/') in the input pattern.
-    2. The resulting pattern matches, in general, a wider set of strings, so
-       each matched string should be additionally compared against the
-       original pattern.
- */
-char *
-glob_to_imap (const char *pat, int recursive)
-{
-  char *p, *q;
-  char *ret = strdup (pat);
-
-  if (!ret)
-    return NULL;
-
-  for (p = q = ret; *q; )
-    {
-      switch (*q)
-       {
-       case '?':
-         *p++ = '%';
-         q++;
-         break;
-
-       case '*':
-         *p++ = recursive ? '*' : '%';
-         q++;
-         break;
-         
-       case '[':
-         for (; *q; q++)
-           if (*q == '\\')
-             q++;
-           else if (*q == ']')
-             {
-               q++;
-               break;
-             }
-         *p++ = '%';
-         break;
-
-       case '\\':
-         q++;
-         if (*q)
-           *p++ = *q++;
-         break;
-         
-       default:
-         *p++ = *q++;
-         break;
-       }
-    }
-  *p = 0;
-  return ret;
-}
-
-/* FIXME: Flags unused */
-static int
-folder_imap_list (mu_folder_t folder, const char *ref, void *name,
-                 int flags, size_t max_level,
-                 mu_list_t flist,
-                 mu_folder_enumerate_fp efp, void *edp)
-{
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-  char *path = NULL;
-  
-  status = mu_folder_open (folder, folder->flags);
-  if (status != 0)
-    return status;
-
-  if (ref == NULL)
-    ref = "";
-  if (name == NULL)
-    name = "";
-
-  f_imap->enum_fun = efp;
-  f_imap->enum_stop = 0;
-  f_imap->enum_data = edp;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      path = glob_to_imap (name, max_level != 1);
-      status = imap_writeline (f_imap, "g%lu LIST \"%s\" \"%s\"\r\n",
-                              (unsigned long) f_imap->seq++, ref, path);
-      free (path);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_LIST;
-
-    case IMAP_LIST:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_LIST_ACK;
-
-    case IMAP_LIST_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;
-    }
-
-  f_imap->enum_fun = NULL;
-  f_imap->enum_stop = 0;
-  f_imap->enum_data = NULL;
-  
-  list_copy (flist, f_imap->flist, strlen (ref),
-            imap_mailbox_name_match, name, max_level);
-
-  mu_list_destroy (&f_imap->flist);
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-static int
-folder_imap_lsub (mu_folder_t folder, const char *ref, const char *name,
-                 mu_list_t flist)
-{
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-
-  status = mu_folder_open (folder, folder->flags);
-  if (status != 0)
-    return status;
-
-  if (ref == NULL)
-    ref = "";
-  if (name == NULL)
-    name = "";
-
-  f_imap->enum_fun = NULL;
-  f_imap->enum_stop = 0;
-  f_imap->enum_data = NULL;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu LSUB \"%s\" \"%s\"\r\n",
-                              (unsigned long) f_imap->seq++, ref, name);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_LSUB;
-
-    case IMAP_LSUB:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_LSUB_ACK;
-
-    case IMAP_LSUB_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;
-    }
-
-  /* Build the folder list.  */
-  list_copy (flist, f_imap->flist, strlen (ref), NULL, NULL, 0);
-  mu_list_destroy (&f_imap->flist);
-  
-  f_imap->state = IMAP_NO_STATE;
-  return 0;
-}
-
-static int
-folder_imap_rename (mu_folder_t folder, const char *oldpath,
-                   const char *newpath)
-{
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-
-  if (oldpath == NULL || newpath == NULL)
-    return EINVAL;
-
-  status = mu_folder_open (folder, folder->flags);
-  if (status != 0)
-    return status;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu RENAME %s %s\r\n",
-                              (unsigned long) f_imap->seq++,
-                              oldpath, newpath);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_RENAME;
-
-    case IMAP_RENAME:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_RENAME_ACK;
-
-    case IMAP_RENAME_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-static int
-folder_imap_subscribe (mu_folder_t folder, const char *name)
-{
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-
-  status = mu_folder_open (folder, folder->flags);
-  if (status != 0)
-    return status;
-
-  if (name == NULL)
-    return EINVAL;
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu SUBSCRIBE %s\r\n",
-                              (unsigned long) f_imap->seq++, name);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_SUBSCRIBE;
-
-    case IMAP_SUBSCRIBE:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_SUBSCRIBE_ACK;
-
-    case IMAP_SUBSCRIBE_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-static int
-folder_imap_unsubscribe (mu_folder_t folder, const char *name)
-{
-  f_imap_t f_imap = folder->data;
-  int status = 0;
-
-  status = mu_folder_open (folder, folder->flags);
-  if (status != 0)
-    return status;
-
-  if (name == NULL)
-    return EINVAL;
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu UNSUBSCRIBE %s\r\n",
-                              (unsigned long) f_imap->seq++, name);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_UNSUBSCRIBE;
-
-    case IMAP_UNSUBSCRIBE:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_UNSUBSCRIBE_ACK;
-
-    case IMAP_UNSUBSCRIBE_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (folder->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-/* A literal is a sequence of zero or more octets (including CR and LF),
-   prefix-quoted with an octet count in the form of an open brace ("{"),
-   the number of octets, close brace ("}"), and CRLF.  The sequence is read
-   and put in the string buffer.  */
-static int
-imap_literal_string (f_imap_t f_imap, char **ptr)
-{
-  size_t len, len0, total;
-  int status = 0;
-  int nl;
-
-  if (f_imap->string.nleft==0)
-    {
-      status = imap_readline (f_imap);
-      *ptr = f_imap->buffer;
-      return status;
-    }
-
-  /* The (len + 1) in the for is to count the strip '\r' by imap_readline.  */
-  for (len0 = len = total = 0; total < f_imap->string.nleft; total += len + 1)
-    {
-      status = imap_readline (f_imap);
-      if (DEBUG_SHOW_DATA)
-       fprintf (stderr, "%s", f_imap->buffer);
-      if (status != 0)
-       {
-         /* Return what we got so far.  */
-         break;
-       }
-      f_imap->ptr = f_imap->buffer;
-
-      /* How much ?  */
-      len0 = len = f_imap->nl - f_imap->buffer;
-      /* Check if the last read did not finish on a line, if yes do not copy in
-        string buffer the terminating sequence ")\r\n".  We are doing this
-         by checking if the amount(total) we got so far + the len of the line
-         +1 (taking to account the strip '\r') goes behond the request.  */
-      if ((total + len + 1) > f_imap->string.nleft)
-       {
-         len0 = len = f_imap->string.nleft - total;
-         /* ALERT: if we ask for a substring, for example we have :
-            "123456\n", and ask for body[]<0.7> the server will send
-            body[] {7} --> "123456\r".  There was not enough space
-            to fit the nl .. annoying.  Take care of this here.  */
-         if (f_imap->buffer[len - 1] == '\r')
-           len0--;
-       }
-
-      mu_stream_write (f_imap->string.stream, f_imap->buffer,
-                   len0, f_imap->string.offset, NULL);
-      f_imap->string.offset += len0;
-
-      /* Depending on the type of request we incremente the xxxx_lines
-        and  xxxx_sizes.  */
-      nl = (memchr (f_imap->buffer, '\n', len0)) ? 1 : 0;
-      if (f_imap->string.msg_imap)
-       {
-         switch (f_imap->string.type)
-           {
-           case IMAP_HEADER:
-             f_imap->string.msg_imap->header_lines += nl;
-             f_imap->string.msg_imap->header_size += len0;
-             break;
-
-           case IMAP_BODY:
-             f_imap->string.msg_imap->body_lines += nl;
-             f_imap->string.msg_imap->body_size += len0;
-             break;
-
-           case IMAP_MESSAGE:
-             f_imap->string.msg_imap->mu_message_lines += nl;
-             /* The message size is known by sending RFC822.SIZE.  */
-
-           default:
-             break;
-           }
-       }
-    }
-  f_imap->string.nleft -= total;
-  /* We may have trailing junk like the closing ")\r\n" from a literal string
-     glob it by moving the command buffer, or doing a full readline.  */
-  if (len == (size_t)(f_imap->nl - f_imap->buffer))
-    {
-      len = 0;
-      status = imap_readline (f_imap);
-    }
-  *ptr = f_imap->buffer + len;
-  return status;
-}
-
-/* A quoted string is a sequence of zero or more 7-bit characters,
-   excluding CR and LF, with double quote (<">) characters at each end.
-   Same thing as the literal, diferent format the result is put in the
-   string buffer for the mailbox/callee.  */
-static int
-imap_quoted_string (f_imap_t f_imap, char **ptr)
-{
-  char *bquote;
-  int escaped = 0;
-  int len;
-
-  (*ptr)++;
-  bquote = *ptr;
-  while (**ptr && (**ptr != '"' || escaped))
-    {
-      escaped = (**ptr == '\\') ? 1 : 0;
-      (*ptr)++;
-    }
-
-  len = *ptr - bquote;
-  mu_stream_write (f_imap->string.stream, bquote, len,
-               f_imap->string.offset, NULL);
-  f_imap->string.offset += len;
-  if (**ptr == '"')
-    (*ptr)++;
-  if (DEBUG_SHOW_DATA)
-    fprintf (stderr, "%.*s", len, bquote);
-  return 0;
-}
-
-/* A number consists of one or more digit characters, and represents a
-   numeric value. */
-      
-static int
-imap_digits (f_imap_t f_imap, char **ptr)
-{
-  char *start = *ptr;
-  int len;
-  
-  for (++*ptr; **ptr && mu_isdigit(**ptr); ++*ptr)
-    ;
-  len = *ptr - start;
-  mu_stream_write (f_imap->string.stream, start, len,
-               f_imap->string.offset, NULL);
-  f_imap->string.offset += len;
-  return 0;
-}
-
-/* Find which type of string the response is: literal or quoted and let the
-   function fill the string buffer.  */
-static int
-imap_string (f_imap_t f_imap, char **ptr)
-{
-  int status = 0;
-
-  /* Skip whites.  */
-  while (**ptr == ' ')
-    (*ptr)++;
-  switch (**ptr)
-    {
-    case '{':
-      f_imap->string.nleft = strtol ((*ptr) + 1, ptr, 10);
-      if (**ptr == '}')
-       {
-         (*ptr)++;
-         /* Reset the buffer to the beginning.  */
-         f_imap->ptr = f_imap->buffer;
-         status = imap_literal_string (f_imap, ptr);
-       }
-      break;
-      
-    case '"':
-      status = imap_quoted_string (f_imap, ptr);
-      break;
-      
-      /* NIL */
-    case 'N':
-    case 'n':
-      (*ptr)++; /* N|n  */
-      (*ptr)++; /* I|i  */
-      (*ptr)++; /* L|l  */
-      break;
-      
-    default:
-      if (mu_isdigit (**ptr))
-       status = imap_digits (f_imap, ptr);
-      else
-       /* Problem. FIXME: Return a more appropriate error code */
-       status = MU_ERR_FAILURE;
-      break;
-    }
-  return status;
-}
-
-/* FIXME: does not work for nonblocking.  */
-static int
-imap_list (f_imap_t f_imap)
-{
-  char *tok;
-  char *sp = NULL;
-  size_t len = f_imap->nl - f_imap->buffer - 1;
-  char *buffer;
-  struct mu_list_response *lr;
-  int status = 0;
-  int argc;
-  char **argv;
-
-  if (f_imap->enum_stop)
-    return 0;
-      
-  buffer = malloc (len + 1);
-  if (!buffer)
-    return ENOMEM;
-  memcpy (buffer, f_imap->buffer, len);
-  buffer[len] = '\0';
-
-  lr = calloc (1, sizeof (*lr));
-  if (!lr)
-    return ENOMEM;
-      
-  if (!f_imap->flist)
-    {
-      mu_list_create (&f_imap->flist);
-      mu_list_set_destroy_item (f_imap->flist, mu_list_response_free);
-    }
-
-  /* Glob untag.  */
-  tok = strtok_r (buffer, " ", &sp);
-  /* Glob LIST.  */
-  tok = strtok_r (NULL, " ", &sp);
-  /* Get the attibutes.  */
-  tok = strtok_r (NULL, ")", &sp);
-  if (tok) 
-    {
-      char *s = NULL;
-      char *p = tok;
-      while ((tok = strtok_r (p, " ()", &s)) != NULL)
-       {
-         if (mu_c_strcasecmp (tok, "\\Noselect") == 0)
-           lr->type |= MU_FOLDER_ATTRIBUTE_DIRECTORY;
-         else if (mu_c_strcasecmp (tok, "\\Noinferiors") == 0)
-           lr->type |= MU_FOLDER_ATTRIBUTE_FILE;
-         else if (mu_c_strcasecmp (tok, "\\Marked") == 0
-                  || mu_c_strcasecmp (tok, "\\Unmarked") == 0)
-           /* nothing */;
-         else
-           lr->type |= MU_FOLDER_ATTRIBUTE_DIRECTORY;
-         p = NULL;
-       }
-    }
-
-  status = mu_argcv_get (sp, "", NULL, &argc, &argv);
-  if (status == 0)
-    {
-      char *s;
-      
-      /* Hiearchy delimeter.  */
-      tok = argv[0];
-      if (tok && tok[1] == 0 && mu_c_strcasecmp (tok, "NIL"))
-       lr->separator = tok[0];
-      /* The path.  */
-      tok = argv[1];
-      s = strchr (tok, '{');
-      if (s)
-       {
-         size_t n = strtoul (s + 1, NULL, 10);
-         lr->name = calloc (n + 1, 1);
-         if (!lr->name)
-           status = ENOMEM;
-         else
-           {
-             f_imap->ptr = f_imap->buffer;
-             imap_readline (f_imap);
-             memcpy (lr->name, f_imap->buffer, n);
-           }
-       }
-      else if ((status = imap_string (f_imap, &tok)) == 0)
-       {
-         mu_off_t sz = 0;
-         
-         mu_stream_size (f_imap->string.stream, &sz);
-         lr->name = calloc (sz + 1, 1);
-         if (!lr->name)
-               status = ENOMEM;
-         else
-           mu_stream_read (f_imap->string.stream, lr->name, sz, 0, NULL);
-         mu_stream_truncate (f_imap->string.stream, 0);
-         f_imap->string.offset = 0;
-         f_imap->string.nleft = 0;
-       }
-      else
-       {
-         lr->name = strdup (tok);
-         if (!lr->name)
-           status = ENOMEM;
-       }
-      if (lr->separator)
-       {
-         size_t off;
-         char delim[2];
-         size_t n = 0;
-         
-         delim[0] = lr->separator;
-         delim[1] = 0;
-         s = lr->name;
-         while (off = strcspn (s, delim), s[off])
-           {
-             n++;
-             off++;
-             s += off;
-           }
-         lr->level = n;
-       }
-    }
-  mu_argcv_free (argc, argv);
-  free (buffer);
-
-  if (f_imap->enum_fun)
-    f_imap->enum_stop = f_imap->enum_fun (f_imap->folder, lr,
-                                         f_imap->enum_data);
-  mu_list_append (f_imap->flist, lr);
-  
-  return status;
-}
-
-/* Helping function to figure out the section name of the message: for example
-   a 2 part message with the first part being sub in two will be:
-   {1}, {1,1} {1,2}  The first subpart of the message and its sub parts
-   {2}  The second subpar of the message.  */
-char *
-section_name (msg_imap_t msg_imap)
-{
-  size_t sectionlen = 0;
-  char *section = strdup ("");
-
-  /* Build the section name, but it is in reverse.  */
-  for (; msg_imap; msg_imap = msg_imap->parent)
-    {
-      if (msg_imap->part != 0)
-       {
-         char *tmp;
-         char part[64];
-         size_t partlen;
-         snprintf (part, sizeof part, "%lu", (unsigned long) msg_imap->part);
-         partlen = strlen (part);
-         tmp = realloc (section, sectionlen + partlen + 2);
-         if (tmp == NULL)
-           break;
-         section = tmp;
-         memset (section + sectionlen, '\0', partlen + 2);
-         if (sectionlen != 0)
-           strcat (section, ".");
-         strcat (section, part);
-         sectionlen = strlen (section);
-       }
-    }
-
-  /* Reverse the string.  */
-  if (section)
-    {
-      char *begin, *last;
-      char c;
-      for (begin = section, last = section + sectionlen - 1; begin < last;
-          begin++, last--)
-       {
-         c = *begin;
-         *begin = *last;
-         *last = c;
-       }
-    }
-  return section;
-}
-
-/* We do not pay particular attention to the content of the bodystructure
-   but rather to the paremetized list layout to discover how many messages
-   the originial message is composed of.  The information is later retrieve
-   when needed via the body[header.fields] command.  Note that this function
-   is recursive. */
-static int
-imap_bodystructure0 (msg_imap_t msg_imap, char **ptr)
-{
-  int paren = 0;
-  int no_arg = 0;
-  int status = 0;
-  int have_size = 0;
-
-  /* Skip space.  */
-  while (**ptr == ' ')
-    (*ptr)++;
-  /* Pass lparen.  */
-  if (**ptr == '(')
-    {
-      ++(*ptr);
-      paren++;
-      no_arg++;
-    }
-  /* NOTE : this loop has side effects in strtol() and imap_string(), the
-     order of the if's are important.  */
-  while (**ptr)
-    {
-      /* Skip the string argument.  */
-      if (**ptr != '(' && **ptr != ')')
-       {
-         char *start = *ptr;
-         /* FIXME: set the command callback if EAGAIN to resume.  */
-          status = imap_string (msg_imap->m_imap->f_imap, ptr);
-         if (status != 0)
-           return status;
-         if (start != *ptr)
-           no_arg = 0;
-       }
-
-      if (mu_isdigit ((unsigned)**ptr))
-       {
-         char *start = *ptr;
-         size_t size = strtoul (*ptr, ptr, 10);
-         if (start != *ptr)
-           {
-             if (!have_size && msg_imap && msg_imap->parent)
-               msg_imap->mu_message_size = size;
-             have_size = 1;
-             no_arg = 0;
-           }
-       }
-
-      if (**ptr == '(')
-       {
-         if (no_arg)
-           {
-             msg_imap_t new_part;
-             msg_imap_t *tmp;
-             tmp = realloc (msg_imap->parts,
-                            ((msg_imap->num_parts + 1) * sizeof (*tmp)));
-             if (tmp)
-               {
-                 new_part = calloc (1, sizeof (*new_part));
-                 if (new_part)
-                   {
-                     msg_imap->parts = tmp;
-                     msg_imap->parts[msg_imap->num_parts] = new_part;
-                     new_part->part = ++(msg_imap->num_parts);
-                     new_part->parent = msg_imap;
-                     new_part->num = msg_imap->num;
-                     new_part->m_imap = msg_imap->m_imap;
-                     new_part->flags = msg_imap->flags;
-                     status = imap_bodystructure0 (new_part, ptr);
-                     /* Jump up, the rparen been swallen already.  */
-                     continue;
-                   }
-                 else
-                   {
-                     status = ENOMEM;
-                     free (tmp);
-                     break;
-                   }
-               }
-             else
-               {
-                 status = ENOMEM;
-                 break;
-               }
-           }
-         paren++;
-        }
-
-      if (**ptr == ')')
-        {
-          no_arg = 1;
-          paren--;
-          /* Did we reach the same number of close paren ?  */
-          if (paren <= 0)
-           {
-             /* Swallow the rparen.  */
-             (*ptr)++;
-             break;
-           }
-        }
-
-      if (**ptr == '\0')
-       break;
-
-      (*ptr)++;
-    }
-  return status;
-}
-
-static int
-imap_bodystructure (f_imap_t f_imap, char **ptr)
-{
-  return imap_bodystructure0 (f_imap->string.msg_imap, ptr);
-}
-
-/* The Format for a FLAG response is :
-   mailbox_data    ::=  "FLAGS" SPACE flag_list
-   flag_list       ::= "(" #flag ")"
-   flag            ::= "\Answered" / "\Flagged" / "\Deleted" /
-   "\Seen" / "\Draft" / flag_keyword / flag_extension
-   flag_extension  ::= "\" atom
-   ;; Future expansion.  Client implementations
-   ;; MUST accept flag_extension flags.  Server
-   ;; implementations MUST NOT generate
-   ;; flag_extension flags except as defined by
-   ;; future standard or standards-track
-   ;; revisions of this specification.
-   flag_keyword    ::= atom
-
-   S: * 14 FETCH (FLAGS (\Seen \Deleted))
-   S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
-
-   We assume that the '*' or the FLAGS keyword are strip.
-
-   FIXME:  User flags are not take to account. */
-static int
-imap_fetch_flags (f_imap_t f_imap, char **ptr)
-{
-  msg_imap_t msg_imap = f_imap->string.msg_imap;
-  if (msg_imap)
-    imap_flags (ptr, &msg_imap->flags);
-  return 0;
-}
-
-static int
-imap_permanentflags (f_imap_t f_imap, char **ptr)
-{
-  imap_flags (ptr, &f_imap->flags);
-  return 0;
-}
-
-static int
-imap_flags (char **ptr, int *pflags)
-{
-  char *start;
-  char *end;
-  int flags = 0;
-
-  /* Skip space.  */
-  while (**ptr == ' ')
-    (*ptr)++;
-
-  /* Skip LPAREN.  */
-  if (**ptr == '(')
-    (*ptr)++;
-
-  /* Go through the list and break on ')'  */
-  do
-    {
-      /* Skip space before next word.  */
-      while (**ptr == ' ')
-        (*ptr)++;
-
-      /* Save the beginning of the word.  */
-      start = *ptr;
-       /* Get the next word boundary.  */
-      while (**ptr && **ptr != ' ' && **ptr != ')')
-        ++(*ptr);
-
-      /* Save the end for the mu_c_strcasecmp.  */
-      end = *ptr;
-
-      /* Bail out.  */
-      if (*start == '\0')
-        break;
-
-      /* Guess the flag.  */
-      if (end == start)
-       flags |= MU_ATTRIBUTE_SEEN;
-      else
-       {
-         if (mu_c_strncasecmp (start, "\\Seen", end - start) == 0)
-           {
-             flags |= MU_ATTRIBUTE_READ;
-           }
-         else if (mu_c_strncasecmp (start, "\\Answered", end - start) == 0)
-           {
-             flags |= MU_ATTRIBUTE_ANSWERED;
-           }
-         else if (mu_c_strncasecmp (start, "\\Flagged", end - start) == 0)
-           {
-             flags |= MU_ATTRIBUTE_FLAGGED;
-           }
-         else if (mu_c_strncasecmp (start, "\\Deleted", end - start) == 0)
-           {
-             flags |= MU_ATTRIBUTE_DELETED;
-           }
-         else if (mu_c_strncasecmp (start, "\\Draft", end - start) == 0)
-           {
-             flags |= MU_ATTRIBUTE_DRAFT;
-           }
-         else if (mu_c_strncasecmp (start, "\\Recent", end - start))
-           flags |= MU_ATTRIBUTE_SEEN;
-       }
-    }
-  while (**ptr && **ptr != ')'); /* do {} */
-
-  /* Skip the last rparen.  */
-  if (**ptr == ')')
-    (*ptr)++;
-
-  if (pflags)
-    *pflags = flags;
-  return 0;
-}
-
-static int
-imap_body (f_imap_t f_imap, char **ptr)
-{
-  int status;
-
-  /* Skip leading spaces.  */
-  while (**ptr && **ptr == ' ')
-    (*ptr)++;
-
-  if (**ptr == '[')
-    {
-      char *sep = strchr (*ptr, ']');
-      (*ptr)++; /* Move past the '[' */
-      if (sep)
-       {
-         size_t len = sep - *ptr;
-         char *section = malloc (len + 1);
-         
-         if (!section)
-           return ENOMEM;
-         
-         strncpy (section, *ptr, len);
-         section[len] = '\0';
-         /* strupper.  */
-         mu_strupper (section);
-         
-         /* Set the string type to update the correct line count.  */
-         /*if (!strstr (section, "FIELD"))*/
-           {
-              if (strstr (section, "MIME") || (strstr (section, "HEADER")))
-                {
-                  f_imap->string.type = IMAP_HEADER;
-                }
-              else if (strstr (section, "TEXT") || len > 0)
-                {
-                  f_imap->string.type = IMAP_BODY;
-                }
-              else if (len == 0) /* body[]  */
-                {
-                  f_imap->string.type = IMAP_MESSAGE;
-                }
-           }
-         free (section);
-         sep++; /* Move past the ']'  */
-         *ptr = sep;
-       }
-    }
-  while (**ptr && **ptr == ' ')
-    (*ptr)++;
-  if (**ptr == '<')
-    {
-      char *sep = strchr (*ptr, '>');
-      if (sep)
-       {
-         sep++;
-         *ptr = sep;
-       }
-    }
-  status = imap_string (f_imap, ptr);
-
-  /* If the state scan.  Catch it here.  */
-  if (f_imap->state == IMAP_SCAN_ACK)
-    {
-      char *buffer;
-      mu_off_t total = 0;
-      if (f_imap->string.msg_imap && f_imap->string.msg_imap->fheader)
-       mu_header_destroy (&f_imap->string.msg_imap->fheader, NULL);
-      mu_stream_size (f_imap->string.stream, &total);
-      buffer = malloc (total + 1);
-      mu_stream_read (f_imap->string.stream, buffer, total, 0, NULL);
-      status = mu_header_create (&f_imap->string.msg_imap->fheader,
-                             buffer, total, NULL);
-      free (buffer);
-      mu_stream_truncate (f_imap->string.stream, 0);
-      f_imap->string.offset = 0;
-      f_imap->string.nleft = 0;
-    }
-  return status;
-}
-
-static int
-imap_internaldate (f_imap_t f_imap, char **ptr)
-{
-  return imap_string (f_imap, ptr);
-}
-
-static int
-imap_uid (f_imap_t f_imap, char **ptr)
-{
-  char token[128];
-  imap_token (token, sizeof token, ptr);
-  if (f_imap->string.msg_imap)
-    f_imap->string.msg_imap->uid = strtoul (token, NULL, 10);
-  return 0;
-}
-
-static int
-imap_rfc822 (f_imap_t f_imap, char **ptr)
-{
-  int status;
-  f_imap->string.type = IMAP_MESSAGE;
-  status = imap_body (f_imap, ptr);
-  f_imap->string.type = 0;
-  return status;
-}
-
-static int
-imap_rfc822_size (f_imap_t f_imap, char **ptr)
-{
-  char token[128];
-  imap_token (token, sizeof token, ptr);
-  if (f_imap->string.msg_imap)
-    f_imap->string.msg_imap->mu_message_size = strtoul (token, NULL, 10);
-  return 0;
-}
-
-static int
-imap_rfc822_header (f_imap_t f_imap, char **ptr)
-{
-  int status;
-  f_imap->string.type = IMAP_HEADER;
-  status = imap_string (f_imap, ptr);
-  f_imap->string.type = 0;
-  return status;
-}
-
-static int
-imap_rfc822_text (f_imap_t f_imap, char **ptr)
-{
-  int status;
-  f_imap->string.type = IMAP_HEADER;
-  status = imap_string (f_imap, ptr);
-  f_imap->string.type = 0;
-  return status;
-}
-
-/* Parse imap unfortunately FETCH is use as response for many commands.
-   We just use a small set an ignore the other ones :
-   not use  : ALL
-   use      : BODY
-   not use  : BODY[<section>]<<partial>>
-   use      : BODY.PEEK[<section>]<<partial>>
-   not use  : BODYSTRUCTURE
-   not use  : ENVELOPE
-   not use  : FAST
-   use      : FLAGS
-   not use  : FULL
-   use      : INTERNALDATE
-   not use  : RFC822
-   not use  : RFC822.HEADER
-   use      : RFC822.SIZE
-   not use  : RFC822.TEXT
-   not use  : UID
- */
-static int
-imap_fetch (f_imap_t f_imap)
-{
-  char token[128];
-  size_t msgno = 0;
-  m_imap_t m_imap = f_imap->selected;
-  int status = 0;
-  char *sp = NULL;
-
-  /* We should have a mailbox selected.  */
-  assert (m_imap != NULL);
-
-  /* Parse the FETCH respones to extract the pieces.  */
-  sp = f_imap->buffer;
-
-  /* Skip untag '*'.  */
-  imap_token (token, sizeof token, &sp);
-  /* Get msgno.  */
-  imap_token (token, sizeof token, &sp);
-  msgno = strtol (token, NULL,  10);
-  /* Skip FETCH .  */
-  imap_token (token, sizeof token, &sp);
-
-  /* It is actually possible, but higly unlikely that we do not have the
-     message yet, for example a "FETCH (FLAGS (\Recent))" notification
-     for a newly messsage.  */
-  if (f_imap->string.msg_imap == NULL
-      || f_imap->string.msg_imap->num != msgno)
-    {
-      /* Find the imap mesg struct.  */
-      size_t i;
-      mu_message_t msg = NULL;
-      mu_mailbox_get_message (m_imap->mailbox, msgno, &msg);
-      for (i = 0; i < m_imap->imessages_count; i++)
-       {
-         if (m_imap->imessages[i] && m_imap->imessages[i]->num == msgno)
-           {
-             f_imap->string.msg_imap = m_imap->imessages[i];
-             break;
-           }
-       }
-      /* mu_message_destroy (&msg);  */
-    }
-
-  while (*sp && *sp != ')')
-    {
-      /* Get the token.  */
-      imap_token (token, sizeof token, &sp);
-
-      if (strncmp (token, "FLAGS", 5) == 0)
-       {
-         status = imap_fetch_flags (f_imap, &sp);
-       }
-      else if (mu_c_strcasecmp (token, "BODY") == 0)
-       {
-         if (*sp == '[')
-           status = imap_body (f_imap, &sp);
-         else
-           status = imap_bodystructure (f_imap, &sp);
-       }
-      else if (mu_c_strcasecmp (token, "BODYSTRUCTURE") == 0)
-       {
-         status = imap_bodystructure (f_imap, &sp);
-       }
-      else if (strncmp (token, "INTERNALDATE", 12) == 0)
-       {
-         status = imap_internaldate (f_imap, &sp);
-       }
-      else if (strncmp (token, "RFC822", 10) == 0)
-       {
-         if (*sp == '.')
-           {
-             sp++;
-             imap_token (token, sizeof token, &sp);
-             if (mu_c_strcasecmp (token, "SIZE") == 0)
-               {
-                 status = imap_rfc822_size (f_imap, &sp);
-               }
-             else if (mu_c_strcasecmp (token, "TEXT") == 0)
-               {
-                 status = imap_rfc822_text (f_imap, &sp);
-               }
-             else if (mu_c_strcasecmp (token, "HEADER") == 0)
-               {
-                 status = imap_rfc822_header (f_imap, &sp);
-               }
-             /* else mu_error (_("not supported RFC822 option"));  */
-           }
-         else
-           {
-             status = imap_rfc822 (f_imap, &sp);
-           }
-       }
-      else if (strncmp (token, "UID", 3) == 0)
-       {
-         status = imap_uid (f_imap, &sp);
-       }
-      /* else mu_error (_("not supported FETCH command"));  */
-    }
-  return status;
-}
-
-static int
-imap_search (f_imap_t f_imap MU_ARG_UNUSED)
-{
-  /* Not implemented.  No provision for this in the API, yet.  */
-  return 0;
-}
-
-static int
-imap_status (f_imap_t f_imap MU_ARG_UNUSED)
-{
-  /* Not implemented.  No provision for this in the API, yet.  */
-  return 0;
-}
-
-static int
-imap_expunge (f_imap_t f_imap MU_ARG_UNUSED, unsigned msgno MU_ARG_UNUSED)
-{
-  /* We should not have this, since do not send the expunge, but rather
-     use SELECT/CLOSE.  */
-  return 0;
-}
-
-
-/* This function will advance ptr to the next character that IMAP
-   recognise as special: " .()[]<>" and put the result in buf which
-   is of size len.  */
-static int
-imap_token (char *buf, size_t len, char **ptr)
-{
-  char *start = *ptr;
-  size_t i;
-  /* Skip leading space.  */
-  while (**ptr && **ptr == ' ')
-    (*ptr)++;
-  /* Break the string by token, when we recognise Atoms we stop.  */
-  for (i = 1; **ptr && i < len; (*ptr)++, buf++, i++)
-    {
-      if (**ptr == ' ' || **ptr == '.'
-         || **ptr == '(' || **ptr == ')'
-         || **ptr == '[' || **ptr == ']'
-         || **ptr == '<' || **ptr  == '>')
-       {
-         /* Advance.  */
-         if (start == (*ptr))
-           (*ptr)++;
-         break;
-       }
-      *buf = **ptr;
-  }
-  *buf = '\0';
-  /* Skip trailing space.  */
-  while (**ptr && **ptr == ' ')
-    (*ptr)++;
-  return  *ptr - start;;
-}
-
-/* Checks to see if a mailbox name matches a pattern, treating
-   INBOX case insensitively, as required (INBOX is a special
-   name no matter what the case is).
-   */
-static int
-imap_mailbox_name_match (const char* pattern, const char* mailbox)
-{
-  if (mu_c_strcasecmp (pattern, "inbox") == 0)
-    {
-      return mu_c_strcasecmp (pattern, mailbox);
-    }
-  return fnmatch (pattern, mailbox, 0);
-}
-
-/* C99 says that a conforming implementations of snprintf () should return the
-   number of char that would have been call but many GNU/Linux && BSD
-   implementations return -1 on error.  Worse QnX/Neutrino actually does not
-   put the terminal null char.  So let's try to cope.  */
-int
-imap_writeline (f_imap_t f_imap, const char *format, ...)
-{
-  int len;
-  va_list ap;
-  int done = 1;
-
-  va_start(ap, format);
-  do
-    {
-      va_list aq;
-      va_copy(aq, ap);
-      len = vsnprintf (f_imap->buffer, f_imap->buflen, format, aq);
-      va_end(aq);
-      if (len < 0 || len >= (int)f_imap->buflen
-          || !memchr (f_imap->buffer, '\0', len + 1))
-        {
-          f_imap->buflen *= 2;
-          f_imap->buffer = realloc (f_imap->buffer, f_imap->buflen);
-          if (f_imap->buffer == NULL)
-            return ENOMEM;
-          done = 0;
-        }
-      else
-        done = 1;
-    }
-  while (!done);
-  va_end(ap);
-  f_imap->ptr = f_imap->buffer + len;
-
-  if (DEBUG_SHOW_COMMAND)
-    fprintf (stderr, "%s", f_imap->buffer);
-  return 0;
-}
-
-/* Cover to send requests.  */
-int
-imap_send (f_imap_t f_imap)
-{
-  int status = 0;
-  if (f_imap->ptr > f_imap->buffer)
-    {
-      size_t len;
-      size_t n = 0;
-      len = f_imap->ptr - f_imap->buffer;
-      status = mu_stream_write (f_imap->folder->stream, f_imap->buffer, len,
-                            0, &n);
-      if (status == 0)
-        {
-          memmove (f_imap->buffer, f_imap->buffer + n, len - n);
-          f_imap->ptr -= n;
-        }
-    }
-  else
-    f_imap->ptr = f_imap->buffer;
-  return status;
-}
-
-/* Read a complete line form the imap server. Transform CRLF to LF, put a null
-   in the buffer when done.  Note f_imap->offset is not really of any use
-   but rather to keep the stream internal buffer scheme happy, so we have to
-   be in sync with the stream.  */
-int
-imap_readline (f_imap_t f_imap)
-{
-  size_t n = 0;
-  size_t total = f_imap->ptr - f_imap->buffer;
-  int status;
-
-  /* Must get a full line before bailing out.  */
-  do
-    {
-      status = mu_stream_readline (f_imap->folder->stream, f_imap->buffer + 
total,
-                               f_imap->buflen - total,  f_imap->offset, &n);
-      if (status != 0)
-        return status;
-
-      /* The server went away:  It maybe a timeout and some imap server
-        does not send the BYE.  Consider like an error.  */
-      if (n == 0)
-       return EIO;
-
-      total += n;
-      f_imap->offset += n;
-      f_imap->nl = memchr (f_imap->buffer, '\n', total);
-      if (f_imap->nl == NULL)  /* Do we have a full line.  */
-        {
-          /* Allocate a bigger buffer ?  */
-          if (total >= f_imap->buflen -1)
-            {
-              f_imap->buflen *= 2;
-              f_imap->buffer = realloc (f_imap->buffer, f_imap->buflen + 1);
-              if (f_imap->buffer == NULL)
-                return ENOMEM;
-            }
-        }
-      f_imap->ptr = f_imap->buffer + total;
-    }
-  while (f_imap->nl == NULL);
-
-  /* Conversion \r\n --> \n\0  */
-  /* FIXME: This should be done transparently by the TCP stream */
-  if (f_imap->nl > f_imap->buffer && f_imap->nl[-1] == '\r')
-    {
-      *(f_imap->nl - 1) = '\n';
-      *(f_imap->nl) = '\0';
-      f_imap->ptr = f_imap->nl;
-    }
-  return 0;
-}
-
-/*
-  The parsing was inspired by this article form the BeNews channel: "BE
-  ENGINEERING INSIGHTS: IMAP for the Masses." By Adam Haberlach address@hidden
-
-  The server responses are in three forms: status responses, server data,
-  and command continuation request, ...
-  An untagged response is indicated by the token "*" instead of a tag.
-  Untagged status responses indicate server greeting, or server status
-  that does not indicate the completion of a command (for example, an
-  impending system shutdown alert).
-  ....
-  The client MUST be prepared to accept any response at all times.
-
-  Status responses are OK, NO, BAD, PREAUTH and BYE.  OK, NO, and BAD
-  may be tagged or untagged.  PREAUTH and BYE are always untagged.
-
-  Server Responses - Status Responses
-  BAD *|tag
-  BYE *
-  NO *|tag
-  OK *|tag
-  PREAUTH *
-
-  The code for status responses are
-  ALERT
-  BADCHARSET(IMAPV)
-  CAPABILITY(IMAPV)
-  NEWNAME
-  PARSE
-  PERMANENTFLAGS
-  READ-ONLY
-  READ-WRITE
-  TRYCREATE
-  UIDNEXT
-  UIDVALIDITY
-  UNSEEN
-
-  Server Responses - Server and Mailbox Status.
-  These responses are always untagged.
-  CAPABILITY *
-  EXISTS *
-  EXPUNGE *
-  FLAGS *
-  FETCH *
-  LIST *
-  LSUB *
-  RECENT *
-  SEARCH *
-  STATUS *
-
-  Server Responses - Command Continuation Request
-  +
-
-*/
-int
-imap_parse (f_imap_t f_imap)
+#ifdef WITH_TLS
+static struct _mu_record _imaps_record =
 {
-  int done = 0;
-  int status = 0;
-  char empty[2];
-  char *buffer = NULL;
-  mu_folder_t folder = f_imap->folder;
-
-  /* We use that moronic hack to not check null for the tockenize strings.  */
-  empty[0] = '\0';
-  empty[1] = '\0';
-  while (! done)
-    {
-      char *tag, *response, *remainder;
-
-      status = imap_readline (f_imap);
-      if (status != 0)
-       {
-         break;
-       }
-      /* Comment out to see all reading traffic.  */
-      if (DEBUG_SHOW_RESPONSE)
-       mu_error ("\t\t%s", f_imap->buffer);
-
-      /* We do not want to step over f_imap->buffer since it can be use
-        further down the chain.  */
-      if (buffer)
-       {
-         free (buffer);
-         buffer = NULL;
-       }
-      buffer = calloc ((f_imap->ptr - f_imap->buffer) + 1, 1);
-      memcpy (buffer, f_imap->buffer, (f_imap->ptr - f_imap->buffer));
-
-      /* Tokenize the string.  */
-      {
-       char *sp = NULL;
-       tag = strtok_r (buffer, " ", &sp);
-       response = strtok_r (NULL, " ", &sp);
-       if (!response)
-         response = empty;
-       remainder = strtok_r (NULL, "\n", &sp);
-       if (!remainder)
-         remainder = empty;
-      }
-
-      if (!tag)
-       {
-         /* Just in case */
-         mu_error (_("no tag in response: %s %s"), response, remainder);
-         status = MU_ERR_FAILURE;
-       }
-      /* Is the response untagged ?  */
-      else if (tag[0] == '*')
-       {
-         MU_DEBUG2 (folder->debug, MU_DEBUG_PROT, "* %s %s\n",
-                    response, remainder);
-         /* Is it a Status Response.  */
-         if (mu_c_strcasecmp (response, "OK") == 0)
-           {
-             /* Check for status response [code].  */
-             if (*remainder == '[')
-               {
-                 char *cruft, *subtag;
-                 char *sp = NULL, *sp1;
-                 remainder++;
-                 cruft = strtok_r (remainder, "]", &sp);
-                 if (!cruft) cruft = empty;
-                 subtag = strtok_r (cruft, " ", &sp1);
-                 if (!subtag) subtag = empty;
-
-                 if (mu_c_strcasecmp (subtag, "ALERT") == 0)
-                   {
-                     /* The human-readable text contains a special alert that
-                        MUST be presented to the user in a fashion that calls
-                        the user's attention to the message.  */
-                     mu_error (_("ALERT: %s"), (sp) ? sp : "");
-                   }
-                 else if (mu_c_strcasecmp (subtag, "BADCHARSET") == 0)
-                   {
-                     /* Optionally followed by a parenthesized list of
-                        charsets.  A SEARCH failed because the given charset
-                        is not supported by this implementation.  If the
-                        optional list of charsets is given, this lists the
-                        charsets that are supported by this implementation. */
-                     mu_error (_("BAD CHARSET: %s"), (sp) ? sp : "");
-                   }
-                 else if (mu_c_strcasecmp (subtag, "CAPABILITY") == 0)
-                   {
-                     /* Followed by a list of capabilities.  This can appear
-                        in the initial OK or PREAUTH response to transmit an
-                        initial capabilities list.  This makes it unnecessary
-                        for a client to send a separate CAPABILITY command if
-                        it recognizes this response.  */
-                     parse_capa (f_imap, cruft);
-                   }
-                 else if (mu_c_strcasecmp (subtag, "NEWNAME") == 0)
-                   {
-                     /* Followed by a mailbox name and a new mailbox name.  A
-                        SELECT or EXAMINE failed because the target mailbox
-                        name (which once existed) was renamed to the new
-                        mailbox name.  This is a hint to the client that the
-                        operation can succeed if the SELECT or EXAMINE is
-                        reissued with the new mailbox name. */
-                     mu_error ("NEWNAME: %s", (sp) ? sp : "");
-                   }
-                 else if (mu_c_strcasecmp (subtag, "PARSE") == 0)
-                   {
-                     /* The human-readable text represents an error in
-                        parsing the [RFC-822] header or [MIME-IMB] headers
-                        of a message in the mailbox.  */
-                     mu_error ("PARSE: %s", (sp) ? sp : "");
-                   }
-                 else if (mu_c_strcasecmp (subtag, "PERMANENTFLAGS") == 0)
-                   {
-                     /* Followed by a parenthesized list of flags, indicates
-                        which of the known flags that the client can change
-                        permanently.  Any flags that are in the FLAGS
-                        untagged response, but not the PERMANENTFLAGS list,
-                        can not be set permanently.  If the client attempts
-                        to STORE a flag that is not in the PERMANENTFLAGS
-                        list, the server will either ignore the change or
-                        store the state change for the remainder of the
-                        current session only. The PERMANENTFLAGS list can
-                        also include the special flag \*, which indicates
-                        that it is possible to create new keywords by
-                        attempting to store those flags in the mailbox.  */
-                   }
-                 else if (mu_c_strcasecmp (subtag, "READ-ONLY") == 0)
-                   {
-                     /* The mailbox is selected read-only, or its access
-                        while selected has changed from read-write to
-                        read-only.  */
-                   }
-                 else if (mu_c_strcasecmp (subtag, "READ-WRITE") == 0)
-                   {
-                     /* The mailbox is selected read-write, or its access
-                        while selected has changed from read-only to
-                        read-write.  */
-                   }
-                 else if (mu_c_strcasecmp (subtag, "TRYCREATE") == 0)
-                   {
-                     /* An APPEND or COPY attempt is failing because the
-                        target mailbox does not exist (as opposed to some
-                        other reason).  This is a hint to the client that
-                        the operation can succeed if the mailbox is first
-                        created by the CREATE command.  */
-                     mu_error ("TRYCREATE: %s", (sp) ? sp : "");
-                   }
-                 else if (mu_c_strcasecmp (subtag, "UIDNEXT") == 0)
-                   {
-                     /* Followed by a decimal number, indicates the next
-                        unique identifier value.  Refer to section 2.3.1.1
-                        for more information.  */
-                     char *value = strtok_r (NULL, " ", &sp1);
-                     if (value)
-                       f_imap->selected->uidnext = strtol (value, NULL, 10);
-                   }
-                 else if (mu_c_strcasecmp (subtag, "UIDVALIDITY") == 0)
-                   {
-                     /* Followed by a decimal number, indicates the unique
-                        identifier validity value.  Refer to section 2.3.1.1
-                        for more information.  */
-                     char *value = strtok_r (NULL, " ", &sp1);
-                     if (value)
-                       f_imap->selected->uidvalidity = strtol (value,
-                                                               NULL, 10);
-                   }
-                 else if (mu_c_strcasecmp (subtag, "UNSEEN") == 0)
-                   {
-                     /* Followed by a decimal number, indicates the number of
-                        the first message without the \Seen flag set.  */
-                     char *value = strtok_r (NULL, " ", &sp1);
-                     if (value)
-                       f_imap->selected->unseen = strtol (value, NULL, 10);
-                   }
-                 else
-                   {
-                     /* Additional response codes defined by particular
-                        client or server implementations SHOULD be prefixed
-                        with an "X" until they are added to a revision of
-                        this protocol.  Client implementations SHOULD ignore
-                        response codes that they do not recognize.  */
-                   }
-               } /* End of code.  */
-             else
-               {
-                 /* Not sure why we would get an untagged ok...but we do... */
-                 /* Still should we be verbose about is ? */
-                 mu_error (_("untagged OK response: %s"), remainder);
-               }
-           }
-         else if (mu_c_strcasecmp (response, "NO") == 0)
-           {
-             /* This does not mean failure but rather a strong warning.  */
-             mu_error (_("untagged NO response: %s"), remainder);
-           }
-         else if (mu_c_strcasecmp (response, "BAD") == 0)
-           {
-             /* We're dead, protocol/syntax error.  */
-             mu_error (_("untagged BAD response: %s"), remainder);
-           }
-         else if (mu_c_strcasecmp (response, "PREAUTH") == 0)
-           {
-             /* Should we be dealing with this?  */
-           }
-         else if (mu_c_strcasecmp (response, "BYE") == 0)
-           {
-             /* We should close the stream. This is not recoverable.  */
-             done = 1;
-             mu_monitor_wrlock (f_imap->folder->monitor);
-             f_imap->isopen = 0;
-             f_imap->selected = NULL;
-             mu_monitor_unlock (f_imap->folder->monitor);
-             mu_stream_close (f_imap->folder->stream);
-           }
-         else if (mu_c_strcasecmp (response, "CAPABILITY") == 0)
-           {
-             parse_capa (f_imap, remainder);
-           }
-         else if (mu_c_strcasecmp (remainder, "EXISTS") == 0)
-           {
-             f_imap->selected->messages_count = strtol (response, NULL, 10);
-           }
-         else if (mu_c_strcasecmp (remainder, "EXPUNGE") == 0)
-           {
-             unsigned int msgno = strtol (response, NULL, 10);
-             status = imap_expunge (f_imap, msgno);
-           }
-         else if (mu_c_strncasecmp (remainder, "FETCH", 5) == 0)
-           {
-             status = imap_fetch (f_imap);
-             if (status != 0)
-               break;
-           }
-         else if (mu_c_strcasecmp (response, "FLAGS") == 0)
-           {
-             /* Flags define on the mailbox not a message flags.  */
-             status = imap_permanentflags (f_imap, &remainder);
-           }
-         else if (mu_c_strcasecmp (response, "LIST") == 0)
-           {
-             status = imap_list (f_imap);
-           }
-         else if (mu_c_strcasecmp (response, "LSUB") == 0)
-           {
-             status = imap_list (f_imap);
-           }
-         else if (mu_c_strcasecmp (remainder, "RECENT") == 0)
-           {
-             f_imap->selected->recent = strtol (response, NULL, 10);
-           }
-         else if (mu_c_strcasecmp (response, "SEARCH") == 0)
-           {
-             status = imap_search (f_imap);
-           }
-         else if (mu_c_strcasecmp (response, "STATUS") == 0)
-           {
-             status = imap_status (f_imap);
-           }
-         else
-           {
-             /* Once again, check for something strange.  */
-             mu_error (_("unknown untagged response: \"%s\"  %s"),
-                       response, remainder);
-           }
-       }
-      /* Continuation token ???.  */
-      else if (tag[0] == '+')
-       {
-         done = 1;
-       }
-      else
-       {
-         /* Every transaction ends with a tagged response.  */
-         done = 1;
-         if (mu_c_strcasecmp (response, "OK") == 0)
-           {
-             /* Cool we are doing ok.  */
-           }
-         else if (mu_c_strcasecmp (response, "NO") == 0)
-           {
-             if (mu_c_strncasecmp (remainder, "LOGIN", 5) == 0)
-               {
-                 mu_observable_t observable = NULL;
-                 mu_folder_get_observable (f_imap->folder, &observable);
-                 mu_observable_notify (observable, 
MU_EVT_FOLDER_AUTHORITY_FAILED,
-                                       NULL);
-                 status = MU_ERR_AUTH_FAILURE;
-               }
-             else if (mu_c_strncasecmp (remainder, "LIST", 4) == 0)
-               status = MU_ERR_NOENT;
-             else
-               status = MU_ERR_FAILURE;
-           }
-         else /* NO and BAD */
-           {
-             status = EINVAL;
-             mu_error (_("NO or BAD tagged response: %s %s %s"),
-                       tag, response, remainder);
-           }
-       }
-      f_imap->ptr = f_imap->buffer;
-    }
-
-  if (buffer)
-    free (buffer);
-  return status;
-}
-
+  MU_IMAP_PRIO,
+  MU_IMAPS_SCHEME,
+  MU_RECORD_DEFAULT,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PATH | MU_URL_PARAM,
+  MU_URL_HOST,
+  _mu_imaps_url_init,     /* url entry.  */
+  _mu_imaps_mailbox_init, /* Mailbox entry.  */
+  NULL,                /* Mailer entry.  */
+  _mu_imap_folder_init,   /* Folder entry.  */
+  NULL, /* No need for a back pointer.  */
+  NULL, /* _is_scheme method.  */
+  NULL, /* _get_url method.  */
+  NULL, /* _get_mailbox method.  */
+  NULL, /* _get_mailer method.  */
+  NULL  /* _get_folder method.  */
+};
+mu_record_t mu_imaps_record = &_imaps_record;
 #else
-#include <stdio.h>
-#include <mailutils/sys/registrar.h>
-mu_record_t mu_imap_record = NULL;
 mu_record_t mu_imaps_record = NULL;
-#endif /* ENABLE_IMAP */
+#endif /* WITH_TLS */
diff --git a/libproto/imap/genlist.c b/libproto/imap/genlist.c
index 5931963..4feeb1c 100644
--- a/libproto/imap/genlist.c
+++ b/libproto/imap/genlist.c
@@ -104,13 +104,15 @@ list_untagged_handler (mu_imap_t imap, mu_list_t resp, 
void *data)
        }
 
       elt = _mu_imap_list_at (resp, 2);
-      if (!(elt && elt->type == imap_eltype_string))
+      if (!elt)
        return;
-      if (mu_c_strcasecmp (elt->v.string, "NIL") == 0)
+      if (_mu_imap_list_element_is_nil (elt))
        {
          rp->separator = 0;
          rp->level = 0;
        }
+      else if (elt->type != imap_eltype_string)
+       return;
       else
        {
          rp->separator = elt->v.string[0];
@@ -131,6 +133,9 @@ mu_imap_genlist (mu_imap_t imap, int lsub,
   struct list_closure clos;
   int rc;
 
+  if (!refname || !mboxname)
+    return EINVAL;
+  
   argv[0] = lsub ? "LSUB" : "LIST";
   argv[1] = refname;
   argv[2] = mboxname;
diff --git a/libproto/imap/login.c b/libproto/imap/login.c
index 807d7b4..efdfb4b 100644
--- a/libproto/imap/login.c
+++ b/libproto/imap/login.c
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <mailutils/errno.h>
 #include <mailutils/stream.h>
+#include <mailutils/secret.h>
 #include <mailutils/sys/imap.h>
 
 int
@@ -77,3 +78,12 @@ mu_imap_login (mu_imap_t imap, const char *user, const char 
*pass)
   return status;
 }
 
+int
+mu_imap_login_secret (mu_imap_t imap, const char *user, mu_secret_t secret)
+{
+  int rc = mu_imap_login (imap, user, mu_secret_password (secret));
+  mu_secret_password_unref (secret);
+  return rc;
+}
+  
+  
diff --git a/libproto/imap/mbox.c b/libproto/imap/mbox.c
deleted file mode 100644
index 87cc10c..0000000
--- a/libproto/imap/mbox.c
+++ /dev/null
@@ -1,2142 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2009,
-   2010, 2011 Free Software Foundation, Inc.
-
-   This library 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 of the License, or (at your option) any later version.
-
-   This library 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 this library.  If not, see
-   <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef ENABLE_IMAP
-
-#include <errno.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#include <stdlib.h>
-#include <assert.h>
-#include <time.h>
-
-#include <mailutils/address.h>
-#include <mailutils/attribute.h>
-#include <mailutils/body.h>
-#include <mailutils/debug.h>
-#include <mailutils/envelope.h>
-#include <mailutils/error.h>
-#include <mailutils/errno.h>
-#include <mailutils/header.h>
-#include <mailutils/message.h>
-#include <mailutils/util.h>
-#include <mailutils/observer.h>
-#include <mailutils/property.h>
-#include <mailutils/stream.h>
-#include <mailutils/io.h>
-
-#include <mailutils/sys/imap.h>
-#include <mailutils/sys/mailbox.h>
-#include <mailutils/sys/registrar.h>
-#include <mailutils/sys/url.h>
-
-#undef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-
-#define MU_IMAP_CACHE_HEADERS "Bcc Cc Content-Language 
Content-Transfer-Encoding Content-Type Date From In-Reply-To Message-ID 
Reference Reply-To Sender Subject To X-UIDL"
-
-/* mu_mailbox_t API.  */
-static void mailbox_imap_destroy  (mu_mailbox_t);
-static int  mailbox_imap_open     (mu_mailbox_t, int);
-static int  mailbox_imap_close    (mu_mailbox_t);
-static int  imap_uidvalidity      (mu_mailbox_t, unsigned long *);
-static int  imap_uidnext          (mu_mailbox_t, size_t *);
-static int  imap_expunge          (mu_mailbox_t);
-static int  imap_get_message      (mu_mailbox_t, size_t, mu_message_t *);
-static int  imap_messages_count   (mu_mailbox_t, size_t *);
-static int  imap_messages_recent  (mu_mailbox_t, size_t *);
-static int  imap_message_unseen   (mu_mailbox_t, size_t *);
-static int  imap_scan             (mu_mailbox_t, size_t, size_t *);
-static int  imap_scan0            (mu_mailbox_t, size_t, size_t *, int);
-static int  imap_is_updated       (mu_mailbox_t);
-static int  imap_append_message   (mu_mailbox_t, mu_message_t);
-static int  imap_append_message0  (mu_mailbox_t, mu_message_t);
-static int  imap_copy_message     (mu_mailbox_t, mu_message_t);
-
-/* mu_message_t API.  */
-static int  imap_submessage_size  (msg_imap_t, size_t *);
-static int  imap_message_size     (mu_message_t, size_t *);
-static int  imap_message_lines    (mu_message_t, size_t *);
-static int  imap_message_get_transport2  (mu_stream_t, mu_transport_t *pin, 
-                                          mu_transport_t *pout);
-static int  imap_message_read     (mu_stream_t , char *, size_t, mu_off_t, 
size_t *);
-static int  imap_message_uid      (mu_message_t, size_t *);
-
-/* mu_mime_t API.  */
-static int  imap_is_multipart     (mu_message_t, int *);
-static int  imap_get_num_parts    (mu_message_t, size_t *);
-static int  imap_get_part         (mu_message_t, size_t, mu_message_t *);
-
-/* mu_envelope_t API  */
-static int  imap_envelope_sender  (mu_envelope_t, char *, size_t, size_t *);
-static int  imap_envelope_date    (mu_envelope_t, char *, size_t, size_t *);
-
-/* mu_attribute_t API  */
-static int  imap_attr_get_flags   (mu_attribute_t, int *);
-static int  imap_attr_set_flags   (mu_attribute_t, int);
-static int  imap_attr_unset_flags (mu_attribute_t, int);
-
-/* mu_header_t API.  */
-static int  imap_header_read      (mu_header_t, char*, size_t, mu_off_t, 
size_t *);
-
-/* mu_body_t API.  */
-static int  imap_body_read        (mu_stream_t, char *, size_t, mu_off_t, 
size_t *);
-static int  imap_body_size        (mu_body_t, size_t *);
-static int  imap_body_lines       (mu_body_t, size_t *);
-static int  imap_body_get_transport2 (mu_stream_t, mu_transport_t *pin, 
mu_transport_t *pout);
-
-/* Helpers.  */
-static int  imap_get_transport2    (msg_imap_t msg_imap, 
-                                    mu_transport_t *pin,
-                                    mu_transport_t *pout);
-static int  imap_get_message0     (msg_imap_t, mu_message_t *);
-static int  fetch_operation       (f_imap_t, msg_imap_t, char *, size_t, 
size_t *);
-static void free_subparts         (msg_imap_t);
-static int  flags_to_string       (char **, int);
-static int  delete_to_string      (m_imap_t, char **);
-static int  is_same_folder        (mu_mailbox_t, mu_message_t);
-
-#define MBX_WRITABLE(mbx) ((mbx)->flags & 
(MU_STREAM_WRITE|MU_STREAM_RDWR|MU_STREAM_CREAT))
-
-/* Initialize the concrete object mu_mailbox_t by overloading the function of 
the
-   structure.  */
-int
-_mailbox_imap_and_imaps_init (mu_mailbox_t mailbox, int imaps)
-{
-  int status;
-  m_imap_t m_imap;
-
-  if (!mailbox)
-    return EINVAL;
-  if (mailbox->folder == NULL)
-    return EINVAL;
-  
-  m_imap = mailbox->data = calloc (1, sizeof (*m_imap));
-  if (m_imap == NULL)
-    return ENOMEM;
-
-  /* Retrieve the name of the mailbox from the URL.  */
-  status = mu_url_aget_path (mailbox->url, &m_imap->name);
-  if (status == MU_ERR_NOENT)
-    {
-      m_imap->name = strdup ("INBOX");
-      if (!m_imap->name)
-        return ENOMEM;
-    }
-  else if (status)
-    return status;
-
-  /* Overload the functions.  */
-  mailbox->_destroy = mailbox_imap_destroy;
-
-  mailbox->_open = mailbox_imap_open;
-  mailbox->_close = mailbox_imap_close;
-
-  /* Messages.  */
-  mailbox->_get_message = imap_get_message;
-  mailbox->_append_message = imap_append_message;
-  mailbox->_messages_count = imap_messages_count;
-  mailbox->_messages_recent = imap_messages_recent;
-  mailbox->_message_unseen = imap_message_unseen;
-  mailbox->_expunge = imap_expunge;
-  mailbox->_uidvalidity = imap_uidvalidity;
-  mailbox->_uidnext = imap_uidnext;
-
-  mailbox->_scan = imap_scan;
-  mailbox->_is_updated = imap_is_updated;
-
-  /* Get the back pointer of the concrete folder. */
-  m_imap->f_imap = mailbox->folder->data;
-  m_imap->f_imap->imaps = imaps;
-  
-  /* maibox back pointer.  */
-  m_imap->mailbox = mailbox;
-
-  /* Set our properties.  */
-  {
-    mu_property_t property = NULL;
-    mu_mailbox_get_property (mailbox, &property);
-    mu_property_set_value (property, "TYPE", "IMAP4", 1);
-  }
-
-  return 0;
-}
-
-int
-_mailbox_imap_init (mu_mailbox_t mailbox)
-{
-  return _mailbox_imap_and_imaps_init (mailbox, 0);
-}
-
-int
-_mailbox_imaps_init (mu_mailbox_t mailbox)
-{
-  return _mailbox_imap_and_imaps_init (mailbox, 1);
-}
-
-
-/* Recursive call to free all the subparts of a message.  */
-static void
-free_subparts (msg_imap_t msg_imap)
-{
-  size_t i;
-  for (i = 0; i < msg_imap->num_parts; i++)
-    {
-      if (msg_imap->parts[i])
-       free_subparts (msg_imap->parts[i]);
-    }
-
-  if (msg_imap->message)
-    mu_message_destroy (&(msg_imap->message), msg_imap);
-  if (msg_imap->parts)
-    free (msg_imap->parts);
-  if (msg_imap->fheader)
-    mu_header_destroy (&msg_imap->fheader, NULL);
-  if (msg_imap->internal_date)
-    free (msg_imap->internal_date);
-  free(msg_imap);
-}
-
-/* Give back all the resources. But it does not mean to shutdown the channel
-   this is done on the folder.  */
-static void
-mailbox_imap_destroy (mu_mailbox_t mailbox)
-{
-  if (mailbox->data)
-    {
-      m_imap_t m_imap = mailbox->data;
-      f_imap_t f_imap = m_imap->f_imap;
-      size_t i;
-
-      /* Deselect.  */
-      if (m_imap != f_imap->selected)
-       f_imap->selected = NULL;
-
-      mu_monitor_wrlock (mailbox->monitor);
-      /* Destroy the imap messages and ressources associated to them.  */
-      for (i = 0; i < m_imap->imessages_count; i++)
-       {
-         if (m_imap->imessages[i])
-           free_subparts (m_imap->imessages[i]);
-       }
-      if (m_imap->imessages)
-       free (m_imap->imessages);
-      if (m_imap->name)
-       free (m_imap->name);
-      free (m_imap);
-      mailbox->data = NULL;
-      mu_monitor_unlock (mailbox->monitor);
-    }
-}
-
-/* If the connection was not up it is open by the folder since the stream
-   socket is actually created by the folder.  It is not necessary
-   to set select the mailbox right away, there are maybe on going operations.
-   But on any operation by a particular mailbox, it will be selected first.  */
-static int
-mailbox_imap_open (mu_mailbox_t mailbox, int flags)
-{
-  int status = 0;
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-  mu_folder_t folder = f_imap->folder;
-  mu_list_t folders = NULL;
-  size_t count;
-  
-  /* m_imap must have been created during mailbox initialization. */
-  assert (mailbox->data);
-  assert (m_imap->name);
-
-  mailbox->flags = flags;
-
-  if ((status = mu_folder_open (mailbox->folder, flags)))
-    return status;
-
-  /* We might not have to SELECT the mailbox, but we need to know it
-     exists, and CREATE it if it doesn't, and CREATE is specified in
-     the flags.
-   */
-
-  switch (m_imap->state)
-    {
-    case IMAP_NO_STATE:
-      m_imap->state = IMAP_LIST;
-
-    case IMAP_LIST:
-      status = mu_folder_list (folder, NULL, m_imap->name, 0, &folders);
-      if (status != 0)
-       {
-         if (status != EAGAIN && status != EINPROGRESS && status != EINTR)
-           m_imap->state = IMAP_NO_STATE;
-
-         return status;
-       }
-      m_imap->state = IMAP_NO_STATE;
-      status = mu_list_count (folders, &count);
-      mu_list_destroy (&folders);
-      if (status || count)
-       return 0;
-
-      if ((flags & MU_STREAM_CREAT) == 0)
-       return ENOENT;
-
-      m_imap->state = IMAP_CREATE;
-
-    case IMAP_CREATE:
-      switch (f_imap->state)
-       {
-       case IMAP_NO_STATE:
-         {
-           const char *path;
-           status = mu_url_sget_path (folder->url, &path);
-           if (status == MU_ERR_NOENT)
-             return 0;
-           else if (status)
-             return status;
-           status = imap_writeline (f_imap, "g%lu CREATE %s\r\n",
-                                    (unsigned long) f_imap->seq, path);
-           MU_DEBUG2 (folder->debug, MU_DEBUG_PROT, "g%lu CREATE %s\n",
-                      (unsigned long) f_imap->seq, path);
-           f_imap->seq++;
-           if (status != 0)
-             {
-               m_imap->state = f_imap->state = IMAP_NO_STATE;
-               return status;
-             }
-           f_imap->state = IMAP_CREATE;
-         }
-
-       case IMAP_CREATE:
-         status = imap_send (f_imap);
-         if (status != 0)
-           {
-             if (status != EAGAIN && status != EINPROGRESS
-                 && status != EINTR)
-               m_imap->state = f_imap->state = IMAP_NO_STATE;
-
-             return status;
-           }
-         f_imap->state = IMAP_CREATE_ACK;
-
-       case IMAP_CREATE_ACK:
-         status = imap_parse (f_imap);
-         if (status != 0)
-           {
-             if (status == EINVAL)
-               status = EACCES;
-
-             if (status != EAGAIN && status != EINPROGRESS
-                 && status != EINTR)
-               m_imap->state = f_imap->state = IMAP_NO_STATE;
-
-             return status;
-           }
-         f_imap->state = IMAP_NO_STATE;
-         break;
-
-       default:
-         status = EINVAL;
-         break;
-       }
-      m_imap->state = IMAP_NO_STATE;
-      break;
-
-    default:
-      status = EINVAL;
-      break;
-    }
-
-  return status;
-}
-
-/* We can not close the folder in term of shuting down the connection but if
-   we were the selected mailbox we send the close and deselect ourself.
-   The CLOSE is also use to expunge instead of sending expunge.  */
-static int
-mailbox_imap_close (mu_mailbox_t mailbox)
-{
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status = 0;
-  
-  /* If we are not the selected mailbox, just close the stream.  */
-  if (m_imap != f_imap->selected)
-    return mu_folder_close (mailbox->folder);
-
-  /* Select first.  */
-  status = imap_messages_count (mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu CLOSE\r\n",
-                              (unsigned long) f_imap->seq++);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_CLOSE;
-
-    case IMAP_CLOSE:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_CLOSE_ACK;
-
-    case IMAP_CLOSE_ACK:
-      {
-       size_t i;
-       status = imap_parse (f_imap);
-       CHECK_EAGAIN (f_imap, status);
-       MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-       mu_monitor_wrlock (mailbox->monitor);
-       /* Destroy the imap messages and ressources associated to them.  */
-       for (i = 0; i < m_imap->imessages_count; i++)
-         {
-           if (m_imap->imessages[i])
-             free_subparts (m_imap->imessages[i]);
-         }
-       if (m_imap->imessages)
-         free (m_imap->imessages);
-       m_imap->imessages = NULL;
-       m_imap->imessages_count = 0;
-       m_imap->messages_count = 0;
-       m_imap->recent = 0;
-       m_imap->unseen = 0;
-       /* Clear the callback string structure.  */
-       mu_stream_truncate (f_imap->string.stream, 0);
-       f_imap->string.offset = 0;
-       f_imap->string.nleft = 0;
-       f_imap->string.type = IMAP_NO_STATE;
-       f_imap->string.msg_imap = NULL;
-       mu_monitor_unlock (mailbox->monitor);
-      }
-      break;
-
-    default:
-      /* mu_error ("imap_close unknown state: reconnect\n");*/
-      break;
-    }
-
-  /* Deselect.  */
-  f_imap->selected = NULL;
-
-  f_imap->state = IMAP_NO_STATE;
-  return mu_folder_close (mailbox->folder);
-}
-
-/* Construction of the mu_message_t, nothing else is done then this setup.  To
-   clarify this is different from say mu_message_get_part().  This call is for 
the
-   mailbox and we are setting up the mu_message_t structure.  */
-static int
-imap_get_message (mu_mailbox_t mailbox, size_t msgno, mu_message_t *pmsg)
-{
-  m_imap_t m_imap = mailbox->data;
-  msg_imap_t msg_imap;
-  int status = 0;
-
-  if (pmsg == NULL)
-    return MU_ERR_OUT_PTR_NULL;
-  if (msgno == 0 || msgno > m_imap->messages_count)
-    return EINVAL;
-
-  /* Check to see if we have already this message.  */
-  mu_monitor_rdlock (mailbox->monitor);
-  {
-    size_t i;
-    for (i = 0; i < m_imap->imessages_count; i++)
-      {
-       if (m_imap->imessages[i])
-         {
-           if (m_imap->imessages[i]->num == msgno)
-             {
-               *pmsg = m_imap->imessages[i]->message;
-               mu_monitor_unlock (mailbox->monitor);
-               return 0;
-             }
-         }
-      }
-  }
-  mu_monitor_unlock (mailbox->monitor);
-
-  /* Allocate a concrete imap message.  */
-  msg_imap = calloc (1, sizeof *msg_imap);
-  if (msg_imap == NULL)
-    return ENOMEM;
-  /* Back pointer.  */
-  msg_imap->m_imap = m_imap;
-  msg_imap->num = msgno;
-  status = imap_get_message0 (msg_imap, pmsg);
-  if (status == 0)
-    {
-      /* Add it to the list.  */
-      mu_monitor_wrlock (mailbox->monitor);
-      {
-       msg_imap_t *m ;
-       m = realloc (m_imap->imessages,
-                    (m_imap->imessages_count + 1) * sizeof *m);
-       if (m == NULL)
-         {
-           mu_message_destroy (pmsg, msg_imap);
-           mu_monitor_unlock (mailbox->monitor);
-           return ENOMEM;
-         }
-       m_imap->imessages = m;
-       m_imap->imessages[m_imap->imessages_count] = msg_imap;
-       m_imap->imessages_count++;
-      }
-      mu_monitor_unlock (mailbox->monitor);
-
-      msg_imap->message = *pmsg;
-    }
-  else
-    free (msg_imap);
-  return status;
-}
-
-/* Set all the mu_message_t functions and parts.  */
-static int
-imap_get_message0 (msg_imap_t msg_imap, mu_message_t *pmsg)
-{
-  int status = 0;
-  mu_message_t msg = NULL;
-  mu_mailbox_t mailbox = msg_imap->m_imap->mailbox;
-
-  /* Create the message and its stream.  */
-  {
-    mu_stream_t stream = NULL;
-    if ((status = mu_message_create (&msg, msg_imap)) != 0
-        || (status = mu_stream_create (&stream, mailbox->flags, msg)) != 0)
-      {
-        mu_stream_destroy (&stream, msg);
-        mu_message_destroy (&msg, msg_imap);
-        return status;
-      }
-    mu_stream_setbufsiz (stream, 128);
-    mu_stream_set_read (stream, imap_message_read, msg);
-    mu_stream_set_get_transport2 (stream, imap_message_get_transport2, msg);
-    mu_message_set_stream (msg, stream, msg_imap);
-    mu_message_set_size (msg, imap_message_size, msg_imap);
-    mu_message_set_lines (msg, imap_message_lines, msg_imap);
-  }
-
-  /* Create the header.  */
-  {
-    mu_header_t header = NULL;
-    if ((status = mu_header_create (&header, NULL, 0,  msg)) != 0)
-      {
-        mu_message_destroy (&msg, msg_imap);
-        return status;
-      }
-    mu_header_set_fill (header, imap_header_read, msg);
-    mu_message_set_header (msg, header, msg_imap);
-  }
-
-  /* Create the attribute.  */
-  {
-    mu_attribute_t attribute;
-    status = mu_attribute_create (&attribute, msg);
-    if (status != 0)
-      {
-        mu_message_destroy (&msg, msg_imap);
-        return status;
-      }
-    mu_attribute_set_get_flags (attribute, imap_attr_get_flags, msg);
-    mu_attribute_set_set_flags (attribute, imap_attr_set_flags, msg);
-    mu_attribute_set_unset_flags (attribute, imap_attr_unset_flags, msg);
-    mu_message_set_attribute (msg, attribute, msg_imap);
-  }
-
-  /* Create the body and its stream.  */
-  {
-    mu_body_t body = NULL;
-    mu_stream_t stream = NULL;
-    if ((status = mu_body_create (&body, msg)) != 0
-        || (status = mu_stream_create (&stream, mailbox->flags, body)) != 0)
-      {
-        mu_body_destroy (&body, msg);
-        mu_stream_destroy (&stream, body);
-        mu_message_destroy (&msg, msg_imap);
-        return status;
-      }
-    mu_stream_setbufsiz (stream, 128);
-    mu_stream_set_read (stream, imap_body_read, body);
-    mu_stream_set_get_transport2 (stream, imap_body_get_transport2, body);
-    mu_body_set_size (body, imap_body_size, msg);
-    mu_body_set_lines (body, imap_body_lines, msg);
-    mu_body_set_stream (body, stream, msg);
-    mu_message_set_body (msg, body, msg_imap);
-  }
-
-  /* Set the envelope.  */
-  {
-    mu_envelope_t envelope= NULL;
-    status = mu_envelope_create (&envelope, msg);
-    if (status != 0)
-      {
-        mu_message_destroy (&msg, msg_imap);
-        return status;
-      }
-    mu_envelope_set_sender (envelope, imap_envelope_sender, msg);
-    mu_envelope_set_date (envelope, imap_envelope_date, msg);
-    mu_message_set_envelope (msg, envelope, msg_imap);
-  }
-
-  /* Set the mime handling.  */
-  mu_message_set_is_multipart (msg, imap_is_multipart, msg_imap);
-  mu_message_set_get_num_parts (msg, imap_get_num_parts, msg_imap);
-  mu_message_set_get_part (msg, imap_get_part, msg_imap);
-
-  /* Set the UID on the message. */
-  mu_message_set_uid (msg, imap_message_uid, msg_imap);
-  mu_message_set_mailbox (msg, mailbox, msg_imap);
-
-  /* We are done here.  */
-  *pmsg = msg;
-  return 0;
-}
-
-static int
-imap_message_unseen (mu_mailbox_t mailbox, size_t *punseen)
-{
-  m_imap_t m_imap = mailbox->data;
-  *punseen = m_imap->unseen;
-  return 0;
-}
-
-static int
-imap_messages_recent (mu_mailbox_t mailbox, size_t *precent)
-{
-  m_imap_t m_imap = mailbox->data;
-  *precent = m_imap->recent;
-  return 0;
-}
-
-static int
-imap_uidvalidity (mu_mailbox_t mailbox, unsigned long *puidvalidity)
-{
-  m_imap_t m_imap = mailbox->data;
-  *puidvalidity = m_imap->uidvalidity;
-  return 0;
-}
-
-static int
-imap_uidnext (mu_mailbox_t mailbox, size_t *puidnext)
-{
-  m_imap_t m_imap = mailbox->data;
-  *puidnext = m_imap->uidnext;
-  return 0;
-}
-
-/* There is no explicit call to get the message count.  The count is send on
-   a SELECT/EXAMINE command it is also sent async, meaning it will be piggy
-   back on other server response as an untag "EXIST" response.  The
-   function is also use as a way to select mailbox by other functions.  */
-static int
-imap_messages_count (mu_mailbox_t mailbox, size_t *pnum)
-{
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status = 0;
-
-  /* FIXME: It is debatable if we should reconnect when the connection
-     timeout or die.  Probably for timeout client should ping i.e. send
-     a NOOP via imap_is_updated() function to keep the connection alive.  */
-  status = mu_folder_open (mailbox->folder, mailbox->flags);
-  if (status != 0)
-    return status;
-
-  /* Are we already selected ? */
-  if (m_imap == (f_imap->selected))
-    {
-      if (pnum)
-       *pnum = m_imap->messages_count;
-      return 0;
-    }
-
-  /*  Put the mailbox as selected.  */
-  f_imap->selected = m_imap;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu %s %s\r\n",
-                              (unsigned long) f_imap->seq++, 
-                               MBX_WRITABLE(mailbox) ? "SELECT" : "EXAMINE",
-                               m_imap->name);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_SELECT;
-
-    case IMAP_SELECT:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_SELECT_ACK;
-
-    case IMAP_SELECT_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      break;
-
-    default:
-      /*mu_error ("imap_message_count unknown state: reconnect\n");*/
-      break;
-    }
-
-  if (pnum)
-    *pnum = m_imap->messages_count;
-
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-static int
-imap_scan (mu_mailbox_t mailbox, size_t msgno, size_t *pcount)
-{
-  return imap_scan0 (mailbox, msgno, pcount , 1);
-}
-
-/* Normally this function is called when an observer is trying to build
-   some sort of list/tree header as the scanning progresses.  But doing
-   this for each message can be time consuming and inefficient.  So we
-   bundle all requests into one and ask the server for everything:
-   "FETCH 1:*".  The good side is that everything will be faster and we
-   do not do lots of small transcations, but rather a big one.  The bad
-   side is that everything will be cached in the structure using a lot of
-   memory.  */
-static int
-imap_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int notif)
-{
-  int status;
-  size_t i;
-  size_t count = 0;
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-
-  /* Selected.  */
-  status = imap_messages_count (mailbox, &count);
-  if (pcount)
-    *pcount = count;
-  if (status != 0)
-    return status;
-
-  /* No need to scan, there is no messages. */
-  if (count == 0)
-    return 0;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap,
-                              "g%lu FETCH 1:* (FLAGS RFC822.SIZE 
BODY.PEEK[HEADER.FIELDS (%s)])\r\n",
-                              (unsigned long) f_imap->seq++,
-                              MU_IMAP_CACHE_HEADERS);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_SCAN;
-
-    case IMAP_SCAN:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_SCAN_ACK;
-      /* Clear the callback string structure.  */
-      mu_stream_truncate (f_imap->string.stream, 0);
-      f_imap->string.offset = 0;
-      f_imap->string.nleft = 0;
-      f_imap->string.type = IMAP_NO_STATE;
-      f_imap->string.msg_imap = NULL;
-
-    case IMAP_SCAN_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      /* Clear the callback string structure.  */
-      mu_stream_truncate (f_imap->string.stream, 0);
-      f_imap->string.offset = 0;
-      f_imap->string.nleft = 0;
-      f_imap->string.type = IMAP_NO_STATE;
-      f_imap->string.msg_imap = NULL;
-      break;
-
-    default:
-      /*mu_error ("imap_scan unknown state: reconnect\n");*/
-      return EINVAL;
-    }
-
-  f_imap->state = IMAP_NO_STATE;
-
-  /* Do not send notifications.  */
-  if (!notif)
-    return 0;
-
-  /* If no callbacks bail out early.  */
-  if (mailbox->observable == NULL)
-    return 0;
-
-  for (i = msgno; i <= count; i++)
-    {
-      size_t tmp = i;
-      if (mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_ADD,
-                                &tmp) != 0)
-       break;
-      if ((i + 1) % 100 == 0)
-       mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_PROGRESS, 
-                              NULL);
-    }
-  return 0;
-}
-
-/* Send a NOOP and see if the count has changed.  */
-static int
-imap_is_updated (mu_mailbox_t mailbox)
-{
-  m_imap_t m_imap = mailbox->data;
-  size_t oldcount = m_imap->messages_count;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status = 0;
-
-  /* Selected.  */
-  status = imap_messages_count (mailbox, &oldcount);
-  if (status != 0)
-    return status;
-
-  /* Send a noop, and let imap piggy pack the information.  */
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      status = imap_writeline (f_imap, "g%lu NOOP\r\n",
-                              (unsigned long) f_imap->seq++);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_NOOP;
-
-    case IMAP_NOOP:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_NOOP_ACK;
-
-    case IMAP_NOOP_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      break;
-
-    default:
-      /*mu_error ("imap_noop unknown state: reconnect\n"); */
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  return (oldcount == m_imap->messages_count);
-}
-
-
-static int
-imap_expunge (mu_mailbox_t mailbox)
-{
-  int status;
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-
-  if (!MBX_WRITABLE(mailbox))
-    return EACCES;
-       
-  /* Select first.  */
-  status = imap_messages_count (mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      {
-       char *set = NULL;
-       status = delete_to_string (m_imap, &set);
-       CHECK_ERROR (f_imap, status);
-       if (set == NULL || *set == '\0')
-         {
-           if (set)
-             free (set);
-           return 0;
-         }
-       status = imap_writeline (f_imap,
-                                "g%lu STORE %s +FLAGS.SILENT (\\Deleted)\r\n",
-                                (unsigned long) f_imap->seq++,
-                                set);
-       free (set);
-       CHECK_ERROR (f_imap, status);
-       MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-       f_imap->state = IMAP_STORE;
-      }
-
-      /* Send DELETE.  */
-    case IMAP_STORE:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_STORE_ACK;
-
-    case IMAP_STORE_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_NO_STATE;
-
-    case IMAP_EXPUNGE:
-    case IMAP_EXPUNGE_ACK:
-      status = imap_writeline (f_imap, "g%lu EXPUNGE\r\n",
-                              (unsigned long) f_imap->seq++);
-      CHECK_ERROR (f_imap, status);
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-
-      /* Rescan after expunging but do not trigger the observers.  */
-    case IMAP_SCAN:
-    case IMAP_SCAN_ACK:
-      status = imap_scan0 (mailbox, 1, NULL, 0);
-      CHECK_EAGAIN (f_imap, status);
-
-    default:
-      /* mu_error ("imap_expunge: unknown state\n"); */
-      break;
-    }
-
-  return status;
-}
-
-/* FIXME: Not ___Nonblocking___ safe.  */
-/* DANGER:  The mu_message_t object makes no guaranty about the size and the 
lines
-   that it returns, if its pointing to non-local file messages, so we
-   make a local copy.  */
-static int
-imap_append_message (mu_mailbox_t mailbox, mu_message_t msg)
-{
-  int status = 0;
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-
-  /* FIXME: It is debatable if we should reconnect when the connection
-   timeout or die.  For timeout client should ping i.e. send
-   a NOOP via imap_is_updated() function to keep the connection alive.  */
-  status = mu_folder_open (mailbox->folder, mailbox->flags);
-  if (status != 0)
-    return status;
-
-  /* FIXME: Can we append to self.  */
-
-  /* Check to see if we are selected. If the message was not modified
-     and came from the same imap folder. use COPY.*/
-  if (f_imap->selected != m_imap && !mu_message_is_modified (msg)
-      && is_same_folder (mailbox, msg))
-    return imap_copy_message (mailbox, msg);
-
-  /* copy the message to local disk by createing a floating message.  */
-  {
-    mu_message_t message = NULL;
-
-    status = mu_message_create_copy(&message, msg);
-
-    if (status == 0)
-      status = imap_append_message0 (mailbox, message);
-    mu_message_destroy (&message, NULL);
-  }
-  return status;
-}
-
-/* Ok this mean that the message is coming from somewhere else.  IMAP
-   is very susceptible on the size, example:
-   A003 APPEND saved-messages (\Seen) {310}
-   if the server does not get the right size advertise in the string literal
-   it will misbehave.  Sine we are assuming that the message will be
-   in native file system format meaning ending with NEWLINE, we will have
-   to do the calculation.  But what is worse; the value return
-   by mu_message_size () and mu_message_lines () are no mean exact but rather
-   a gross approximation for certain type of mailbox.  So the sane
-   thing to do is to save the message in temporary file, this we say
-   we guarantee the size of the message.  */
-static int
-imap_append_message0 (mu_mailbox_t mailbox, mu_message_t msg)
-{
-  size_t total;
-  int status = 0;
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      {
-       size_t lines, size;
-       const char *path;
-       char *abuf = malloc (1);
-       /* Get the desired flags attribute.  */
-       if (abuf == NULL)
-         return ENOMEM;
-       *abuf = '\0';
-       {
-         mu_attribute_t attribute = NULL;
-         int flags = 0;
-         mu_message_get_attribute (msg, &attribute);
-         mu_attribute_get_flags (attribute, &flags);
-         status = flags_to_string (&abuf, flags);
-         if (status != 0)
-           return status;
-         /* Put the surrounding parenthesis, wu-IMAP is sensible to this.  */
-         {
-           char *tmp = calloc (strlen (abuf) + 3, 1);
-           if (tmp == NULL)
-             {
-               free (abuf);
-               return ENOMEM;
-             }
-           sprintf (tmp, "(%s)", abuf);
-           free (abuf);
-           abuf = tmp;
-         }
-       }
-
-       /* Get the mailbox filepath.  */
-        status = mu_url_sget_path (mailbox->url, &path);
-        if (status == MU_ERR_NOENT)
-          path = "INBOX";
-
-       /* FIXME: we need to get the mu_envelope_date and use it.
-          currently it is ignored.  */
-
-       /* Get the total size, assuming that it is in UNIX format.  */
-       lines = size = 0;
-       mu_message_size (msg, &size);
-       mu_message_lines (msg, &lines);
-       total = size + lines;
-       status = imap_writeline (f_imap, "g%lu APPEND %s %s {%lu}\r\n",
-                                (unsigned long) f_imap->seq++,
-                                path,
-                                abuf,
-                                (unsigned long) (size + lines));
-       free (abuf);
-       CHECK_ERROR (f_imap, status);
-       MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-       f_imap->state = IMAP_APPEND;
-      }
-
-    case IMAP_APPEND:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_APPEND_CONT;
-
-    case IMAP_APPEND_CONT:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      /* If we did not receive the continuation token, it is an error
-         bail out.  */
-      if (f_imap->buffer[0] != '+')
-       {
-         status = EACCES;
-         break;
-       }
-      f_imap->state = IMAP_APPEND_SEND;
-
-    case IMAP_APPEND_SEND:
-      {
-       mu_stream_t stream = NULL;
-       mu_off_t off = 0;
-       size_t n = 0;
-       char buffer[255];
-       mu_message_get_stream (msg, &stream);
-       while (mu_stream_readline (stream, buffer, sizeof buffer, off, &n) == 0
-              && n > 0)
-         {
-           if (buffer[n - 1] == '\n')
-             {
-               buffer[n - 1] = '\0';
-               status = imap_writeline (f_imap, "%s\r\n", buffer);
-             }
-           else
-             imap_writeline (f_imap, "%s", buffer);
-           off += n;
-           status = imap_send (f_imap);
-           CHECK_EAGAIN (f_imap, status);
-         }
-       f_imap->state = IMAP_APPEND_ACK;
-      }
-      /* address@hidden UW-IMAP and Gimap server hack: both insist on the last 
line.  */
-      imap_writeline (f_imap, "\r\n");
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-
-    case IMAP_APPEND_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      /* mu_error ("imap_append: unknown state\n"); */
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-/* If the message is on the same server.  Use the COPY command much more
-   efficient.  */
-static int
-imap_copy_message (mu_mailbox_t mailbox, mu_message_t msg)
-{
-  m_imap_t m_imap = mailbox->data;
-  f_imap_t f_imap = m_imap->f_imap;
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  int status = 0;
-
-  /* FIXME: It is debatable if we should reconnect when the connection
-   timeout or die.  For timeout client should ping i.e. send
-   a NOOP via imap_is_updated() function to keep the connection alive.  */
-  status = mu_folder_open (mailbox->folder, mailbox->flags);
-  if (status != 0)
-    return status;
-
-  switch (f_imap->state)
-    {
-    case IMAP_NO_STATE:
-      {
-       const char *path;
-       /* Check for a valid mailbox name.  */
-       status = mu_url_sget_path (mailbox->url, &path);
-       if (status == 0)
-         status = imap_writeline (f_imap, "g%lu COPY %lu %s\r\n",
-                                  (unsigned long) f_imap->seq++,
-                                  (unsigned long) msg_imap->num,
-                                  path);
-       CHECK_ERROR (f_imap, status);
-       MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-       f_imap->state = IMAP_COPY;
-      }
-
-    case IMAP_COPY:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      f_imap->state = IMAP_COPY_ACK;
-
-    case IMAP_COPY_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      MU_DEBUG (mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-
-    default:
-      break;
-    }
-  f_imap->state = IMAP_NO_STATE;
-  return status;
-}
-
-/* Message read overload  */
-static int
-imap_message_read (mu_stream_t stream, char *buffer, size_t buflen,
-                  mu_off_t offset, size_t *plen)
-{
-  mu_message_t msg = mu_stream_get_owner (stream);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  char *oldbuf = NULL;
-  char newbuf[2];
-  int status;
-
-  /* This is so annoying, a buffer len of 1 is a killer. If you have for
-     example "\n" to retrieve from the server, IMAP will transform this to
-     "\r\n" and since you ask for only 1, the server will send '\r' only.
-     And ... '\r' will be stripped by (imap_readline()) the number of char
-     read will be 0 which means we're done .... sigh ...  So we guard by at
-     least ask for 2 chars.  */
-  if (buflen == 1)
-    {
-      oldbuf = buffer;
-      buffer = newbuf;
-      buflen = 2;
-    }
-
-  /* Start over.  */
-  if (offset == 0)
-    msg_imap->mu_message_lines = 0;
-
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  /* Select first.  */
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      char *section = NULL;
-
-      if (msg_imap->part)
-       section = section_name (msg_imap);
-
-      /* We have strip the \r, but the offset on the imap server is with that
-        octet(CFLF) so add it in the offset, it's the number of lines.  */
-      status = imap_writeline (f_imap,
-                              "g%lu FETCH %lu BODY.PEEK[%s]<%lu.%lu>\r\n",
-                              (unsigned long) f_imap->seq++,
-                              (unsigned long) msg_imap->num,
-                              (section) ? section : "",
-                              (unsigned long) (offset +
-                                               msg_imap->mu_message_lines),
-                              (unsigned long) buflen);
-      if (section)
-       free (section);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_FETCH;
-    }
-  status = fetch_operation (f_imap, msg_imap, buffer, buflen, plen);
-
-  if (oldbuf)
-    oldbuf[0] = buffer[0];
-  return status;
-}
-
-static int
-imap_message_lines (mu_message_t msg, size_t *plines)
-{
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  if (plines && msg_imap)
-    {
-      if (msg_imap->mu_message_lines == 0)
-       *plines = msg_imap->body_lines + msg_imap->header_lines;
-      else
-       *plines = msg_imap->mu_message_lines;
-    }
-  return 0;
-}
-
-/* Sometimes a message is just a place container for other sub parts.
-   In those cases imap bodystructure does not set the mu_message_size aka
-   the mu_body_size.  But we can calculate it since the mu_message_size
-   is the sum of its subparts.  */
-static int
-imap_submessage_size (msg_imap_t msg_imap, size_t *psize)
-{
-  if (psize)
-    {
-      *psize = 0;
-      if (msg_imap->mu_message_size == 0)
-       {
-         size_t i, size;
-         for (size = i = 0; i < msg_imap->num_parts; i++, size = 0)
-           {
-             if (msg_imap->parts[i])
-               imap_submessage_size (msg_imap->parts[i], &size);
-             *psize += size;
-           }
-       }
-      else
-       *psize = (msg_imap->mu_message_size + msg_imap->header_size)
-         - msg_imap->mu_message_lines;
-    }
-  return 0;
-}
-
-static int
-imap_message_size (mu_message_t msg, size_t *psize)
-{
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status = 0;;
-
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  /* If there is a parent it means it is a sub message, IMAP does not give
-     the full size of mime messages, so the mu_message_size retrieved from
-     doing a bodystructure represents rather the mu_body_size.  */
-  if (msg_imap->parent)
-    return imap_submessage_size (msg_imap, psize);
-
-  if (msg_imap->mu_message_size == 0)
-    {
-      /* Select first.  */
-      if (f_imap->state == IMAP_NO_STATE)
-       {
-         /* We strip the \r, but the offset/size on the imap server is with
-            that octet so add it in the offset, since it's the number of
-            lines.  */
-         status = imap_writeline (f_imap,
-                                  "g%lu FETCH %lu RFC822.SIZE\r\n",
-                                  (unsigned long) f_imap->seq++,
-                                  (unsigned long) msg_imap->num);
-         CHECK_ERROR (f_imap, status);
-         MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-         f_imap->state = IMAP_FETCH;
-       }
-      status = fetch_operation (f_imap, msg_imap, 0, 0, 0);
-    }
-
-  if (status == 0)
-    {
-      if (psize)
-       *psize = msg_imap->mu_message_size - msg_imap->mu_message_lines;
-    }
-  return status;
-}
-
-static int
-imap_message_uid (mu_message_t msg, size_t *puid)
-{
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status;
-
-  if (puid)
-    return 0;
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      if (msg_imap->uid)
-       {
-         *puid = msg_imap->uid;
-         return 0;
-       }
-      status = imap_writeline (f_imap, "g%lu FETCH %lu UID\r\n",
-                              (unsigned long) f_imap->seq++,
-                              (unsigned long) msg_imap->num);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_FETCH;
-    }
-  status = fetch_operation (f_imap, msg_imap, 0, 0, 0);
-  if (status != 0)
-    return status;
-  *puid = msg_imap->uid;
-  return 0;
-}
-
-static int
-imap_message_get_transport2 (mu_stream_t stream, mu_transport_t *pin, 
mu_transport_t *pout)
-{
-  mu_message_t msg = mu_stream_get_owner (stream);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  return imap_get_transport2 (msg_imap, pin, pout);
-}
-
-/* Mime.  */
-static int
-imap_is_multipart (mu_message_t msg, int *ismulti)
-{
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status;
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      if (msg_imap->num_parts || msg_imap->part)
-       {
-         if (ismulti)
-           *ismulti = (msg_imap->num_parts > 1);
-         return 0;
-       }
-      status = imap_writeline (f_imap,
-                              "g%lu FETCH %lu BODYSTRUCTURE\r\n",
-                              (unsigned long) f_imap->seq++,
-                              (unsigned long) msg_imap->num);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_FETCH;
-    }
-  status = fetch_operation (f_imap, msg_imap, 0, 0, 0);
-  if (status != 0)
-    return status;
-  if (ismulti)
-    *ismulti = (msg_imap->num_parts > 1);
-  return 0;
-}
-
-static int
-imap_get_num_parts (mu_message_t msg, size_t *nparts)
-{
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  if (msg_imap)
-    {
-      if (msg_imap->num_parts == 0)
-       {
-         int status = imap_is_multipart (msg, NULL);
-         if (status != 0)
-           return status;
-       }
-      if (nparts)
-       *nparts = (msg_imap->num_parts == 0) ? 1 : msg_imap->num_parts;
-    }
-  return 0;
-}
-
-static int
-imap_get_part (mu_message_t msg, size_t partno, mu_message_t *pmsg)
-{
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  int status = 0;
-
-  if (msg_imap->num_parts == 0)
-    {
-      status = imap_get_num_parts (msg, NULL);
-      if (status != 0)
-       return status;
-    }
-
-  if (partno <= msg_imap->num_parts)
-    {
-      if (msg_imap->parts[partno - 1]->message)
-       {
-         if (pmsg)
-           *pmsg = msg_imap->parts[partno - 1]->message;
-       }
-      else
-       {
-         mu_message_t message;
-         status = imap_get_message0 (msg_imap->parts[partno - 1], &message);
-         if (status == 0)
-           {
-             mu_header_t header;
-             mu_message_get_header (message, &header);
-             mu_message_set_stream (message, NULL, msg_imap->parts[partno - 
1]);
-             /* mu_message_set_size (message, NULL, msg_imap->parts[partno - 
1]); */
-             msg_imap->parts[partno - 1]->message = message;
-             if (pmsg)
-               *pmsg = message;
-           }
-       }
-    }
-  else
-    {
-      if (pmsg)
-       *pmsg = msg_imap->message;
-    }
-  return status;
-}
-
-/* Envelope.  */
-static int
-imap_envelope_sender (mu_envelope_t envelope, char *buffer, size_t buflen,
-                     size_t *plen)
-{
-  mu_message_t msg = mu_envelope_get_owner (envelope);
-  mu_header_t header;
-  const char *sender;
-  int status;
-
-  mu_message_get_header (msg, &header);
-  status = mu_header_sget_value (header, MU_HEADER_SENDER, &sender);
-  if (status == EAGAIN)
-    return status;
-  else if (status != 0)
-    status = mu_header_sget_value (header, MU_HEADER_FROM, &sender);
-  if (status == 0)
-    {
-      const char *email = NULL;
-      size_t len;
-      mu_address_t address;
-      if (mu_address_create (&address, sender) == 0)
-       {
-         if (mu_address_sget_email (address, 1, &email) == 0)
-           len = mu_cpystr (buffer, email, buflen);
-         mu_address_destroy (&address);
-       }
-
-      if (!email)
-       return MU_ERR_NOENT;
-      
-      if (plen)
-       *plen = len;
-    }
-  return status;
-}
-
-static int
-imap_envelope_date (mu_envelope_t envelope, char *buffer, size_t buflen,
-                   size_t *plen)
-{
-  mu_message_t msg = mu_envelope_get_owner (envelope);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  struct tm tm;
-  mu_timezone tz;
-  time_t now;
-  char datebuf[] = "mm-dd-yyyy hh:mm:ss +0000";
-  const char* date = datebuf;
-  const char** datep = &date;
-  /* reserve as much space as we need for internal-date */
-  int status;
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-  if (msg_imap->internal_date == NULL)
-    {
-      if (f_imap->state == IMAP_NO_STATE)
-       {
-         status = imap_writeline (f_imap,
-                                  "g%lu FETCH %lu INTERNALDATE\r\n",
-                                  (unsigned long) f_imap->seq++,
-                                  (unsigned long) msg_imap->num);
-         CHECK_ERROR (f_imap, status);
-         MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-         f_imap->state = IMAP_FETCH;
-       }
-      status = fetch_operation (f_imap, msg_imap, datebuf,
-                               sizeof datebuf, NULL);
-      if (status != 0)
-       return status;
-      msg_imap->internal_date = strdup (datebuf);
-    }
-  else
-    {
-      date = msg_imap->internal_date;
-      datep = &date;
-    }
-
-  if (mu_parse_imap_date_time(datep, &tm, &tz) != 0)
-    now = (time_t)-1;
-  else
-    now = mu_datetime_to_utc (&tm, &tz);
-
-  /* if the time was unparseable, or mktime() didn't like what we
-     parsed, use the calendar time. */
-  if (now == (time_t)-1)
-    {
-      time (&now);
-      tm = *gmtime (&now);
-    }
-
-  {
-    char tmpbuf[MU_ENVELOPE_DATE_LENGTH+1];
-    size_t n = mu_strftime (tmpbuf, sizeof tmpbuf,
-                            MU_ENVELOPE_DATE_FORMAT, &tm);
-    n = mu_cpystr (buffer, tmpbuf, buflen);
-    if (plen)
-      *plen = n;
-  }
-  return 0;
-}
-
-/* Attributes.  */
-static int
-imap_attr_get_flags (mu_attribute_t attribute, int *pflags)
-{
-  mu_message_t msg = mu_attribute_get_owner (attribute);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status = 0;
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  /* Did we retrieve it alread ?  */
-  if (msg_imap->flags != 0)
-    {
-      if (pflags)
-       *pflags = msg_imap->flags;
-      return 0;
-    }
-
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      status = imap_writeline (f_imap, "g%lu FETCH %lu FLAGS\r\n",
-                              (unsigned long) f_imap->seq++,
-                              (unsigned long) msg_imap->num);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_FETCH;
-    }
-  status = fetch_operation (f_imap, msg_imap, NULL, 0, NULL);
-  if (status == 0)
-    {
-      if (pflags)
-       *pflags = msg_imap->flags;
-    }
-  return status;
-}
-
-static int
-imap_attr_set_flags (mu_attribute_t attribute, int flag)
-{
-  mu_message_t msg = mu_attribute_get_owner (attribute);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status = 0;
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  /* If already set don't bother.  */
-  if (msg_imap->flags & flag)
-    return 0;
-
-  /* The delete FLAG is not pass yet but only on the expunge.  */
-  if (flag & MU_ATTRIBUTE_DELETED)
-    {
-      msg_imap->flags |= MU_ATTRIBUTE_DELETED;
-      flag &= ~MU_ATTRIBUTE_DELETED;
-    }
-
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      char *abuf = malloc (1);
-      if (abuf == NULL)
-       return ENOMEM;
-      *abuf = '\0';
-      status = flags_to_string (&abuf, flag);
-      if (status != 0)
-       return status;
-      /* No flags to send??  */
-      if (*abuf == '\0')
-       {
-         free (abuf);
-         return 0;
-       }
-      status = imap_writeline (f_imap, "g%lu STORE %lu +FLAGS.SILENT (%s)\r\n",
-                              (unsigned long) f_imap->seq++,
-                              (unsigned long) msg_imap->num,
-                              abuf);
-      free (abuf);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      msg_imap->flags |= flag;
-      f_imap->state = IMAP_FETCH;
-    }
-  return fetch_operation (f_imap, msg_imap, NULL, 0, NULL);
-}
-
-static int
-imap_attr_unset_flags (mu_attribute_t attribute, int flag)
-{
-  mu_message_t msg = mu_attribute_get_owner (attribute);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  int status = 0;
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  /* The delete FLAG is not pass yet but only on the expunge.  */
-  if (flag & MU_ATTRIBUTE_DELETED)
-    {
-      msg_imap->flags &= ~MU_ATTRIBUTE_DELETED;
-      flag &= ~MU_ATTRIBUTE_DELETED;
-    }
-
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      char *abuf = malloc (1);
-      if (abuf == NULL)
-       return ENOMEM;
-      *abuf = '\0';
-      status = flags_to_string (&abuf, flag);
-      if (status != 0)
-       return status;
-      /* No flags to send??  */
-      if (*abuf == '\0')
-       {
-         free (abuf);
-         return 0;
-       }
-      status = imap_writeline (f_imap, "g%lu STORE %lu -FLAGS.SILENT (%s)\r\n",
-                              (unsigned long) f_imap->seq++,
-                              (unsigned long) msg_imap->num,
-                              abuf);
-      free (abuf);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      msg_imap->flags &= ~flag;
-      f_imap->state = IMAP_FETCH;
-    }
-  return fetch_operation (f_imap, msg_imap, NULL, 0, NULL);
-}
-
-/* Header.  */
-static int
-imap_header_read (mu_header_t header, char *buffer,
-                 size_t buflen, mu_off_t offset,
-                 size_t *plen)
-{
-  mu_message_t msg = mu_header_get_owner (header);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  char *oldbuf = NULL;
-  char newbuf[2];
-  int status;
-
-  /* This is so annoying, a buffer len of 1 is a killer. If you have for
-     example "\n" to retrieve from the server, IMAP will transform this to
-     "\r\n" and since you ask for only 1, the server will send '\r' only.
-     And ... '\r' will be stripped by (imap_readline()) the number of char
-     read will be 0 which means we're done .... sigh ...  So we guard by at
-     least ask for 2 chars.  */
-  if (buflen == 1)
-    {
-      oldbuf = buffer;
-      buffer = newbuf;
-      buflen = 2;
-    }
-
-  /* Start over.  */
-  if (offset == 0)
-    msg_imap->header_lines = 0;
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      /* We strip the \r, but the offset/size on the imap server is with that
-         octet so add it in the offset, since it's the number of lines.  */
-      if (msg_imap->part)
-        {
-          char *section = section_name (msg_imap);
-          status = imap_writeline (f_imap,
-                                   "g%lu FETCH %lu 
BODY.PEEK[%s.MIME]<%lu.%lu>\r\n",
-                                   (unsigned long) f_imap->seq++,
-                                  (unsigned long) msg_imap->num,
-                                   (section) ? section : "",
-                                   (unsigned long) (offset +
-                                                   msg_imap->header_lines),
-                                  (unsigned long) buflen);
-          if (section)
-            free (section);
-        }
-      else
-        status = imap_writeline (f_imap,
-                                 "g%lu FETCH %lu 
BODY.PEEK[HEADER]<%lu.%lu>\r\n",
-                                 (unsigned long) f_imap->seq++,
-                                (unsigned long) msg_imap->num,
-                                 (unsigned long) (offset +
-                                                 msg_imap->header_lines),
-                                (unsigned long) buflen);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_FETCH;
-
-    }
-  status = fetch_operation (f_imap, msg_imap, buffer, buflen, plen);
-  if (oldbuf)
-    oldbuf[0] = buffer[0];
-  return status;
-}
-
-/* Body.  */
-static int
-imap_body_size (mu_body_t body, size_t *psize)
-{
-  mu_message_t msg = mu_body_get_owner (body);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  if (psize && msg_imap)
-    {
-      /* If there is a parent it means it is a sub message, IMAP does not give
-        the full size of mime messages, so the mu_message_size was retrieve 
from
-        doing a bodystructure and represents rather the mu_body_size.  */
-      if (msg_imap->parent)
-       {
-         *psize = msg_imap->mu_message_size - msg_imap->mu_message_lines;
-       }
-      else
-       {
-         if (msg_imap->body_size)
-           *psize = msg_imap->body_size;
-         else if (msg_imap->mu_message_size)
-           *psize = msg_imap->mu_message_size
-             - (msg_imap->header_size + msg_imap->header_lines);
-         else
-           *psize = 0;
-       }
-    }
-  return 0;
-}
-
-static int
-imap_body_lines (mu_body_t body, size_t *plines)
-{
-  mu_message_t msg = mu_body_get_owner (body);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  if (plines && msg_imap)
-    *plines = msg_imap->body_lines;
-  return 0;
-}
-
-/* FIXME: Send EISPIPE if trying to seek back.  */
-static int
-imap_body_read (mu_stream_t stream, char *buffer, size_t buflen,
-               mu_off_t offset, size_t *plen)
-{
-  mu_body_t body = mu_stream_get_owner (stream);
-  mu_message_t msg = mu_body_get_owner (body);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  m_imap_t m_imap = msg_imap->m_imap;
-  f_imap_t f_imap = m_imap->f_imap;
-  char *oldbuf = NULL;
-  char newbuf[2];
-  int status;
-
-  /* This is so annoying, a buffer len of 1 is a killer. If you have for
-     example "\n" to retrieve from the server, IMAP will transform this to
-     "\r\n" and since you ask for only 1, the server will send '\r' only.
-     And ... '\r' will be stripped by (imap_readline()) the number of char
-     read will be 0 which means we're done .... sigh ...  So we guard by at
-     least ask for 2 chars.  */
-  if (buflen == 1)
-    {
-      oldbuf = buffer;
-      buffer = newbuf;
-      buflen = 2;
-    }
-
-  /* Start over.  */
-  if (offset == 0)
-    {
-      msg_imap->body_lines = 0;
-      msg_imap->body_size = 0;
-    }
-
-  /* Select first.  */
-  status = imap_messages_count (m_imap->mailbox, NULL);
-  if (status != 0)
-    return status;
-
-  if (f_imap->state == IMAP_NO_STATE)
-    {
-      /* We strip the \r, but the offset/size on the imap server is with the
-         octet, so add it since it's the number of lines.  */
-      if (msg_imap->part)
-        {
-          char *section = section_name (msg_imap);
-          status = imap_writeline (f_imap,
-                                   "g%lu FETCH %lu BODY.PEEK[%s]<%lu.%lu>\r\n",
-                                   (unsigned long) f_imap->seq++,
-                                  (unsigned long) msg_imap->num,
-                                   (section) ? section: "",
-                                   (unsigned long) (offset +
-                                                   msg_imap->body_lines),
-                                  (unsigned long) buflen);
-          if (section)
-            free (section);
-        }
-      else
-        status = imap_writeline (f_imap,
-                                 "g%lu FETCH %lu BODY.PEEK[TEXT]<%lu.%lu>\r\n",
-                                 (unsigned long) f_imap->seq++,
-                                (unsigned long) msg_imap->num,
-                                 (unsigned long) (offset +
-                                                 msg_imap->body_lines),
-                                (unsigned long) buflen);
-      CHECK_ERROR (f_imap, status);
-      MU_DEBUG (m_imap->mailbox->debug, MU_DEBUG_PROT, f_imap->buffer);
-      f_imap->state = IMAP_FETCH;
-
-    }
-  status = fetch_operation (f_imap, msg_imap, buffer, buflen, plen);
-  if (oldbuf)
-    oldbuf[0] = buffer[0];
-  return status;
-}
-
-static int
-imap_body_get_transport2 (mu_stream_t stream, mu_transport_t *pin, 
-                         mu_transport_t *pout)
-{
-  mu_body_t body = mu_stream_get_owner (stream);
-  mu_message_t msg = mu_body_get_owner (body);
-  msg_imap_t msg_imap = mu_message_get_owner (msg);
-  return imap_get_transport2 (msg_imap, pin, pout);
-}
-
-
-static int
-imap_get_transport2 (msg_imap_t msg_imap, mu_transport_t *pin, mu_transport_t 
*pout)
-{
-  if (   msg_imap
-      && msg_imap->m_imap
-      && msg_imap->m_imap->f_imap
-      && msg_imap->m_imap->f_imap->folder)
-    return mu_stream_get_transport2 (msg_imap->m_imap->f_imap->folder->stream,
-                                pin, pout);
-  return EINVAL;
-}
-
-/* Since so many operations are fetch, we regoup this into one function.  */
-static int
-fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer,
-                size_t buflen, size_t *plen)
-{
-  int status = 0;
-
-  switch (f_imap->state)
-    {
-    case IMAP_FETCH:
-      status = imap_send (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      mu_stream_truncate (f_imap->string.stream, 0);
-      f_imap->string.offset = 0;
-      f_imap->string.nleft = 0;
-      f_imap->string.type = IMAP_NO_STATE;
-      f_imap->string.msg_imap = msg_imap;
-      f_imap->state = IMAP_FETCH_ACK;
-
-    case IMAP_FETCH_ACK:
-      status = imap_parse (f_imap);
-      CHECK_EAGAIN (f_imap, status);
-      if (f_imap->selected)
-       MU_DEBUG (f_imap->selected->mailbox->debug, MU_DEBUG_PROT,
-                 f_imap->buffer);
-
-    default:
-      break;
-    }
-
-  f_imap->state = IMAP_NO_STATE;
-
-  /* The server may have timeout any case connection is gone away.  */
-  if (status == 0 && f_imap->isopen == 0 && f_imap->string.offset == 0)
-    status = MU_ERR_CONN_CLOSED;
-
-  if (buffer)
-    mu_stream_read (f_imap->string.stream, buffer, buflen, 0, plen);
-  else if (plen)
-    *plen = 0;
-  mu_stream_truncate (f_imap->string.stream, 0);
-  f_imap->string.offset = 0;
-  f_imap->string.nleft = 0;
-  f_imap->string.type = IMAP_NO_STATE;
-  f_imap->string.msg_imap = NULL;
-  return status;
-}
-
-/* Decide whether the message came from the same folder as the mailbox.  */
-static int
-is_same_folder (mu_mailbox_t mailbox, mu_message_t msg)
-{
-  mu_mailbox_t mbox = NULL;
-  mu_message_get_mailbox (msg, &mbox);
-  return (mbox != NULL && mbox->url != NULL
-          && mu_url_is_same_scheme (mbox->url, mailbox->url)
-          && mu_url_is_same_host (mbox->url, mailbox->url)
-          && mu_url_is_same_port (mbox->url, mailbox->url));
-}
-
-/* Convert flag attribute to IMAP String attributes.  */
-static int
-flags_to_string (char **pbuf, int flag)
-{
-  char *abuf = *pbuf;
-  if (flag & MU_ATTRIBUTE_DELETED)
-    {
-      char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Deleted") + 2);
-      if (tmp == NULL)
-        {
-          free (abuf);
-          return ENOMEM;
-        }
-      abuf = tmp;
-      if (*abuf)
-        strcat (abuf, " ");
-      strcat (abuf, "\\Deleted");
-    }
-  if (flag & MU_ATTRIBUTE_READ)
-    {
-      char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Seen") + 2);
-      if (tmp == NULL)
-        {
-          free (abuf);
-          return ENOMEM;
-        }
-      abuf = tmp;
-      if (*abuf)
-        strcat (abuf, " ");
-      strcat (abuf, "\\Seen");
-    }
-  if (flag & MU_ATTRIBUTE_ANSWERED)
-    {
-      char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Answered") + 2);
-      if (tmp == NULL)
-        {
-          free (abuf);
-          return ENOMEM;
-        }
-      abuf = tmp;
-      if (*abuf)
-        strcat (abuf, " ");
-      strcat (abuf, "\\Answered");
-    }
-  if (flag & MU_ATTRIBUTE_DRAFT)
-    {
-      char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Draft") + 2);
-      if (tmp == NULL)
-        {
-          free (abuf);
-          return ENOMEM;
-        }
-      abuf = tmp;
-      if (*abuf)
-        strcat (abuf, " ");
-      strcat (abuf, "\\Draft");
-    }
-  if (flag & MU_ATTRIBUTE_FLAGGED)
-    {
-      char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Flagged") + 2);
-      if (tmp == NULL)
-        {
-          free (abuf);
-          return ENOMEM;
-        }
-      abuf = tmp;
-      if (*abuf)
-        strcat (abuf, " ");
-      strcat (abuf, "\\Flagged");
-    }
-  *pbuf = abuf;
-  return 0;
-}
-
-/* Convert a suite of number to IMAP message number.  */
-static int
-add_number (char **pset, size_t start, size_t end)
-{
-  char *buf = NULL;
-  char *set;
-  char *tmp;
-  size_t set_len = 0;
-
-  if (pset == NULL)
-    return 0;
-
-  set = *pset;
-
-  if (set)
-    set_len = strlen (set);
-
-  /* We had a previous seqence.  */
-  if (start == 0)
-    /* nothing */;
-  else if (start != end)
-    mu_asprintf (&buf, "%lu:%lu",
-                 (unsigned long) start, (unsigned long) end);
-  else
-    mu_asprintf (&buf, "%lu", (unsigned long) start);
-
-  if (set_len)
-    tmp = realloc (set, set_len + strlen (buf) + 2 /* null and comma */);
-  else
-    tmp = calloc (strlen (buf) + 1, 1);
-
-  if (tmp == NULL)
-    {
-      free (set);
-      free (buf);
-      return ENOMEM;
-    }
-  set = tmp;
-
-  /* If we had something add a comma separator.  */
-  if (set_len)
-    strcat (set, ",");
-  strcat (set, buf);
-  free (buf);
-  
-  *pset = set;
-  return 0;
-}
-
-static int
-delete_to_string (m_imap_t m_imap, char **pset)
-{
-  int status;
-  size_t i, prev = 0, is_range = 0;
-  size_t start = 0, cur = 0;
-  char *set = NULL;
-
-  /* Reformat the number for IMAP.  */
-  for (i = 0; i < m_imap->imessages_count; ++i)
-    {
-      if (m_imap->imessages[i]
-         && (m_imap->imessages[i]->flags & MU_ATTRIBUTE_DELETED))
-       {
-         cur = m_imap->imessages[i]->num;
-         /* The first number.  */
-         if (start == 0)
-           {
-             start = prev = cur;
-           }
-         /* Is it a sequence?  */
-         else if ((prev + 1) == cur)
-           {
-             prev = cur;
-             is_range = 1;
-           }
-         continue;
-       }
-
-      if (start)
-       {
-         status = add_number (&set, start, cur);
-         if (status != 0)
-           return status;
-         start = 0;
-         prev = 0;
-         cur = 0;
-         is_range = 0;
-       }
-    } /* for () */
-
-  if (start)
-    {
-      status = add_number (&set, start, cur);
-      if (status != 0)
-       return status;
-    }
-  *pset = set;
-  return 0;
-}
-
-#endif
diff --git a/libproto/imap/rename.c b/libproto/imap/rename.c
index 334df7d..3348380 100644
--- a/libproto/imap/rename.c
+++ b/libproto/imap/rename.c
@@ -29,6 +29,9 @@ mu_imap_rename (mu_imap_t imap, const char *mailbox, const 
char *new_mailbox)
   char const *argv[3];
   static struct imap_command com;
 
+  if (!mailbox || !new_mailbox)
+    return EINVAL;
+
   argv[0] = "RENAME";
   argv[1] = mailbox;
   argv[2] = new_mailbox;
diff --git a/libproto/imap/resplist.c b/libproto/imap/resplist.c
index cca7f33..65d78dc 100644
--- a/libproto/imap/resplist.c
+++ b/libproto/imap/resplist.c
@@ -57,6 +57,7 @@ _mu_imap_response_list_create (mu_imap_t imap, mu_list_t 
*plist)
 
 #define IS_LBRACE(p) ((p)[0] == '(')
 #define IS_RBRACE(p) ((p)[0] == ')')
+#define IS_NIL(p) (strcmp (p, "NIL") == 0)
 
 static struct imap_list_element *
 _new_imap_list_element (mu_imap_t imap, enum imap_eltype type)
@@ -181,6 +182,7 @@ _parse_element (struct parsebuf *pb)
       
       if (IS_RBRACE (tok))
        {
+         parsebuf_gettok (pb);
          elt = _new_imap_list_element (pb->pb_imap, imap_eltype_list);
          if (!elt)
            {
@@ -203,6 +205,16 @@ _parse_element (struct parsebuf *pb)
        parsebuf_seterr (pb, MU_ERR_PARSE);
       return NULL;
     }
+  else if (IS_NIL (tok))
+    {
+      elt = _new_imap_list_element (pb->pb_imap, imap_eltype_list);
+      if (!elt)
+       {
+         parsebuf_seterr (pb, ENOMEM);
+         return NULL;
+       }
+      elt->v.list = NULL;
+    }
   else
     {
       char *s;
@@ -255,6 +267,12 @@ _mu_imap_list_element_is_string (struct imap_list_element 
*elt,
   return strcmp (elt->v.string, str) == 0;
 }
 
+int
+_mu_imap_list_element_is_nil (struct imap_list_element *elt)
+{
+  return elt->type == imap_eltype_list && mu_list_is_empty (elt->v.list);
+}
+
 struct imap_list_element *
 _mu_imap_list_at (mu_list_t list, int idx)
 {
diff --git a/libproto/imap/subscribe.c b/libproto/imap/subscribe.c
index 3cf71a6..f370f3a 100644
--- a/libproto/imap/subscribe.c
+++ b/libproto/imap/subscribe.c
@@ -19,6 +19,7 @@
 # include <config.h>
 #endif
 
+#include <errno.h>
 #include <mailutils/imap.h>
 #include <mailutils/sys/imap.h>
 
@@ -28,6 +29,9 @@ mu_imap_subscribe (mu_imap_t imap, const char *mailbox)
   char const *argv[2];
   static struct imap_command com;
 
+  if (!mailbox)
+    return EINVAL;
+  
   argv[0] = "SUBSCRIBE";
   argv[1] = mailbox;
 
diff --git a/libproto/imap/tests/.gitignore b/libproto/imap/tests/.gitignore
new file mode 100644
index 0000000..0e29c74
--- /dev/null
+++ b/libproto/imap/tests/.gitignore
@@ -0,0 +1 @@
+imapfolder
diff --git a/libproto/mbox/Makefile.am b/libproto/imap/tests/Makefile.am
similarity index 77%
copy from libproto/mbox/Makefile.am
copy to libproto/imap/tests/Makefile.am
index c0fcaf2..7294934 100644
--- a/libproto/mbox/Makefile.am
+++ b/libproto/imap/tests/Makefile.am
@@ -13,16 +13,14 @@
 ## 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/>. 
+## along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-INCLUDES = @MU_LIB_COMMON_INCLUDES@ 
-
-lib_LTLIBRARIES = libmu_mbox.la
-libmu_mbox_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
-libmu_mbox_la_LIBADD = ${MU_LIB_MAILUTILS}
-libmu_mbox_la_SOURCES = \
- folder.c\
- mbox.c\
- mboxscan.c\
- mbox0.h
+noinst_PROGRAMS = \
+ imapfolder
 
+INCLUDES = @MU_LIB_COMMON_INCLUDES@ 
+LDADD = \
+ @address@hidden
+ @address@hidden
+ @address@hidden
+ @MU_LIB_MAILUTILS@
diff --git a/libproto/imap/tests/imapfolder.c b/libproto/imap/tests/imapfolder.c
new file mode 100644
index 0000000..cb3a08b
--- /dev/null
+++ b/libproto/imap/tests/imapfolder.c
@@ -0,0 +1,242 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This library 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 of the License, or (at your option) any later version.
+
+   This library 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 this library.  If not, see
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <mailutils/mailutils.h>
+
+struct command
+{
+  char *verb;
+  int nargs;
+  char *args;
+  void (*handler) (mu_folder_t folder, char **argv);
+};
+
+static int
+_print_list_entry (void *item, void *data)
+{
+  struct mu_list_response *resp = item;
+  mu_printf ("%c%c %c %4d %s\n",
+            (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) ? 'd' : '-',
+            (resp->type & MU_FOLDER_ATTRIBUTE_FILE) ? 'f' : '-',
+            resp->separator ? resp->separator : ' ',
+            resp->level,
+            resp->name);
+  return 0;
+}
+
+static void
+com_list (mu_folder_t folder, char **argv)
+{
+  int rc;
+  mu_list_t list;
+  
+  mu_printf ("listing %s %s\n", argv[0], argv[1]);
+  rc = mu_folder_list (folder, argv[0], argv[1], 0, &list);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_list", argv[0], rc);
+  else
+    {
+      mu_list_foreach (list, _print_list_entry, NULL);
+      mu_list_destroy (&list);
+    }
+}
+
+static void
+com_lsub (mu_folder_t folder, char **argv)
+{
+  int rc;
+  mu_list_t list;
+  
+  mu_printf ("listing subscriptions for '%s' '%s'\n", argv[0], argv[1]);
+  rc = mu_folder_lsub (folder, argv[0], argv[1], &list);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_lsub", argv[0], rc);
+  else
+    {
+      mu_list_foreach (list, _print_list_entry, NULL);
+      mu_list_destroy (&list);
+    }
+}
+
+static void
+com_delete (mu_folder_t folder, char **argv)
+{
+  int rc;
+  
+  mu_printf ("deleting %s\n", argv[0]);
+  rc = mu_folder_delete (folder, argv[0]);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_lsub", argv[0], rc);
+  else
+    mu_printf ("delete successful\n");
+}
+
+static void
+com_rename (mu_folder_t folder, char **argv)
+{
+  int rc;
+
+  mu_printf ("renaming %s to %s\n", argv[0], argv[1]);
+  rc = mu_folder_rename (folder, argv[0], argv[1]);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_rename", argv[0], rc);
+  else
+    mu_printf ("rename successful\n");
+}
+
+static void
+com_subscribe (mu_folder_t folder, char **argv)
+{
+  int rc;
+
+  mu_printf ("subscribing %s\n", argv[0]);
+  rc = mu_folder_subscribe (folder, argv[0]);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_subscribe", argv[0], rc);
+  else
+    mu_printf ("subscribe successful\n");
+}
+
+static void
+com_unsubscribe (mu_folder_t folder, char **argv)
+{
+  int rc;
+
+  mu_printf ("unsubscribing %s\n", argv[0]);
+  rc = mu_folder_unsubscribe (folder, argv[0]);
+  if (rc)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_unsubscribe", argv[0], rc);
+  else
+    mu_printf ("unsubscribe successful\n");
+}
+
+static struct command comtab[] = {
+  { "list", 2, "REF MBX", com_list },
+  { "lsub", 2, "REF MBX", com_lsub },
+  { "delete", 1, "MBX", com_delete },
+  { "rename", 2, "OLD NEW", com_rename },
+  { "delete", 1, "MBOX", com_delete },
+  { "subscribe", 1, "MBX", com_subscribe },
+  { "unsubscribe", 1, "MBX", com_unsubscribe },
+  { NULL }
+};
+
+static struct command *
+find_command (const char *name)
+{
+  struct command *cp;
+  
+  for (cp = comtab; cp->verb; cp++)
+    if (strcmp (cp->verb, name) == 0)
+      return cp;
+  return NULL;
+}
+
+static void
+usage ()
+{
+  struct command *cp;
+  
+  mu_printf (
+    "usage: %s [debug=SPEC] url=URL OP ARG [ARG...] [OP ARG [ARG...]...]\n",
+    mu_program_name);
+  mu_printf ("OPerations and corresponding ARGuments are:\n");
+  for (cp = comtab; cp->verb; cp++)
+    mu_printf (" %s %s\n", cp->verb, cp->args);
+}
+
+int
+main (int argc, char **argv)
+{
+  int i;
+  int rc;
+  mu_folder_t folder;
+  char *fname = NULL;
+  
+  mu_set_program_name (argv[0]);
+  mu_registrar_record (mu_imap_record);
+  mu_registrar_record (mu_imaps_record);
+
+  if (argc == 1)
+    {
+      usage ();
+      exit (0);
+    }
+
+  for (i = 1; i < argc; i++)
+    {
+      if (strncmp (argv[i], "debug=", 6) == 0)
+       mu_debug_parse_spec (argv[i] + 6);
+      else if (strncmp (argv[i], "url=", 4) == 0)
+       fname = argv[i] + 4;
+      else
+       break;
+    }
+
+  if (!fname)
+    {
+      mu_error ("URL not specified");
+      exit (1);
+    }
+      
+  rc = mu_folder_create (&folder, fname);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", fname, rc);
+      return 1;
+    }
+  
+  rc = mu_folder_open (folder, MU_STREAM_READ);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", fname, rc);
+      return 1;
+    }
+  
+  while (i < argc)
+    {
+      char *comargs[2];
+      struct command *cmd;
+      
+      cmd = find_command (argv[i]);
+      if (!cmd)
+       {
+         mu_error ("unknown command %s\n", argv[i]);
+         break;
+       }
+
+      i++;
+      if (i + cmd->nargs > argc)
+       {
+         mu_error ("not enough arguments for %s", cmd->verb);
+         break;
+       }
+      memcpy (comargs, argv + i, cmd->nargs * sizeof (comargs[0]));
+      i += cmd->nargs;
+
+      cmd->handler (folder, comargs);
+    }
+
+  mu_folder_close (folder);
+  mu_folder_destroy (&folder);
+
+  return 0;
+}
diff --git a/libproto/imap/unsubscribe.c b/libproto/imap/unsubscribe.c
index 4831829..159b442 100644
--- a/libproto/imap/unsubscribe.c
+++ b/libproto/imap/unsubscribe.c
@@ -19,6 +19,7 @@
 # include <config.h>
 #endif
 
+#include <errno.h>
 #include <mailutils/imap.h>
 #include <mailutils/sys/imap.h>
 
@@ -28,6 +29,9 @@ mu_imap_unsubscribe (mu_imap_t imap, const char *mailbox)
   char const *argv[2];
   static struct imap_command com;
 
+  if (!mailbox)
+    return EINVAL;
+  
   argv[0] = "UNSUBSCRIBE";
   argv[1] = mailbox;
 
diff --git a/libproto/imap/url.c b/libproto/imap/url.c
index e9ddd2f..27ccea6 100644
--- a/libproto/imap/url.c
+++ b/libproto/imap/url.c
@@ -20,18 +20,15 @@
 # include <config.h>
 #endif
 
-#ifdef ENABLE_IMAP
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
+#include <string.h>
 
 #include <mailutils/sys/registrar.h>
 #include <mailutils/sys/url.h>
+#include <mailutils/sys/imap.h>
 
 static void url_imap_destroy (mu_url_t url);
 
@@ -47,7 +44,7 @@ url_imap_destroy (mu_url_t url MU_ARG_UNUSED)
 */
 
 int
-_url_imap_init (mu_url_t url)
+_mu_imap_url_init (mu_url_t url)
 {
   if (url->port == 0)
     url->port = MU_IMAP_PORT;
@@ -78,7 +75,7 @@ _url_imap_init (mu_url_t url)
 */
 
 int
-_url_imaps_init (mu_url_t url)
+_mu_imaps_url_init (mu_url_t url)
 {
   if (url->port == 0)
     url->port = MU_IMAPS_PORT;
@@ -102,4 +99,3 @@ _url_imaps_init (mu_url_t url)
   return 0;
 }
 
-#endif /* ENABLE_IMAP */
diff --git a/mu/imap.c b/mu/imap.c
index f615de9..2bebae4 100644
--- a/mu/imap.c
+++ b/mu/imap.c
@@ -160,7 +160,7 @@ imap_prompt_env ()
 
 /* Callbacks */
 static void
-imap_popauth_callback (void *data, int code, size_t sdat, void *pdat)
+imap_preauth_callback (void *data, int code, size_t sdat, void *pdat)
 {
   const char *text = pdat;
   if (text)
@@ -425,7 +425,7 @@ com_connect (int argc, char **argv)
 
          /* Set callbacks */
          mu_imap_register_callback_function (imap, MU_IMAP_CB_PREAUTH,
-                                             imap_popauth_callback,
+                                             imap_preauth_callback,
                                              NULL);
          mu_imap_register_callback_function (imap, MU_IMAP_CB_BYE,
                                              imap_bye_callback,


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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