libidav/resource.c

changeset 609
dc3d70848c7c
parent 605
bbc66c72661a
child 713
a1c36a6410f6
equal deleted inserted replaced
608:3e4c0285a868 609:dc3d70848c7c
118 118
119 return res; 119 return res;
120 } 120 }
121 121
122 void resource_free_properties(DavSession *sn, UcxMap *properties) { 122 void resource_free_properties(DavSession *sn, UcxMap *properties) {
123 if(!properties) return;
124
123 UcxMapIterator i = ucx_map_iterator(properties); 125 UcxMapIterator i = ucx_map_iterator(properties);
124 DavXmlNode *node; 126 DavProperty *property;
125 UCX_MAP_FOREACH(key, node, i) { 127 UCX_MAP_FOREACH(key, property, i) {
126 // TODO: free everything 128 // TODO: free everything
127 dav_session_free(sn, node); 129 dav_session_free(sn, property);
128 } 130 }
129 ucx_map_free(properties); 131 ucx_map_free(properties);
130 } 132 }
131 133
132 void dav_resource_free(DavResource *res) { 134 void dav_resource_free(DavResource *res) {
138 dav_session_free(sn, res->href); 140 dav_session_free(sn, res->href);
139 } 141 }
140 142
141 DavResourceData *data = res->data; 143 DavResourceData *data = res->data;
142 resource_free_properties(sn, data->properties); 144 resource_free_properties(sn, data->properties);
145 resource_free_properties(sn, data->crypto_properties);
143 146
144 UCX_FOREACH(elm, data->set) { 147 UCX_FOREACH(elm, data->set) {
145 DavProperty *p = elm->data; 148 DavProperty *p = elm->data;
146 dav_session_free(sn, p->ns->name); 149 dav_session_free(sn, p->ns->name);
147 if(p->ns->prefix) { 150 if(p->ns->prefix) {
219 sizeof(DavResourceData)); 222 sizeof(DavResourceData));
220 if(!data) { 223 if(!data) {
221 return NULL; 224 return NULL;
222 } 225 }
223 data->properties = ucx_map_new_a(sn->mp->allocator, 32); 226 data->properties = ucx_map_new_a(sn->mp->allocator, 32);
227 data->crypto_properties = NULL;
224 data->set = NULL; 228 data->set = NULL;
225 data->remove = NULL; 229 data->remove = NULL;
230 data->crypto_set = NULL;
231 data->crypto_remove = NULL;
232 data->read = NULL;
226 data->content = NULL; 233 data->content = NULL;
227 data->read = NULL;
228 data->seek = NULL; 234 data->seek = NULL;
229 data->length = 0; 235 data->length = 0;
230 return data; 236 return data;
231 } 237 }
232 238
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;
588 *count, 680 *count,
589 sizeof(DavPropName)); 681 sizeof(DavPropName));
590 682
591 683
592 UcxMapIterator i = ucx_map_iterator(data->properties); 684 UcxMapIterator i = ucx_map_iterator(data->properties);
593 void *value; 685 DavProperty *value;
594 int j = 0; 686 int j = 0;
595 UCX_MAP_FOREACH(key, value, i) { 687 UCX_MAP_FOREACH(key, value, i) {
596 DavPropName *name = &names[j]; 688 DavPropName *name = &names[j];
597 // the map key is namespace + '\0' + name 689
598 name->ns = (char*)key.data; 690 name->ns = value->ns->name;
599 for(int k=0;j<key.len;k++) { 691 name->name = value->name;
600 if(((char*)key.data)[k] == '\0') { 692
601 name->name = (char*)key.data + k + 1;
602 break;
603 }
604 }
605 j++; 693 j++;
606 } 694 }
607 695
608 qsort(names, *count, sizeof(DavPropName), compare_propname); 696 qsort(names, *count, sizeof(DavPropName), compare_propname);
609 697
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);
856 } 1005 }
857 1006
858 ucx_buffer_free(request); 1007 ucx_buffer_free(request);
859 ucx_buffer_free(response); 1008 ucx_buffer_free(response);
860 } 1009 }
861 1010
862 return r; 1011 return r;
863 } 1012 }
864 1013
865 #if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32 1014 #if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
866 static void set_progressfunc(DavResource *res) { 1015 static void set_progressfunc(DavResource *res) {
1350 free(crypto_prop_content); 1499 free(crypto_prop_content);
1351 } 1500 }
1352 return ret; 1501 return ret;
1353 } 1502 }
1354 1503
1355 UcxMap* parse_crypto_prop(DavSession *sn, DavXmlNode *node) { 1504 UcxMap* parse_crypto_prop(DavSession *sn, DavKey *key, DavXmlNode *node) {
1356 if(!node || node->type != DAV_XML_TEXT || node->contentlength == 0) { 1505 if(!node || node->type != DAV_XML_TEXT || node->contentlength == 0) {
1357 return NULL; 1506 return NULL;
1358 } 1507 }
1359 1508
1509 return parse_crypto_prop_str(sn, key, node->content);
1510 }
1511
1512 UcxMap* parse_crypto_prop_str(DavSession *sn, DavKey *key, const char *content) {
1360 size_t len = 0; 1513 size_t len = 0;
1361 char *dec_str = aes_decrypt(node->content, &len, sn->key); 1514 char *dec_str = aes_decrypt(content, &len, key);
1362 1515
1363 xmlDoc *doc = xmlReadMemory(dec_str, len, NULL, NULL, 0); 1516 xmlDoc *doc = xmlReadMemory(dec_str, len, NULL, NULL, 0);
1364 free(dec_str); 1517 free(dec_str);
1365 if(!doc) { 1518 if(!doc) {
1366 return NULL; 1519 return NULL;

mercurial