commit cf79cd9fc0077d5c871a5b5deaf778bf0914cc33
Author: Oswald Buddenhagen <[email protected]>
Date:   Sat Jul 27 14:31:13 2013 +0200

    make parse_list() callback based
    
    this allows us to parse IMAP literals ({}) in every list.

 src/drv_imap.c |  100 +++++++++++++++++++++++++++++++++--------------
 1 files changed, 70 insertions(+), 30 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 1f40bf2..34d2c47 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -70,8 +70,11 @@ typedef struct _list {
 
 #define MAX_LIST_DEPTH 5
 
+struct imap_store;
+
 typedef struct parse_list_state {
        list_t *head, **stack[MAX_LIST_DEPTH];
+       int (*callback)( struct imap_store *ctx, list_t *list, char *cmd );
        int level, need_bytes;
 } parse_list_state_t;
 
@@ -642,18 +645,63 @@ parse_list_init( parse_list_state_t *sts )
        sts->stack[0] = &sts->head;
 }
 
-static list_t *
-parse_list( char **sp )
+static int
+parse_list_continue( imap_store_t *ctx, char *s )
+{
+       list_t *list;
+       int resp;
+       if ((resp = parse_imap_list( ctx, &s, &ctx->parse_list_sts )) == 
LIST_PARTIAL)
+               return 0;
+       list = (resp == LIST_BAD) ? 0 : ctx->parse_list_sts.head;
+       ctx->parse_list_sts.head = 0;
+       return ctx->parse_list_sts.callback( ctx, list, s );
+}
+
+static int
+parse_list( imap_store_t *ctx, char *s, int (*cb)( imap_store_t *ctx, list_t 
*list, char *s ) )
+{
+       parse_list_init( &ctx->parse_list_sts );
+       ctx->parse_list_sts.callback = cb;
+       return parse_list_continue( ctx, s );
+}
+
+static int parse_namespace_rsp_p2( imap_store_t *, list_t *, char * );
+static int parse_namespace_rsp_p3( imap_store_t *, list_t *, char * );
+
+static int
+parse_namespace_rsp_fail( void )
+{
+       error( "IMAP error: malformed NAMESPACE response\n" );
+       return -1;
+}
+
+static int
+parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s )
 {
-       parse_list_state_t sts;
-       parse_list_init( &sts );
-       if (parse_imap_list( 0, sp, &sts ) == LIST_OK)
-               return sts.head;
-       return NULL;
+       if (!(ctx->ns_personal = list))
+               return parse_namespace_rsp_fail();
+       return parse_list( ctx, s, parse_namespace_rsp_p2 );
 }
 
 static int
-parse_fetch( imap_store_t *ctx, list_t *list )
+parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s )
+{
+       if (!(ctx->ns_other = list))
+               return parse_namespace_rsp_fail();
+       return parse_list( ctx, s, parse_namespace_rsp_p3 );
+}
+
+static int
+parse_namespace_rsp_p3( imap_store_t *ctx, list_t *list, char *s )
+{
+       (void)s;
+       if (!(ctx->ns_shared = list))
+               return parse_namespace_rsp_fail();
+       return 0;
+}
+
+static int
+parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s )
 {
        list_t *tmp, *flags;
        char *body = 0, *tuid = 0;
@@ -663,6 +711,7 @@ parse_fetch( imap_store_t *ctx, list_t *list )
        int uid = 0, mask = 0, status = 0, size = 0;
        unsigned i;
 
+       (void)s;
        if (!is_list( list )) {
                error( "IMAP error: bogus FETCH response\n" );
                free_list( list );
@@ -832,14 +881,16 @@ parse_response_code( imap_store_t *ctx, struct imap_cmd 
*cmd, char *s )
 }
 
 static int
-parse_list_rsp( imap_store_t *ctx, char *cmd )
+parse_list_rsp( imap_store_t *ctx, list_t *list, char *cmd )
 {
        char *arg;
-       list_t *list, *lp;
+       list_t *lp;
        int l;
 
-       if (!(list = parse_list( &cmd )))
+       if (!list) {
+               error( "IMAP error: malformed LIST response\n" );
                return -1;
+       }
        if (list->val == LIST)
                for (lp = list->child; lp; lp = lp->next)
                        if (is_atom( lp ) && !strcasecmp( lp->val, "\\NoSelect" 
)) {
@@ -922,11 +973,12 @@ imap_socket_read( void *aux )
        int resp, resp2, tag, greeted;
 
        greeted = ctx->greeting;
-       if (ctx->parse_list_sts.level) {
-               cmd = 0;
-               goto do_fetch;
-       }
        for (;;) {
+               if (ctx->parse_list_sts.level) {
+                       if (parse_list_continue( ctx, 0 ) < 0)
+                               break;
+                       continue;
+               }
                if (!(cmd = socket_read_line( &ctx->conn )))
                        return;
 
@@ -943,12 +995,8 @@ imap_socket_read( void *aux )
                        }
 
                        if (!strcmp( "NAMESPACE", arg )) {
-                               if (!(ctx->ns_personal = parse_list( &cmd )) ||
-                                   !(ctx->ns_other = parse_list( &cmd )) ||
-                                   !(ctx->ns_shared = parse_list( &cmd ))) {
-                                       error( "IMAP error: malformed NAMESPACE 
response\n" );
+                               if (parse_list( ctx, cmd, parse_namespace_rsp ) 
< 0)
                                        break;
-                               }
                        } else if (ctx->greeting == GreetingPending && !strcmp( 
"PREAUTH", arg )) {
                                ctx->greeting = GreetingPreauth;
                                parse_response_code( ctx, 0, cmd );
@@ -961,23 +1009,15 @@ imap_socket_read( void *aux )
                        } else if (!strcmp( "CAPABILITY", arg )) {
                                parse_capability( ctx, cmd );
                        } else if (!strcmp( "LIST", arg )) {
-                               if (parse_list_rsp( ctx, cmd ) < 0) {
-                                       error( "IMAP error: malformed LIST 
response\n" );
+                               if (parse_list( ctx, cmd, parse_list_rsp ) < 0)
                                        break;
-                               }
                        } else if ((arg1 = next_arg( &cmd ))) {
                                if (!strcmp( "EXISTS", arg1 ))
                                        ctx->gen.count = atoi( arg );
                                else if (!strcmp( "RECENT", arg1 ))
                                        ctx->gen.recent = atoi( arg );
                                else if(!strcmp ( "FETCH", arg1 )) {
-                                       parse_list_init( &ctx->parse_list_sts );
-                                 do_fetch:
-                                       if ((resp = parse_imap_list( ctx, &cmd, 
&ctx->parse_list_sts )) == LIST_BAD)
-                                               break; /* stream is likely to 
be useless now */
-                                       if (resp == LIST_PARTIAL)
-                                               return;
-                                       if (parse_fetch( ctx, 
ctx->parse_list_sts.head ) < 0)
+                                       if (parse_list( ctx, cmd, 
parse_fetch_rsp ) < 0)
                                                break; /* this may mean 
anything, so prefer not to spam the log */
                                }
                        } else {

------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to