commit 8fdd74013d2ab6f5b07646abb8a8a48b9d3c38d0
Author: Oswald Buddenhagen <o...@kde.org>
Date:   Sat Sep 15 11:24:57 2012 +0200

    make config parser a bit more careful about quotes
    
    the parsing is more shell-like now:
    - quoted and unquoted parts can be mixed in one argument
    - the hashmark can be meaningfully quoted

 src/config.c   |   70 +++++++++++++++++++++++++++++++++++++-----------
 src/drv_imap.c |   31 +++++++++++++++++++++
 src/isync.h    |    2 -
 src/util.c     |   32 ----------------------
 4 files changed, 85 insertions(+), 50 deletions(-)

diff --git a/src/config.c b/src/config.c
index 9421bae..1404c32 100644
--- a/src/config.c
+++ b/src/config.c
@@ -22,10 +22,12 @@
 
 #include "isync.h"
 
+#include <assert.h>
 #include <unistd.h>
 #include <limits.h>
 #include <pwd.h>
 #include <sys/types.h>
+#include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -38,6 +40,46 @@ group_conf_t *groups;
 int global_ops[2];
 char *global_sync_state;
 
+#define ARG_OPTIONAL 0
+#define ARG_REQUIRED 1
+
+static char *
+get_arg( conffile_t *cfile, int required, int *comment )
+{
+       char *ret, *p, *t;
+       int quoted;
+       char c;
+
+       p = cfile->rest;
+       assert( p );
+       while ((c = *p) && isspace( (unsigned char) c ))
+               p++;
+       if (!c || c == '#') {
+               if (comment)
+                       *comment = (c == '#');
+               if (required)
+                       error( "%s:%d: parameter missing\n", cfile->file, 
cfile->line );
+               ret = 0;
+       } else {
+               for (quoted = 0, ret = t = p; c; c = *p) {
+                       p++;
+                       if (c == '"')
+                               quoted ^= 1;
+                       else if (!quoted && isspace( (unsigned char) c ))
+                               break;
+                       else
+                               *t++ = c;
+               }
+               *t = 0;
+               if (quoted) {
+                       error( "%s:%d: missing closing quote\n", cfile->file, 
cfile->line );
+                       ret = 0;
+               }
+       }
+       cfile->rest = p;
+       return ret;
+}
+
 int
 parse_bool( conffile_t *cfile )
 {
@@ -132,7 +174,7 @@ getopt_helper( conffile_t *cfile, int *cops, int ops[], 
char **sync_state )
                        else if (strcasecmp( "None", arg ) && strcasecmp( 
"Noop", arg ))
                                error( "%s:%d: invalid Sync arg '%s'\n",
                                       cfile->file, cfile->line, arg );
-               while ((arg = next_arg( &cfile->rest )));
+               while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
                ops[M] |= XOP_HAVE_TYPE;
        } else if (!strcasecmp( "Expunge", cfile->cmd )) {
                arg = cfile->val;
@@ -146,7 +188,7 @@ getopt_helper( conffile_t *cfile, int *cops, int ops[], 
char **sync_state )
                        else if (strcasecmp( "None", arg ))
                                error( "%s:%d: invalid Expunge arg '%s'\n",
                                       cfile->file, cfile->line, arg );
-               while ((arg = next_arg( &cfile->rest )));
+               while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
                ops[M] |= XOP_HAVE_EXPUNGE;
        } else if (!strcasecmp( "Create", cfile->cmd )) {
                arg = cfile->val;
@@ -160,7 +202,7 @@ getopt_helper( conffile_t *cfile, int *cops, int ops[], 
char **sync_state )
                        else if (strcasecmp( "None", arg ))
                                error( "%s:%d: invalid Create arg '%s'\n",
                                       cfile->file, cfile->line, arg );
-               while ((arg = next_arg( &cfile->rest )));
+               while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 )));
                ops[M] |= XOP_HAVE_CREATE;
        } else if (!strcasecmp( "SyncState", cfile->cmd ))
                *sync_state = expand_strdup( cfile->val );
@@ -172,20 +214,18 @@ getopt_helper( conffile_t *cfile, int *cops, int ops[], 
char **sync_state )
 int
 getcline( conffile_t *cfile )
 {
-       char *p;
+       int comment;
 
        while (fgets( cfile->buf, cfile->bufl, cfile->fp )) {
                cfile->line++;
-               p = cfile->buf;
-               if (!(cfile->cmd = next_arg( &p )))
+               cfile->rest = cfile->buf;
+               if (!(cfile->cmd = get_arg( cfile, ARG_OPTIONAL, &comment ))) {
+                       if (comment)
+                               continue;
                        return 1;
-               if (*cfile->cmd == '#')
-                       continue;
-               if (!(cfile->val = next_arg( &p ))) {
-                       error( "%s:%d: parameter missing\n", cfile->file, 
cfile->line );
-                       continue;
                }
-               cfile->rest = p;
+               if (!(cfile->val = get_arg( cfile, ARG_REQUIRED, 0 )))
+                       continue;
                return 1;
        }
        return 0;
@@ -311,7 +351,7 @@ load_config( const char *where, int pseudo )
                                        arg = cfile.val;
                                        do
                                                add_string_list( 
&channel->patterns, arg );
-                                       while ((arg = next_arg( &cfile.rest )));
+                                       while ((arg = get_arg( &cfile, 
ARG_OPTIONAL, 0 )));
                                }
                                else if (!strcasecmp( "Master", cfile.cmd )) {
                                        ms = M;
@@ -367,8 +407,7 @@ load_config( const char *where, int pseudo )
                        *groupapp = 0;
                        chanlistapp = &group->channels;
                        *chanlistapp = 0;
-                       p = cfile.rest;
-                       while ((arg = next_arg( &p ))) {
+                       while ((arg = get_arg( &cfile, ARG_OPTIONAL, 0 ))) {
                          addone:
                                len = strlen( arg );
                                chanlist = nfmalloc( sizeof(*chanlist) + len );
@@ -383,7 +422,6 @@ load_config( const char *where, int pseudo )
                                if (!strcasecmp( "Channel", cfile.cmd ) ||
                                    !strcasecmp( "Channels", cfile.cmd ))
                                {
-                                       p = cfile.rest;
                                        arg = cfile.val;
                                        goto addone;
                                }
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 4dbf0b4..51d7d10 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -450,6 +450,37 @@ imap_refcounted_done_box( imap_store_t *ctx ATTR_UNUSED, 
struct imap_cmd *cmd, i
        imap_refcounted_done( sts );
 }
 
+static char *
+next_arg( char **s )
+{
+       char *ret;
+
+       if (!s || !*s)
+               return 0;
+       while (isspace( (unsigned char) **s ))
+               (*s)++;
+       if (!**s) {
+               *s = 0;
+               return 0;
+       }
+       if (**s == '"') {
+               ++*s;
+               ret = *s;
+               *s = strchr( *s, '"' );
+       } else {
+               ret = *s;
+               while (**s && !isspace( (unsigned char) **s ))
+                       (*s)++;
+       }
+       if (*s) {
+               if (**s)
+                       *(*s)++ = 0;
+               if (!**s)
+                       *s = 0;
+       }
+       return ret;
+}
+
 static int
 is_atom( list_t *list )
 {
diff --git a/src/isync.h b/src/isync.h
index c637dac..4cb2f3e 100644
--- a/src/isync.h
+++ b/src/isync.h
@@ -412,8 +412,6 @@ void ATTR_PRINTFLIKE(1, 2) error( const char *, ... );
 void ATTR_PRINTFLIKE(1, 2) sys_error( const char *, ... );
 void flushn( void );
 
-char *next_arg( char ** );
-
 void add_string_list( string_list_t **list, const char *str );
 void free_string_list( string_list_t *list );
 
diff --git a/src/util.c b/src/util.c
index bc614e6..507f91a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -28,7 +28,6 @@
 #include <fcntl.h>
 #include <string.h>
 #include <pwd.h>
-#include <ctype.h>
 
 int DFlags;
 static int need_nl;
@@ -145,37 +144,6 @@ sys_error( const char *msg, ... )
        perror( buf );
 }
 
-char *
-next_arg( char **s )
-{
-       char *ret;
-
-       if (!s || !*s)
-               return 0;
-       while (isspace( (unsigned char) **s ))
-               (*s)++;
-       if (!**s) {
-               *s = 0;
-               return 0;
-       }
-       if (**s == '"') {
-               ++*s;
-               ret = *s;
-               *s = strchr( *s, '"' );
-       } else {
-               ret = *s;
-               while (**s && !isspace( (unsigned char) **s ))
-                       (*s)++;
-       }
-       if (*s) {
-               if (**s)
-                       *(*s)++ = 0;
-               if (!**s)
-                       *s = 0;
-       }
-       return ret;
-}
-
 void
 add_string_list( string_list_t **list, const char *str )
 {

------------------------------------------------------------------------------
How fast is your code?
3 out of 4 devs don\\\'t know how their code performs in production.
Find out how slow your code is with AppDynamics Lite.
http://ad.doubleclick.net/clk;262219672;13503038;z?
http://info.appdynamics.com/FreeJavaPerformanceDownload.html
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to