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-453-g3571832


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-453-g3571832
Date: Sat, 19 Nov 2011 18:39:08 +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=35718326403f83b3e44cbeb8a3899e9d0d4dab90

The branch, master has been updated
       via  35718326403f83b3e44cbeb8a3899e9d0d4dab90 (commit)
      from  530953e151f011eb2f57918039c402f475431a09 (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 35718326403f83b3e44cbeb8a3899e9d0d4dab90
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Nov 19 20:34:24 2011 +0200

    Implement general-purpose processing of unsolicited responses in imap 
client.
    
    * include/mailutils/imap.h (mu_imap_response_action_t): New typedef.
    (mu_imap_foreach_response): New proto.
    (MU_IMAP_CB_PERMANENT_FLAGS,MU_IMAP_CB_MESSAGE_COUNT)
    (MU_IMAP_CB_RECENT_COUNT,MU_IMAP_CB_FIRST_UNSEEN)
    (MU_IMAP_CB_UIDNEXT,MU_IMAP_CB_UIDVALIDITY)
    (MU_IMAP_CB_OK,_MU_IMAP_CB_MAX): New constants.
    (mu_imap_callback_t): New typedef.
    (mu_imap_callback,mu_imap_register_callback_function): New protos.
    (MU_IMAP_RESPONSE_ALERT,MU_IMAP_RESPONSE_BADCHARSET)
    (MU_IMAP_RESPONSE_CAPABILITY,MU_IMAP_RESPONSE_PARSE)
    (MU_IMAP_RESPONSE_PERMANENTFLAGS,MU_IMAP_RESPONSE_READ_ONLY)
    (MU_IMAP_RESPONSE_READ_WRITE,MU_IMAP_RESPONSE_TRYCREATE)
    (MU_IMAP_RESPONSE_UIDNEXT,MU_IMAP_RESPONSE_UIDVALIDITY)
    (MU_IMAP_RESPONSE_UNSEEN): New constants.
    (mu_imap_response_codes): New extern.
    * include/mailutils/sys/imap.h (_mu_imap) <callback>: New member.
    (_mu_imap_collect_flags, _mu_imap_list_at): New protos.
    * libproto/imap/resplist.c (_mu_imap_list_at): New function.
    * libproto/imap/callback.c: New file.
    * libproto/imap/resproc.c: New file.
    * libproto/imap/Makefile.am: Add new files.
    * libproto/imap/capability.c: Rewrite using mu_imap_foreach_response.
    * libproto/imap/id.c: Likewise.
    * libproto/imap/select.c: Likewise.

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

Summary of changes:
 include/mailutils/imap.h                          |   40 ++++
 include/mailutils/sys/imap.h                      |   11 +
 libproto/imap/Makefile.am                         |    2 +
 libmu_dbm/datumfree.c => libproto/imap/callback.c |   35 ++-
 libproto/imap/capability.c                        |   39 ++--
 libproto/imap/id.c                                |   50 +---
 libproto/imap/resplist.c                          |   16 ++
 libproto/imap/resproc.c                           |  260 +++++++++++++++++++++
 libproto/imap/select.c                            |  111 ++--------
 9 files changed, 406 insertions(+), 158 deletions(-)
 copy libmu_dbm/datumfree.c => libproto/imap/callback.c (51%)
 create mode 100644 libproto/imap/resproc.c

diff --git a/include/mailutils/imap.h b/include/mailutils/imap.h
index 3093ec6..e33ff08 100644
--- a/include/mailutils/imap.h
+++ b/include/mailutils/imap.h
@@ -18,6 +18,7 @@
 #ifndef _MAILUTILS_IMAP_H
 #define _MAILUTILS_IMAP_H
 
+#include <stdarg.h>
 #include <mailutils/iterator.h>
 #include <mailutils/debug.h>
 #include <mailutils/stream.h>
@@ -99,6 +100,45 @@ int mu_imap_select (mu_imap_t imap, const char *mbox, int 
writable,
 int mu_imap_status (mu_imap_t imap, const char *mbox, struct mu_imap_stat *ps);
 
 extern struct mu_kwd _mu_imap_status_name_table[];
+
+typedef void (*mu_imap_response_action_t) (mu_imap_t imap, mu_list_t resp,
+                                          void *data);
+
+int mu_imap_foreach_response (mu_imap_t imap, mu_imap_response_action_t fun,
+                             void *data);
+  
+
+#define MU_IMAP_CB_PERMANENT_FLAGS  0
+#define MU_IMAP_CB_MESSAGE_COUNT    1
+#define MU_IMAP_CB_RECENT_COUNT     2
+#define MU_IMAP_CB_FIRST_UNSEEN     3
+#define MU_IMAP_CB_UIDNEXT          4 
+#define MU_IMAP_CB_UIDVALIDITY      5
+#define MU_IMAP_CB_OK               6
+#define _MU_IMAP_CB_MAX             7
+
+typedef void (*mu_imap_callback_t) (void *, int code, mu_list_t resp,
+                                   va_list ap);
+  
+void mu_imap_callback (mu_imap_t imap, int code, mu_list_t resp, ...);
+
+void mu_imap_register_callback_function (mu_imap_t imap, int code,
+                                        mu_imap_callback_t callback,
+                                        void *data);
+
+#define MU_IMAP_RESPONSE_ALERT            0
+#define MU_IMAP_RESPONSE_BADCHARSET       1
+#define MU_IMAP_RESPONSE_CAPABILITY       2
+#define MU_IMAP_RESPONSE_PARSE            3
+#define MU_IMAP_RESPONSE_PERMANENTFLAGS   4
+#define MU_IMAP_RESPONSE_READ_ONLY        5     
+#define MU_IMAP_RESPONSE_READ_WRITE       6
+#define MU_IMAP_RESPONSE_TRYCREATE        7
+#define MU_IMAP_RESPONSE_UIDNEXT          8
+#define MU_IMAP_RESPONSE_UIDVALIDITY      9
+#define MU_IMAP_RESPONSE_UNSEEN          10
+
+extern struct mu_kwd mu_imap_response_codes[];  
   
 #ifdef __cplusplus
 }
diff --git a/include/mailutils/sys/imap.h b/include/mailutils/sys/imap.h
index dd4b1df..de3d1bf 100644
--- a/include/mailutils/sys/imap.h
+++ b/include/mailutils/sys/imap.h
@@ -83,6 +83,13 @@ struct _mu_imap
     char *mbox_name;  /* Name of the currently opened mailbox */
     int mbox_writable:1; /* Is it open read/write? */
     struct mu_imap_stat mbox_stat;  /* Stats obtained from it */
+
+    /* Callbacks */
+    struct
+    {
+      mu_imap_callback_t action;
+      void *data;
+    } callback[_MU_IMAP_CB_MAX];
 };
 
 enum imap_eltype
@@ -160,6 +167,10 @@ int _mu_imap_untagged_response_add (mu_imap_t imap);
 
 int _mu_imap_list_element_is_string (struct imap_list_element *elt,
                                     const char *str);
+int _mu_imap_collect_flags (struct imap_list_element *arg, int *res);
+
+struct imap_list_element *_mu_imap_list_at (mu_list_t list, int idx);
+  
   
 # ifdef __cplusplus
 }
diff --git a/libproto/imap/Makefile.am b/libproto/imap/Makefile.am
index 956b0b5..ee89f90 100644
--- a/libproto/imap/Makefile.am
+++ b/libproto/imap/Makefile.am
@@ -28,6 +28,7 @@ libmu_imap_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} 
@INTLLIBS@
 #  url.c
 libmu_imap_la_SOURCES = \
  fake-folder.c\
+ callback.c\
  capability.c\
  capatst.c\
  carrier.c\
@@ -41,6 +42,7 @@ libmu_imap_la_SOURCES = \
  logout.c\
  resplist.c\
  response.c\
+ resproc.c\
  select.c\
  state.c\
  status.c\
diff --git a/libmu_dbm/datumfree.c b/libproto/imap/callback.c
similarity index 51%
copy from libmu_dbm/datumfree.c
copy to libproto/imap/callback.c
index c11db26..63df696 100644
--- a/libmu_dbm/datumfree.c
+++ b/libproto/imap/callback.c
@@ -1,4 +1,5 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
+/* Response processing for IMAP client.
+   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
@@ -18,19 +19,33 @@
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
-#include <stdlib.h>
-#include <mailutils/types.h>
-#include <mailutils/dbm.h>
 #include <mailutils/errno.h>
-#include "mudbm.h"
+#include <mailutils/sys/imap.h>
 
 void
-mu_dbm_datum_free (struct mu_dbm_datum *datum)
+mu_imap_callback (mu_imap_t imap, int code, mu_list_t resp, ...)
 {
-  if (datum && datum->mu_data &&
-      datum->mu_sys && datum->mu_sys->_dbm_datum_free)
+  va_list ap;
+  
+  if (code < 0 || code > _MU_IMAP_CB_MAX || !imap->callback[code].action)
+    return;
+  
+  va_start (ap, resp);
+  imap->callback[code].action (imap->callback[code].data, code, resp, ap);
+  va_end (ap);
+}
+
+void
+mu_imap_register_callback_function (mu_imap_t imap, int code,
+                                   mu_imap_callback_t callback,
+                                   void *data)
+{
+  if (code < 0 || code > _MU_IMAP_CB_MAX)
     {
-      datum->mu_sys->_dbm_datum_free (datum);
-      datum->mu_data = NULL;
+      mu_error ("%s:%d: ignoring unsupported callback code %d",
+               __FILE__, __LINE__, code);
+      return;
     }
+  imap->callback[code].action = callback;
+  imap->callback[code].data = data;
 }
diff --git a/libproto/imap/capability.c b/libproto/imap/capability.c
index feaed0d..14dff87 100644
--- a/libproto/imap/capability.c
+++ b/libproto/imap/capability.c
@@ -54,17 +54,25 @@ _map_capa (void **itmv, size_t itmc, void *call_data)
     return MU_LIST_MAP_STOP;
   if (*n == 0)
     {
-      ++*n;
-      if (strcmp (elt->v.string, "CAPABILITY") == 0)
-       return MU_LIST_MAP_SKIP;
-      else
-       return MU_LIST_MAP_STOP;
+      *n = 1;
+      return MU_LIST_MAP_SKIP;
     }
   itmv[0] = elt->v.string;
   elt->v.string = NULL;
   return MU_LIST_MAP_OK;
 }
 
+static void
+_capability_response_action (mu_imap_t imap, mu_list_t response, void *data)
+{
+  struct imap_list_element *elt = _mu_imap_list_at (response, 0);
+  if (elt && _mu_imap_list_element_is_string (elt, "CAPABILITY"))
+    {
+      int n = 0;
+      mu_list_map (response, _map_capa, &n, 1, &imap->capa);
+    }
+}
+
 int
 mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
 {
@@ -113,22 +121,17 @@ mu_imap_capability (mu_imap_t imap, int reread, 
mu_iterator_t *piter)
        return MU_ERR_REPLY;
       else
        {
-         size_t count;
-         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*)&elt) == 0)
+         status = mu_imap_foreach_response (imap,
+                                            _capability_response_action,
+                                            NULL);
+         if (status == 0)
            {
-             /* Top-level elements are always of imap_eltype_list type. */
-             int n = 0;
-             status = mu_list_map (elt->v.list, _map_capa, &n, 1,
-                                   &imap->capa);
+             if (piter)
+               status = mu_list_get_iterator (imap->capa, piter);
+             else
+               status = 0;
            }
-         if (piter)
-           status = mu_list_get_iterator (imap->capa, piter);
-         else
-           status = 0;
        }  
       break;
       
diff --git a/libproto/imap/id.c b/libproto/imap/id.c
index 2ba44ef..bd5d447 100644
--- a/libproto/imap/id.c
+++ b/libproto/imap/id.c
@@ -48,44 +48,25 @@ _id_mapper (void **itmv, size_t itmc, void *call_data)
   return rc;
 }
 
-struct id_convert_state
+static void
+_id_response_action (mu_imap_t imap, mu_list_t response, void *data)
 {
-  int item;
-  mu_assoc_t assoc;
-  int ret;
-};
-
-static int
-_id_convert (void *item, void *data)
-{
-  struct imap_list_element *elt = item;
-  struct id_convert_state *stp = data;
+  mu_assoc_t assoc = data;
+  struct imap_list_element *elt;
 
-  switch (stp->item)
+  elt = _mu_imap_list_at (response, 0);
+  if (elt && _mu_imap_list_element_is_string (elt, "ID"))
     {
-    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:
+      elt = _mu_imap_list_at (response, 1);
       if (elt->type == imap_eltype_list)
-       mu_list_gmap (elt->v.list, _id_mapper, 2, stp->assoc);
+       mu_list_gmap (elt->v.list, _id_mapper, 2, assoc);
     }
-  return 1;
-}      
+}
 
 static int
 parse_id_reply (mu_imap_t imap, mu_assoc_t *passoc)
 {
   int rc;
-  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);
@@ -93,16 +74,11 @@ parse_id_reply (mu_imap_t imap, mu_assoc_t *passoc)
     return rc;
   mu_assoc_set_free (assoc, _id_free);
   
-  rc = mu_list_get (imap->untagged_resp, 0, (void*) &response);
+  rc = mu_imap_foreach_response (imap, _id_response_action, assoc);
+  if (rc)
+    return rc;
   *passoc = assoc;
-  if (rc == MU_ERR_NOENT)
-    return 0;
-
-  st.item = 0;
-  st.assoc = assoc;
-  st.ret = 0;
-  mu_list_foreach (response->v.list, _id_convert, &st);
-  return st.ret;
+  return 0;
 }
   
 int
diff --git a/libproto/imap/resplist.c b/libproto/imap/resplist.c
index f46417c..de2e523 100644
--- a/libproto/imap/resplist.c
+++ b/libproto/imap/resplist.c
@@ -264,3 +264,19 @@ _mu_imap_list_element_is_string (struct imap_list_element 
*elt,
   return strcmp (elt->v.string, str) == 0;
 }
 
+struct imap_list_element *
+_mu_imap_list_at (mu_list_t list, int idx)
+{
+  struct imap_list_element *arg;
+  int rc = mu_list_get (list, idx, (void*) &arg);
+  if (rc)
+    {
+      mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
+               ("%s:%d: cannot get list element: %s",
+                __FILE__, __LINE__, mu_strerror (rc)));
+      return NULL;
+    }
+  return arg;
+}
+
+
diff --git a/libproto/imap/resproc.c b/libproto/imap/resproc.c
new file mode 100644
index 0000000..af752b9
--- /dev/null
+++ b/libproto/imap/resproc.c
@@ -0,0 +1,260 @@
+/* Response processing for IMAP client.
+   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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <mailutils/cstr.h>
+#include <mailutils/stream.h>
+#include <mailutils/errno.h>
+#include <mailutils/sys/imap.h>
+
+struct mu_kwd mu_imap_response_codes[] = {
+  /* [ALERT] */
+  { "ALERT",          MU_IMAP_RESPONSE_ALERT },
+  /* [BADCHARSET (opt-list)] */
+  { "BADCHARSET",     MU_IMAP_RESPONSE_BADCHARSET },
+  /* [CAPABILITY (list)] */
+  { "CAPABILITY",     MU_IMAP_RESPONSE_CAPABILITY },
+  /* [PARSE] text */
+  { "PARSE",          MU_IMAP_RESPONSE_PARSE }, 
+  /* [PERMANENTFLAGS (list)] */
+  { "PERMANENTFLAGS", MU_IMAP_RESPONSE_PERMANENTFLAGS },
+  /* [READ-ONLY] */
+  { "READ-ONLY",      MU_IMAP_RESPONSE_READ_ONLY },
+  /* [READ-WRITE] */
+  { "READ-WRITE",     MU_IMAP_RESPONSE_READ_WRITE },
+  /* [TRYCREATE] */
+  { "TRYCREATE",      MU_IMAP_RESPONSE_TRYCREATE },  
+  /* [UIDNEXT N] */
+  { "UIDNEXT",        MU_IMAP_RESPONSE_UIDNEXT }, 
+  /* [UIDVALIDITY N] */
+  { "UIDVALIDITY",    MU_IMAP_RESPONSE_UIDVALIDITY },
+  /* [UNSEEN N] */
+  { "UNSEEN",         MU_IMAP_RESPONSE_UNSEEN },
+  { NULL }
+};
+
+static void
+ok_response (mu_imap_t imap, mu_list_t resp, void *data)
+{
+  struct imap_list_element *arg;
+  int rcode = -1;
+  size_t n = 0;
+  
+  arg = _mu_imap_list_at (resp, 1);
+  if (!arg)
+    return;
+  if (arg->type == imap_eltype_string && arg->v.string[0] == '[')
+    {
+      char *p;
+      
+      size_t len = strcspn (arg->v.string, "]");
+      
+      if (mu_kwd_xlat_name_len (mu_imap_response_codes,
+                               arg->v.string + 1, len - 1, &rcode))
+       rcode = -1;
+      
+      switch (rcode)
+       {
+       case MU_IMAP_RESPONSE_PERMANENTFLAGS:
+         arg = _mu_imap_list_at (resp, 2);
+         if (!arg ||
+             _mu_imap_collect_flags (arg, &imap->mbox_stat.permanent_flags))
+           break;
+         imap->mbox_stat.flags |= MU_IMAP_STAT_PERMANENT_FLAGS;
+         mu_imap_callback (imap, MU_IMAP_CB_PERMANENT_FLAGS, resp,
+                           &imap->mbox_stat);
+         return;
+         
+       case MU_IMAP_RESPONSE_UIDNEXT:
+         arg = _mu_imap_list_at (resp, 2);
+         if (!arg || arg->type != imap_eltype_string)
+           break;
+         n = strtoul (arg->v.string, &p, 10);
+         if (*p == ']')
+           {
+             imap->mbox_stat.uidnext = n;
+             imap->mbox_stat.flags |= MU_IMAP_STAT_UIDNEXT;
+             mu_imap_callback (imap, MU_IMAP_CB_UIDNEXT, resp,
+                               &imap->mbox_stat);
+           }
+         return;
+                           
+       case MU_IMAP_RESPONSE_UIDVALIDITY:
+         arg = _mu_imap_list_at (resp, 2);
+         if (!arg || arg->type != imap_eltype_string)
+           break;
+         n = strtoul (arg->v.string, &p, 10);
+         if (*p == ']')
+           {
+             imap->mbox_stat.uidvalidity = n;
+             imap->mbox_stat.flags |= MU_IMAP_STAT_UIDVALIDITY;
+             mu_imap_callback (imap, MU_IMAP_CB_UIDVALIDITY, resp,
+                               &imap->mbox_stat);
+           }
+         return;
+                           
+       case MU_IMAP_RESPONSE_UNSEEN:
+         arg = _mu_imap_list_at (resp, 2);
+         if (!arg || arg->type != imap_eltype_string)
+           break;
+         n = strtoul (arg->v.string, &p, 10);
+         if (*p == ']')
+           {
+             imap->mbox_stat.first_unseen = n;
+             imap->mbox_stat.flags |= MU_IMAP_STAT_FIRST_UNSEEN;
+             mu_imap_callback (imap, MU_IMAP_CB_FIRST_UNSEEN, resp,
+                               &imap->mbox_stat);
+           }
+         return;
+       }
+    }
+  mu_imap_callback (imap, MU_IMAP_CB_OK, resp, rcode);
+}
+
+
+struct response_closure
+{
+  mu_imap_t imap;
+  mu_imap_response_action_t fun;
+  void *data;
+};
+
+struct resptab
+{
+  char *name;
+  mu_imap_response_action_t action;
+};
+
+static struct resptab resptab[] = {
+  { "OK", ok_response },
+  { "NO", },
+  { "BAD", },
+  { "PREAUTH", },
+  { "BYE", },
+  { NULL }
+};
+
+static int
+_std_unsolicited_response (mu_imap_t imap, size_t count, mu_list_t resp)
+{
+  struct resptab *rp;
+  struct imap_list_element *arg = _mu_imap_list_at (resp, 0);
+
+  if (!arg)
+    return 1;
+
+  if (arg->type == imap_eltype_string)
+    for (rp = resptab; rp->name; rp++)
+      {
+       if (mu_c_strcasecmp (rp->name, arg->v.string) == 0)
+         {
+           if (!rp->action)
+             mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE9,
+                       ("%s:%d: ignoring %s response",
+                        __FILE__, __LINE__, rp->name));
+           else
+             rp->action (imap, resp, NULL);
+           return 0;
+         }
+      }
+  return 1;
+}
+
+static int
+_process_unsolicited_response (mu_imap_t imap, mu_list_t resp)
+{
+  size_t count;
+  struct imap_list_element *arg;
+  
+  if (mu_list_count (resp, &count))
+    return 1;
+
+  if (_std_unsolicited_response (imap, count, resp) == 0)
+    return 0;
+  if (count == 2)
+    {
+      size_t n;
+      char *p;
+
+      arg = _mu_imap_list_at (resp, 1);
+      if (!arg)
+       return 1;
+      
+      if (_mu_imap_list_element_is_string (arg, "EXISTS"))
+       {
+         arg = _mu_imap_list_at (resp, 0);
+         if (!arg)
+           return 1;
+         
+         n = strtoul (arg->v.string, &p, 10);
+         if (*p)
+           return 1;
+         imap->mbox_stat.message_count = n;
+         imap->mbox_stat.flags |= MU_IMAP_STAT_MESSAGE_COUNT;
+         mu_imap_callback (imap, MU_IMAP_CB_MESSAGE_COUNT, resp, n);
+         return 0;
+       }
+      else if (_mu_imap_list_element_is_string (arg, "RECENT"))
+       {
+         arg = _mu_imap_list_at (resp, 0);
+         if (!arg)
+           return 1;
+         n = strtoul (arg->v.string, &p, 10);
+         if (*p)
+           return 1;
+         imap->mbox_stat.recent_count = n;
+         imap->mbox_stat.flags |= MU_IMAP_STAT_RECENT_COUNT;
+         mu_imap_callback (imap, MU_IMAP_CB_RECENT_COUNT, resp, n);
+         return 0;
+       }
+    }
+  return 1;
+}
+
+static int
+_process_response (void *item, void *data)
+{
+  struct imap_list_element *elt = item;
+  struct response_closure *clos = data;
+
+  if (elt->type != imap_eltype_list)
+    {
+      mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
+               ("ignoring string response \"%s\"", elt->v.string));
+    }
+  else if (_process_unsolicited_response (clos->imap, elt->v.list))
+    clos->fun (clos->imap, elt->v.list, clos->data);
+  return 0;
+}
+
+int
+mu_imap_foreach_response (mu_imap_t imap, mu_imap_response_action_t fun,
+                         void *data)
+{
+  struct response_closure clos;
+  clos.imap = imap;
+  clos.fun = fun;
+  clos.data = data;
+  return mu_list_foreach (imap->untagged_resp, _process_response, &clos);
+}
+                         
diff --git a/libproto/imap/select.c b/libproto/imap/select.c
index 75e94e6..0679197 100644
--- a/libproto/imap/select.c
+++ b/libproto/imap/select.c
@@ -38,103 +38,28 @@ _collect_flags (void *item, void *data)
   return 0;
 }
 
-static int
-_parse_stat (void *item, void *data)
+int
+_mu_imap_collect_flags (struct imap_list_element *arg, int *res)
+{
+  if (arg->type != imap_eltype_list)
+    return EINVAL;
+  mu_list_foreach (arg->v.list, _collect_flags, res);
+  return 0;
+}
+
+static void
+_select_response_action (mu_imap_t imap, mu_list_t response, void *data)
 {
-  struct imap_list_element *response = item;
-  mu_imap_t imap = data;
   struct imap_list_element *elt;
-  size_t count;
-  int rc;
-  char *p;
   
-  if (response->type != imap_eltype_list)
-    return 0;
-
-  mu_list_count (response->v.list, &count);
-  
-  rc = mu_list_get (response->v.list, 0, (void*) &elt);
-  if (rc)
-    return rc;
-  
-  if (_mu_imap_list_element_is_string (elt, "OK"))
-    {
-      struct imap_list_element *arg;
-      
-      if (count < 3)
-       return 0; /* ignore the line */
-      rc = mu_list_get (response->v.list, 1, (void*) &elt);
-      if (rc)
-       return rc;
-      rc = mu_list_get (response->v.list, 2, (void*) &arg);
-      if (rc)
-       return rc;
-      
-      if (_mu_imap_list_element_is_string (elt, "[UIDVALIDITY"))
-       {
-         if (arg->type != imap_eltype_string)
-           return 0;
-         imap->mbox_stat.uidvalidity = strtoul (arg->v.string, &p, 10);
-         if (*p == ']')
-           imap->mbox_stat.flags |= MU_IMAP_STAT_UIDVALIDITY;
-       }
-      else if (_mu_imap_list_element_is_string (elt, "[UIDNEXT"))
-       {
-         if (arg->type != imap_eltype_string)
-           return 0;
-         imap->mbox_stat.uidnext = strtoul (arg->v.string, &p, 10);
-         if (*p == ']')
-           imap->mbox_stat.flags |= MU_IMAP_STAT_UIDNEXT;
-       }
-      else if (_mu_imap_list_element_is_string (elt, "[UNSEEN"))
-       {
-         if (arg->type != imap_eltype_string)
-           return 0;
-         imap->mbox_stat.first_unseen = strtoul (arg->v.string, &p, 10);
-         if (*p == ']')
-           imap->mbox_stat.flags |= MU_IMAP_STAT_FIRST_UNSEEN;
-       }
-      else if (_mu_imap_list_element_is_string (elt, "[PERMANENTFLAGS"))
-       {
-         if (arg->type != imap_eltype_list)
-           return 0;
-         mu_list_foreach (arg->v.list, _collect_flags,
-                     &imap->mbox_stat.permanent_flags);
-         imap->mbox_stat.flags |= MU_IMAP_STAT_PERMANENT_FLAGS;
-       }
-    }
-  else if (_mu_imap_list_element_is_string (elt, "FLAGS"))
-    {
-      struct imap_list_element *arg;
-      rc = mu_list_get (response->v.list, 1, (void*) &arg);
-      if (rc)
-       return 0;
-      if (arg->type != imap_eltype_list)
-       return 0;
-      mu_list_foreach (arg->v.list, _collect_flags, 
&imap->mbox_stat.defined_flags);
-      imap->mbox_stat.flags |= MU_IMAP_STAT_DEFINED_FLAGS;
-    }
-  else if (count == 2)
+  elt = _mu_imap_list_at (response, 0);
+  if (elt && _mu_imap_list_element_is_string (elt, "FLAGS"))
     {
-      struct imap_list_element *arg;
-      rc = mu_list_get (response->v.list, 1, (void*) &arg);
-      if (rc)
-       return rc;
-      if (_mu_imap_list_element_is_string (arg, "EXISTS"))
-       {
-         imap->mbox_stat.message_count = strtoul (elt->v.string, &p, 10);
-         if (*p == 0)
-           imap->mbox_stat.flags |= MU_IMAP_STAT_MESSAGE_COUNT;
-       }
-      else if (_mu_imap_list_element_is_string (arg, "RECENT"))
-       {
-         imap->mbox_stat.recent_count = strtoul (elt->v.string, &p, 10);
-         if (*p == 0)
-           imap->mbox_stat.flags |= MU_IMAP_STAT_RECENT_COUNT;
-       }
+      struct imap_list_element *arg = _mu_imap_list_at (response, 1);
+      if (arg &&
+         _mu_imap_collect_flags (arg, &imap->mbox_stat.defined_flags) == 0)
+       imap->mbox_stat.flags |= MU_IMAP_STAT_DEFINED_FLAGS;
     }
-  
-  return 0;
 }
 
 int
@@ -202,7 +127,7 @@ mu_imap_select (mu_imap_t imap, const char *mbox, int 
writable,
            }
          imap->mbox_writable = writable;
          memset (&imap->mbox_stat, 0, sizeof (imap->mbox_stat));
-         mu_list_foreach (imap->untagged_resp, _parse_stat, imap);
+         mu_imap_foreach_response (imap, _select_response_action, NULL);
          if (ps)
            *ps = imap->mbox_stat;
          break;


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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