fixes tag filter evaluation not respecting mode for subfilter combination

Wed, 30 May 2018 20:07:19 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 30 May 2018 20:07:19 +0200
changeset 397
ddda42712f39
parent 396
1490c24c6077
child 398
26fdeed98cd7

fixes tag filter evaluation not respecting mode for subfilter combination

dav/sync.c file | annotate | diff | comparison | revisions
--- a/dav/sync.c	Wed May 30 19:56:28 2018 +0200
+++ b/dav/sync.c	Wed May 30 20:07:19 2018 +0200
@@ -468,24 +468,53 @@
     return matches_exactly_one;
 }
 
-static int matches_tags_none(UcxList *dav_tags, UcxList *tags, int ignorecase) {
-    UCX_FOREACH(e, tags) {
-        if (ucx_list_contains(dav_tags, e->data,
-                (cmp_func) compare_tagname, &ignorecase)) {
-            return 0;
+static int matches_tagfilter(UcxList *dav_tags, SyncTagFilter *tagfilter);
+
+static int matches_subfilters_and(UcxList *dav_tags, SyncTagFilter *filter) {
+    int ret = 1;
+    for (size_t i = 0 ; i < filter->subfilter_count ; i++) {
+        ret &= matches_tagfilter(dav_tags, filter->subfilters[i]);
+    }
+    return ret;
+}
+
+static int matches_subfilters_or(UcxList *dav_tags, SyncTagFilter *filter) {
+    int ret = 0;
+    for (size_t i = 0 ; i < filter->subfilter_count ; i++) {
+        ret |= matches_tagfilter(dav_tags, filter->subfilters[i]);
+    }
+    return ret;
+}
+
+static int matches_subfilters_one(UcxList *dav_tags, SyncTagFilter *filter) {
+    int one = 0;
+    for (size_t i = 0 ; i < filter->subfilter_count ; i++) {
+        if (matches_tagfilter(dav_tags, filter->subfilters[i])) {
+            if (one) {
+                return 0;
+            } else {
+                one = 1;
+            }
         }
     }
-    return 1;
+    return one;
 }
 
-static int matches_tags(UcxList *dav_tags, SyncTagFilter *tagfilter) {
+static int matches_tagfilter(UcxList *dav_tags, SyncTagFilter *tagfilter) {
 
     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]);
+        switch (tagfilter->mode) {
+        case DAV_SYNC_TAGFILTER_OR:
+            return matches_subfilters_or(dav_tags, tagfilter);
+        case DAV_SYNC_TAGFILTER_AND:
+            return matches_subfilters_and(dav_tags, tagfilter);
+        case DAV_SYNC_TAGFILTER_NONE:
+            return !matches_subfilters_or(dav_tags, tagfilter);
+        case DAV_SYNC_TAGFILTER_ONE:
+            return matches_subfilters_one(dav_tags, tagfilter);
+        default:
+            abort();
         }
-        return ret;
     } else {
         int ignorecase = 0; // TODO: maybe add support later
         switch (tagfilter->mode) {
@@ -494,7 +523,7 @@
         case DAV_SYNC_TAGFILTER_AND:
             return matches_tags_and(dav_tags, tagfilter->tags, ignorecase);
         case DAV_SYNC_TAGFILTER_NONE:
-            return matches_tags_none(dav_tags, tagfilter->tags, ignorecase);
+            return !matches_tags_or(dav_tags, tagfilter->tags, ignorecase);
         case DAV_SYNC_TAGFILTER_ONE:
             return matches_tags_one(dav_tags, tagfilter->tags, ignorecase);
         default:
@@ -511,7 +540,7 @@
     DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags");
     UcxList *res_tags = parse_dav_xml_taglist(tagsprop);
     
-    int ret = matches_tags(res_tags, tagfilter);
+    int ret = matches_tagfilter(res_tags, tagfilter);
     
     ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag);
     ucx_list_free(res_tags);

mercurial