fixes whitespace handling and error detection for basic tag filters

Wed, 30 May 2018 18:38:42 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 30 May 2018 18:38:42 +0200
changeset 395
b491d207ee16
parent 394
4826f5fdd865
child 396
1490c24c6077

fixes whitespace handling and error detection for basic tag filters

dav/sync.c file | annotate | diff | comparison | revisions
dav/sync.h file | annotate | diff | comparison | revisions
--- a/dav/sync.c	Wed May 30 18:04:43 2018 +0200
+++ b/dav/sync.c	Wed May 30 18:38:42 2018 +0200
@@ -257,9 +257,9 @@
 }
 
 // TODO: use scstr_t after update to UCX 2.0
-static sstr_t rtrimskip(sstr_t str, size_t skip) {
+static size_t rtrimskip(sstr_t str, size_t skip) {
     while (skip < str.length && isspace(str.ptr[skip])) skip++;
-    return sstrsubs(str, skip);
+    return skip;
 }
 
 static size_t parse_tagfilter_taglist(sstr_t fs, SyncTagFilter* tagfilter) {
@@ -274,6 +274,55 @@
     return csvlen;
 }
 
+static size_t parse_tagfilter_subfilters(sstr_t fs, SyncTagFilter* tagfilter);
+
+static size_t parse_tagfilter_filter(sstr_t fs, SyncTagFilter* tagfilter) {
+    
+    size_t consumed = rtrimskip(fs, 0);
+    fs = sstrsubs(fs, consumed);
+    
+    if (fs.length == 0) {
+        memset(tagfilter, 0, sizeof(SyncTagFilter));
+        return consumed;
+    } else {
+
+        // optional operator
+        int hasop = 0;
+        if (fs.ptr[0] == '&') {
+            tagfilter->mode = DAV_SYNC_TAGFILTER_AND;
+            hasop = 1;
+        } else if (fs.ptr[0] == '|') {
+            tagfilter->mode = DAV_SYNC_TAGFILTER_OR;
+            hasop = 1;
+        } else if (fs.ptr[0] == '0') {
+            tagfilter->mode = DAV_SYNC_TAGFILTER_NONE;
+            hasop = 1;
+        } else if (fs.ptr[0] == '1') {
+            tagfilter->mode = DAV_SYNC_TAGFILTER_ONE;
+            hasop = 1;
+        } else {
+            // default operator is AND
+            tagfilter->mode = DAV_SYNC_TAGFILTER_AND;
+        }
+        
+        if (hasop) {
+            size_t skip = rtrimskip(fs, 1);
+            consumed += skip;
+            fs = sstrsubs(fs, skip);
+        }
+
+        if (fs.length > 0 && fs.ptr[0] == '(') {
+            consumed += parse_tagfilter_subfilters(fs, tagfilter);
+        } else {
+            tagfilter->subfilter_count = 0;
+            tagfilter->subfilters = NULL;
+            consumed += parse_tagfilter_taglist(fs, tagfilter);
+        }
+        
+        return consumed;
+    }
+}
+
 /*
  * Parses:  ( "(" , filter , ")" )+
  */
@@ -293,50 +342,29 @@
     }
     
     // TODO: use scstr_t after update to UCX 2.0
-    sstr_t fs = sstrtrim(sstr((char*) filterstring));
+    sstr_t fs = sstr((char*) filterstring);
+    size_t consumed = parse_tagfilter_filter(fs, tagfilter);
     
-    if (fs.length == 0) {
-        memset(tagfilter, 0, sizeof(SyncTagFilter));
-        return tagfilter;
-    } else {
-        
-        // optional operator
-        if (fs.ptr[0] == '&') {
-            tagfilter->mode = DAV_SYNC_TAGFILTER_AND;
-            fs = rtrimskip(fs, 1);
-        } else if (fs.ptr[0] == '|') {
-            tagfilter->mode = DAV_SYNC_TAGFILTER_OR;
-            fs = rtrimskip(fs, 1);
-        } else if (fs.ptr[0] == '0') {
-            tagfilter->mode = DAV_SYNC_TAGFILTER_NONE;
-            fs = rtrimskip(fs, 1);
-        } else if (fs.ptr[0] == '1') {
-            tagfilter->mode = DAV_SYNC_TAGFILTER_ONE;
-            fs = rtrimskip(fs, 1);
-        } else {
-            // default operator is AND
-            tagfilter->mode = DAV_SYNC_TAGFILTER_AND;
-        }
-        
-        size_t consumed;
-        if (fs.length > 0 && fs.ptr[0] == '(') {
-            consumed = parse_tagfilter_subfilters(fs, tagfilter);
-        } else {
-            tagfilter->subfilter_count = 0;
-            tagfilter->subfilters = NULL;
-            consumed = parse_tagfilter_taglist(fs, tagfilter);
-        }
-        
-        if (consumed != fs.length) {
-            free(tagfilter->subfilters);
-            free(tagfilter);
-            return NULL;
-        }        
+    // consume trailing white spaces
+    consumed = rtrimskip(fs, consumed);
+    
+    // sanity check: have we consumed the whole string?
+    if (consumed != fs.length) {
+        free_tagfilter(tagfilter);
+        return NULL;
     }
         
     return tagfilter;
 }
 
+void free_tagfilter(SyncTagFilter* filter) {
+    for (size_t i = 0 ; i < filter->subfilter_count ; i++) {
+        free_tagfilter(filter->subfilters[i]);
+    }
+    free(filter->subfilters);
+    free(filter);
+}
+
 static int matches_tags_and(UcxList *dav_tags, UcxList *tags, int ignorecase) {
     UCX_FOREACH(e, tags) {
         if (!ucx_list_contains(dav_tags, e->data,
@@ -387,7 +415,7 @@
     if (tagfilter->subfilter_count > 0) {
         int ret = 1;
         for (size_t i = 0 ; i < tagfilter->subfilter_count ; i++) {
-            ret &= matches_tags(dav_tags, &(tagfilter->subfilters[i]));
+            ret &= matches_tags(dav_tags, tagfilter->subfilters[i]);
         }
         return ret;
     } else {
@@ -489,6 +517,8 @@
         fprintf(stderr, "Malformed tag filter\n");
         return -1;
     }
+    // TODO: tons of memory leaks...
+    //       call free_tagfilter() before each return
     
     SyncDirectory *dir = scfg_get_dir(a->argv[0]);
     if(!dir) {
--- a/dav/sync.h	Wed May 30 18:04:43 2018 +0200
+++ b/dav/sync.h	Wed May 30 18:38:42 2018 +0200
@@ -129,9 +129,10 @@
     int mode;
     UcxList* tags;
     size_t subfilter_count;
-    SyncTagFilter* subfilters;
+    SyncTagFilter** subfilters;
 };
 SyncTagFilter* parse_tagfilter_string(const char* filterstring);
+void free_tagfilter(SyncTagFilter* filter);
 
 int cmd_add_tag(CmdArgs *args);
 int cmd_remove_tag(CmdArgs *args);

mercurial