implement encrypted properties

Sun, 28 Jul 2019 13:07:53 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 28 Jul 2019 13:07:53 +0200
changeset 609
dc3d70848c7c
parent 608
3e4c0285a868
child 610
aa3baf1dd81b

implement encrypted properties

dav/main.c file | annotate | diff | comparison | revisions
libidav/davqlexec.c file | annotate | diff | comparison | revisions
libidav/methods.c file | annotate | diff | comparison | revisions
libidav/methods.h file | annotate | diff | comparison | revisions
libidav/resource.c file | annotate | diff | comparison | revisions
libidav/resource.h file | annotate | diff | comparison | revisions
libidav/session.h file | annotate | diff | comparison | revisions
libidav/utils.c file | annotate | diff | comparison | revisions
libidav/webdav.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
--- a/dav/main.c	Fri Jul 12 16:59:08 2019 +0200
+++ b/dav/main.c	Sun Jul 28 13:07:53 2019 +0200
@@ -381,9 +381,8 @@
             repo->url = strdup(url);
             *path = strdup("/");
         } else if (strchr(url, '/')) {
-            repo->url = util_parent_path(url);
-            // TODO: check/fix
-            *path = strdup(util_resource_name(url)-1);
+            repo->url = util_url_base(url);
+            *path = util_url_path(url);
         } else {
             repo->url = strdup(url);
             *path = strdup("/");
--- a/libidav/davqlexec.c	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/davqlexec.c	Sun Jul 28 13:07:53 2019 +0200
@@ -309,7 +309,7 @@
     DavResourceData *data = (DavResourceData*)res->data;
     
     // add basic properties
-    char *value;
+    void *value;
     
     sstr_t cl_keystr = dav_property_key("DAV:", "getcontentlength");
     UcxKey cl_key = ucx_key(cl_keystr.ptr, cl_keystr.length);
--- a/libidav/methods.c	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/methods.c	Sun Jul 28 13:07:53 2019 +0200
@@ -135,6 +135,22 @@
     return buf;
 }
 
+UcxBuffer* create_cryptoprop_propfind_request(void) {
+    UcxBuffer *buf = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOFREE);
+    scstr_t s;
+    
+    s = SC("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    s = SC("<D:propfind xmlns:D=\"DAV:\" xmlns:idav=\"" DAV_NS "\">\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    s = SC("<D:prop><idav:crypto-prop/></D:prop></D:propfind>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    return buf;
+}
+
 UcxBuffer* create_propfind_request(DavSession *sn, UcxList *properties, char *rootelm, DavBool nocrypt) {
     UcxBuffer *buf = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND);
     sstr_t s;
@@ -534,10 +550,35 @@
 void add_properties(DavResource *res, ResponseTag *response) {
     res->iscollection = response->iscollection;
     
+    int decrypt_props = DAV_ENCRYPT_PROPERTIES(res->session);
+    xmlNode *crypto_prop = NULL;
+    char *crypto_key = NULL;
+    
     // add properties
     UCX_FOREACH(elm, response->properties) {
         xmlNode *prop = elm->data;
         resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, prop->children);
+        
+        if (decrypt_props &&
+            prop->children &&
+            prop->children->type == XML_TEXT_NODE &&
+            xstreq(prop->ns->href, DAV_NS))
+        {
+            if(xstreq(prop->name, "crypto-prop")) {
+                crypto_prop = prop;
+            } else if(xstreq(prop->name, "crypto-key")) {
+                crypto_key = util_xml_get_text(prop);
+            }
+        }
+    }
+    
+    if(crypto_prop && crypto_key) {
+        char *crypto_prop_content = util_xml_get_text(crypto_prop);
+        DavKey *key = dav_context_get_key(res->session->context, crypto_key);
+        if(crypto_prop_content) {
+            UcxMap *cprops = parse_crypto_prop_str(res->session, key, crypto_prop_content);
+            resource_set_crypto_properties(res, cprops);
+        }
     }
     
     set_davprops(res);
@@ -667,12 +708,35 @@
     res->iscollection = iscollection;
     
     // add properties
+    int decrypt_props = DAV_ENCRYPT_PROPERTIES(res->session);
+    xmlNode *crypto_prop = NULL;
+    
     UCX_FOREACH(elm, properties) {
         xmlNode *prop = elm->data;
         resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, prop->children);
+        
+        if (decrypt_props &&
+            prop->children &&
+            prop->children->type == XML_TEXT_NODE &&
+            xstreq(prop->ns->href, DAV_NS))
+        {
+            if(xstreq(prop->name, "crypto-prop")) {
+                crypto_prop = prop;
+            }
+        }
     }
     ucx_list_free(properties);
     
+    if(crypto_prop && crypto_key) {
+        char *crypto_prop_content = util_xml_get_text(crypto_prop);
+        DavKey *key = dav_context_get_key(res->session->context, crypto_key);
+        if(crypto_prop_content && key) {
+            UcxMap *cprops = parse_crypto_prop_str(res->session, key, crypto_prop_content);
+            resource_set_crypto_properties(res, cprops);
+        }
+    }
+    
+    
     set_davprops(res);
     if(res != resource) {
         resource_add_child(resource, res);
--- a/libidav/methods.h	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/methods.h	Sun Jul 28 13:07:53 2019 +0200
@@ -83,6 +83,7 @@
         size_t length);
 
 UcxBuffer* create_allprop_propfind_request(void);
+UcxBuffer* create_cryptoprop_propfind_request(void);
 UcxBuffer* create_propfind_request(DavSession *sn, UcxList *properties, char *rootelm, DavBool nocrypt);
 UcxBuffer* create_basic_propfind_request(void);
 
--- a/libidav/resource.c	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/resource.c	Sun Jul 28 13:07:53 2019 +0200
@@ -120,11 +120,13 @@
 }
 
 void resource_free_properties(DavSession *sn, UcxMap *properties) {
+    if(!properties) return;
+    
     UcxMapIterator i = ucx_map_iterator(properties);
-    DavXmlNode *node;
-    UCX_MAP_FOREACH(key, node, i) {
+    DavProperty *property;
+    UCX_MAP_FOREACH(key, property, i) {
         // TODO: free everything
-        dav_session_free(sn, node);
+        dav_session_free(sn, property);
     }
     ucx_map_free(properties);
 }
@@ -140,6 +142,7 @@
     
     DavResourceData *data = res->data;
     resource_free_properties(sn, data->properties);
+    resource_free_properties(sn, data->crypto_properties);
     
     UCX_FOREACH(elm, data->set) {
         DavProperty *p = elm->data;
@@ -221,10 +224,13 @@
         return NULL;
     }
     data->properties = ucx_map_new_a(sn->mp->allocator, 32);
+    data->crypto_properties = NULL;
     data->set = NULL;
     data->remove = NULL;
+    data->crypto_set = NULL;
+    data->crypto_remove = NULL;
+    data->read = NULL;
     data->content = NULL;
-    data->read = NULL;
     data->seek = NULL;
     data->length = 0;
     return data;
@@ -239,15 +245,29 @@
     return resource->href;
 }
 
+void resource_add_prop(DavResource *res, const char *ns, const char *name, DavXmlNode *val) {
+    DavSession *sn = res->session;
+    
+    DavNamespace *namespace = dav_session_malloc(sn, sizeof(DavNamespace));
+    namespace->prefix = NULL;
+    namespace->name = dav_session_strdup(sn, ns);
+    
+    DavProperty *prop = dav_session_malloc(sn, sizeof(DavProperty));
+    prop->name = dav_session_strdup(sn, name);
+    prop->ns = namespace;
+    prop->value = val;
+    
+    sstr_t key = dav_property_key(ns, name);
+    ucx_map_sstr_put(((DavResourceData*)res->data)->properties, key, prop);
+    free(key.ptr);
+}
+
 void resource_add_property(DavResource *res, const char *ns, const char *name, xmlNode *val) {
     if(!val) {
         return;
     }
     
-    sstr_t key = dav_property_key(ns, name);
-    DavXmlNode *v = dav_convert_xml(res->session, val);
-    ucx_map_sstr_put(((DavResourceData*)res->data)->properties, key, v);
-    free(key.ptr);
+    resource_add_prop(res, ns, name, dav_convert_xml(res->session, val));
 }
 
 void resource_add_string_property(DavResource *res, char *ns, char *name, char *val) {
@@ -255,23 +275,45 @@
         return;
     }
     
-    sstr_t key = dav_property_key(ns, name);
-    DavXmlNode *v = dav_text_node(res->session, val);
-    ucx_map_sstr_put(((DavResourceData*)res->data)->properties, key, v);
-    free(key.ptr);
+    resource_add_prop(res, ns, name, dav_text_node(res->session, val));
+}
+
+void resource_set_crypto_properties(DavResource *res, UcxMap *cprops) {
+    DavResourceData *data = res->data;
+    resource_free_properties(res->session, data->crypto_properties);
+    data->crypto_properties = cprops;
 }
 
 DavXmlNode* resource_get_property(DavResource *res, const char *ns, const char *name) {
     sstr_t keystr = dav_property_key(ns, name);
     UcxKey key = ucx_key(keystr.ptr, keystr.length);
-    DavXmlNode *property = resource_get_property_k(res, key);
+    DavXmlNode *ret = resource_get_property_k(res, key);
     free(keystr.ptr);
-    return property;
+    
+    return ret;
+}
+
+DavXmlNode* resource_get_encrypted_property(DavResource *res, const char *ns, const char *name) {
+    sstr_t keystr = dav_property_key(ns, name);
+    UcxKey key = ucx_key(keystr.ptr, keystr.length);
+    DavXmlNode *ret = resource_get_encrypted_property_k(res, key);
+    free(keystr.ptr);
+    
+    return ret;
 }
 
 DavXmlNode* resource_get_property_k(DavResource *res, UcxKey key) {
     DavResourceData *data = (DavResourceData*)res->data;
-    return ucx_map_get(data->properties, key);
+    DavProperty *property = ucx_map_get(data->properties, key);
+    
+    return property ? property->value : NULL;
+}
+
+DavXmlNode* resource_get_encrypted_property_k(DavResource *res, UcxKey key) {
+    DavResourceData *data = (DavResourceData*)res->data;
+    DavProperty *property = ucx_map_get(data->crypto_properties, key);
+    
+    return property ? property->value : NULL;
 }
 
 sstr_t dav_property_key(const char *ns, const char *name) {
@@ -445,17 +487,37 @@
     return dav_get_property_ns(res, pns, pname);
 }
 
-DavXmlNode* dav_get_property_ns(DavResource *res, const char *ns, const char *name) {
+static DavXmlNode* get_property_ns(DavResource *res, DavBool encrypted, const char *ns, const char *name) {
     if(!ns || !name) {
         return NULL;
     }
-    DavXmlNode *property = resource_get_property(res, ns, name);
+    
     DavResourceData *data = res->data;
+    
+    DavXmlNode *property = NULL;
+    UcxList *remove_list = NULL;
+    UcxList *set_list = NULL;
+    
+    if(encrypted) {
+        // check if crypto_properties because it will only be created
+        // if the resource has encrypted properties
+        if(!data->crypto_properties) {
+            return NULL;
+        }
+        property = resource_get_encrypted_property(res, ns, name);
+        remove_list = data->crypto_remove;
+        set_list = data->crypto_set;
+    } else {
+        property = resource_get_property(res, ns, name);
+        remove_list = data->remove;
+        set_list = data->set;
+    }
+    
     // resource_get_property only returns persistent properties
     // check the remove and set list
     if(property) {
         // if the property is in the remove list, we return NULL
-        UCX_FOREACH(elm, data->remove) {
+        UCX_FOREACH(elm, remove_list) {
             DavProperty *p = elm->data;
             if(!strcmp(p->name, name) && !strcmp(p->ns->name, ns)) {
                 return NULL;
@@ -464,16 +526,31 @@
     }
     // the set list contains property updates
     // we return an updated property if possible
-    UCX_FOREACH(elm, data->set) {
+    UCX_FOREACH(elm, set_list) {
         DavProperty *p = elm->data;
         if(!strcmp(p->name, name) && !strcmp(p->ns->name, ns)) {
             return p->value; // TODO: fix
         }
     }
     // no property update
+    
     return property;
 }
 
+DavXmlNode* dav_get_property_ns(DavResource *res, const char *ns, const char *name) {
+    DavXmlNode *property_value = get_property_ns(res, FALSE, ns, name);
+    
+    if(!property_value && DAV_DECRYPT_PROPERTIES(res->session)) {
+        property_value = get_property_ns(res, TRUE, ns, name);
+    }
+    
+    return property_value;
+}
+
+DavXmlNode* dav_get_encrypted_property_ns(DavResource *res, const char *ns, const char *name) {
+    return get_property_ns(res, TRUE, ns, name);
+}
+
 static DavProperty* createprop(DavSession *sn, const char *ns, const char *name) {
     DavProperty *property = dav_session_malloc(sn, sizeof(DavProperty));
     property->name = dav_session_strdup(sn, name);
@@ -496,13 +573,18 @@
 }
 
 void dav_set_string_property_ns(DavResource *res, char *ns, char *name, char *value) {
+    DavSession *sn = res->session;
     UcxAllocator *a = res->session->mp->allocator;
     DavResourceData *data = res->data;
     
     DavProperty *property = createprop(res->session, ns, name);
     property->value = dav_text_node(res->session, value);
     
-    data->set = ucx_list_append_a(a, data->set, property);
+    if(DAV_ENCRYPT_PROPERTIES(sn) && dav_namespace_is_encrypted(sn->context, ns)) {
+        data->crypto_set = ucx_list_append_a(a, data->crypto_set, property);
+    } else {
+        data->set = ucx_list_append_a(a, data->set, property);
+    }
 }
 
 void dav_set_property(DavResource *res, char *name, DavXmlNode *value) {
@@ -513,13 +595,18 @@
 }
 
 void dav_set_property_ns(DavResource *res, char *ns, char *name, DavXmlNode *value) {
-    UcxAllocator *a = res->session->mp->allocator;
+    DavSession *sn = res->session;
+    UcxAllocator *a = sn->mp->allocator; 
     DavResourceData *data = res->data;
     
-    DavProperty *property = createprop(res->session, ns, name);
+    DavProperty *property = createprop(sn, ns, name);
     property->value = value; // TODO: copy node?
     
-    data->set = ucx_list_append_a(a, data->set, property);
+    if(DAV_ENCRYPT_PROPERTIES(sn) && dav_namespace_is_encrypted(sn->context, ns)) {
+        data->crypto_set = ucx_list_append_a(a, data->crypto_set, property);
+    } else {
+        data->set = ucx_list_append_a(a, data->set, property);
+    }
 }
 
 void dav_remove_property(DavResource *res, char *name) {
@@ -530,12 +617,17 @@
 }
 
 void dav_remove_property_ns(DavResource *res, char *ns, char *name) {
+    DavSession *sn = res->session;
     DavResourceData *data = res->data;
     UcxAllocator *a = res->session->mp->allocator;
     
     DavProperty *property = createprop(res->session, ns, name);
     
-    data->remove = ucx_list_append_a(a, data->remove, property);
+    if(DAV_ENCRYPT_PROPERTIES(sn) && dav_namespace_is_encrypted(sn->context, ns)) {
+        data->crypto_remove = ucx_list_append_a(a, data->crypto_remove, property);
+    } else {
+        data->remove = ucx_list_append_a(a, data->remove, property);
+    }
 }
 
 void dav_set_encrypted_property_ns(DavResource *res, char *ns, char *name, DavXmlNode *value) {
@@ -590,18 +682,14 @@
     
     
     UcxMapIterator i = ucx_map_iterator(data->properties);
-    void *value;
+    DavProperty *value;
     int j = 0;
     UCX_MAP_FOREACH(key, value, i) {
         DavPropName *name = &names[j];
-        // the map key is namespace + '\0' + name
-        name->ns = (char*)key.data;
-        for(int k=0;j<key.len;k++) {
-            if(((char*)key.data)[k] == '\0') {
-                name->name = (char*)key.data + k + 1;
-                break;
-            }
-        }
+        
+        name->ns = value->ns->name;
+        name->name = value->name;
+        
         j++;
     }
     
@@ -833,6 +921,67 @@
         }
     }
     
+    // generate crypto-prop content
+    if(DAV_ENCRYPT_PROPERTIES(sn) && sn->key && (data->crypto_set || data->crypto_remove)) {
+        DavResource *crypto_res = dav_resource_new_href(sn, res->href);
+        int ret = 1;
+        
+        if(crypto_res) {
+            UcxBuffer *rqbuf = create_cryptoprop_propfind_request();
+            ret = dav_propfind(res->session, res, rqbuf);
+            ucx_buffer_free(rqbuf);
+        }
+        
+        if(!ret) {
+            DavXmlNode *crypto_prop_node = dav_get_property_ns(crypto_res, DAV_NS, "crypto-prop");
+            UcxMap *crypto_props = parse_crypto_prop(sn, sn->key, crypto_prop_node);
+            if(!crypto_props) {
+                // resource hasn't encrypted properties yet
+                crypto_props = ucx_map_new(32); // create new map
+            }
+            
+            // remove all properties
+            UCX_FOREACH(elm, data->crypto_remove) {
+                if(crypto_props->count == 0) {
+                    break; // map already empty, can't remove any more
+                }
+                
+                DavProperty *property = elm->data;
+                sstr_t key = dav_property_key(property->ns->name, property->name);
+                DavProperty *existing_prop = ucx_map_sstr_remove(crypto_props, key);
+                if(existing_prop) {
+                    // TODO: free existing_prop
+                }                
+                free(key.ptr);
+            }
+            
+            // set properties
+            UCX_FOREACH(elm, data->crypto_set) {
+                DavProperty *property = elm->data;
+                sstr_t key = dav_property_key(property->ns->name, property->name);
+                DavProperty *existing_prop = ucx_map_sstr_remove(crypto_props, key);
+                ucx_map_sstr_put(crypto_props, key, property);
+                if(existing_prop) {
+                    // TODO: free existing_prop
+                }  
+                free(key.ptr);
+            }
+            
+            DavXmlNode *crypto_prop_value = create_crypto_prop(sn, crypto_props);
+            if(crypto_prop_value) {
+                DavProperty *new_crypto_prop = createprop(sn, DAV_NS, "crypto-prop");
+                new_crypto_prop->value = crypto_prop_value;
+                data->set = ucx_list_prepend_a(sn->mp->allocator, data->set, new_crypto_prop);
+            }
+            
+            dav_resource_free(crypto_res);
+        }
+        
+        if(ret) {
+            return 1;
+        }
+    }
+    
     // store properties
     int r = 0;
     sn->error = DAV_OK;
@@ -858,7 +1007,7 @@
         ucx_buffer_free(request);
         ucx_buffer_free(response);
     }
-    
+     
     return r;
 }
 
@@ -1352,13 +1501,17 @@
     return ret;
 }
 
-UcxMap* parse_crypto_prop(DavSession *sn, DavXmlNode *node) {
+UcxMap* parse_crypto_prop(DavSession *sn, DavKey *key, DavXmlNode *node) {
     if(!node || node->type != DAV_XML_TEXT || node->contentlength == 0) {
         return NULL;
     }
     
+    return parse_crypto_prop_str(sn, key, node->content);
+}
+
+UcxMap* parse_crypto_prop_str(DavSession *sn, DavKey *key, const char *content) {
     size_t len = 0;
-    char *dec_str = aes_decrypt(node->content, &len, sn->key);
+    char *dec_str = aes_decrypt(content, &len, key);
     
     xmlDoc *doc = xmlReadMemory(dec_str, len, NULL, NULL, 0);
     free(dec_str);
--- a/libidav/resource.h	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/resource.h	Sun Jul 28 13:07:53 2019 +0200
@@ -82,8 +82,11 @@
 void resource_set_info(DavResource *res, char *href_str);
 DavResourceData* resource_data_new(DavSession *sn);
 void resource_add_property(DavResource *res, const char *ns, const char *name, xmlNode *val);
+void resource_set_crypto_properties(DavResource *res, UcxMap *cprops);
 DavXmlNode* resource_get_property(DavResource *res, const char *ns, const char *name);
+DavXmlNode* resource_get_encrypted_property(DavResource *res, const char *ns, const char *name);
 DavXmlNode* resource_get_property_k(DavResource *res, UcxKey key);
+DavXmlNode* resource_get_encrypted_property_k(DavResource *res, UcxKey key);
 void resource_add_child(DavResource *parent, DavResource *child);
 void resource_add_ordered_child(DavResource *parent, DavResource *child, UcxList *ordercr);
 int resource_add_crypto_info(DavSession *sn, const char *href, const char *name, const char *hash);
@@ -91,7 +94,8 @@
 sstr_t dav_property_key_a(UcxAllocator *a, const char *ns, const char *name);
 
 DavXmlNode* create_crypto_prop(DavSession *sn, UcxMap *properties);
-UcxMap* parse_crypto_prop(DavSession *sn, DavXmlNode *node);
+UcxMap* parse_crypto_prop(DavSession *sn, DavKey *key, DavXmlNode *node);
+UcxMap* parse_crypto_prop_str(DavSession *sn, DavKey *key, const char *content);
 
 #ifdef	__cplusplus
 }
--- a/libidav/session.h	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/session.h	Sun Jul 28 13:07:53 2019 +0200
@@ -59,6 +59,12 @@
 #define DAV_CRYPTO(sn) \
     (DAV_ENCRYPT_NAME(sn) || DAV_DECRYPT_NAME(sn) || \
      DAV_ENCRYPT_CONTENT(sn) || DAV_DECRYPT_CONTENT(sn))
+
+#define DAV_ENCRYPT_PROPERTIES(sn) \
+    (((sn)->flags & DAV_SESSION_ENCRYPT_PROPERTIES) == DAV_SESSION_ENCRYPT_PROPERTIES)
+
+#define DAV_DECRYPT_PROPERTIES(sn) \
+    (((sn)->flags & DAV_SESSION_DECRYPT_PROPERTIES) == DAV_SESSION_DECRYPT_PROPERTIES)
     
 /*
 typedef struct DavPathCacheElement {
--- a/libidav/utils.c	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/utils.c	Sun Jul 28 13:07:53 2019 +0200
@@ -321,6 +321,9 @@
             }
         }
     } 
+    if(!path) {
+        path = url + len; // empty string
+    }
     return path;
 }
 
@@ -679,6 +682,11 @@
 char* util_base64decode_len(const char* in, int *outlen) {
     /* code is mostly from wikibooks */
     
+    if(!in) {
+        *outlen = 0;
+        return NULL;
+    }
+    
     size_t inlen = strlen(in);
     size_t bufsize = (inlen*3) / 4;
     char *outbuf = malloc(bufsize+1);
--- a/libidav/webdav.c	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/webdav.c	Sun Jul 28 13:07:53 2019 +0200
@@ -186,6 +186,26 @@
     return ucx_map_sstr_get(context->namespaces, prefix);
 }
 
+int dav_enable_namespace_encryption(DavContext *context, const char *ns, DavBool encrypt) {
+    DavNSInfo *info = ucx_map_cstr_get(context->namespaceinfo, ns);
+    if(!info) {
+        info = calloc(1, sizeof(DavNSInfo));
+        info->encrypt = encrypt;
+        ucx_map_cstr_put(context->namespaceinfo, ns, info);
+    } else {
+        info->encrypt = encrypt;
+    }
+    return 0;
+}
+
+int dav_namespace_is_encrypted(DavContext *context, const char *ns) {
+    DavNSInfo *info = ucx_map_cstr_get(context->namespaceinfo, ns);
+    if(info) {
+        return info->encrypt;
+    }
+    return 0;
+}
+
 void dav_get_property_namespace_str(
         DavContext *ctx,
         char *prefixed_name,
@@ -301,7 +321,7 @@
 int dav_propfind(DavSession *sn, DavResource *root, UcxBuffer *rqbuf) {
     // clean resource properties
     DavResourceData *data = root->data;
-    ucx_map_clear(data->properties);
+    ucx_map_clear(data->properties); // TODO: free existing content
     
     CURL *handle = sn->handle;
     util_set_url(sn, dav_resource_get_href(root));
@@ -315,6 +335,7 @@
     if(ret == CURLE_OK && status == 207) {
         //printf("response\n%s\n", rpbuf->space); 
         dav_set_effective_href(sn, resource);
+        // TODO: use PropfindParser
         resource = parse_propfind_response(sn, resource, rpbuf);
         sn->error = DAV_OK;
         root->exists = 1;
--- a/libidav/webdav.h	Fri Jul 12 16:59:08 2019 +0200
+++ b/libidav/webdav.h	Sun Jul 28 13:07:53 2019 +0200
@@ -58,6 +58,7 @@
 typedef struct DavProperty   DavProperty;
 typedef struct DavPropName   DavPropName;
 typedef struct DavKey        DavKey;
+typedef struct DavNSInfo     DavNSInfo;
 typedef struct DavXmlNode    DavXmlNode;
 typedef struct DavXmlAttr    DavXmlAttr;
 
@@ -162,6 +163,7 @@
 
 struct DavContext {
     UcxMap   *namespaces;
+    UcxMap   *namespaceinfo;
     UcxMap   *keys;
     UcxList  *sessions;
     DavProxy *http_proxy;
@@ -201,6 +203,11 @@
     size_t  length;
 };
 
+struct DavNSInfo {
+    char    *prefix;
+    DavBool encrypt;
+};
+
 struct DavXmlNode {
     DavXmlNodeType type;
     
@@ -233,6 +240,9 @@
 int dav_add_namespace(DavContext *context, const char *prefix, const char *ns);
 DavNamespace* dav_get_namespace(DavContext *context, const char *prefix);
 
+int dav_enable_namespace_encryption(DavContext *context, const char *ns, DavBool encrypt);
+int dav_namespace_is_encrypted(DavContext *context, const char *ns);
+
 DavSession* dav_session_new(DavContext *context, char *base_url);
 DavSession* dav_session_new_auth(
         DavContext *context,
@@ -301,6 +311,7 @@
 
 DavXmlNode* dav_get_property(DavResource *res, char *name);
 DavXmlNode* dav_get_property_ns(DavResource *res, const char *ns, const char *name);
+DavXmlNode* dav_get_encrypted_property_ns(DavResource *res, const char *ns, const char *name);
 char* dav_get_string_property(DavResource *res, char *name);
 char* dav_get_string_property_ns(DavResource *res, char *ns, char *name);
 void dav_set_string_property(DavResource *res, char *name, char *value);

mercurial