# HG changeset patch # User Mike Becker # Date 1527703639 -7200 # Node ID ddda42712f3937b21e08300428cc8e025f1a30f3 # Parent 1490c24c6077fb4d1002ccf509c4937f1664916b fixes tag filter evaluation not respecting mode for subfilter combination diff -r 1490c24c6077 -r ddda42712f39 dav/sync.c --- 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);