src/server/webdav/operation.c

branch
webdav
changeset 241
4adad7faf452
parent 239
d5031c30022c
child 245
a193c42fc809
equal deleted inserted replaced
240:cd74667f6c85 241:4adad7faf452
35 35
36 #include "operation.h" 36 #include "operation.h"
37 37
38 #define WEBDAV_PATH_MAX 8192 38 #define WEBDAV_PATH_MAX 8192
39 39
40
41 size_t webdav_num_backends(WebdavBackend *dav) {
42 size_t count = 0;
43 while(dav) {
44 count++;
45 dav = dav->next;
46 }
47 return count;
48 }
49
40 /**************************************************************************** 50 /****************************************************************************
41 * 51 *
42 * PROPFIND OPERATION 52 * PROPFIND OPERATION
43 * 53 *
44 ****************************************************************************/ 54 ****************************************************************************/
365 op->dav = dav; 375 op->dav = dav;
366 op->sn = sn; 376 op->sn = sn;
367 op->rq = rq; 377 op->rq = rq;
368 op->reqprops = NULL; 378 op->reqprops = NULL;
369 op->response = response; 379 op->response = response;
380 op->proppatch = proppatch;
370 op->response_close = webdav_op_proppatch_close_resource; 381 op->response_close = webdav_op_proppatch_close_resource;
371 response->op = op; 382 response->op = op;
372 383
373 return op; 384 return op;
385 }
386
387
388
389 int webdav_op_proppatch(
390 WebdavOperation *op,
391 const char *href,
392 const char *path)
393 {
394 WebdavProppatchRequest *orig_request = op->proppatch;
395 UcxAllocator *a = session_get_allocator(op->sn);
396
397 // create WebdavResource object for the requested resource
398 WebdavResource *resource = op->response->addresource(op->response, href);
399 if(!resource) {
400 return REQ_ABORTED;
401 }
402
403 VFSContext *ctx = NULL;
404 VFSFile *file = NULL;
405
406 // requests for each backends
407 WebdavProppatchRequest **requests = pool_calloc(
408 op->sn->pool,
409 webdav_num_backends(op->dav),
410 sizeof(WebdavProppatchRequest*));
411 if(requests == NULL) {
412 return REQ_ABORTED;
413 }
414
415 WebdavPList *prev_set = orig_request->set;
416 WebdavPList *prev_remove = orig_request->remove;
417 size_t set_count = orig_request->setcount;
418 size_t remove_count = orig_request->removecount;
419
420 int ret = REQ_PROCEED;
421
422 // iterate backends and execute proppatch_do
423 WebdavBackend *dav = op->dav;
424 size_t numrequests = 0;
425 while(dav) {
426 WebdavPList *set = webdav_plist_clone_s(
427 op->sn->pool,
428 prev_set,
429 &set_count);
430 WebdavPList *remove = webdav_plist_clone_s(
431 op->sn->pool,
432 prev_remove,
433 &remove_count);
434 if((prev_set && !set) || (prev_remove && !remove)) {
435 // clone failed, OOM
436 ret = REQ_ABORTED;
437 break;
438 }
439
440 // create new WebdavProppatchRequest object for this backend
441 WebdavProppatchRequest *req = pool_malloc(
442 op->sn->pool,
443 sizeof(WebdavProppatchRequest));
444 memcpy(req, orig_request, sizeof(WebdavProppatchRequest));
445 req->set = set;
446 req->setcount = set_count;
447 req->remove = remove;
448 req->removecount = remove_count;
449 req->userdata = NULL;
450
451 // check if we need to open the file because the backend want's it
452 if(!file && (dav->settings & WS_WEBDAV_PROPPATCH_USE_VFS)
453 == WS_WEBDAV_PROPPATCH_USE_VFS)
454 {
455 ctx = vfs_request_context(op->sn, op->rq);
456 if(!ctx) {
457 ret = REQ_ABORTED;
458 break;
459 }
460
461 file = vfs_open(ctx, path, O_RDONLY);
462 if(!file) {
463 protocol_status(
464 op->sn,
465 op->rq,
466 util_errno2status(ctx->vfs_errno),
467 NULL);
468 ret = REQ_ABORTED;
469 }
470 }
471
472 // execute proppatch_do
473 if(dav->proppatch_do(req, resource, file, &set, &remove)) {
474 // return later, because we need do execute proppatch_finish
475 // for all successfully called backends
476 ret = REQ_ABORTED;
477 break;
478 }
479
480 // proppatch_do should remove all handled props from set and remove
481 // in the next iteration, the backend must use these reduced lists
482 prev_set = set;
483 prev_remove = remove;
484
485 requests[numrequests++] = req;
486
487 // continue with next backend
488 dav = dav->next;
489 }
490
491 WSBool commit = FALSE;
492 if(ret == REQ_PROCEED && resource->err == 0) {
493 // no errors, no properties with errors -> save the changes
494 commit = TRUE;
495 }
496
497 // call proppatch_finish for each successfully called proppatch_do
498 dav = op->dav;
499 int i = 0;
500 while(dav && i < numrequests) {
501 if(dav->proppatch_finish(requests[i], resource, file, commit)) {
502 ret = REQ_ABORTED;
503 }
504 i++;
505 dav = dav->next;
506 }
507
508 if(file) {
509 vfs_close(file);
510 }
511
512 if(resource->close(resource)) {
513 ret = REQ_ABORTED;
514 }
515
516 return ret;
374 } 517 }
375 518
376 int webdav_op_proppatch_close_resource( 519 int webdav_op_proppatch_close_resource(
377 WebdavOperation *op, 520 WebdavOperation *op,
378 WebdavResource *resource) 521 WebdavResource *resource)
379 { 522 {
380 return 0; 523 return 0; // NOP
381 } 524 }
382 525

mercurial