253 } |
253 } |
254 } |
254 } |
255 return 1; |
255 return 1; |
256 } |
256 } |
257 |
257 |
258 static int matches_tags(UcxList *resource_tags, SyncTagFilter *tagfilter) { |
258 static int matches_tags_and(UcxList *dav_tags, UcxList *tags, int ignorecase) { |
259 if(!resource_tags) { |
259 UCX_FOREACH(e, tags) { |
260 return 0; |
260 if (!ucx_list_contains(dav_tags, e->data, |
261 } |
261 (cmp_func) compare_tagname, &ignorecase)) { |
262 |
262 return 0; |
263 UcxMap *res_tagmap = ucx_map_new(32); |
263 } |
264 UCX_FOREACH(elm, resource_tags) { |
264 } |
265 DavTag *t = elm->data; |
265 return 1; |
266 // the value actually doesn't matter |
266 } |
267 ucx_map_cstr_put(res_tagmap, t->name, t); |
267 |
268 } |
268 static int matches_tags_or(UcxList *dav_tags, UcxList *tags, int ignorecase) { |
269 |
269 UCX_FOREACH(e, tags) { |
270 int ret = 1; |
270 if (ucx_list_contains(dav_tags, e->data, |
271 |
271 (cmp_func) compare_tagname, &ignorecase)) { |
272 // TODO: replace FOREACH with new tag expression evaluation |
272 return 1; |
273 UCX_FOREACH(elm, tagfilter->tags) { |
273 } |
274 DavTag *matches_tag = elm->data; |
274 } |
275 if(!ucx_map_cstr_get(res_tagmap, matches_tag->name)) { |
275 return 0; |
276 ret = 0; |
276 } |
277 break; |
277 |
278 } |
278 static int matches_tags_one(UcxList *dav_tags, UcxList *tags, int ignorecase) { |
279 } |
279 int matches_exactly_one = 0; |
280 |
280 UCX_FOREACH(e, tags) { |
281 ucx_map_free(res_tagmap); |
281 if (ucx_list_contains(dav_tags, e->data, |
282 return ret; |
282 (cmp_func) compare_tagname, &ignorecase)) { |
|
283 if (matches_exactly_one) { |
|
284 return 0; |
|
285 } else { |
|
286 matches_exactly_one = 1; |
|
287 } |
|
288 } |
|
289 } |
|
290 return matches_exactly_one; |
|
291 } |
|
292 |
|
293 static int matches_tags_none(UcxList *dav_tags, UcxList *tags, int ignorecase) { |
|
294 UCX_FOREACH(e, tags) { |
|
295 if (ucx_list_contains(dav_tags, e->data, |
|
296 (cmp_func) compare_tagname, &ignorecase)) { |
|
297 return 0; |
|
298 } |
|
299 } |
|
300 return 1; |
|
301 } |
|
302 |
|
303 static int matches_tags(UcxList *dav_tags, SyncTagFilter *tagfilter) { |
|
304 |
|
305 if (tagfilter->subfilter_count > 0) { |
|
306 int ret = 1; |
|
307 for (size_t i = 0 ; i < tagfilter->subfilter_count ; i++) { |
|
308 ret &= matches_tags(dav_tags, &(tagfilter->subfilters[i])); |
|
309 } |
|
310 return ret; |
|
311 } else { |
|
312 int ignorecase = 0; // TODO: maybe add support later |
|
313 switch (tagfilter->mode) { |
|
314 case DAV_SYNC_TAGFILTER_OR: |
|
315 return matches_tags_or(dav_tags, tagfilter->tags, ignorecase); |
|
316 case DAV_SYNC_TAGFILTER_AND: |
|
317 return matches_tags_and(dav_tags, tagfilter->tags, ignorecase); |
|
318 case DAV_SYNC_TAGFILTER_NONE: |
|
319 return matches_tags_none(dav_tags, tagfilter->tags, ignorecase); |
|
320 case DAV_SYNC_TAGFILTER_ONE: |
|
321 return matches_tags_one(dav_tags, tagfilter->tags, ignorecase); |
|
322 default: |
|
323 abort(); |
|
324 } |
|
325 } |
283 } |
326 } |
284 |
327 |
285 static int res_matches_tags(DavResource *res, SyncTagFilter *tagfilter) { |
328 static int res_matches_tags(DavResource *res, SyncTagFilter *tagfilter) { |
286 if(!tagfilter) { |
329 if(!tagfilter) { |
287 return 1; |
330 return 1; |
289 |
332 |
290 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); |
333 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); |
291 UcxList *res_tags = parse_dav_xml_taglist(tagsprop); |
334 UcxList *res_tags = parse_dav_xml_taglist(tagsprop); |
292 |
335 |
293 int ret = matches_tags(res_tags, tagfilter); |
336 int ret = matches_tags(res_tags, tagfilter); |
294 // TODO: free list content |
337 |
|
338 ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag); |
295 ucx_list_free(res_tags); |
339 ucx_list_free(res_tags); |
|
340 |
296 return ret; |
341 return ret; |
297 } |
342 } |
298 |
343 |
299 static int localres_matches_tags(LocalResource *res, SyncTagFilter *tagfilter) { |
344 static int localres_matches_tags(LocalResource *res, SyncTagFilter *tagfilter) { |
300 if(!tagfilter) { |
345 if(!tagfilter) { |
472 if (res_matches_filter(dir, res->path)) { |
517 if (res_matches_filter(dir, res->path)) { |
473 res = res->next; |
518 res = res->next; |
474 continue; |
519 continue; |
475 } |
520 } |
476 |
521 |
477 |
522 // TODO: remove this fake and let the cmd parser store the filter |
478 SyncTagFilter tagfilter; |
523 SyncTagFilter tagfilter; |
|
524 tagfilter.mode = DAV_SYNC_TAGFILTER_AND; |
|
525 tagfilter.subfilter_count = 0; |
479 tagfilter.tags = NULL; |
526 tagfilter.tags = NULL; |
480 char *tags_str = cmd_getoption(a, "tags"); |
527 char *tags_str = cmd_getoption(a, "tags"); |
481 if(tags_str) { |
528 if(tags_str) { |
482 tagfilter.tags = parse_csv_taglist(tags_str, strlen(tags_str)); |
529 tagfilter.tags = parse_csv_taglist(tags_str, strlen(tags_str)); |
483 } |
530 } |