diff -r 6518b035a9df -r 03076907b58a libidav/methods.c --- 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("\n"); @@ -129,6 +153,22 @@ s = S("\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("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + // properties + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + // end + s = S("\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("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = S("\n\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + if(DAV_ENCRYPT_NAME(sn)) { + s = S(""); + ucx_buffer_write(s.ptr, 1, s.length, buf); + char *crname = aes_encrypt(name, key); + ucx_buffer_puts(buf, crname); + free(crname); + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + } + + s = S(""); + ucx_buffer_write(s.ptr, 1, s.length, buf); + ucx_buffer_puts(buf, key->name); + s = S("\n"); + ucx_buffer_write(s.ptr, 1, s.length, buf); + + s = S("\n\n\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);