libidav/methods.c

changeset 43
03076907b58a
parent 38
b855f76e965b
child 44
e4e23a88d4de
equal deleted inserted replaced
42:6518b035a9df 43:03076907b58a
31 #include <string.h> 31 #include <string.h>
32 32
33 #include "utils.h" 33 #include "utils.h"
34 #include "methods.h" 34 #include "methods.h"
35 #include "davql.h" 35 #include "davql.h"
36 #include "crypto.h"
37 #include "session.h"
36 38
37 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) 39 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b)
38 40
39 /* ----------------------------- PROPFIND ----------------------------- */ 41 /* ----------------------------- PROPFIND ----------------------------- */
40 42
78 ucx_buffer_write(s.ptr, 1, s.length, buf); 80 ucx_buffer_write(s.ptr, 1, s.length, buf);
79 81
80 return buf; 82 return buf;
81 } 83 }
82 84
83 UcxBuffer* create_propfind_request(UcxList *properties) { 85 UcxBuffer* create_propfind_request(DavSession *sn, UcxList *properties) {
84 UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0); 86 UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0);
85 sstr_t s; 87 sstr_t s;
86 88
89 int add_crypto_name = 1;
90 int add_crypto_key = 1;
91 char *crypto_ns = "idav";
87 UcxMap *namespaces = ucx_map_new(8); 92 UcxMap *namespaces = ucx_map_new(8);
88 UCX_FOREACH(elm, properties) { 93 UCX_FOREACH(elm, properties) {
89 DavProperty *p = elm->data; 94 DavProperty *p = elm->data;
90 if(strcmp(p->ns->name, "DAV:")) { 95 if(strcmp(p->ns->name, "DAV:")) {
91 ucx_map_cstr_put(namespaces, p->ns->prefix, p->ns); 96 ucx_map_cstr_put(namespaces, p->ns->prefix, p->ns);
92 } 97 }
98
99 // if the properties list contains the idav properties crypto-name
100 // and crypto-key, mark them as existent
101 if(!strcmp(p->ns->name, DAV_NS)) {
102 if(!strcmp(p->name, "crypto-name")) {
103 add_crypto_name = 0;
104 crypto_ns = p->ns->prefix;
105 } else if(!strcmp(p->name, "crypto-key")) {
106 add_crypto_key = 0;
107 crypto_ns = p->ns->prefix;
108 }
109 }
110 }
111
112 DavNamespace idav_ns;
113 if(add_crypto_name && add_crypto_key && DAV_CRYPTO(sn)) {
114 idav_ns.prefix = "idav";
115 idav_ns.name = DAV_NS;
116 ucx_map_cstr_put(namespaces, "idav", &idav_ns);
93 } 117 }
94 118
95 s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"); 119 s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
96 ucx_buffer_write(s.ptr, 1, s.length, buf); 120 ucx_buffer_write(s.ptr, 1, s.length, buf);
97 121
127 ucx_buffer_write(s.ptr, 1, s.length, buf); 151 ucx_buffer_write(s.ptr, 1, s.length, buf);
128 152
129 s = S("<D:resourcetype />\n"); 153 s = S("<D:resourcetype />\n");
130 ucx_buffer_write(s.ptr, 1, s.length, buf); 154 ucx_buffer_write(s.ptr, 1, s.length, buf);
131 155
156 // crypto properties
157 if(DAV_CRYPTO(sn)) {
158 if(add_crypto_name) {
159 ucx_buffer_putc(buf, '<');
160 ucx_buffer_puts(buf, crypto_ns);
161 s = S(":crypto-name />\n");
162 ucx_buffer_write(s.ptr, 1, s.length, buf);
163 }
164 if(add_crypto_key) {
165 ucx_buffer_putc(buf, '<');
166 ucx_buffer_puts(buf, crypto_ns);
167 s = S(":crypto-key />\n");
168 ucx_buffer_write(s.ptr, 1, s.length, buf);
169 }
170 }
171
132 // extra properties 172 // extra properties
133 UCX_FOREACH(elm, properties) { 173 UCX_FOREACH(elm, properties) {
134 DavProperty *prop = elm->data; 174 DavProperty *prop = elm->data;
135 s = S("<"); 175 s = S("<");
136 ucx_buffer_write(s.ptr, 1, s.length, buf); 176 ucx_buffer_write(s.ptr, 1, s.length, buf);
149 ucx_buffer_write(s.ptr, 1, s.length, buf); 189 ucx_buffer_write(s.ptr, 1, s.length, buf);
150 190
151 return buf; 191 return buf;
152 } 192 }
153 193
194 UcxBuffer* create_basic_propfind_request() {
195 UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0);
196 sstr_t s;
197
198 s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
199 ucx_buffer_write(s.ptr, 1, s.length, buf);
200
201 s = S("<D:propfind xmlns:D=\"DAV:\" xmlns:i=\"");
202 ucx_buffer_write(s.ptr, 1, s.length, buf);
203 s = S(DAV_NS);
204 ucx_buffer_write(s.ptr, 1, s.length, buf);
205 s = S("\" >\n");
206 ucx_buffer_write(s.ptr, 1, s.length, buf);
207
208 // properties
209 s = S("<D:prop>\n");
210 ucx_buffer_write(s.ptr, 1, s.length, buf);
211 s = S("<D:resourcetype />\n");
212 ucx_buffer_write(s.ptr, 1, s.length, buf);
213 s = S("<i:crypto-key />\n");
214 ucx_buffer_write(s.ptr, 1, s.length, buf);
215 s = S("<i:crypto-name />\n");
216 ucx_buffer_write(s.ptr, 1, s.length, buf);
217 s = S("</D:prop>\n");
218 ucx_buffer_write(s.ptr, 1, s.length, buf);
219
220 // end
221 s = S("</D:propfind>\n");
222 ucx_buffer_write(s.ptr, 1, s.length, buf);
223
224 return buf;
225 }
226
154 DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response, DavQOp *cond, size_t len) { 227 DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response, DavQOp *cond, size_t len) {
155 char *url = NULL; 228 char *url = NULL;
156 curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &url); 229 curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &url);
157 if(!root) { 230 if(!root) {
158 root = dav_resource_new_href(sn, util_url_path(url)); 231 root = dav_resource_new_href(sn, util_url_path(url)); // TODO: remove
159 } 232 }
160 233
161 xmlDoc *doc = xmlReadMemory(response->space, response->size, url, NULL, 0); 234 xmlDoc *doc = xmlReadMemory(response->space, response->size, url, NULL, 0);
162 if(!doc) { 235 if(!doc) {
163 // TODO: free stuff 236 // TODO: free stuff
179 252
180 return root; 253 return root;
181 } 254 }
182 255
183 int parse_response_tag(DavResource *resource, xmlNode *node, DavQOp *cond, size_t clen) { 256 int parse_response_tag(DavResource *resource, xmlNode *node, DavQOp *cond, size_t clen) {
184 DavResource *res = resource; 257 DavSession *sn = resource->session;
258
259 //DavResource *res = resource;
260 DavResource *res = NULL;
261 char *href = NULL;
262 UcxList *properties = NULL; // xmlNode list
263 char *crypto_name = NULL; // name set by crypto-name property
264 char *crypto_key = NULL;
265
266 int iscollection = 0; // TODO: remove
267
185 node = node->children; 268 node = node->children;
186 while(node) { 269 while(node) {
187 if(node->type == XML_ELEMENT_NODE) { 270 if(node->type == XML_ELEMENT_NODE) {
188 if(xstreq(node->name, "href")) { 271 if(xstreq(node->name, "href")) {
189 xmlNode *href_node = node->children; 272 xmlNode *href_node = node->children;
190 if(href_node->type != XML_TEXT_NODE) { 273 if(href_node->type != XML_TEXT_NODE) {
191 // error 274 // error
192 resource->session->error = DAV_ERROR; 275 sn->error = DAV_ERROR;
193 return 1; 276 return 1;
194 } 277 }
195 char *href = (char*)href_node->content; 278 //char *href = (char*)href_node->content;
196 href = util_url_path(href); 279 href = util_url_path((char*)href_node->content);
197 if(xstreq(resource->href, href)) { 280 if(xstreq(resource->href, href)) {
198 res = resource; 281 res = resource;
199 } else { 282 } else {
200 res = dav_resource_new_href(resource->session, href); 283 //res = dav_resource_new_href(resource->session, href);
201 res->parent = resource; 284 //res->parent = resource;
202 } 285 }
203 } else if(xstreq(node->name, "propstat")) { 286 } else if(xstreq(node->name, "propstat")) {
204 xmlNode *n = node->children; 287 xmlNode *n = node->children;
205 xmlNode *prop_node = NULL; 288 xmlNode *prop_node = NULL;
206 int ok = 0; 289 int ok = 0;
210 if(xstreq(n->name, "prop")) { 293 if(xstreq(n->name, "prop")) {
211 prop_node = n; 294 prop_node = n;
212 } else if(xstreq(n->name, "status")) { 295 } else if(xstreq(n->name, "status")) {
213 xmlNode *status_node = n->children; 296 xmlNode *status_node = n->children;
214 if(status_node->type != XML_TEXT_NODE) { 297 if(status_node->type != XML_TEXT_NODE) {
215 resource->session->error = DAV_ERROR; 298 sn->error = DAV_ERROR;
216 return 1; 299 return 1;
217 } 300 }
218 sstr_t status_str = sstr((char*)status_node->content); 301 sstr_t status_str = sstr((char*)status_node->content);
219 if(status_str.length < 13) { 302 if(status_str.length < 13) {
220 resource->session->error = DAV_ERROR; 303 sn->error = DAV_ERROR;
221 return 1; 304 return 1;
222 } 305 }
223 status_str = sstrsubsl(status_str, 9, 3); 306 status_str = sstrsubsl(status_str, 9, 3);
224 if(!sstrcmp(status_str, S("200"))) { 307 if(!sstrcmp(status_str, S("200"))) {
225 ok = 1; 308 ok = 1;
231 // if status is ok, get all properties 314 // if status is ok, get all properties
232 if(ok) { 315 if(ok) {
233 n = prop_node->children; 316 n = prop_node->children;
234 while(n) { 317 while(n) {
235 if(n->type == XML_ELEMENT_NODE) { 318 if(n->type == XML_ELEMENT_NODE) {
319 properties = ucx_list_append(properties, n);
236 if(xstreq(n->name, "resourcetype")) { 320 if(xstreq(n->name, "resourcetype")) {
237 xmlNode *rsnode = n->children; 321 xmlNode *rsnode = n->children;
238 if(rsnode && rsnode->type == XML_ELEMENT_NODE) { 322 if(rsnode && rsnode->type == XML_ELEMENT_NODE) {
239 // TODO: this is a ugly lazy hack 323 // TODO: this is a ugly lazy hack
240 resource_add_property(res, "DAV:", (char*)n->name, "collection"); 324 //resource_add_property(res, "DAV:", (char*)n->name, "collection");
241 res->iscollection = 1; 325 iscollection = 1;
242 } 326 }
243 } else { 327 } else if(xstreq(n->ns->href, DAV_NS)) {
244 xmlNode *content = n->children; 328 if(xstreq(n->name, "crypto-name")) {
245 if(content) { 329 crypto_name = util_xml_get_text(n);
246 resource_add_property( 330 } else if(xstreq(n->name, "crypto-key")) {
247 res, 331 crypto_key = util_xml_get_text(n);
248 (char*)n->ns->href,
249 (char*)n->name,
250 (char*)content->content);
251 } 332 }
252 } 333 }
253 } 334 }
254 n = n->next; 335 n = n->next;
255 } 336 }
256 } 337 }
257 } 338 }
258 } 339 }
259 340
260 node = node->next; 341 node = node->next;
342 }
343
344 if(!res) {
345 // create new resource object
346 char *name = NULL;
347 if(DAV_DECRYPT_NAME(sn) && crypto_name) {
348 if(!crypto_key) {
349 // TODO: error
350 fprintf(stderr, "encrypted resource without key\n");
351 }
352 name = util_decrypt_str(sn, crypto_name, crypto_key);
353 if(!name) {
354 // TODO: error
355 fprintf(stderr, "decrypted name is null\n");
356 }
357 } else {
358 name = util_resource_name(href);
359 }
360
361 href = dav_session_strdup(sn, href);
362 res = dav_resource_new_full(sn, resource->path, name, href);
363 }
364 res->iscollection = iscollection;
365
366 // add properties
367 UCX_FOREACH(elm, properties) {
368 xmlNode *prop = elm->data;
369
370 // TODO: add xml data instead of a string
371 char *text = util_xml_get_text(prop);
372 if(text) {
373 resource_add_property(res, (char*)prop->ns->href, (char*)prop->name, text);
374 }
261 } 375 }
262 376
263 set_davprops(res); 377 set_davprops(res);
264 if(res != resource) { 378 if(res != resource) {
265 if(clen > 0) { 379 if(clen > 0) {
434 ucx_buffer_write(s.ptr, 1, s.length, buf); 548 ucx_buffer_write(s.ptr, 1, s.length, buf);
435 549
436 return buf; 550 return buf;
437 } 551 }
438 552
553 UcxBuffer* create_crypto_proppatch_request(DavSession *sn, DavKey *key, char *name) {
554 UcxBuffer *buf = ucx_buffer_new(NULL, 512, 0);
555 sstr_t s;
556
557 s = S("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
558 ucx_buffer_write(s.ptr, 1, s.length, buf);
559
560 s = S("<D:propertyupdate xmlns:D=\"DAV:\" xmlns:idav=\"" DAV_NS "\">\n");
561 ucx_buffer_write(s.ptr, 1, s.length, buf);
562
563 s = S("<D:set>\n<D:prop>\n");
564 ucx_buffer_write(s.ptr, 1, s.length, buf);
565
566 if(DAV_ENCRYPT_NAME(sn)) {
567 s = S("<idav:crypto-name>");
568 ucx_buffer_write(s.ptr, 1, s.length, buf);
569 char *crname = aes_encrypt(name, key);
570 ucx_buffer_puts(buf, crname);
571 free(crname);
572 s = S("</idav:crypto-name>\n");
573 ucx_buffer_write(s.ptr, 1, s.length, buf);
574 }
575
576 s = S("<idav:crypto-key>");
577 ucx_buffer_write(s.ptr, 1, s.length, buf);
578 ucx_buffer_puts(buf, key->name);
579 s = S("</idav:crypto-key>\n");
580 ucx_buffer_write(s.ptr, 1, s.length, buf);
581
582 s = S("</D:prop>\n</D:set>\n</D:propertyupdate>\n");
583 ucx_buffer_write(s.ptr, 1, s.length, buf);
584
585 return buf;
586 }
587
439 /* ----------------------------- PUT ----------------------------- */ 588 /* ----------------------------- PUT ----------------------------- */
440 589
441 static size_t dummy_write(void *buf, size_t s, size_t n, void *data) { 590 static size_t dummy_write(void *buf, size_t s, size_t n, void *data) {
442 return s*n; 591 return s*n;
443 } 592 }
445 CURLcode do_put_request(CURL *handle, void *data, dav_read_func read_func, size_t length) { 594 CURLcode do_put_request(CURL *handle, void *data, dav_read_func read_func, size_t length) {
446 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, NULL); 595 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, NULL);
447 curl_easy_setopt(handle, CURLOPT_PUT, 1L); 596 curl_easy_setopt(handle, CURLOPT_PUT, 1L);
448 curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L); 597 curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
449 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); 598 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
599
600 // clear headers
601 struct curl_slist *headers = NULL;
602 curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
450 603
451 UcxBuffer *buf = NULL; 604 UcxBuffer *buf = NULL;
452 if(!read_func) { 605 if(!read_func) {
453 buf = ucx_buffer_new(data, length, 0); 606 buf = ucx_buffer_new(data, length, 0);
454 buf->size = length; 607 buf->size = length;
476 } 629 }
477 return ret; 630 return ret;
478 } 631 }
479 632
480 CURLcode do_delete_request(CURL *handle, UcxBuffer *response) { 633 CURLcode do_delete_request(CURL *handle, UcxBuffer *response) {
634 struct curl_slist *headers = NULL;
635 curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
636
481 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "DELETE"); 637 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "DELETE");
482 curl_easy_setopt(handle, CURLOPT_PUT, 0L); 638 curl_easy_setopt(handle, CURLOPT_PUT, 0L);
483 curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L); 639 curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L);
484 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); 640 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
485 641
489 CURLcode ret = curl_easy_perform(handle); 645 CURLcode ret = curl_easy_perform(handle);
490 return ret; 646 return ret;
491 } 647 }
492 648
493 CURLcode do_mkcol_request(CURL *handle) { 649 CURLcode do_mkcol_request(CURL *handle) {
650 struct curl_slist *headers = NULL;
651 curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
652
494 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MKCOL"); 653 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MKCOL");
495 curl_easy_setopt(handle, CURLOPT_PUT, 0L); 654 curl_easy_setopt(handle, CURLOPT_PUT, 0L);
496 curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L); 655 curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L);
497 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); 656 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
498 657

mercurial