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 |