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-446-gf7942ce


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-446-gf7942ce
Date: Fri, 18 Nov 2011 10:59:36 +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=f7942ced21d97774e678be261cc5b9094e47e8da

The branch, master has been updated
       via  f7942ced21d97774e678be261cc5b9094e47e8da (commit)
       via  a4a3755edc99af0d3522179f9f5213b7646ef078 (commit)
      from  6f309ce61dcfb461c3fe1270efe2b23a7ac5d676 (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 f7942ced21d97774e678be261cc5b9094e47e8da
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Nov 18 13:00:05 2011 +0200

    Rewrite existing imap client support using imapio.

commit a4a3755edc99af0d3522179f9f5213b7646ef078
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Nov 18 09:51:53 2011 +0200

    Implement mu_imapio_reply_string function.
    
    * include/mailutils/imapio.h (mu_imapio_reply_string): New proto.
    * libmailutils/imapio/replstr.c: New file.
    * libmailutils/imapio/Makefile.am: Add replstr.c

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

Summary of changes:
 include/mailutils/imap.h                   |    2 +-
 include/mailutils/imapio.h                 |    2 +
 include/mailutils/sys/imap.h               |   32 +++-
 libmailutils/imapio/Makefile.am            |    1 +
 libmailutils/imapio/getline.c              |    2 +-
 libmailutils/imapio/{words.c => replstr.c} |   32 ++--
 libproto/imap/Makefile.am                  |    1 +
 libproto/imap/capability.c                 |   47 +++---
 libproto/imap/carrier.c                    |   19 ++-
 libproto/imap/connect.c                    |   83 ++++-----
 libproto/imap/create.c                     |    2 +-
 libproto/imap/destroy.c                    |    9 +-
 libproto/imap/disconnect.c                 |    8 +-
 libproto/imap/id.c                         |  163 ++++++++++--------
 libproto/imap/login.c                      |    4 +-
 libproto/imap/logout.c                     |    4 +-
 libproto/imap/resplist.c                   |  256 ++++++++++++++++++++++++++++
 libproto/imap/response.c                   |   93 +++++------
 libproto/imap/trace.c                      |   81 +++------
 mu/imap.c                                  |   58 ++++---
 20 files changed, 565 insertions(+), 334 deletions(-)
 copy libmailutils/imapio/{words.c => replstr.c} (63%)
 create mode 100644 libproto/imap/resplist.c

diff --git a/include/mailutils/imap.h b/include/mailutils/imap.h
index 9855856..3e04391 100644
--- a/include/mailutils/imap.h
+++ b/include/mailutils/imap.h
@@ -53,7 +53,7 @@ int mu_imap_capability_test (mu_imap_t imap, const char *name,
 int mu_imap_login (mu_imap_t imap, const char *user, const char *pass);
 int mu_imap_logout (mu_imap_t imap);
 
-int mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist);
+int mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc);
   
 int mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier);
 int mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier);
diff --git a/include/mailutils/imapio.h b/include/mailutils/imapio.h
index 387e3df..9b92622 100644
--- a/include/mailutils/imapio.h
+++ b/include/mailutils/imapio.h
@@ -43,6 +43,8 @@ int mu_imapio_trace_disable (mu_imapio_t io);
 int mu_imapio_get_trace (mu_imapio_t io);
 
 int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize);
+
+int mu_imapio_reply_string (struct _mu_imapio *io, size_t start, char **pbuf);
   
 #ifdef __cplusplus
 }
diff --git a/include/mailutils/sys/imap.h b/include/mailutils/sys/imap.h
index 3e90809..17a0095 100644
--- a/include/mailutils/sys/imap.h
+++ b/include/mailutils/sys/imap.h
@@ -22,6 +22,7 @@
 # include <mailutils/sys/mailbox.h>
 # include <mailutils/sys/registrar.h>
 # include <mailutils/sys/auth.h>
+# include <mailutils/imapio.h>
 # include <mailutils/imap.h>
 
 # ifdef __cplusplus
@@ -29,7 +30,7 @@ extern "C" {
 # endif
 
 #define MU_IMAP_RESP  0x01
-#define MU_IMAP_TRACE 0x02  
+#define MU_IMAP_TRACE 0x02
 #define MU_IMAP_XSCRIPT_MASK(n) (1<<((n)+1))
 
 enum mu_imap_client_state
@@ -56,9 +57,7 @@ struct _mu_imap
   {
     int flags;
 
-    /* Holds the tagged response to the last command */
-    char *tagbuf;
-    size_t tagsize;
+    /* Holds the recect response code */
     enum mu_imap_response resp_code;
     
     /* Untagged responses */
@@ -68,10 +67,6 @@ struct _mu_imap
     char *errstr;
     size_t errsize;
     
-    /* Input line buffer */
-    char *rdbuf;
-    size_t rdsize;
-
     enum mu_imap_state state;
     enum mu_imap_state imap_state;
 
@@ -81,7 +76,23 @@ struct _mu_imap
     char *tag_str;   /* String representation (tag_len + 1 bytes, asciiz) */
     
     mu_list_t capa;
-    mu_stream_t carrier;
+    mu_imapio_t io;
+};
+
+enum imap_eltype
+  {
+    imap_eltype_string,
+    imap_eltype_list
+  };
+
+struct imap_list_element
+{
+  enum imap_eltype type;
+  union
+  {
+    mu_list_t list;
+    char *string;
+  } v;
 };
 
 #define MU_IMAP_FSET(p,f) ((p)->flags |= (f))
@@ -137,6 +148,9 @@ int _mu_imap_tag_next (mu_imap_t imap);
 int _mu_imap_tag_clr (mu_imap_t imap);
 
 int _mu_imap_response (mu_imap_t imap);
+
+int _mu_imap_untagged_response_clear (mu_imap_t imap);
+int _mu_imap_untagged_response_add (mu_imap_t imap);
   
 # ifdef __cplusplus
 }
diff --git a/libmailutils/imapio/Makefile.am b/libmailutils/imapio/Makefile.am
index 74f36a2..20c0784 100644
--- a/libmailutils/imapio/Makefile.am
+++ b/libmailutils/imapio/Makefile.am
@@ -23,6 +23,7 @@ libimapio_la_SOURCES = \
  literal.c\
  printf.c\
  qstring.c\
+ replstr.c\
  send.c\
  trace.c\
  words.c\
diff --git a/libmailutils/imapio/getline.c b/libmailutils/imapio/getline.c
index 28c8d4b..f586d86 100644
--- a/libmailutils/imapio/getline.c
+++ b/libmailutils/imapio/getline.c
@@ -30,7 +30,7 @@ mu_imapio_getline (struct _mu_imapio *io)
 {
   int rc;
   char *last_arg;
-
+  
   io->_imap_ws_flags &= ~MU_WRDSF_APPEND;
 
   if (io->_imap_reply_ready)
diff --git a/libmailutils/imapio/words.c b/libmailutils/imapio/replstr.c
similarity index 63%
copy from libmailutils/imapio/words.c
copy to libmailutils/imapio/replstr.c
index 7fa1c81..56b3fa2 100644
--- a/libmailutils/imapio/words.c
+++ b/libmailutils/imapio/replstr.c
@@ -15,28 +15,26 @@
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include <stdlib.h>
-#include <mailutils/errno.h>
+#include <mailutils/types.h>
 #include <mailutils/imapio.h>
+#include <mailutils/errno.h>
+#include <mailutils/argcv.h>
 #include <mailutils/sys/imapio.h>
 
+/* FIXME: It would be good to have a `, size_t *psize' argument, to allow
+   for passing an already allocated buffer.  This implies similar changes
+   to mu_argcv_join. */
 int
-mu_imapio_get_words (mu_imapio_t io, size_t *pwc, char ***pwv)
+mu_imapio_reply_string (struct _mu_imapio *io, size_t start, char **pbuf)
 {
   if (!io->_imap_reply_ready)
-    return MU_ERR_INFO_UNAVAILABLE;
-  *pwc = io->_imap_ws.ws_wordc;
-  *pwv = io->_imap_ws.ws_wordv;
-  return 0;
-}
+    return MU_ERR_NOENT;
 
-int
-mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize)
-{
-  if (!io->_imap_reply_ready)
-    return MU_ERR_INFO_UNAVAILABLE;
-  *pptr  = io->_imap_buf_base;
-  *psize = io->_imap_buf_level;
-  return 0;
-}
+  if (start >= io->_imap_ws.ws_wordc)
+    return EINVAL;
   
+  return mu_argcv_join (io->_imap_ws.ws_wordc - start,
+                       io->_imap_ws.ws_wordv + start, " ",
+                       mu_argcv_escape_no,
+                       pbuf);
+}
diff --git a/libproto/imap/Makefile.am b/libproto/imap/Makefile.am
index c280042..2f54f70 100644
--- a/libproto/imap/Makefile.am
+++ b/libproto/imap/Makefile.am
@@ -39,6 +39,7 @@ libmu_imap_la_SOURCES = \
  id.c\
  login.c\
  logout.c\
+ resplist.c\
  response.c\
  state.c\
  tag.c\
diff --git a/libproto/imap/capability.c b/libproto/imap/capability.c
index 1f74702..ab69ad2 100644
--- a/libproto/imap/capability.c
+++ b/libproto/imap/capability.c
@@ -19,13 +19,14 @@
 # include <config.h>
 #endif
 
+#include <string.h>
 #include <mailutils/types.h>
 #include <mailutils/cctype.h>
 #include <mailutils/cstr.h>
 #include <mailutils/errno.h>
 #include <mailutils/stream.h>
 #include <mailutils/list.h>
-#include <mailutils/wordsplit.h>
+#include <mailutils/iterator.h>
 #include <mailutils/sys/imap.h>
 
 static int
@@ -50,7 +51,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t 
*piter)
   
   if (imap == NULL)
     return EINVAL;
-  if (!imap->carrier)
+  if (!imap->io)
     return MU_ERR_NO_TRANSPORT;
   if (imap->state != MU_IMAP_CONNECTED)
     return MU_ERR_SEQ;
@@ -78,7 +79,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t 
*piter)
     case MU_IMAP_CONNECTED:
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_stream_printf (imap->carrier, "%s CAPABILITY\r\n",
+      status = mu_imapio_printf (imap->io, "%s CAPABILITY\r\n",
                                 imap->tag_str); 
       MU_IMAP_CHECK_EAGAIN (imap, status);
       MU_IMAP_FCLR (imap, MU_IMAP_RESP);
@@ -92,35 +93,35 @@ mu_imap_capability (mu_imap_t imap, int reread, 
mu_iterator_t *piter)
       else
        {
          size_t count;
-         char *str;
+         struct imap_list_element *elt;
          
          imap->state = MU_IMAP_CONNECTED;
          mu_list_count (imap->untagged_resp, &count);
-         if (mu_list_get (imap->untagged_resp, 0, (void*)&str) == 0)
+         if (mu_list_get (imap->untagged_resp, 0, (void*)&elt) == 0)
            {
-             size_t i;
+             /* Top-level elements are always of imap_eltype_list type. */
+             mu_iterator_t itr;
              
-             struct mu_wordsplit ws;
-
-             if (mu_wordsplit (str, &ws,
-                               MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
-                               MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS))
-               {
-                 int ec = errno;
-                 mu_error ("mu_imap_capability: cannot split line: %s",
-                           mu_wordsplit_strerror (&ws));
-                 return ec;
-               }
-             if (ws.ws_wordc > 1 &&
-                 mu_c_strcasecmp (ws.ws_wordv[0], "CAPABILITY") == 0)
+             mu_list_get_iterator (elt->v.list, &itr);
+             mu_iterator_first (itr);
+             if (mu_iterator_is_done (itr))
+               return MU_ERR_PARSE;
+             mu_iterator_current (itr, (void **) &elt);
+             if (elt->type == imap_eltype_string &&
+                 strcmp (elt->v.string, "CAPABILITY") == 0)
                {
-                 for (i = 1; i < ws.ws_wordc; i++)
+                 for (mu_iterator_next (itr); !mu_iterator_is_done (itr);
+                      mu_iterator_next (itr))
                    {
-                     mu_list_append (imap->capa, ws.ws_wordv[i]);
-                     ws.ws_wordv[i] = NULL;
+                     mu_iterator_current (itr, (void **) &elt);
+                     if (elt->type == imap_eltype_string)
+                       {
+                         mu_list_append (imap->capa, elt->v.string);
+                         elt->v.string = NULL;
+                       }
                    }
                }
-             mu_wordsplit_free (&ws);
+             mu_iterator_destroy (&itr);
            }
          if (piter)
            status = mu_list_get_iterator (imap->capa, piter);
diff --git a/libproto/imap/carrier.c b/libproto/imap/carrier.c
index 0ff40e5..afb8563 100644
--- a/libproto/imap/carrier.c
+++ b/libproto/imap/carrier.c
@@ -23,23 +23,30 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <mailutils/errno.h>
+#include <mailutils/imapio.h>
 #include <mailutils/sys/imap.h>
+#include <mailutils/sys/imapio.h>
 
 int
 mu_imap_set_carrier (mu_imap_t imap, mu_stream_t carrier)
 {
+  int rc;
+  mu_imapio_t io;
+  
   /* Sanity checks.  */
   if (imap == NULL)
     return EINVAL;
 
-  if (imap->carrier)
+  rc = mu_imapio_create (&io, carrier);
+  if (rc)
+    return rc;
+  if (imap->io)
     {
       /* Close any old carrier.  */
       mu_imap_disconnect (imap);
-      mu_stream_destroy (&imap->carrier);
+      mu_imapio_free (imap->io);
     }
-  mu_stream_ref (carrier);
-  imap->carrier = carrier;
+  imap->io = io;
   if (MU_IMAP_FISSET (imap, MU_IMAP_TRACE))
     _mu_imap_trace_enable (imap);
   imap->state = MU_IMAP_CONNECT;
@@ -55,8 +62,8 @@ mu_imap_get_carrier (mu_imap_t imap, mu_stream_t *pcarrier)
   if (pcarrier == NULL)
     return MU_ERR_OUT_PTR_NULL;
 
-  mu_stream_ref (imap->carrier);
-  *pcarrier = imap->carrier;
+  mu_stream_ref (imap->io->_imap_stream);
+  *pcarrier = imap->io->_imap_stream;
   return 0;
 }
 
diff --git a/libproto/imap/connect.c b/libproto/imap/connect.c
index 6585e8c..a925e84 100644
--- a/libproto/imap/connect.c
+++ b/libproto/imap/connect.c
@@ -24,18 +24,23 @@
 #include <sys/select.h>
 #include <sys/time.h>
 #include <mailutils/errno.h>
-#include <mailutils/wordsplit.h>
+#include <mailutils/imapio.h>
 #include <mailutils/sys/imap.h>
+#include <mailutils/sys/imapio.h>
 
 
 int
 mu_imap_connect (mu_imap_t imap)
 {
   int status;
-
+  size_t wc;
+  char **wv;
+  char *bufptr;
+  size_t bufsize;
+  
   if (imap == NULL)
     return EINVAL;
-  if (imap->carrier == NULL)
+  if (imap->io == NULL)
     return EINVAL;
   switch (imap->state)
     {
@@ -54,66 +59,48 @@ mu_imap_connect (mu_imap_t imap)
 
     case MU_IMAP_CONNECT:
       /* Establish the connection.  */
-      if (!mu_stream_is_open (imap->carrier))
+      if (!mu_stream_is_open (imap->io->_imap_stream))
         {
-          status = mu_stream_open (imap->carrier);
+          status = mu_stream_open (imap->io->_imap_stream);
           MU_IMAP_CHECK_EAGAIN (imap, status);
           MU_IMAP_FCLR (imap, MU_IMAP_RESP);
         }
       imap->state = MU_IMAP_GREETINGS;
 
     case MU_IMAP_GREETINGS:
-      status = mu_stream_getline (imap->carrier, &imap->rdbuf,
-                                 &imap->rdsize, NULL);
+      status = mu_imapio_getline (imap->io);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      if (imap->rdsize < 2 ||
-         !(imap->rdbuf[0] == '*' && imap->rdbuf[1] == ' '))
+      mu_imapio_get_words (imap->io, &wc, &wv);
+      if (wc < 2 || strcmp (wv[0], "*"))
        {
+         mu_imapio_getbuf (imap->io, &bufptr, &bufsize);
          mu_error ("mu_imap_connect: invalid server response: %s",
-                   imap->rdbuf);
+                   bufptr);
          imap->state = MU_IMAP_ERROR;
          return MU_ERR_BADREPLY;
        }
+      else if (strcmp (wv[1], "BYE") == 0)
+       {
+         status = EACCES;
+         mu_imapio_getbuf (imap->io, &bufptr, &bufsize);
+         _mu_imap_seterrstr (imap, bufptr + 2, bufsize - 2);
+       }
+      else if (strcmp (wv[1], "PREAUTH") == 0)
+       {
+         status = 0;
+         imap->state = MU_IMAP_CONNECTED;
+         imap->imap_state = MU_IMAP_STATE_AUTH;
+       }
+      else if (strcmp (wv[1], "OK") == 0)
+       {
+         status = 0;
+         imap->state = MU_IMAP_CONNECTED;
+         imap->imap_state = MU_IMAP_STATE_NONAUTH;
+       }
       else
        {
-         struct mu_wordsplit ws;
-         
-         if (mu_wordsplit (imap->rdbuf, &ws,
-                           MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
-                           MU_WRDSF_SQUEEZE_DELIMS))
-           {
-             int ec = errno;
-             mu_error ("mu_imap_connect: cannot split line: %s",
-                       mu_wordsplit_strerror (&ws));
-             imap->state = MU_IMAP_ERROR;
-             return ec;
-           }
-         if (ws.ws_wordc < 2)
-           status = MU_ERR_BADREPLY;
-         else if (strcmp (ws.ws_wordv[1], "BYE") == 0)
-           {
-             status = EACCES;
-             _mu_imap_seterrstr (imap, imap->rdbuf + 2,
-                                 strlen (imap->rdbuf + 2));
-           }
-         else if (strcmp (ws.ws_wordv[1], "PREAUTH") == 0)
-           {
-             status = 0;
-             imap->state = MU_IMAP_CONNECTED;
-             imap->imap_state = MU_IMAP_STATE_AUTH;
-           }
-         else if (strcmp (ws.ws_wordv[1], "OK") == 0)
-           {
-             status = 0;
-             imap->state = MU_IMAP_CONNECTED;
-             imap->imap_state = MU_IMAP_STATE_NONAUTH;
-           }
-         else
-           {
-             status = MU_ERR_BADREPLY;
-             imap->state = MU_IMAP_ERROR;
-           }
-         mu_wordsplit_free (&ws);
+         status = MU_ERR_BADREPLY;
+         imap->state = MU_IMAP_ERROR;
        }
     }
   
diff --git a/libproto/imap/create.c b/libproto/imap/create.c
index e3d9901..96cc4ac 100644
--- a/libproto/imap/create.c
+++ b/libproto/imap/create.c
@@ -49,7 +49,7 @@ _mu_imap_init (mu_imap_t imap)
 {
   if (imap == NULL)
     return EINVAL;
-  if (imap->carrier == 0)
+  if (!imap->io)
     {
       int rc;
       
diff --git a/libproto/imap/destroy.c b/libproto/imap/destroy.c
index e49a844..ff8076f 100644
--- a/libproto/imap/destroy.c
+++ b/libproto/imap/destroy.c
@@ -31,13 +31,6 @@ mu_imap_destroy (mu_imap_t *pimap)
     {
       mu_imap_t imap = *pimap;
       
-      /* Free the response buffer.  */
-      if (imap->tagbuf)
-       free (imap->tagbuf);
-      /* Free the read buffer.  */
-      if (imap->rdbuf)
-       free (imap->rdbuf);
-
       if (imap->errstr)
        free (imap->errstr);
 
@@ -49,7 +42,7 @@ mu_imap_destroy (mu_imap_t *pimap)
       mu_list_destroy (&imap->untagged_resp);
       mu_list_destroy (&imap->capa);
       
-      mu_stream_destroy (&imap->carrier);
+      mu_imapio_destroy (&imap->io);
 
       free (imap);
 
diff --git a/libproto/imap/disconnect.c b/libproto/imap/disconnect.c
index 36a34ab..6803008 100644
--- a/libproto/imap/disconnect.c
+++ b/libproto/imap/disconnect.c
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <mailutils/imapio.h>
 #include <mailutils/sys/imap.h>
 
 int
@@ -34,14 +35,11 @@ mu_imap_disconnect (mu_imap_t imap)
   imap->state = MU_IMAP_NO_STATE;
   MU_IMAP_FCLR (imap, MU_IMAP_RESP);
 
-  if (imap->rdbuf)
-    imap->rdbuf[0] = 0;
-
   mu_list_clear (imap->untagged_resp);
   mu_list_clear (imap->capa);
   
   /* Close the stream.  */
-  if (mu_stream_is_open (imap->carrier))
-    return mu_stream_close (imap->carrier);
+  mu_imapio_destroy (&imap->io);
+
   return 0;
 }
diff --git a/libproto/imap/id.c b/libproto/imap/id.c
index 03db874..ef0974d 100644
--- a/libproto/imap/id.c
+++ b/libproto/imap/id.c
@@ -22,93 +22,109 @@
 #include <stdlib.h>
 #include <string.h>
 #include <mailutils/errno.h>
-#include <mailutils/cstr.h>
-#include <mailutils/wordsplit.h>
+#include <mailutils/assoc.h>
 #include <mailutils/stream.h>
+#include <mailutils/imap.h>
 #include <mailutils/sys/imap.h>
 
-static int
-id_comp (const void *item, const void *value)
+void
+_id_free (void *data)
 {
-  const char *id = item;
-  const char *needle = value;
-  return mu_c_strcasecmp (id, needle);
+  char *s = *(char**)data;
+  free (s);
 }
 
+struct id_convert_state
+{
+  int item;
+  mu_assoc_t assoc;
+  int ret;
+};
+
 static int
-parse_id_reply (mu_imap_t imap, mu_list_t *plist)
+_id_convert (void *item, void *data)
+{
+  struct imap_list_element *elt = item;
+  struct id_convert_state *stp = data;
+
+  switch (stp->item)
+    {
+    case 0:
+      if (!(elt->type == imap_eltype_string &&
+           strcmp (elt->v.string, "ID") == 0))
+       {
+         stp->ret = MU_ERR_PARSE;
+         return 1;
+       }
+      stp->item++;
+      return 0;
+
+    case 1:
+      if (elt->type == imap_eltype_list)
+       {
+         mu_iterator_t itr;
+
+         mu_list_get_iterator (elt->v.list, &itr);
+         for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+              mu_iterator_next (itr))
+           {
+             char *key, *val;
+             mu_iterator_current (itr, (void **) &elt);
+
+             if (elt->type != imap_eltype_string)
+               break;
+             key = elt->v.string;
+             elt->v.string = NULL;
+
+             mu_iterator_next (itr);
+             if (mu_iterator_is_done (itr))
+               break;
+             mu_iterator_current (itr, (void **) &elt);
+             if (elt->type != imap_eltype_string)
+               break;
+             val = elt->v.string;
+             elt->v.string = NULL;
+             mu_assoc_install (stp->assoc, key, &val);
+           }
+       }
+    }
+  return 1;
+}      
+
+static int
+parse_id_reply (mu_imap_t imap, mu_assoc_t *passoc)
 {
-  mu_list_t list;
   int rc;
-  const char *response;
-  struct mu_wordsplit ws;
-  size_t i;
-    
-  rc = mu_list_create (&list);
+  struct imap_list_element const *response;
+  struct id_convert_state st;
+  mu_assoc_t assoc;
+  
+  rc = mu_assoc_create (&assoc, sizeof (char**), MU_ASSOC_ICASE);
   if (rc)
     return rc;
-  mu_list_set_comparator (list, id_comp);
-  mu_list_set_destroy_item (list, mu_list_free_item);
+  mu_assoc_set_free (assoc, _id_free);
   
   rc = mu_list_get (imap->untagged_resp, 0, (void*) &response);
+  *passoc = assoc;
   if (rc == MU_ERR_NOENT)
-    {
-      *plist = list;
-      return 0;
-    }
-  else if (rc)
-    {
-      mu_list_destroy (&list);
-      return rc;
-    }
-
-  ws.ws_delim = "() \t";
-  if (mu_wordsplit (response, &ws,
-                   MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
-                   MU_WRDSF_QUOTE | MU_WRDSF_DELIM |
-                   MU_WRDSF_SQUEEZE_DELIMS |
-                   MU_WRDSF_WS))
-    {
-      int ec = errno;
-      mu_error ("mu_imap_id: cannot split line: %s",
-               mu_wordsplit_strerror (&ws));
-      mu_list_destroy (&list);
-      return ec;
-    }
+    return 0;
 
-  for (i = 1; i < ws.ws_wordc; i += 2)
-    {
-      size_t len, l1, l2;
-      char *elt;
-      
-      if (i + 1 == ws.ws_wordc)
-       break;
-      l1 = strlen (ws.ws_wordv[i]);
-      l2 = strlen (ws.ws_wordv[i+1]);
-      len = l1 + l2 + 1;
-      elt = malloc (len + 1);
-      if (!elt)
-       break;
-
-      memcpy (elt, ws.ws_wordv[i], l1);
-      elt[l1] = 0;
-      memcpy (elt + l1 + 1, ws.ws_wordv[i+1], l2);
-      elt[len] = 0;
-      mu_list_append (list, elt);
-    }
-  mu_wordsplit_free (&ws);
-  *plist = list;
-  return 0;
+  st.item = 0;
+  st.assoc = assoc;
+  st.ret = 0;
+  mu_list_do (response->v.list, _id_convert, &st);
+  return st.ret;
 }
-
+  
+  
 int
-mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist)
+mu_imap_id (mu_imap_t imap, char **idenv, mu_assoc_t *passoc)
 {
   int status;
   
   if (imap == NULL)
     return EINVAL;
-  if (!imap->carrier)
+  if (!imap->io)
     return MU_ERR_NO_TRANSPORT;
   if (imap->state != MU_IMAP_CONNECTED)
     return MU_ERR_SEQ;
@@ -118,11 +134,10 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t 
*plist)
     case MU_IMAP_CONNECTED:
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_stream_printf (imap->carrier, "%s ID ",
-                                imap->tag_str);
+      status = mu_imapio_printf (imap->io, "%s ID ", imap->tag_str);
       MU_IMAP_CHECK_ERROR (imap, status);
       if (!idenv)
-       status = mu_stream_printf (imap->carrier, "NIL");
+       status = mu_imapio_printf (imap->io, "NIL");
       else
        {
          if (idenv[0])
@@ -131,7 +146,7 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist)
              char *delim = "(";
              for (i = 0; idenv[i]; i++)
                {
-                 status = mu_stream_printf (imap->carrier, "%s\"%s\"",
+                 status = mu_imapio_printf (imap->io, "%s\"%s\"",
                                             delim, idenv[i]);
                  MU_IMAP_CHECK_ERROR (imap, status);
                  
@@ -139,13 +154,13 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t 
*plist)
                  if (status)
                    break;
                }
-             status = mu_stream_printf (imap->carrier, ")");
+             status = mu_imapio_printf (imap->io, ")");
            }
          else
-           status = mu_stream_printf (imap->carrier, "()");
+           status = mu_imapio_printf (imap->io, "()");
        }
       MU_IMAP_CHECK_ERROR (imap, status);
-      status = mu_stream_printf (imap->carrier, "\r\n");
+      status = mu_imapio_printf (imap->io, "\r\n");
       MU_IMAP_CHECK_ERROR (imap, status);
       MU_IMAP_FCLR (imap, MU_IMAP_RESP);
       imap->state = MU_IMAP_ID_RX;
@@ -157,8 +172,8 @@ mu_imap_id (mu_imap_t imap, char **idenv, mu_list_t *plist)
        {
        case MU_IMAP_OK:
          imap->imap_state = MU_IMAP_STATE_AUTH;
-         if (plist)
-           status = parse_id_reply (imap, plist);
+         if (passoc)
+           status = parse_id_reply (imap, passoc);
          break;
 
        case MU_IMAP_NO:
diff --git a/libproto/imap/login.c b/libproto/imap/login.c
index bce17ee..fe0af0c 100644
--- a/libproto/imap/login.c
+++ b/libproto/imap/login.c
@@ -30,7 +30,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char 
*pass)
   
   if (imap == NULL)
     return EINVAL;
-  if (!imap->carrier)
+  if (!imap->io)
     return MU_ERR_NO_TRANSPORT;
   if (imap->state != MU_IMAP_CONNECTED)
     return MU_ERR_SEQ;
@@ -44,7 +44,7 @@ mu_imap_login (mu_imap_t imap, const char *user, const char 
*pass)
        _mu_imap_xscript_level (imap, MU_XSCRIPT_SECURE);
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_stream_printf (imap->carrier, "%s LOGIN \"%s\" \"%s\"\r\n",
+      status = mu_imapio_printf (imap->io, "%s LOGIN \"%s\" \"%s\"\r\n",
                                 imap->tag_str, user, pass);
       _mu_imap_xscript_level (imap, MU_XSCRIPT_NORMAL);
       /* FIXME: how to obscure the passwd in the stream buffer? */
diff --git a/libproto/imap/logout.c b/libproto/imap/logout.c
index 922fc33..3565bb7 100644
--- a/libproto/imap/logout.c
+++ b/libproto/imap/logout.c
@@ -30,7 +30,7 @@ mu_imap_logout (mu_imap_t imap)
   
   if (imap == NULL)
     return EINVAL;
-  if (!imap->carrier)
+  if (!imap->io)
     return MU_ERR_NO_TRANSPORT;
   if (imap->state != MU_IMAP_CONNECTED)
     return MU_ERR_SEQ;
@@ -40,7 +40,7 @@ mu_imap_logout (mu_imap_t imap)
     case MU_IMAP_CONNECTED:
       status = _mu_imap_tag_next (imap);
       MU_IMAP_CHECK_EAGAIN (imap, status);
-      status = mu_stream_printf (imap->carrier, "%s LOGOUT\r\n",
+      status = mu_imapio_printf (imap->io, "%s LOGOUT\r\n",
                                 imap->tag_str); 
       MU_IMAP_CHECK_EAGAIN (imap, status);
       MU_IMAP_FCLR (imap, MU_IMAP_RESP);
diff --git a/libproto/imap/resplist.c b/libproto/imap/resplist.c
new file mode 100644
index 0000000..3031fee
--- /dev/null
+++ b/libproto/imap/resplist.c
@@ -0,0 +1,256 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 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
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <mailutils/cctype.h>
+#include <mailutils/cstr.h>
+#include <mailutils/stream.h>
+#include <mailutils/errno.h>
+#include <mailutils/sys/imap.h>
+
+static void
+_imap_list_free (void *ptr)
+{
+  struct imap_list_element *elt = ptr;
+
+  switch (elt->type)
+    {
+    case imap_eltype_string:
+      free (elt->v.string);
+      break;
+      
+    case imap_eltype_list:
+      mu_list_destroy (&elt->v.list);
+    }
+  free (ptr);
+}
+
+static int
+_mu_imap_response_list_create (mu_imap_t imap, mu_list_t *plist)
+{
+  mu_list_t list;
+  int status = mu_list_create (&list);
+  MU_IMAP_CHECK_ERROR (imap, status);
+  mu_list_set_destroy_item (list, _imap_list_free);
+  *plist = list;
+  return 0;
+}
+
+int
+_mu_imap_untagged_response_clear (mu_imap_t imap)
+{
+  if (imap->untagged_resp)
+    mu_list_clear (imap->untagged_resp);
+  else
+    return _mu_imap_response_list_create (imap, &imap->untagged_resp);
+  return 0;
+}
+
+#define IS_LBRACE(p) ((p)[0] == '(')
+#define IS_RBRACE(p) ((p)[0] == ')')
+
+static struct imap_list_element *
+_new_imap_list_element (mu_imap_t imap, enum imap_eltype type)
+{
+  struct imap_list_element *elt = calloc (1, sizeof (*elt));
+  if (!elt)
+    {
+      imap->state = MU_IMAP_ERROR;
+    }
+  else
+    elt->type = type;
+  return elt;
+}
+
+struct parsebuf
+{
+  mu_imap_t pb_imap;
+  size_t pb_count;
+  char **pb_arr;
+  int pb_err;
+  int pb_inlist;
+};
+
+static void
+parsebuf_init (struct parsebuf *pb, mu_imap_t imap)
+{
+  memset (pb, 0, sizeof *pb);
+  pb->pb_imap = imap;
+}
+
+static int
+parsebuf_advance (struct parsebuf *pb)
+{
+  if (pb->pb_count == 0)
+    return MU_ERR_NOENT;
+  pb->pb_count--;
+  pb->pb_arr++;
+  return 0;
+}
+
+static char *
+parsebuf_gettok (struct parsebuf *pb)
+{
+  char *p;
+  
+  if (pb->pb_count == 0)
+    return NULL;
+  p = *pb->pb_arr;
+  parsebuf_advance (pb);
+  return p;
+}
+
+static char *
+parsebuf_peek (struct parsebuf *pb)
+{
+  if (pb->pb_count == 0)
+    return NULL;
+  return *pb->pb_arr;
+}
+
+static void
+parsebuf_seterr (struct parsebuf *pb, int err)
+{
+  pb->pb_err = err;
+}
+
+static struct imap_list_element *_parse_element (struct parsebuf *pb);
+
+static struct imap_list_element *
+_parse_list (struct parsebuf *pb)
+{
+  int rc;
+  struct imap_list_element *elt, *list_elt;
+
+  elt = _new_imap_list_element (pb->pb_imap, imap_eltype_list);
+  if (!elt)
+    {
+      parsebuf_seterr (pb, ENOMEM);
+      return NULL;
+    }
+
+  rc = _mu_imap_response_list_create (pb->pb_imap, &elt->v.list);
+  if (rc)
+    {
+      free (elt);
+      parsebuf_seterr (pb, rc);
+      return NULL;
+    }
+
+  while ((list_elt = _parse_element (pb)))
+    mu_list_append (elt->v.list, list_elt);
+
+  return elt;
+}
+
+static struct imap_list_element *
+_parse_element (struct parsebuf *pb)
+{
+  struct imap_list_element *elt;
+  char *tok;
+
+  if (pb->pb_err)
+    return NULL;
+
+  tok = parsebuf_gettok (pb);
+  
+  if (!tok)
+    {
+      if (pb->pb_inlist)
+       parsebuf_seterr (pb, MU_ERR_PARSE);
+      return NULL;
+    }
+  
+  if (IS_LBRACE (tok))
+    {
+      tok = parsebuf_peek (pb);
+      if (!tok)
+       {
+         parsebuf_seterr (pb, MU_ERR_PARSE);
+         return NULL;
+       }
+      
+      if (IS_RBRACE (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
+       {
+         pb->pb_inlist++;
+         elt = _parse_list (pb);
+       }
+    }
+  else if (IS_RBRACE (tok))
+    {
+      if (pb->pb_inlist)
+       pb->pb_inlist--;
+      else
+       parsebuf_seterr (pb, MU_ERR_PARSE);
+      return NULL;
+    }
+  else
+    {
+      char *s;
+      elt = _new_imap_list_element (pb->pb_imap, imap_eltype_string);
+      if (!elt)
+       {
+         parsebuf_seterr (pb, ENOMEM);
+         return NULL;
+       }
+      s = strdup (tok);
+      if (!s)
+       {
+         free (elt);
+         parsebuf_seterr (pb, ENOMEM);
+         return NULL;
+       }
+      elt->v.string = s;
+    }
+  return elt;
+}
+
+int
+_mu_imap_untagged_response_add (mu_imap_t imap)
+{
+  struct imap_list_element *elt;
+  struct parsebuf pb;
+
+  parsebuf_init (&pb, imap);
+  mu_imapio_get_words (imap->io, &pb.pb_count, &pb.pb_arr);
+  parsebuf_advance (&pb); /* Skip initial '*' */
+  elt = _parse_list (&pb);
+  if (pb.pb_err)
+    {
+      if (elt)
+       _imap_list_free (elt);
+      imap->state = MU_IMAP_ERROR;
+      return pb.pb_err;
+    }
+  mu_list_append (imap->untagged_resp, elt);
+  return 0;
+}
diff --git a/libproto/imap/response.c b/libproto/imap/response.c
index 7612b71..67087ad 100644
--- a/libproto/imap/response.c
+++ b/libproto/imap/response.c
@@ -27,15 +27,9 @@
 #include <mailutils/errno.h>
 #include <mailutils/sys/imap.h>
 
-#define IS_PREFIX(s, len, pfx)                         \
-  ((len) >= sizeof (pfx) - 1 &&                                \
-   memcmp ((s), (pfx), sizeof (pfx) - 1) == 0 &&       \
-   s[sizeof (pfx) - 1] == ' ')
-
 int
 _mu_imap_response (mu_imap_t imap)
 {
-  size_t n = 0;
   int status = 0;
 
   if (imap == NULL)
@@ -45,81 +39,74 @@ _mu_imap_response (mu_imap_t imap)
     return 0;
 
   _mu_imap_clrerrstr (imap);
-  if (imap->untagged_resp)
-    mu_list_clear (imap->untagged_resp);
-  else
-    {
-      status = mu_list_create (&imap->untagged_resp);
-      MU_IMAP_CHECK_ERROR (imap, status);
-      mu_list_set_destroy_item (imap->untagged_resp, mu_list_free_item);
-    }
-
+  status = _mu_imap_untagged_response_clear (imap);
+  if (status)
+    return status;
+  
   while (1)
     {
-      status = mu_stream_getline (imap->carrier, &imap->rdbuf,
-                                 &imap->rdsize, NULL);
+      status = mu_imapio_getline (imap->io);
       if (status == 0)
        {
-         n = mu_rtrim_class (imap->rdbuf, MU_CTYPE_SPACE);
-         if (imap->rdbuf[0] == '*' && imap->rdbuf[1] == ' ')
+         char **wv;
+         size_t wc;
+         char *p;
+         
+         mu_imapio_get_words (imap->io, &wc, &wv);
+         if (strcmp (wv[0], "*") == 0)
            {
-             char *p = mu_str_skip_cset (imap->rdbuf + 2, " ");
-             mu_list_append (imap->untagged_resp, strdup (p));
+             _mu_imap_untagged_response_add (imap);/* FIXME: error checking */
+             continue;
            }
-         else if (n > imap->tag_len + 3 &&
-                  memcmp (imap->rdbuf, imap->tag_str, imap->tag_len) == 0
-                  && imap->rdbuf[imap->tag_len] == ' ')
+         else if (strlen (wv[0]) == imap->tag_len &&
+                  memcmp (wv[0], imap->tag_str, imap->tag_len) == 0)
            {
-             char *p = mu_str_skip_cset (imap->rdbuf + imap->tag_len, " ");
-             size_t len = strlen (p);
-
-             if (len >= imap->tagsize)
+             /* Handle the tagged response */
+             if (wc < 2)
                {
-                 char *np = realloc (imap->tagbuf, len + 1);
-                 if (!np)
-                   {
-                     imap->state = MU_IMAP_ERROR;
-                     return ENOMEM;
-                   }
-                 imap->tagsize = len + 1;
-                 imap->tagbuf = np;
+                 /*imap->state = MU_IMAP_ERROR;*/
+                 status = MU_ERR_BADREPLY;
                }
-             strcpy (imap->tagbuf, p);
-             if (IS_PREFIX (p, len, "OK"))
+             else if (strcmp (wv[1], "OK") == 0)
                {
                  imap->resp_code = MU_IMAP_OK;
-                 p = mu_str_skip_cset (p + 2, " ");
-                 _mu_imap_seterrstr (imap, p, strlen (p));
+                 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
+                   {
+                     _mu_imap_seterrstr (imap, p, strlen (p));
+                     free (p);
+                   }
                }
-             else if (IS_PREFIX (p, len, "NO"))
+             else if (strcmp (wv[1], "NO") == 0)
                {
                  imap->resp_code = MU_IMAP_NO;
-                 p = mu_str_skip_cset (p + 2, " ");
-                 _mu_imap_seterrstr (imap, p, strlen (p));
+                 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
+                   {
+                     _mu_imap_seterrstr (imap, p, strlen (p));
+                     free (p);
+                   }
                }
-             else if (IS_PREFIX (p, len, "BAD"))
+             else if (strcmp (wv[1], "BAD") == 0)
                {
                  imap->resp_code = MU_IMAP_BAD;
-                 p = mu_str_skip_cset (p + 2, " ");
-                 _mu_imap_seterrstr (imap, p, strlen (p));
+                 if (mu_imapio_reply_string (imap->io, 2, &p) == 0)
+                   {
+                     _mu_imap_seterrstr (imap, p, strlen (p));
+                     free (p);
+                   }
                }
              else
                status = MU_ERR_BADREPLY;
              MU_IMAP_FSET (imap, MU_IMAP_RESP);
-             break;
            }
          else
            {
              imap->state = MU_IMAP_ERROR;
-             return MU_ERR_BADREPLY;
+             status = MU_ERR_BADREPLY;
            }
        }
       else
-       {
-         imap->state = MU_IMAP_ERROR;
-         return status;
-       }
+       imap->state = MU_IMAP_ERROR;
+      break;
     }
   return status;
 }
-         
diff --git a/libproto/imap/trace.c b/libproto/imap/trace.c
index 0fc274b..152e9df 100644
--- a/libproto/imap/trace.c
+++ b/libproto/imap/trace.c
@@ -19,78 +19,50 @@
 # include <config.h>
 #endif
 
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include <mailutils/error.h>
 #include <mailutils/errno.h>
-#include <mailutils/nls.h>
-#include <mailutils/stream.h>
+#include <mailutils/imapio.h>
 #include <mailutils/sys/imap.h>
 
-static const char *imap_prefix[] = {
-  "S: ", "C: "
-};
-
 int
 _mu_imap_trace_enable (mu_imap_t imap)
 {
-  int rc = 0;
-  mu_stream_t dstr, xstr;
-
-  if (!imap->carrier)
+  int rc;
+  if (!imap->io)
+    return 0;
+  rc = mu_imapio_trace_enable (imap->io);
+  switch (rc)
     {
+    case 0:
+    case MU_ERR_OPEN:
       MU_IMAP_FSET (imap, MU_IMAP_TRACE);
-      return 0;
-    }
-  
-  rc = mu_dbgstream_create (&dstr, MU_DIAG_DEBUG);
-  if (rc)
-    mu_error (_("cannot create debug stream; transcript disabled: %s"),
-             mu_strerror (rc));
-  else
-    {
-      rc = mu_xscript_stream_create (&xstr, imap->carrier, dstr,
-                                    imap_prefix);
-      if (rc)
-       mu_error (_("cannot create transcript stream: %s"),
-                 mu_strerror (rc));
-      else
-       {
-         mu_stream_unref (imap->carrier);
-         imap->carrier = xstr;
-         MU_IMAP_FSET (imap, MU_IMAP_TRACE);
-       }
+      break;
     }
-
   return rc;
 }
 
 int
 _mu_imap_trace_disable (mu_imap_t imap)
 {
-  mu_stream_t xstr = imap->carrier;
-  mu_stream_t stream[2];
   int rc;
-
-  if (!xstr)
+  if (!imap->io)
     return 0;
-  
-  rc = mu_stream_ioctl (xstr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, stream);
-  if (rc)
-    return rc;
+  rc = mu_imapio_trace_disable (imap->io);
+  switch (rc)
+    {
+    case 0:
+    case MU_ERR_NOT_OPEN:
+      MU_IMAP_FCLR (imap, MU_IMAP_TRACE);
+      break;
+    }
+  return rc;
 
-  imap->carrier = stream[0];
-  mu_stream_destroy (&xstr);
-  MU_IMAP_FCLR (imap, MU_IMAP_TRACE);
-  return 0;
 }
 
 int
 mu_imap_trace (mu_imap_t imap, int op)
 {
-  int trace_on = MU_IMAP_FISSET (imap, MU_IMAP_TRACE);
-  
+  int trace_on = mu_imapio_get_trace (imap->io);
+
   switch (op)
     {
     case MU_IMAP_TRACE_SET:
@@ -117,15 +89,15 @@ mu_imap_trace_mask (mu_imap_t imap, int op, int lev)
   switch (op)
     {
     case MU_IMAP_TRACE_SET:
-      imap->flags |= MU_IMAP_XSCRIPT_MASK(lev);
+      imap->flags |= MU_IMAP_XSCRIPT_MASK (lev);
       break;
       
     case MU_IMAP_TRACE_CLR:
-      imap->flags &= ~MU_IMAP_XSCRIPT_MASK(lev);
+      imap->flags &= ~MU_IMAP_XSCRIPT_MASK (lev);
       break;
       
     case MU_IMAP_TRACE_QRY:
-      if (imap->flags & MU_IMAP_XSCRIPT_MASK(lev))
+      if (imap->flags & MU_IMAP_XSCRIPT_MASK (lev))
        break;
       return MU_ERR_NOENT;
       
@@ -138,8 +110,5 @@ mu_imap_trace_mask (mu_imap_t imap, int op, int lev)
 int
 _mu_imap_xscript_level (mu_imap_t imap, int xlev)
 {
-  if (mu_stream_ioctl (imap->carrier, MU_IOCTL_XSCRIPTSTREAM,
-                       MU_IOCTL_XSCRIPTSTREAM_LEVEL, &xlev) == 0)
-    return xlev;
-  return MU_XSCRIPT_NORMAL;
+  return mu_imapio_set_xscript_level (imap->io, xlev);
 }
diff --git a/mu/imap.c b/mu/imap.c
index c531d9b..e6fa2d1 100644
--- a/mu/imap.c
+++ b/mu/imap.c
@@ -364,6 +364,12 @@ com_login (int argc, char **argv)
   int status;
   char *pwd, *passbuf = NULL;
 
+  if (!imap)
+    {
+      mu_error (_("you need to connect first"));
+      return 0;
+    }
+  
   if (argc == 2)
     {
       if (!mutool_shell_interactive)
@@ -395,22 +401,13 @@ com_login (int argc, char **argv)
   return 0;
 }
 
-
-static int
-_print_id (void *item, void *data)
-{
-  const char *id = item;
-  mu_printf ("ID: %s %s\n", id, id + strlen (id) + 1);
-  return 0;
-}
-
 static int
 com_id (int argc, char **argv)
 {
-  mu_list_t list;
+  mu_assoc_t assoc;
   char *test = NULL;
   int status;
-  
+
   argv++;
   if (argv[0] && strcmp (argv[0], "-test") == 0)
     {
@@ -424,31 +421,36 @@ com_id (int argc, char **argv)
       argv++;
     }
   
-  status = mu_imap_id (imap, argv + 1, &list);
+  status = mu_imap_id (imap, argv + 1, &assoc);
   if (status == 0)
     {
       if (test)
        {
-         const char *res;
-         int rc = mu_list_locate (list, test, (void*)&res);
-
-         switch (rc)
+         void *res = mu_assoc_ref (assoc, test);
+         if (res)
            {
-           case 0:
-             mu_printf ("%s: %s\n", test, res + strlen (res) + 1);
-             break;
-             
-           case MU_ERR_NOENT:
-             mu_printf ("%s is not set\n", test);
-             break;
-
-           default:
-             return rc;
+             mu_printf ("%s: %s\n", test, *(char **)res);
            }
+         else
+           mu_printf ("%s is not set\n", test);
        }
       else
-       mu_list_do (list, _print_id, NULL);
-      mu_list_destroy (&list);
+       {
+         mu_iterator_t itr;
+         
+         mu_assoc_get_iterator (assoc, &itr);
+         for (mu_iterator_first (itr);
+              !mu_iterator_is_done (itr); mu_iterator_next (itr))
+           {
+             char *key;
+             void *val;
+
+             mu_iterator_current_kv (itr, (const void**)&key, &val);
+             mu_printf ("ID: %s %s\n", key, *(char**)val);
+           }
+         mu_iterator_destroy (&itr);
+       }
+      mu_assoc_destroy (&assoc);
     }
   return status;
 }


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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