libidav/methods.c

changeset 43
03076907b58a
parent 38
b855f76e965b
child 44
e4e23a88d4de
--- a/libidav/methods.c	Tue Mar 18 13:59:02 2014 +0100
+++ b/libidav/methods.c	Thu Jun 05 15:11:29 2014 +0200
@@ -33,6 +33,8 @@
 #include "utils.h"
 #include "methods.h"
 #include "davql.h"
+#include "crypto.h"
+#include "session.h"
 
 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b)
 
@@ -80,16 +82,38 @@
     return buf;
 }
 
-UcxBuffer* create_propfind_request(UcxList *properties) {
+UcxBuffer* create_propfind_request(DavSession *sn, UcxList *properties) {
     UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0);
     sstr_t s;
     
+    int add_crypto_name = 1;
+    int add_crypto_key = 1;
+    char *crypto_ns = "idav";
     UcxMap *namespaces = ucx_map_new(8);
     UCX_FOREACH(elm, properties) {
         DavProperty *p = elm->data;
         if(strcmp(p->ns->name, "DAV:")) {
             ucx_map_cstr_put(namespaces, p->ns->prefix, p->ns);
         }
+        
+        // if the properties list contains the idav properties crypto-name
+        // and crypto-key, mark them as existent 
+        if(!strcmp(p->ns->name, DAV_NS)) {
+            if(!strcmp(p->name, "crypto-name")) {
+                add_crypto_name = 0;
+                crypto_ns = p->ns->prefix;
+            } else if(!strcmp(p->name, "crypto-key")) {
+                add_crypto_key = 0;
+                crypto_ns = p->ns->prefix;
+            }
+        }
+    }
+    
+    DavNamespace idav_ns;
+    if(add_crypto_name && add_crypto_key && DAV_CRYPTO(sn)) {
+        idav_ns.prefix = "idav";
+        idav_ns.name = DAV_NS;
+        ucx_map_cstr_put(namespaces, "idav", &idav_ns);
     }
     
     s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
@@ -129,6 +153,22 @@
     s = S("<D:resourcetype />\n");
     ucx_buffer_write(s.ptr, 1, s.length, buf);
     
+    // crypto properties
+    if(DAV_CRYPTO(sn)) {
+        if(add_crypto_name) {
+            ucx_buffer_putc(buf, '<');
+            ucx_buffer_puts(buf, crypto_ns);
+            s = S(":crypto-name />\n");
+            ucx_buffer_write(s.ptr, 1, s.length, buf);
+        }
+        if(add_crypto_key) {
+            ucx_buffer_putc(buf, '<');
+            ucx_buffer_puts(buf, crypto_ns);
+            s = S(":crypto-key />\n");
+            ucx_buffer_write(s.ptr, 1, s.length, buf);
+        }
+    }
+    
     // extra properties
     UCX_FOREACH(elm, properties) {
         DavProperty *prop = elm->data;
@@ -151,11 +191,44 @@
     return buf;
 }
 
+UcxBuffer* create_basic_propfind_request() {
+    UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0);
+    sstr_t s;
+    
+    s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    s = S("<D:propfind xmlns:D=\"DAV:\" xmlns:i=\"");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);  
+    s = S(DAV_NS);
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    s = S("\" >\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    // properties
+    s = S("<D:prop>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    s = S("<D:resourcetype />\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    s = S("<i:crypto-key />\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    s = S("<i:crypto-name />\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    s = S("</D:prop>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    // end
+    s = S("</D:propfind>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    return buf;
+}
+
 DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response, DavQOp *cond, size_t len) {
     char *url = NULL;
     curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &url);
     if(!root) {
-        root = dav_resource_new_href(sn, util_url_path(url));
+        root = dav_resource_new_href(sn, util_url_path(url)); // TODO: remove
     }
     
     xmlDoc *doc = xmlReadMemory(response->space, response->size, url, NULL, 0);
@@ -181,7 +254,17 @@
 }
 
 int parse_response_tag(DavResource *resource, xmlNode *node, DavQOp *cond, size_t clen) {
-    DavResource *res = resource;
+    DavSession *sn = resource->session;
+    
+    //DavResource *res = resource;
+    DavResource *res = NULL;
+    char *href = NULL;
+    UcxList *properties = NULL; // xmlNode list
+    char *crypto_name = NULL; // name set by crypto-name property
+    char *crypto_key = NULL;
+    
+    int iscollection = 0; // TODO: remove
+    
     node = node->children;
     while(node) {
         if(node->type == XML_ELEMENT_NODE) {
@@ -189,16 +272,16 @@
                 xmlNode *href_node = node->children;
                 if(href_node->type != XML_TEXT_NODE) {
                     // error
-                    resource->session->error = DAV_ERROR;
+                    sn->error = DAV_ERROR;
                     return 1;
                 }
-                char *href = (char*)href_node->content;
-                href = util_url_path(href);
+                //char *href = (char*)href_node->content;
+                href = util_url_path((char*)href_node->content);
                 if(xstreq(resource->href, href)) {
                     res = resource;
                 } else {
-                    res = dav_resource_new_href(resource->session, href);
-                    res->parent = resource;
+                    //res = dav_resource_new_href(resource->session, href);
+                    //res->parent = resource;
                 }
             } else if(xstreq(node->name, "propstat")) {
                 xmlNode *n = node->children;
@@ -212,12 +295,12 @@
                         } else if(xstreq(n->name, "status")) {
                             xmlNode *status_node = n->children;
                             if(status_node->type != XML_TEXT_NODE) {
-                                resource->session->error = DAV_ERROR;
+                                sn->error = DAV_ERROR;
                                 return 1;
                             }
                             sstr_t status_str = sstr((char*)status_node->content);
                             if(status_str.length < 13) {
-                                resource->session->error = DAV_ERROR;
+                                sn->error = DAV_ERROR;
                                 return 1;
                             }
                             status_str = sstrsubsl(status_str, 9, 3);
@@ -233,21 +316,19 @@
                     n = prop_node->children;
                     while(n) {
                         if(n->type == XML_ELEMENT_NODE) {
+                            properties = ucx_list_append(properties, n);
                             if(xstreq(n->name, "resourcetype")) {
                                 xmlNode *rsnode = n->children;
                                 if(rsnode && rsnode->type == XML_ELEMENT_NODE) {
                                     // TODO: this is a ugly lazy hack
-                                    resource_add_property(res, "DAV:", (char*)n->name, "collection");
-                                    res->iscollection = 1;
+                                    //resource_add_property(res, "DAV:", (char*)n->name, "collection");
+                                    iscollection = 1;
                                 }
-                            } else {
-                                xmlNode *content = n->children;
-                                if(content) {
-                                    resource_add_property(
-                                            res,
-                                            (char*)n->ns->href,
-                                            (char*)n->name,
-                                            (char*)content->content);
+                            } else if(xstreq(n->ns->href, DAV_NS)) {
+                                if(xstreq(n->name, "crypto-name")) {
+                                    crypto_name = util_xml_get_text(n);
+                                } else if(xstreq(n->name, "crypto-key")) {
+                                    crypto_key = util_xml_get_text(n);
                                 }
                             }
                         }
@@ -260,6 +341,39 @@
         node = node->next;
     }
     
+    if(!res) {
+        // create new resource object
+        char *name = NULL;
+        if(DAV_DECRYPT_NAME(sn) && crypto_name) {
+            if(!crypto_key) {
+                // TODO: error
+                fprintf(stderr, "encrypted resource without key\n");
+            }
+            name = util_decrypt_str(sn, crypto_name, crypto_key);
+            if(!name) {
+                // TODO: error
+                fprintf(stderr, "decrypted name is null\n");
+            }
+        } else {
+            name = util_resource_name(href);
+        }
+        
+        href = dav_session_strdup(sn, href);
+        res = dav_resource_new_full(sn, resource->path, name, href);
+    }
+    res->iscollection = iscollection;
+    
+    // add properties
+    UCX_FOREACH(elm, properties) {
+        xmlNode *prop = elm->data;
+        
+        // TODO: add xml data instead of a string
+        char *text = util_xml_get_text(prop);
+        if(text) {
+            resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, text);
+        }
+    }
+    
     set_davprops(res);
     if(res != resource) {
         if(clen > 0) {
@@ -436,6 +550,41 @@
     return buf;
 }
 
+UcxBuffer* create_crypto_proppatch_request(DavSession *sn, DavKey *key, char *name) {
+    UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0);
+    sstr_t s;
+    
+    s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    s = S("<D:propertyupdate xmlns:D=\"DAV:\" xmlns:idav=\"" DAV_NS "\">\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    s = S("<D:set>\n<D:prop>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    if(DAV_ENCRYPT_NAME(sn)) {
+        s = S("<idav:crypto-name>");
+        ucx_buffer_write(s.ptr, 1, s.length, buf);
+        char *crname = aes_encrypt(name, key);
+        ucx_buffer_puts(buf, crname);
+        free(crname);
+        s = S("</idav:crypto-name>\n");
+        ucx_buffer_write(s.ptr, 1, s.length, buf);
+    }
+    
+    s = S("<idav:crypto-key>");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    ucx_buffer_puts(buf, key->name);
+    s = S("</idav:crypto-key>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    s = S("</D:prop>\n</D:set>\n</D:propertyupdate>\n");
+    ucx_buffer_write(s.ptr, 1, s.length, buf);
+    
+    return buf;
+}
+
 /* ----------------------------- PUT ----------------------------- */
 
 static size_t dummy_write(void *buf, size_t s, size_t n, void *data) {
@@ -448,6 +597,10 @@
     curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
     curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
     
+    // clear headers
+    struct curl_slist *headers = NULL;
+    curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+    
     UcxBuffer *buf = NULL;
     if(!read_func) {
         buf = ucx_buffer_new(data, length, 0);
@@ -478,6 +631,9 @@
 }
 
 CURLcode do_delete_request(CURL *handle, UcxBuffer *response) {
+    struct curl_slist *headers = NULL;
+    curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+    
     curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "DELETE");
     curl_easy_setopt(handle, CURLOPT_PUT, 0L);  
     curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L);
@@ -491,6 +647,9 @@
 }
 
 CURLcode do_mkcol_request(CURL *handle) { 
+    struct curl_slist *headers = NULL;
+    curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+    
     curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MKCOL");
     curl_easy_setopt(handle, CURLOPT_PUT, 0L);  
     curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L);

mercurial