237 resource->path); |
243 resource->path); |
238 } |
244 } |
239 return resource->href; |
245 return resource->href; |
240 } |
246 } |
241 |
247 |
|
248 void resource_add_prop(DavResource *res, const char *ns, const char *name, DavXmlNode *val) { |
|
249 DavSession *sn = res->session; |
|
250 |
|
251 DavNamespace *namespace = dav_session_malloc(sn, sizeof(DavNamespace)); |
|
252 namespace->prefix = NULL; |
|
253 namespace->name = dav_session_strdup(sn, ns); |
|
254 |
|
255 DavProperty *prop = dav_session_malloc(sn, sizeof(DavProperty)); |
|
256 prop->name = dav_session_strdup(sn, name); |
|
257 prop->ns = namespace; |
|
258 prop->value = val; |
|
259 |
|
260 sstr_t key = dav_property_key(ns, name); |
|
261 ucx_map_sstr_put(((DavResourceData*)res->data)->properties, key, prop); |
|
262 free(key.ptr); |
|
263 } |
|
264 |
242 void resource_add_property(DavResource *res, const char *ns, const char *name, xmlNode *val) { |
265 void resource_add_property(DavResource *res, const char *ns, const char *name, xmlNode *val) { |
243 if(!val) { |
266 if(!val) { |
244 return; |
267 return; |
245 } |
268 } |
246 |
269 |
247 sstr_t key = dav_property_key(ns, name); |
270 resource_add_prop(res, ns, name, dav_convert_xml(res->session, val)); |
248 DavXmlNode *v = dav_convert_xml(res->session, val); |
|
249 ucx_map_sstr_put(((DavResourceData*)res->data)->properties, key, v); |
|
250 free(key.ptr); |
|
251 } |
271 } |
252 |
272 |
253 void resource_add_string_property(DavResource *res, char *ns, char *name, char *val) { |
273 void resource_add_string_property(DavResource *res, char *ns, char *name, char *val) { |
254 if(!val) { |
274 if(!val) { |
255 return; |
275 return; |
256 } |
276 } |
257 |
277 |
258 sstr_t key = dav_property_key(ns, name); |
278 resource_add_prop(res, ns, name, dav_text_node(res->session, val)); |
259 DavXmlNode *v = dav_text_node(res->session, val); |
279 } |
260 ucx_map_sstr_put(((DavResourceData*)res->data)->properties, key, v); |
280 |
261 free(key.ptr); |
281 void resource_set_crypto_properties(DavResource *res, UcxMap *cprops) { |
|
282 DavResourceData *data = res->data; |
|
283 resource_free_properties(res->session, data->crypto_properties); |
|
284 data->crypto_properties = cprops; |
262 } |
285 } |
263 |
286 |
264 DavXmlNode* resource_get_property(DavResource *res, const char *ns, const char *name) { |
287 DavXmlNode* resource_get_property(DavResource *res, const char *ns, const char *name) { |
265 sstr_t keystr = dav_property_key(ns, name); |
288 sstr_t keystr = dav_property_key(ns, name); |
266 UcxKey key = ucx_key(keystr.ptr, keystr.length); |
289 UcxKey key = ucx_key(keystr.ptr, keystr.length); |
267 DavXmlNode *property = resource_get_property_k(res, key); |
290 DavXmlNode *ret = resource_get_property_k(res, key); |
268 free(keystr.ptr); |
291 free(keystr.ptr); |
269 return property; |
292 |
|
293 return ret; |
|
294 } |
|
295 |
|
296 DavXmlNode* resource_get_encrypted_property(DavResource *res, const char *ns, const char *name) { |
|
297 sstr_t keystr = dav_property_key(ns, name); |
|
298 UcxKey key = ucx_key(keystr.ptr, keystr.length); |
|
299 DavXmlNode *ret = resource_get_encrypted_property_k(res, key); |
|
300 free(keystr.ptr); |
|
301 |
|
302 return ret; |
270 } |
303 } |
271 |
304 |
272 DavXmlNode* resource_get_property_k(DavResource *res, UcxKey key) { |
305 DavXmlNode* resource_get_property_k(DavResource *res, UcxKey key) { |
273 DavResourceData *data = (DavResourceData*)res->data; |
306 DavResourceData *data = (DavResourceData*)res->data; |
274 return ucx_map_get(data->properties, key); |
307 DavProperty *property = ucx_map_get(data->properties, key); |
|
308 |
|
309 return property ? property->value : NULL; |
|
310 } |
|
311 |
|
312 DavXmlNode* resource_get_encrypted_property_k(DavResource *res, UcxKey key) { |
|
313 DavResourceData *data = (DavResourceData*)res->data; |
|
314 DavProperty *property = ucx_map_get(data->crypto_properties, key); |
|
315 |
|
316 return property ? property->value : NULL; |
275 } |
317 } |
276 |
318 |
277 sstr_t dav_property_key(const char *ns, const char *name) { |
319 sstr_t dav_property_key(const char *ns, const char *name) { |
278 return dav_property_key_a(ucx_default_allocator(), ns, name); |
320 return dav_property_key_a(ucx_default_allocator(), ns, name); |
279 } |
321 } |
443 return NULL; |
485 return NULL; |
444 } |
486 } |
445 return dav_get_property_ns(res, pns, pname); |
487 return dav_get_property_ns(res, pns, pname); |
446 } |
488 } |
447 |
489 |
448 DavXmlNode* dav_get_property_ns(DavResource *res, const char *ns, const char *name) { |
490 static DavXmlNode* get_property_ns(DavResource *res, DavBool encrypted, const char *ns, const char *name) { |
449 if(!ns || !name) { |
491 if(!ns || !name) { |
450 return NULL; |
492 return NULL; |
451 } |
493 } |
452 DavXmlNode *property = resource_get_property(res, ns, name); |
494 |
453 DavResourceData *data = res->data; |
495 DavResourceData *data = res->data; |
|
496 |
|
497 DavXmlNode *property = NULL; |
|
498 UcxList *remove_list = NULL; |
|
499 UcxList *set_list = NULL; |
|
500 |
|
501 if(encrypted) { |
|
502 // check if crypto_properties because it will only be created |
|
503 // if the resource has encrypted properties |
|
504 if(!data->crypto_properties) { |
|
505 return NULL; |
|
506 } |
|
507 property = resource_get_encrypted_property(res, ns, name); |
|
508 remove_list = data->crypto_remove; |
|
509 set_list = data->crypto_set; |
|
510 } else { |
|
511 property = resource_get_property(res, ns, name); |
|
512 remove_list = data->remove; |
|
513 set_list = data->set; |
|
514 } |
|
515 |
454 // resource_get_property only returns persistent properties |
516 // resource_get_property only returns persistent properties |
455 // check the remove and set list |
517 // check the remove and set list |
456 if(property) { |
518 if(property) { |
457 // if the property is in the remove list, we return NULL |
519 // if the property is in the remove list, we return NULL |
458 UCX_FOREACH(elm, data->remove) { |
520 UCX_FOREACH(elm, remove_list) { |
459 DavProperty *p = elm->data; |
521 DavProperty *p = elm->data; |
460 if(!strcmp(p->name, name) && !strcmp(p->ns->name, ns)) { |
522 if(!strcmp(p->name, name) && !strcmp(p->ns->name, ns)) { |
461 return NULL; |
523 return NULL; |
462 } |
524 } |
463 } |
525 } |
464 } |
526 } |
465 // the set list contains property updates |
527 // the set list contains property updates |
466 // we return an updated property if possible |
528 // we return an updated property if possible |
467 UCX_FOREACH(elm, data->set) { |
529 UCX_FOREACH(elm, set_list) { |
468 DavProperty *p = elm->data; |
530 DavProperty *p = elm->data; |
469 if(!strcmp(p->name, name) && !strcmp(p->ns->name, ns)) { |
531 if(!strcmp(p->name, name) && !strcmp(p->ns->name, ns)) { |
470 return p->value; // TODO: fix |
532 return p->value; // TODO: fix |
471 } |
533 } |
472 } |
534 } |
473 // no property update |
535 // no property update |
|
536 |
474 return property; |
537 return property; |
|
538 } |
|
539 |
|
540 DavXmlNode* dav_get_property_ns(DavResource *res, const char *ns, const char *name) { |
|
541 DavXmlNode *property_value = get_property_ns(res, FALSE, ns, name); |
|
542 |
|
543 if(!property_value && DAV_DECRYPT_PROPERTIES(res->session)) { |
|
544 property_value = get_property_ns(res, TRUE, ns, name); |
|
545 } |
|
546 |
|
547 return property_value; |
|
548 } |
|
549 |
|
550 DavXmlNode* dav_get_encrypted_property_ns(DavResource *res, const char *ns, const char *name) { |
|
551 return get_property_ns(res, TRUE, ns, name); |
475 } |
552 } |
476 |
553 |
477 static DavProperty* createprop(DavSession *sn, const char *ns, const char *name) { |
554 static DavProperty* createprop(DavSession *sn, const char *ns, const char *name) { |
478 DavProperty *property = dav_session_malloc(sn, sizeof(DavProperty)); |
555 DavProperty *property = dav_session_malloc(sn, sizeof(DavProperty)); |
479 property->name = dav_session_strdup(sn, name); |
556 property->name = dav_session_strdup(sn, name); |
494 dav_get_property_namespace_str(res->session->context, name, &pns, &pname); |
571 dav_get_property_namespace_str(res->session->context, name, &pns, &pname); |
495 dav_set_string_property_ns(res, pns, pname, value); |
572 dav_set_string_property_ns(res, pns, pname, value); |
496 } |
573 } |
497 |
574 |
498 void dav_set_string_property_ns(DavResource *res, char *ns, char *name, char *value) { |
575 void dav_set_string_property_ns(DavResource *res, char *ns, char *name, char *value) { |
|
576 DavSession *sn = res->session; |
499 UcxAllocator *a = res->session->mp->allocator; |
577 UcxAllocator *a = res->session->mp->allocator; |
500 DavResourceData *data = res->data; |
578 DavResourceData *data = res->data; |
501 |
579 |
502 DavProperty *property = createprop(res->session, ns, name); |
580 DavProperty *property = createprop(res->session, ns, name); |
503 property->value = dav_text_node(res->session, value); |
581 property->value = dav_text_node(res->session, value); |
504 |
582 |
505 data->set = ucx_list_append_a(a, data->set, property); |
583 if(DAV_ENCRYPT_PROPERTIES(sn) && dav_namespace_is_encrypted(sn->context, ns)) { |
|
584 data->crypto_set = ucx_list_append_a(a, data->crypto_set, property); |
|
585 } else { |
|
586 data->set = ucx_list_append_a(a, data->set, property); |
|
587 } |
506 } |
588 } |
507 |
589 |
508 void dav_set_property(DavResource *res, char *name, DavXmlNode *value) { |
590 void dav_set_property(DavResource *res, char *name, DavXmlNode *value) { |
509 char *pns; |
591 char *pns; |
510 char *pname; |
592 char *pname; |
511 dav_get_property_namespace_str(res->session->context, name, &pns, &pname); |
593 dav_get_property_namespace_str(res->session->context, name, &pns, &pname); |
512 dav_set_property_ns(res, pns, pname, value); |
594 dav_set_property_ns(res, pns, pname, value); |
513 } |
595 } |
514 |
596 |
515 void dav_set_property_ns(DavResource *res, char *ns, char *name, DavXmlNode *value) { |
597 void dav_set_property_ns(DavResource *res, char *ns, char *name, DavXmlNode *value) { |
516 UcxAllocator *a = res->session->mp->allocator; |
598 DavSession *sn = res->session; |
|
599 UcxAllocator *a = sn->mp->allocator; |
517 DavResourceData *data = res->data; |
600 DavResourceData *data = res->data; |
518 |
601 |
519 DavProperty *property = createprop(res->session, ns, name); |
602 DavProperty *property = createprop(sn, ns, name); |
520 property->value = value; // TODO: copy node? |
603 property->value = value; // TODO: copy node? |
521 |
604 |
522 data->set = ucx_list_append_a(a, data->set, property); |
605 if(DAV_ENCRYPT_PROPERTIES(sn) && dav_namespace_is_encrypted(sn->context, ns)) { |
|
606 data->crypto_set = ucx_list_append_a(a, data->crypto_set, property); |
|
607 } else { |
|
608 data->set = ucx_list_append_a(a, data->set, property); |
|
609 } |
523 } |
610 } |
524 |
611 |
525 void dav_remove_property(DavResource *res, char *name) { |
612 void dav_remove_property(DavResource *res, char *name) { |
526 char *pns; |
613 char *pns; |
527 char *pname; |
614 char *pname; |
528 dav_get_property_namespace_str(res->session->context, name, &pns, &pname); |
615 dav_get_property_namespace_str(res->session->context, name, &pns, &pname); |
529 dav_remove_property_ns(res, pns, pname); |
616 dav_remove_property_ns(res, pns, pname); |
530 } |
617 } |
531 |
618 |
532 void dav_remove_property_ns(DavResource *res, char *ns, char *name) { |
619 void dav_remove_property_ns(DavResource *res, char *ns, char *name) { |
|
620 DavSession *sn = res->session; |
533 DavResourceData *data = res->data; |
621 DavResourceData *data = res->data; |
534 UcxAllocator *a = res->session->mp->allocator; |
622 UcxAllocator *a = res->session->mp->allocator; |
535 |
623 |
536 DavProperty *property = createprop(res->session, ns, name); |
624 DavProperty *property = createprop(res->session, ns, name); |
537 |
625 |
538 data->remove = ucx_list_append_a(a, data->remove, property); |
626 if(DAV_ENCRYPT_PROPERTIES(sn) && dav_namespace_is_encrypted(sn->context, ns)) { |
|
627 data->crypto_remove = ucx_list_append_a(a, data->crypto_remove, property); |
|
628 } else { |
|
629 data->remove = ucx_list_append_a(a, data->remove, property); |
|
630 } |
539 } |
631 } |
540 |
632 |
541 void dav_set_encrypted_property_ns(DavResource *res, char *ns, char *name, DavXmlNode *value) { |
633 void dav_set_encrypted_property_ns(DavResource *res, char *ns, char *name, DavXmlNode *value) { |
542 UcxAllocator *a = res->session->mp->allocator; |
634 UcxAllocator *a = res->session->mp->allocator; |
543 DavResourceData *data = res->data; |
635 DavResourceData *data = res->data; |
831 dav_session_set_error(sn, ret, status); |
919 dav_session_set_error(sn, ret, status); |
832 return 1; |
920 return 1; |
833 } |
921 } |
834 } |
922 } |
835 |
923 |
|
924 // generate crypto-prop content |
|
925 if(DAV_ENCRYPT_PROPERTIES(sn) && sn->key && (data->crypto_set || data->crypto_remove)) { |
|
926 DavResource *crypto_res = dav_resource_new_href(sn, res->href); |
|
927 int ret = 1; |
|
928 |
|
929 if(crypto_res) { |
|
930 UcxBuffer *rqbuf = create_cryptoprop_propfind_request(); |
|
931 ret = dav_propfind(res->session, res, rqbuf); |
|
932 ucx_buffer_free(rqbuf); |
|
933 } |
|
934 |
|
935 if(!ret) { |
|
936 DavXmlNode *crypto_prop_node = dav_get_property_ns(crypto_res, DAV_NS, "crypto-prop"); |
|
937 UcxMap *crypto_props = parse_crypto_prop(sn, sn->key, crypto_prop_node); |
|
938 if(!crypto_props) { |
|
939 // resource hasn't encrypted properties yet |
|
940 crypto_props = ucx_map_new(32); // create new map |
|
941 } |
|
942 |
|
943 // remove all properties |
|
944 UCX_FOREACH(elm, data->crypto_remove) { |
|
945 if(crypto_props->count == 0) { |
|
946 break; // map already empty, can't remove any more |
|
947 } |
|
948 |
|
949 DavProperty *property = elm->data; |
|
950 sstr_t key = dav_property_key(property->ns->name, property->name); |
|
951 DavProperty *existing_prop = ucx_map_sstr_remove(crypto_props, key); |
|
952 if(existing_prop) { |
|
953 // TODO: free existing_prop |
|
954 } |
|
955 free(key.ptr); |
|
956 } |
|
957 |
|
958 // set properties |
|
959 UCX_FOREACH(elm, data->crypto_set) { |
|
960 DavProperty *property = elm->data; |
|
961 sstr_t key = dav_property_key(property->ns->name, property->name); |
|
962 DavProperty *existing_prop = ucx_map_sstr_remove(crypto_props, key); |
|
963 ucx_map_sstr_put(crypto_props, key, property); |
|
964 if(existing_prop) { |
|
965 // TODO: free existing_prop |
|
966 } |
|
967 free(key.ptr); |
|
968 } |
|
969 |
|
970 DavXmlNode *crypto_prop_value = create_crypto_prop(sn, crypto_props); |
|
971 if(crypto_prop_value) { |
|
972 DavProperty *new_crypto_prop = createprop(sn, DAV_NS, "crypto-prop"); |
|
973 new_crypto_prop->value = crypto_prop_value; |
|
974 data->set = ucx_list_prepend_a(sn->mp->allocator, data->set, new_crypto_prop); |
|
975 } |
|
976 |
|
977 dav_resource_free(crypto_res); |
|
978 } |
|
979 |
|
980 if(ret) { |
|
981 return 1; |
|
982 } |
|
983 } |
|
984 |
836 // store properties |
985 // store properties |
837 int r = 0; |
986 int r = 0; |
838 sn->error = DAV_OK; |
987 sn->error = DAV_OK; |
839 if(data->set || data->remove) { |
988 if(data->set || data->remove) { |
840 UcxBuffer *request = create_proppatch_request(data); |
989 UcxBuffer *request = create_proppatch_request(data); |