libidav/session.c

changeset 747
efbd59642577
parent 742
7e67689241fd
child 777
15006651a5d1
equal deleted inserted replaced
746:a569148841ff 747:efbd59642577
28 28
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <string.h> 31 #include <string.h>
32 32
33 #include <ucx/buffer.h> 33 #include <cx/buffer.h>
34 #include <ucx/utils.h> 34 #include <cx/utils.h>
35 #include <cx/basic_mempool.h>
36 #include <cx/hash_map.h>
35 37
36 #include "utils.h" 38 #include "utils.h"
37 #include "session.h" 39 #include "session.h"
38 #include "resource.h" 40 #include "resource.h"
39 #include "methods.h" 41 #include "methods.h"
40 42
41 DavSession* dav_session_new(DavContext *context, char *base_url) { 43 DavSession* dav_session_new(DavContext *context, char *base_url) {
42 if(!base_url) { 44 if(!base_url) {
43 return NULL; 45 return NULL;
44 } 46 }
45 sstr_t url = sstr(base_url); 47 cxstring url = cx_str(base_url);
46 if(url.length == 0) { 48 if(url.length == 0) {
47 return NULL; 49 return NULL;
48 } 50 }
49 DavSession *sn = malloc(sizeof(DavSession)); 51 DavSession *sn = malloc(sizeof(DavSession));
50 memset(sn, 0, sizeof(DavSession)); 52 memset(sn, 0, sizeof(DavSession));
51 sn->mp = ucx_mempool_new(DAV_SESSION_MEMPOOL_SIZE); 53 sn->mp = cxBasicMempoolCreate(DAV_SESSION_MEMPOOL_SIZE);
52 sn->pathcache = ucx_map_new_a(sn->mp->allocator, DAV_PATH_CACHE_SIZE); 54 sn->pathcache = cxHashMapCreate(sn->mp->allocator, CX_STORE_POINTERS, DAV_PATH_CACHE_SIZE);
53 sn->key = NULL; 55 sn->key = NULL;
54 sn->errorstr = NULL; 56 sn->errorstr = NULL;
55 sn->error = DAV_OK; 57 sn->error = DAV_OK;
56 sn->flags = 0; 58 sn->flags = 0;
57 59
58 dav_session_set_baseurl(sn, base_url); 60 dav_session_set_baseurl(sn, base_url);
59 61
60 sn->handle = curl_easy_init(); 62 sn->handle = curl_easy_init();
61 curl_easy_setopt(sn->handle, CURLOPT_FOLLOWLOCATION, 1L); 63 curl_easy_setopt(sn->handle, CURLOPT_FOLLOWLOCATION, 1L);
62 64
63 // create lock manager 65 // lock manager is created on-demand
64 DavLockManager *locks = ucx_mempool_malloc(sn->mp, sizeof(DavLockManager)); 66 sn->locks = NULL;
65 locks->resource_locks = ucx_map_new_a(sn->mp->allocator, 16);
66 locks->collection_locks = NULL;
67 sn->locks = locks;
68 67
69 // set proxy 68 // set proxy
70 DavProxy *proxy = sstrprefix(url, S("https")) ? context->https_proxy 69 DavProxy *proxy = cx_strprefix(url, CX_STR("https")) ? context->https_proxy
71 : context->http_proxy; 70 : context->http_proxy;
72 71
73 if (proxy->url) { 72 if (proxy->url) {
74 curl_easy_setopt(sn->handle, CURLOPT_PROXY, proxy->url); 73 curl_easy_setopt(sn->handle, CURLOPT_PROXY, proxy->url);
75 if (proxy->username) { 74 if (proxy->username) {
93 curl_easy_setopt(sn->handle, CURLOPT_DEFAULT_PROTOCOL, "http"); 92 curl_easy_setopt(sn->handle, CURLOPT_DEFAULT_PROTOCOL, "http");
94 #endif 93 #endif
95 curl_easy_setopt(sn->handle, CURLOPT_URL, base_url); 94 curl_easy_setopt(sn->handle, CURLOPT_URL, base_url);
96 95
97 // add to context 96 // add to context
98 context->sessions = ucx_list_append(context->sessions, sn); 97 cxListAdd(context->sessions, sn);
99 sn->context = context; 98 sn->context = context;
100 99
101 return sn; 100 return sn;
102 } 101 }
103 102
126 free(upwdbuf); 125 free(upwdbuf);
127 } 126 }
128 } 127 }
129 128
130 void dav_session_set_baseurl(DavSession *sn, char *base_url) { 129 void dav_session_set_baseurl(DavSession *sn, char *base_url) {
130 const CxAllocator *a = sn->mp->allocator;
131 if(sn->base_url) { 131 if(sn->base_url) {
132 ucx_mempool_free(sn->mp, sn->base_url); 132 cxFree(a, sn->base_url);
133 } 133 }
134 134
135 sstr_t url = sstr(base_url); 135 cxstring url = cx_str(base_url);
136 if(url.ptr[url.length - 1] == '/') { 136 if(url.ptr[url.length - 1] == '/') {
137 sstr_t url = sstrdup_a(sn->mp->allocator, sstr(base_url)); 137 cxmutstr url_m = cx_strdup_a(a, cx_str(base_url));
138 sn->base_url = url.ptr; 138 sn->base_url = url_m.ptr;
139 } else { 139 } else {
140 char *url_str = ucx_mempool_malloc(sn->mp, url.length + 2); 140 char *url_str = cxMalloc(a, url.length + 2);
141 memcpy(url_str, base_url, url.length); 141 memcpy(url_str, base_url, url.length);
142 url_str[url.length] = '/'; 142 url_str[url.length] = '/';
143 url_str[url.length + 1] = '\0'; 143 url_str[url.length + 1] = '\0';
144 sn->base_url = url_str; 144 sn->base_url = url_str;
145 } 145 }
168 168
169 CURLcode dav_session_curl_perform(DavSession *sn, long *status) { 169 CURLcode dav_session_curl_perform(DavSession *sn, long *status) {
170 return dav_session_curl_perform_buf(sn, NULL, NULL, status); 170 return dav_session_curl_perform_buf(sn, NULL, NULL, status);
171 } 171 }
172 172
173 CURLcode dav_session_curl_perform_buf(DavSession *sn, UcxBuffer *request, UcxBuffer *response, long *status) { 173 CURLcode dav_session_curl_perform_buf(DavSession *sn, CxBuffer *request, CxBuffer *response, long *status) {
174 CURLcode ret = curl_easy_perform(sn->handle); 174 CURLcode ret = curl_easy_perform(sn->handle);
175 long http_status; 175 long http_status;
176 curl_easy_getinfo(sn->handle, CURLINFO_RESPONSE_CODE, &http_status); 176 curl_easy_getinfo(sn->handle, CURLINFO_RESPONSE_CODE, &http_status);
177 if(ret == CURLE_OK && http_status == 401 && sn->auth_prompt) { 177 if(ret == CURLE_OK && http_status == 401 && sn->auth_prompt) {
178 if(!sn->auth_prompt(sn, sn->authprompt_userdata)) { 178 if(!sn->auth_prompt(sn, sn->authprompt_userdata)) {
179 if(request) { 179 if(request) {
180 ucx_buffer_seek(request, 0, SEEK_SET); 180 cxBufferSeek(request, 0, SEEK_SET);
181 } 181 }
182 if(response) { 182 if(response) {
183 ucx_buffer_seek(response, 0, SEEK_SET); 183 cxBufferSeek(response, 0, SEEK_SET);
184 } 184 }
185 ret = curl_easy_perform(sn->handle); 185 ret = curl_easy_perform(sn->handle);
186 curl_easy_getinfo(sn->handle, CURLINFO_RESPONSE_CODE, &http_status); 186 curl_easy_getinfo(sn->handle, CURLINFO_RESPONSE_CODE, &http_status);
187 } 187 }
188 } 188 }
272 sn->errorstr = errstr; 272 sn->errorstr = errstr;
273 } 273 }
274 274
275 void dav_session_destroy(DavSession *sn) { 275 void dav_session_destroy(DavSession *sn) {
276 // remove session from context 276 // remove session from context
277 UcxList *sessions = sn->context->sessions; 277 CxList *sessions = sn->context->sessions;
278 ssize_t i = ucx_list_find(sessions, sn, ucx_cmp_ptr, NULL); 278 ssize_t i = cxListFind(sessions, sn);
279 if(i >= 0) { 279 if(i >= 0) {
280 UcxList *elm = ucx_list_get(sessions, i); 280 cxListRemove(sessions, i);
281 if(elm) { 281 }
282 sn->context->sessions = ucx_list_remove(sessions, elm); 282
283 } 283 cxMempoolDestroy(sn->mp);
284 }
285
286 ucx_mempool_destroy(sn->mp);
287 curl_easy_cleanup(sn->handle); 284 curl_easy_cleanup(sn->handle);
288 free(sn); 285 free(sn);
289 } 286 }
290 287
291 288
292 void* dav_session_malloc(DavSession *sn, size_t size) { 289 void* dav_session_malloc(DavSession *sn, size_t size) {
293 return ucx_mempool_malloc(sn->mp, size); 290 return cxMalloc(sn->mp->allocator, size);
294 } 291 }
295 292
296 void* dav_session_calloc(DavSession *sn, size_t nelm, size_t size) { 293 void* dav_session_calloc(DavSession *sn, size_t nelm, size_t size) {
297 return ucx_mempool_calloc(sn->mp, nelm, size); 294 return cxCalloc(sn->mp->allocator, nelm, size);
298 } 295 }
299 296
300 void* dav_session_realloc(DavSession *sn, void *ptr, size_t size) { 297 void* dav_session_realloc(DavSession *sn, void *ptr, size_t size) {
301 return ucx_mempool_realloc(sn->mp, ptr, size); 298 return cxRealloc(sn->mp->allocator, ptr, size);
302 } 299 }
303 300
304 void dav_session_free(DavSession *sn, void *ptr) { 301 void dav_session_free(DavSession *sn, void *ptr) {
305 ucx_mempool_free(sn->mp, ptr); 302 cxFree(sn->mp->allocator, ptr);
306 } 303 }
307 304
308 char* dav_session_strdup(DavSession *sn, const char *str) { 305 char* dav_session_strdup(DavSession *sn, const char *str) {
309 return sstrdup_a(sn->mp->allocator, sstr((char*)str)).ptr; 306 return cx_strdup_a(sn->mp->allocator, cx_str((char*)str)).ptr;
310 } 307 }
311 308
312 309
313 char* dav_session_create_plain_href(DavSession *sn, char *path) { 310 char* dav_session_create_plain_href(DavSession *sn, const char *path) {
314 if(!DAV_ENCRYPT_NAME(sn) && !DAV_DECRYPT_NAME(sn)) { 311 if(!DAV_ENCRYPT_NAME(sn) && !DAV_DECRYPT_NAME(sn)) {
315 // non encrypted file names 312 // non encrypted file names
316 char *url = util_path_to_url(sn, path); 313 char *url = util_path_to_url(sn, path);
317 char *href = dav_session_strdup(sn, util_url_path(url)); 314 char *href = dav_session_strdup(sn, util_url_path(url));
318 free(url); 315 free(url);
320 } else { 317 } else {
321 return NULL; 318 return NULL;
322 } 319 }
323 } 320 }
324 321
325 char* dav_session_get_href(DavSession *sn, char *path) { 322 char* dav_session_get_href(DavSession *sn, const char *path) {
326 if(DAV_DECRYPT_NAME(sn) || DAV_ENCRYPT_NAME(sn)) { 323 if(DAV_DECRYPT_NAME(sn) || DAV_ENCRYPT_NAME(sn)) {
327 sstr_t p = sstr(path); 324 cxstring p = cx_str(path);
328 UcxBuffer *href = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); 325 CxBuffer href;
329 UcxBuffer *pbuf = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); 326 CxBuffer pbuf;
327 cxBufferInit(&href, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
328 cxBufferInit(&pbuf, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
329
330 int start = 0; 330 int start = 0;
331 int begin = 0; 331 int begin = 0;
332 332
333 // check path cache 333 // check path cache
334 char *cp = strdup(path); 334 char *cp = strdup(path);
335 //printf("cp: %s\n", cp); 335 //printf("cp: %s\n", cp);
336 while(strlen(cp) > 1) { 336 while(strlen(cp) > 1) {
337 char *cached = ucx_map_cstr_get(sn->pathcache, cp); 337 char *cached = cxMapGet(sn->pathcache, cx_hash_key_str(cp));
338 if(cached) { 338 if(cached) {
339 start = strlen(cp); 339 start = strlen(cp);
340 begin = start; 340 begin = start;
341 ucx_buffer_puts(href, cached); 341 cxBufferPutString(&href, cached);
342 break; 342 break;
343 } else { 343 } else {
344 // check, if the parent path is cached 344 // check, if the parent path is cached
345 char *f = cp; 345 char *f = cp;
346 cp = util_parent_path(cp); 346 cp = util_parent_path(cp);
347 free(f); 347 free(f);
348 } 348 }
349 } 349 }
350 free(cp); 350 free(cp);
351 if(href->pos == 0) { 351 if(href.pos == 0) {
352 // if there are no cached elements we have to add the base url path 352 // if there are no cached elements we have to add the base url path
353 // to the href buffer 353 // to the href buffer
354 ucx_buffer_puts(href, util_url_path(sn->base_url)); 354 cxBufferPutString(&href, util_url_path(sn->base_url));
355 } 355 }
356 356
357 // create resource for name lookup 357 // create resource for name lookup
358 sstr_t rp = sstrdup(sstrn(path, start)); 358 cxmutstr rp = cx_strdup(cx_strn(path, start));
359 DavResource *root = dav_resource_new(sn, rp.ptr); 359 DavResource *root = dav_resource_new(sn, rp.ptr);
360 free(rp.ptr); 360 free(rp.ptr);
361 resource_set_href(root, sstrn(href->space, href->pos)); 361 resource_set_href(root, cx_strn(href.space, href.pos));
362 362
363 // create request buffer for propfind requests 363 // create request buffer for propfind requests
364 UcxBuffer *rqbuf = create_basic_propfind_request(); 364 CxBuffer *rqbuf = create_basic_propfind_request();
365 365
366 sstr_t remaining = sstrsubs(p, start); 366 cxstring remaining = cx_strsubs(p, start);
367 ssize_t nelm = 0; 367 CxStrtokCtx elms = cx_strtok(remaining, CX_STR("/"), INT_MAX);
368 sstr_t *elms = sstrsplit(remaining, S("/"), &nelm);
369 DavResource *res = root; 368 DavResource *res = root;
370 ucx_buffer_puts(pbuf, res->path); 369 cxBufferPutString(&pbuf, res->path);
371 // iterate over all remaining path elements 370 // iterate over all remaining path elements
372 for(int i=0;i<nelm;i++) { 371 cxstring elm;
373 sstr_t elm = elms[i]; 372 while(cx_strtok_next(&elms, &elm)) {
374 if(elm.length > 0) { 373 if(elm.length > 0) {
375 //printf("elm: %.*s\n", elm.length, elm.ptr); 374 //printf("elm: %.*s\n", elm.length, elm.ptr);
376 DavResource *child = dav_find_child(sn, res, rqbuf, elm.ptr); 375 DavResource *child = dav_find_child(sn, res, rqbuf, elm.ptr);
377 376
378 // if necessary add a path separator 377 // if necessary add a path separator
379 if(pbuf->space[pbuf->pos-1] != '/') { 378 if(pbuf.space[pbuf.pos-1] != '/') {
380 if(href->space[href->pos-1] != '/') { 379 if(href.space[href.pos-1] != '/') {
381 ucx_buffer_putc(href, '/'); 380 cxBufferPut(&href, '/');
382 } 381 }
383 ucx_buffer_putc(pbuf, '/'); 382 cxBufferPut(&pbuf, '/');
384 } 383 }
385 // add last path/href to the cache 384 // add last path/href to the cache
386 sstr_t pp = sstrn(pbuf->space, pbuf->size); 385 cxstring pp = cx_strn(pbuf.space, pbuf.size);
387 sstr_t hh = sstrn(href->space, href->size); 386 cxstring hh = cx_strn(href.space, href.size);
388 dav_session_cache_path(sn, pp, hh); 387 dav_session_cache_path(sn, pp, hh);
389 388
390 ucx_buffer_write(elm.ptr, 1, elm.length, pbuf); 389 cxBufferWrite(elm.ptr, 1, elm.length, &pbuf);
391 if(child) { 390 if(child) {
392 // href is already URL encoded, so don't encode again 391 // href is already URL encoded, so don't encode again
393 ucx_buffer_puts(href, util_resource_name(child->href)); 392 cxBufferPutString(&href, util_resource_name(child->href));
394 res = child; 393 res = child;
395 } else if(DAV_ENCRYPT_NAME(sn)) { 394 } else if(DAV_ENCRYPT_NAME(sn)) {
396 char *random_name = util_random_str(); 395 char *random_name = util_random_str();
397 ucx_buffer_puts(href, random_name); 396 cxBufferPutString(&href, random_name);
398 free(random_name); 397 free(random_name);
399 } else { 398 } else {
400 // path is not URL encoded, so we have to do this here 399 // path is not URL encoded, so we have to do this here
401 scstr_t resname = scstr(util_resource_name(path)); 400 cxstring resname = cx_str(util_resource_name((const char*)path));
402 // the name of collections ends with 401 // the name of collections ends with
403 // a trailing slash, which MUST NOT be encoded 402 // a trailing slash, which MUST NOT be encoded
404 if(resname.ptr[resname.length-1] == '/') { 403 if(resname.ptr[resname.length-1] == '/') {
405 char *esc = curl_easy_escape(sn->handle, 404 char *esc = curl_easy_escape(sn->handle,
406 resname.ptr, resname.length-1); 405 resname.ptr, resname.length-1);
407 ucx_buffer_write(esc, 1, strlen(esc), href); 406 cxBufferWrite(esc, 1, strlen(esc), &href);
408 ucx_buffer_putc(href, '/'); 407 cxBufferPut(&href, '/');
409 curl_free(esc); 408 curl_free(esc);
410 } else { 409 } else {
411 char *esc = curl_easy_escape(sn->handle, 410 char *esc = curl_easy_escape(sn->handle,
412 resname.ptr, resname.length); 411 resname.ptr, resname.length);
413 ucx_buffer_write(esc, 1, strlen(esc), href); 412 cxBufferWrite(esc, 1, strlen(esc), &href);
414 curl_free(esc); 413 curl_free(esc);
415 } 414 }
416 } 415 }
417 } 416 }
418 417 }
419 // cleanup
420 free(elm.ptr);
421 }
422 free(elms);
423 418
424 // if necessary add a path separator 419 // if necessary add a path separator
425 if(p.ptr[p.length-1] == '/') { 420 if(p.ptr[p.length-1] == '/') {
426 if(href->space[href->pos-1] != '/') { 421 if(href.space[href.pos-1] != '/') {
427 ucx_buffer_putc(href, '/'); 422 cxBufferPut(&href, '/');
428 } 423 }
429 ucx_buffer_putc(pbuf, '/'); 424 cxBufferPut(&pbuf, '/');
430 } 425 }
431 // add the final path to the cache 426 // add the final path to the cache
432 sstr_t pp = sstrn(pbuf->space, pbuf->size); 427 cxstring pp = cx_strn(pbuf.space, pbuf.size);
433 sstr_t hh = sstrn(href->space, href->size); 428 cxstring hh = cx_strn(href.space, href.size);
434 dav_session_cache_path(sn, pp, hh); 429 dav_session_cache_path(sn, pp, hh);
435 430
436 sstr_t href_str = sstrdup_a( 431 cxmutstr href_str = cx_strdup_a(
437 sn->mp->allocator, 432 sn->mp->allocator,
438 sstrn(href->space, 433 cx_strn(href.space, href.size));
439 href->size));
440 434
441 // cleanup 435 // cleanup
442 dav_resource_free_all(root); 436 dav_resource_free_all(root);
443 ucx_buffer_free(rqbuf); 437 cxBufferFree(rqbuf);
444 ucx_buffer_free(pbuf); 438
445 ucx_buffer_free(href); 439 cxBufferDestroy(&pbuf);
440 cxBufferDestroy(&href);
446 441
447 return href_str.ptr; 442 return href_str.ptr;
448 } else { 443 } else {
449 return dav_session_create_plain_href(sn, path); 444 return dav_session_create_plain_href(sn, path);
450 } 445 }
451 } 446 }
452 447
453 DavResource* dav_find_child(DavSession *sn, DavResource *res, UcxBuffer *rqbuf, char *name) { 448 DavResource* dav_find_child(DavSession *sn, DavResource *res, CxBuffer *rqbuf, const char *name) {
454 if(res && !dav_propfind(sn, res, rqbuf)) { 449 if(res && !dav_propfind(sn, res, rqbuf)) {
455 DavResource *child = res->children; 450 DavResource *child = res->children;
456 while(child) { 451 while(child) {
457 if(!strcmp(child->name, name)) { 452 if(!strcmp(child->name, name)) {
458 return child; 453 return child;
461 } 456 }
462 } 457 }
463 return NULL; 458 return NULL;
464 } 459 }
465 460
466 void dav_session_cache_path(DavSession *sn, sstr_t path, sstr_t href) { 461 void dav_session_cache_path(DavSession *sn, cxstring path, cxstring href) {
467 char *elm = ucx_map_sstr_get(sn->pathcache, path); 462 CxHashKey path_key = cx_hash_key(path.ptr, path.length);
463 char *elm = cxMapGet(sn->pathcache, path_key);
468 if(!elm) { 464 if(!elm) {
469 href = sstrdup_a(sn->mp->allocator, href); 465 cxmutstr href_s = cx_strdup_a(sn->mp->allocator, href);
470 ucx_map_sstr_put(sn->pathcache, path, href.ptr); 466 cxMapPut(sn->pathcache, path_key, href_s.ptr);
471 } 467 }
472 } 468 }
473 469
474 470
475 DavLock* dav_create_lock(DavSession *sn, char *token, char *timeout) { 471 DavLock* dav_create_lock(DavSession *sn, const char *token, char *timeout) {
476 DavLock *lock = dav_session_malloc(sn, sizeof(DavLock)); 472 DavLock *lock = dav_session_malloc(sn, sizeof(DavLock));
477 lock->path = NULL; 473 lock->path = NULL;
478 lock->token = dav_session_strdup(sn, token); 474 lock->token = dav_session_strdup(sn, token);
479 475
480 // TODO: timeout 476 // TODO: timeout
488 dav_session_free(sn, lock->path); 484 dav_session_free(sn, lock->path);
489 } 485 }
490 dav_session_free(sn, lock); 486 dav_session_free(sn, lock);
491 } 487 }
492 488
493 int dav_add_resource_lock(DavSession *sn, char *path, DavLock *lock) { 489
490 static int dav_lock_cmp(void const *left, void const *right) {
491 const DavLock *l = left;
492 const DavLock *r = right;
493 return strcmp(l->path, r->path);
494 }
495
496 static int create_lock_manager(DavSession *sn) {
497 // create lock manager
498 DavLockManager *locks = cxMalloc(sn->mp->allocator, sizeof(DavLockManager));
499 locks->resource_locks = cxHashMapCreate(sn->mp->allocator, CX_STORE_POINTERS, 16);
500 locks->collection_locks = cxLinkedListCreate(sn->mp->allocator, dav_lock_cmp, CX_STORE_POINTERS);
501 sn->locks = locks;
502 return 0;
503 }
504
505 static DavLockManager* get_lock_manager(DavSession *sn) {
494 DavLockManager *locks = sn->locks; 506 DavLockManager *locks = sn->locks;
495 if(ucx_map_cstr_get(locks->resource_locks, path)) { 507 if(!locks) {
508 if(create_lock_manager(sn)) {
509 return NULL;
510 }
511 locks = sn->locks;
512 }
513 return locks;
514 }
515
516 int dav_add_resource_lock(DavSession *sn, const char *path, DavLock *lock) {
517 DavLockManager *locks = get_lock_manager(sn);
518 if(!locks) {
496 return -1; 519 return -1;
497 } 520 }
498 521
499 ucx_map_cstr_put(locks->resource_locks, path, lock); 522 CxHashKey path_key = cx_hash_key_str(path);
523 if(cxMapGet(locks->resource_locks, path_key)) {
524 return -1;
525 }
526
527 cxMapPut(locks->resource_locks, path_key, lock);
500 return 0; 528 return 0;
501 } 529 }
502 530
503 static void insert_lock(DavSession *sn, UcxList *elm, UcxList *newelm) { 531 int dav_add_collection_lock(DavSession *sn, const char *path, DavLock *lock) {
504 UcxList *next = elm->next; 532 DavLockManager *locks = get_lock_manager(sn);
505 if(next) { 533 if(!locks) {
506 next->prev = newelm; 534 return -1;
507 newelm->next = next; 535 }
508 } 536
509 newelm->prev = elm; 537 cxListAdd(locks->collection_locks, lock);
510 elm->next = newelm; 538 cxListSort(locks->collection_locks);
511 }
512
513 int dav_add_collection_lock(DavSession *sn, char *path, DavLock *lock) {
514 DavLockManager *locks = sn->locks;
515 if(!locks->collection_locks) {
516 locks->collection_locks = ucx_list_append_a(
517 sn->mp->allocator,
518 NULL,
519 lock);
520 lock->path = dav_session_strdup(sn, path);
521 return 0;
522 }
523
524 UcxList *elm = locks->collection_locks;
525 for(;;) {
526 DavLock *l = elm->data;
527 int cmp = strcmp(path, l->path);
528 if(cmp > 0) {
529 UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock);
530 lock->path = dav_session_strdup(sn, path);
531 insert_lock(sn, elm, newelm);
532 } else if(cmp == 0) {
533 return -1;
534 }
535
536 if(elm->next) {
537 elm = elm->next;
538 } else {
539 UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock);
540 lock->path = dav_session_strdup(sn, path);
541 ucx_list_concat(elm, newelm);
542 break;
543 }
544 }
545 539
546 return 0; 540 return 0;
547 } 541 }
548 542
549 DavLock* dav_get_lock(DavSession *sn, char *path) { 543 DavLock* dav_get_lock(DavSession *sn, const char *path) {
550 DavLockManager *locks = sn->locks; 544 DavLockManager *locks = get_lock_manager(sn);
551 545 if(!locks) {
552 DavLock *lock = ucx_map_cstr_get(locks->resource_locks, path); 546 return NULL;
547 }
548
549 cxstring p = cx_str(path);
550
551 DavLock *lock = cxMapGet(locks->resource_locks, cx_hash_key(p.ptr, p.length));
553 if(lock) { 552 if(lock) {
554 return lock; 553 return lock;
555 } 554 }
556 555
557 sstr_t p = sstr(path); 556 CxIterator i = cxListIterator(locks->collection_locks);
558 UCX_FOREACH(elm, locks->collection_locks) { 557 cx_foreach(DavLock*, cl, i) {
559 DavLock *cl = elm->data;
560 int cmd = strcmp(path, cl->path); 558 int cmd = strcmp(path, cl->path);
561 if(cmd == 0) { 559 if(cmd == 0) {
562 return cl; 560 return cl;
563 } else if(sstrprefix(p, sstr(cl->path))) { 561 } else if(cx_strprefix(p, cx_str(cl->path))) {
564 return cl; 562 return cl;
565 } else if(cmd > 0) { 563 } else if(cmd > 0) {
566 break; 564 break;
567 } 565 }
568 } 566 }
569 567
570 return NULL; 568 return NULL;
571 } 569 }
572 570
573 void dav_remove_lock(DavSession *sn, char *path, DavLock *lock) { 571 void dav_remove_lock(DavSession *sn, const char *path, DavLock *lock) {
574 DavLockManager *locks = sn->locks; 572 DavLockManager *locks = get_lock_manager(sn);
575 573 if(!locks) {
576 if(ucx_map_cstr_remove(locks->resource_locks, path)) {
577 return; 574 return;
578 } 575 }
579 576
580 UcxList *rm = NULL; 577 if(cxMapRemoveAndGet(locks->resource_locks, cx_hash_key_str(path))) {
581 UCX_FOREACH(elm, locks->collection_locks) { 578 return;
582 DavLock *cl = elm->data; 579 }
580
581 CxMutIterator i = cxListMutIterator(locks->collection_locks);
582 int rm = 0;
583 cx_foreach(DavLock* , cl, i) {
584 if(rm) {
585 break;
586 }
583 if(cl == lock) { 587 if(cl == lock) {
584 rm = elm; 588 cxIteratorFlagRemoval(i);
585 break; 589 rm = 1;
586 } 590 }
587 } 591 }
588 592 }
589 if(rm) {
590 locks->collection_locks = ucx_list_remove_a(
591 sn->mp->allocator,
592 locks->collection_locks,
593 rm);
594 }
595 }

mercurial