32 #include <libxml/tree.h> |
32 #include <libxml/tree.h> |
33 |
33 |
34 #include "utils.h" |
34 #include "utils.h" |
35 #include "methods.h" |
35 #include "methods.h" |
36 #include "davql.h" |
36 #include "davql.h" |
|
37 #include "crypto.h" |
37 #include "ucx/buffer.h" |
38 #include "ucx/buffer.h" |
38 #include "ucx/utils.h" |
39 #include "ucx/utils.h" |
39 |
40 |
40 #include "resource.h" |
41 #include "resource.h" |
41 |
42 |
42 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) |
43 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) |
43 |
44 |
44 DavResource* dav_resource_new(DavSession *sn, char *path) { |
45 DavResource* dav_resource_new(DavSession *sn, char *path) { |
45 char *url = util_concat_path(sn->base_url, path); |
46 int plen = 0; |
|
47 char *url = util_path_to_url(sn, path); |
46 char *href = util_url_path(url); |
48 char *href = util_url_path(url); |
47 DavResource *res = dav_resource_new_href(sn, href); |
49 DavResource *res = dav_resource_new_href(sn, href); |
48 free(url); |
50 free(url); |
49 return res; |
51 return res; |
50 } |
52 } |
51 |
53 |
52 |
54 |
53 DavResource* dav_resource_new_href(DavSession *sn, char *href) { |
55 DavResource* dav_resource_new_href(DavSession *sn, char *href) { |
54 UcxMempool *mp = sn->mp; |
56 DavResource *res = ucx_mempool_calloc(sn->mp, 1, sizeof(DavResource)); |
55 UcxAllocator *a = sn->allocator; |
|
56 |
|
57 DavResource *res = ucx_mempool_calloc(mp, 1, sizeof(DavResource)); |
|
58 res->session = sn; |
57 res->session = sn; |
59 |
58 |
60 // set name, path and href |
59 // set name, path and href |
61 resource_set_info(res, href); |
60 resource_set_info(res, href); |
62 |
61 |
73 sstr_t href = sstr(href_str); |
72 sstr_t href = sstr(href_str); |
74 |
73 |
75 sstr_t base_href = sstr(util_url_path(res->session->base_url)); |
74 sstr_t base_href = sstr(util_url_path(res->session->base_url)); |
76 sstr_t path = sstrsubs(href, base_href.length - 1); |
75 sstr_t path = sstrsubs(href, base_href.length - 1); |
77 |
76 |
78 UcxAllocator *a = res->session->allocator; |
77 UcxAllocator *a = res->session->mp->allocator; |
79 res->name = sstrdup_a(a, name).ptr; |
78 CURL *handle = res->session->handle; |
|
79 |
|
80 int nlen = 0; |
|
81 char *uname = curl_easy_unescape(handle, name.ptr, name.length , &nlen); |
|
82 int plen = 0; |
|
83 char *upath = curl_easy_unescape(handle, path.ptr, path.length, &plen); |
|
84 |
|
85 res->name = sstrdup_a(a, sstrn(uname, nlen)).ptr; |
80 res->href = sstrdup_a(a, href).ptr; |
86 res->href = sstrdup_a(a, href).ptr; |
81 res->path = sstrdup_a(a, path).ptr; |
87 res->path = sstrdup_a(a, sstrn(upath, plen)).ptr; |
|
88 |
|
89 curl_free(uname); |
|
90 curl_free(upath); |
82 } |
91 } |
83 |
92 |
84 DavResourceData* resource_data_new(DavSession *sn) { |
93 DavResourceData* resource_data_new(DavSession *sn) { |
85 DavResourceData *data = ucx_mempool_malloc( |
94 DavResourceData *data = ucx_mempool_malloc( |
86 sn->mp, |
95 sn->mp, |
87 sizeof(DavResourceData)); |
96 sizeof(DavResourceData)); |
88 if(!data) { |
97 if(!data) { |
89 return NULL; |
98 return NULL; |
90 } |
99 } |
91 data->properties = ucx_map_new_a(sn->allocator, 32); |
100 data->properties = ucx_map_new_a(sn->mp->allocator, 32); |
92 data->set = NULL; |
101 data->set = NULL; |
93 data->remove = NULL; |
102 data->remove = NULL; |
94 data->content = NULL; |
103 data->content = NULL; |
95 data->read = NULL; |
104 data->read = NULL; |
96 data->length = 0; |
105 data->length = 0; |
99 |
108 |
100 void resource_add_property(DavResource *res, char *ns, char *name, char *val) { |
109 void resource_add_property(DavResource *res, char *ns, char *name, char *val) { |
101 if(!val) { |
110 if(!val) { |
102 return; |
111 return; |
103 } |
112 } |
104 UcxAllocator *a = res->session->allocator; |
|
105 |
113 |
106 UcxKey key = dav_property_key(ns, name); |
114 UcxKey key = dav_property_key(ns, name); |
107 sstr_t v = sstrdup_a(a, sstr(val)); |
115 sstr_t v = sstrdup_a(res->session->mp->allocator, sstr(val)); |
108 ucx_map_put(((DavResourceData*)res->data)->properties, key, v.ptr); |
116 ucx_map_put(((DavResourceData*)res->data)->properties, key, v.ptr); |
109 free(key.data); |
117 free(key.data); |
110 } |
118 } |
111 |
119 |
112 char* resource_get_property(DavResource *res, char *ns, char *name) { |
120 char* resource_get_property(DavResource *res, char *ns, char *name) { |
187 dav_get_property_namespace(res->session->context, name, &pns, &pname); |
195 dav_get_property_namespace(res->session->context, name, &pns, &pname); |
188 dav_set_property_ns(res, pns, pname, value); |
196 dav_set_property_ns(res, pns, pname, value); |
189 } |
197 } |
190 |
198 |
191 void dav_set_property_ns(DavResource *res, char *ns, char *name, char *value) { |
199 void dav_set_property_ns(DavResource *res, char *ns, char *name, char *value) { |
192 UcxAllocator *a = res->session->allocator; |
200 UcxAllocator *a = res->session->mp->allocator; |
193 DavResourceData *data = res->data; |
201 DavResourceData *data = res->data; |
194 |
202 |
195 DavProperty *property = a->malloc(a->pool, sizeof(DavProperty)); |
203 DavProperty *property = dav_session_malloc( |
|
204 res->session, |
|
205 sizeof(DavProperty)); |
196 property->name = sstrdup_a(a, sstr(name)).ptr; |
206 property->name = sstrdup_a(a, sstr(name)).ptr; |
197 property->value = sstrdup_a(a, sstr(value)).ptr; |
207 property->value = sstrdup_a(a, sstr(value)).ptr; |
198 DavNamespace *namespace = a->malloc(a->pool, sizeof(DavNamespace)); |
208 |
|
209 DavNamespace *namespace = dav_session_malloc( |
|
210 res->session, |
|
211 sizeof(DavNamespace)); |
199 namespace->prefix = NULL; |
212 namespace->prefix = NULL; |
200 namespace->name = sstrdup_a(a, sstr(ns)).ptr; |
213 namespace->name = sstrdup_a(a, sstr(ns)).ptr; |
201 property->ns = namespace; |
214 property->ns = namespace; |
202 |
215 |
203 data->set = ucx_list_append_a(a, data->set, property); |
216 data->set = ucx_list_append_a(a, data->set, property); |
209 dav_get_property_namespace(res->session->context, name, &pns, &pname); |
222 dav_get_property_namespace(res->session->context, name, &pns, &pname); |
210 dav_remove_property_ns(res, pns, pname); |
223 dav_remove_property_ns(res, pns, pname); |
211 } |
224 } |
212 |
225 |
213 void dav_remove_property_ns(DavResource *res, char *ns, char *name) { |
226 void dav_remove_property_ns(DavResource *res, char *ns, char *name) { |
214 UcxAllocator *a = res->session->allocator; |
|
215 DavResourceData *data = res->data; |
227 DavResourceData *data = res->data; |
216 |
228 UcxAllocator *a = res->session->mp->allocator; |
217 DavProperty *property = a->malloc(a->pool, sizeof(DavProperty)); |
229 |
|
230 DavProperty *property = dav_session_malloc( |
|
231 res->session, |
|
232 sizeof(DavProperty)); |
218 property->name = sstrdup_a(a, sstr(name)).ptr; |
233 property->name = sstrdup_a(a, sstr(name)).ptr; |
219 property->value = NULL; |
234 property->value = NULL; |
220 DavNamespace *namespace = a->malloc(a->pool, sizeof(DavNamespace)); |
235 |
|
236 DavNamespace *namespace = dav_session_malloc( |
|
237 res->session, |
|
238 sizeof(DavNamespace)); |
221 namespace->prefix = NULL; |
239 namespace->prefix = NULL; |
222 namespace->name = sstrdup_a(a, sstr(ns)).ptr; |
240 namespace->name = sstrdup_a(a, sstr(ns)).ptr; |
223 property->ns = namespace; |
241 property->ns = namespace; |
224 |
242 |
225 data->remove = ucx_list_append_a(a, data->remove, property); |
243 data->remove = ucx_list_append_a(a, data->remove, property); |
226 } |
244 } |
227 |
245 |
228 |
246 |
229 void dav_set_content(DavResource *res, void *stream, dav_read_func read_func) { |
247 void dav_set_content(DavResource *res, void *stream, dav_read_func read_func) { |
230 DavResourceData *data = res->data; |
248 DavSession *sn = res->session; |
231 data->content = stream; |
249 if((sn->flags & DAV_SESSION_ENCRYPT_FILE) == DAV_SESSION_ENCRYPT_FILE) { |
232 data->read = read_func; |
250 AESEncrypter *enc = aes_encrypter_new(sn->key, stream, read_func); |
233 data->length = 0; |
251 DavResourceData *data = res->data; |
|
252 data->content = enc; |
|
253 data->read = (dav_read_func)aes_read; |
|
254 data->length = 0; |
|
255 dav_set_property_ns( |
|
256 res, |
|
257 "http://www.uap-core.de/", |
|
258 "crypto-key", |
|
259 sn->key->name); |
|
260 } else { |
|
261 DavResourceData *data = res->data; |
|
262 data->content = stream; |
|
263 data->read = read_func; |
|
264 data->length = 0; |
|
265 } |
234 } |
266 } |
235 |
267 |
236 void dav_set_content_data(DavResource *res, char *content, size_t length) { |
268 void dav_set_content_data(DavResource *res, char *content, size_t length) { |
237 DavSession *sn = res->session; |
269 DavSession *sn = res->session; |
238 DavResourceData *data = res->data; |
270 DavResourceData *data = res->data; |
251 UcxMapIterator i = ucx_map_iterator(data->properties); |
283 UcxMapIterator i = ucx_map_iterator(data->properties); |
252 UCX_MAP_FOREACH(key, value, i) { |
284 UCX_MAP_FOREACH(key, value, i) { |
253 ucx_map_remove(data->properties, key); |
285 ucx_map_remove(data->properties, key); |
254 } |
286 } |
255 |
287 |
256 char *url = util_concat_path(sn->base_url, res->path); |
288 util_set_url(sn, res->path); |
257 |
|
258 CURL *handle = sn->handle; |
|
259 curl_easy_setopt(handle, CURLOPT_URL, url); |
|
260 free(url); |
|
261 |
289 |
262 UcxBuffer *rqbuf = create_allprop_propfind_request(); |
290 UcxBuffer *rqbuf = create_allprop_propfind_request(); |
263 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
291 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
264 |
292 |
265 //fwrite(rpbuf->space, 1, rpbuf->size, stdout); |
293 //fwrite(rpbuf->space, 1, rpbuf->size, stdout); |
266 //printf("\n"); |
294 //printf("\n"); |
267 |
295 |
268 CURLcode ret = do_propfind_request(handle, rqbuf, rpbuf); |
296 CURLcode ret = do_propfind_request(sn->handle, rqbuf, rpbuf); |
269 int status = 0; |
297 int status = 0; |
270 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
298 curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &status); |
271 if(ret == CURLE_OK) { |
299 if(ret == CURLE_OK) { |
272 //printf("response\n%s\n", rpbuf->space); |
300 //printf("response\n%s\n", rpbuf->space); |
273 // TODO: use parse_propfind_response() |
301 // TODO: use parse_propfind_response() |
274 xmlDoc *doc = xmlReadMemory(rpbuf->space, rpbuf->size, url, NULL, 0); |
302 xmlDoc *doc = xmlReadMemory(rpbuf->space, rpbuf->size, NULL, NULL, 0); |
275 if(!doc) { |
303 if(!doc) { |
276 return 1; |
304 return 1; |
277 } |
305 } |
278 |
306 |
279 xmlNode *xml_root = xmlDocGetRootElement(doc); |
307 xmlNode *xml_root = xmlDocGetRootElement(doc); |
296 |
324 |
297 int dav_store(DavResource *res) { |
325 int dav_store(DavResource *res) { |
298 DavSession *sn = res->session; |
326 DavSession *sn = res->session; |
299 DavResourceData *data = res->data; |
327 DavResourceData *data = res->data; |
300 |
328 |
301 char *url = util_concat_path(sn->base_url, res->path); |
329 util_set_url(sn, res->path);; |
302 CURL *handle = res->session->handle; |
|
303 curl_easy_setopt(handle, CURLOPT_URL, url); |
|
304 free(url); |
|
305 |
330 |
306 // store content |
331 // store content |
307 if(data->content) { |
332 if(data->content) { |
308 CURLcode ret = do_put_request(handle, data->content, data->read, data->length); |
333 CURLcode ret = do_put_request(sn->handle, data->content, data->read, data->length); |
309 int status = 0; |
334 int status = 0; |
310 curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &status); |
335 curl_easy_getinfo(sn->handle, CURLINFO_RESPONSE_CODE, &status); |
311 if(ret == CURLE_OK && (status >= 200 && status < 300)) { |
336 if(ret == CURLE_OK && (status >= 200 && status < 300)) { |
312 res->session->error = 0; |
337 res->session->error = 0; |
313 // cleanup node data |
338 // cleanup node data |
314 if(!data->read) { |
339 if(!data->read) { |
315 ucx_mempool_free(sn->mp, data->content); |
340 ucx_mempool_free(sn->mp, data->content); |
326 // store properties |
351 // store properties |
327 if(data->set || data->remove) { |
352 if(data->set || data->remove) { |
328 UcxBuffer *request = create_proppatch_request(data); |
353 UcxBuffer *request = create_proppatch_request(data); |
329 UcxBuffer *response = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); |
354 UcxBuffer *response = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); |
330 |
355 |
331 CURLcode ret = do_proppatch_request(handle, request, response); |
356 CURLcode ret = do_proppatch_request(sn->handle, request, response); |
332 int status = 0; |
357 int status = 0; |
333 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
358 curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &status); |
334 if(ret == CURLE_OK && status == 207) { |
359 if(ret == CURLE_OK && status == 207) { |
335 //printf("%s\n", response->space); |
360 //printf("%s\n", response->space); |
336 // TODO: parse response |
361 // TODO: parse response |
337 // TODO: cleanup node data correctly |
362 // TODO: cleanup node data correctly |
338 data->set = NULL; |
363 data->set = NULL; |
345 sn->error = DAV_OK; |
370 sn->error = DAV_OK; |
346 return 0; |
371 return 0; |
347 } |
372 } |
348 |
373 |
349 int dav_get_content(DavResource *res, void *stream, dav_write_func write_fnc) { |
374 int dav_get_content(DavResource *res, void *stream, dav_write_func write_fnc) { |
350 char *url = util_concat_path(res->session->base_url, res->path); |
|
351 CURL *handle = res->session->handle; |
375 CURL *handle = res->session->handle; |
352 curl_easy_setopt(handle, CURLOPT_URL, url); |
376 util_set_url(res->session, res->path); |
353 free(url); |
|
354 |
377 |
355 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); |
378 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); |
356 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, NULL); |
379 curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, NULL); |
357 curl_easy_setopt(handle, CURLOPT_PUT, 0L); |
380 curl_easy_setopt(handle, CURLOPT_PUT, 0L); |
358 curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L); |
381 curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L); |
376 // TODO |
399 // TODO |
377 return NULL; |
400 return NULL; |
378 } |
401 } |
379 |
402 |
380 int dav_delete(DavResource *res) { |
403 int dav_delete(DavResource *res) { |
381 char *url = util_concat_path(res->session->base_url, res->path); |
|
382 CURL *handle = res->session->handle; |
404 CURL *handle = res->session->handle; |
383 curl_easy_setopt(handle, CURLOPT_URL, url); |
405 util_set_url(res->session, res->path); |
384 free(url); |
|
385 |
406 |
386 UcxBuffer *response = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
407 UcxBuffer *response = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
387 CURLcode ret = do_delete_request(handle, response); |
408 CURLcode ret = do_delete_request(handle, response); |
388 int status = 0; |
409 int status = 0; |
389 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
410 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
399 return 1; |
420 return 1; |
400 } |
421 } |
401 } |
422 } |
402 |
423 |
403 int dav_create(DavResource *res) { |
424 int dav_create(DavResource *res) { |
404 char *url = util_concat_path(res->session->base_url, res->path); |
425 //char *url = util_concat_path(res->session->base_url, res->path); |
405 char *parent = util_parent_path(res->path); |
426 char *parent = util_parent_path(res->path); |
406 |
427 |
407 DavSession *sn = res->session; |
428 DavSession *sn = res->session; |
408 DavResource *parent_res = dav_get(sn, parent, NULL); |
429 DavResource *parent_res = dav_get(sn, parent, NULL); |
409 if(!parent_res && sn->error == DAV_NOT_FOUND) { |
430 if(!parent_res && sn->error == DAV_NOT_FOUND) { |
453 status = 0; |
473 status = 0; |
454 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
474 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
455 if(ret == CURLE_OK && (status >= 200 && status < 300)) { |
475 if(ret == CURLE_OK && (status >= 200 && status < 300)) { |
456 //printf("response\n%s\n", rpbuf->space); |
476 //printf("response\n%s\n", rpbuf->space); |
457 // TODO: use parse_propfind_response() |
477 // TODO: use parse_propfind_response() |
458 xmlDoc *doc = xmlReadMemory(rpbuf->space, rpbuf->size, url, NULL, 0); |
478 xmlDoc *doc = xmlReadMemory(rpbuf->space, rpbuf->size, NULL, NULL, 0); |
459 if(!doc) { |
479 if(!doc) { |
460 return 1; |
480 return 1; |
461 } |
481 } |
462 |
482 |
463 xmlNode *xml_root = xmlDocGetRootElement(doc); |
483 xmlNode *xml_root = xmlDocGetRootElement(doc); |
479 } |
499 } |
480 } |
500 } |
481 |
501 |
482 int dav_exists(DavResource *res) { |
502 int dav_exists(DavResource *res) { |
483 DavSession *sn = res->session; |
503 DavSession *sn = res->session; |
484 char *url = util_concat_path(sn->base_url, res->path); |
|
485 CURL *handle = sn->handle; |
504 CURL *handle = sn->handle; |
486 curl_easy_setopt(handle, CURLOPT_URL, url); |
505 util_set_url(sn, res->path); |
487 free(url); |
|
488 |
506 |
489 CURLcode ret = do_head_request(handle); |
507 CURLcode ret = do_head_request(handle); |
490 int status = 0; |
508 int status = 0; |
491 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
509 curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); |
492 if(ret == CURLE_OK && (status >= 200 && status < 300)) { |
510 if(ret == CURLE_OK && (status >= 200 && status < 300)) { |