122 } |
122 } |
123 } |
123 } |
124 } |
124 } |
125 *error = DAVQL_OK; |
125 *error = DAVQL_OK; |
126 |
126 |
127 return sstrdup_a(a, sstrn(buf->space, buf->size)); |
127 sstr_t ret = sstrdup_a(a, sstrn(buf->space, buf->size)); |
|
128 ucx_buffer_free(buf); |
|
129 return ret; |
128 } |
130 } |
129 |
131 |
130 static int fl_add_properties(DavSession *sn, UcxMempool *mp, UcxMap *map, DavQLExpression *expression) { |
132 static int fl_add_properties(DavSession *sn, UcxMempool *mp, UcxMap *map, DavQLExpression *expression) { |
131 if(!expression) { |
133 if(!expression) { |
132 return 0; |
134 return 0; |
175 ucx_map_free(properties); |
177 ucx_map_free(properties); |
176 *isallprop = 1; |
178 *isallprop = 1; |
177 return create_allprop_propfind_request(); |
179 return create_allprop_propfind_request(); |
178 } else if(!sstrcmp(field->name, S("-"))) { |
180 } else if(!sstrcmp(field->name, S("-"))) { |
179 ucx_map_free(properties); |
181 ucx_map_free(properties); |
180 return create_basic_propfind_request(); |
182 return create_propfind_request(sn, NULL); |
181 } else { |
183 } else { |
182 if(fl_add_properties(sn, mp, properties, field->expr)) { |
184 if(fl_add_properties(sn, mp, properties, field->expr)) { |
183 // TODO: set error |
185 // TODO: set error |
|
186 ucx_map_free(properties); |
184 return NULL; |
187 return NULL; |
185 } |
188 } |
186 } |
189 } |
187 } |
190 } |
188 |
191 |
194 list = ucx_list_append(list, value); |
197 list = ucx_list_append(list, value); |
195 } |
198 } |
196 |
199 |
197 UcxBuffer *reqbuf = create_propfind_request(sn, list); |
200 UcxBuffer *reqbuf = create_propfind_request(sn, list); |
198 ucx_list_free(list); |
201 ucx_list_free(list); |
|
202 ucx_map_free(properties); |
199 return reqbuf; |
203 return reqbuf; |
200 } |
204 } |
201 |
205 |
202 static int reset_properties(DavSession *sn, DavResult *result, DavResource *res, UcxList *fields) { |
206 static int reset_properties(DavSession *sn, DavResult *result, DavResource *res, UcxList *fields) { |
203 UcxMap *new_properties = ucx_map_new_a(sn->mp->allocator, 32); |
207 UcxMap *new_properties = ucx_map_new_a(sn->mp->allocator, 32); |
269 } |
273 } |
270 } |
274 } |
271 if(str.ptr) { |
275 if(str.ptr) { |
272 UcxKey key = dav_property_key(field->ns, field->name); |
276 UcxKey key = dav_property_key(field->ns, field->name); |
273 ucx_map_put(new_properties, key, str.ptr); |
277 ucx_map_put(new_properties, key, str.ptr); |
|
278 free(key.data); |
274 } |
279 } |
275 } else { |
280 } else { |
276 // TODO: error |
281 // TODO: error |
277 resource_free_properties(sn, new_properties); |
282 resource_free_properties(sn, new_properties); |
278 return -1; |
283 return -1; |
314 UcxBuffer *rqbuf = fieldlist2propfindrequest(sn, mp, st->fields, &isallprop); |
319 UcxBuffer *rqbuf = fieldlist2propfindrequest(sn, mp, st->fields, &isallprop); |
315 if(!rqbuf) { |
320 if(!rqbuf) { |
316 ucx_mempool_destroy(mp); |
321 ucx_mempool_destroy(mp); |
317 return result; |
322 return result; |
318 } |
323 } |
|
324 ucx_mempool_reg_destr(mp, rqbuf, (ucx_destructor)ucx_buffer_free); |
319 |
325 |
320 // compile field list |
326 // compile field list |
321 UcxList *cfieldlist = NULL; |
327 UcxList *cfieldlist = NULL; |
322 UCX_FOREACH(elm, st->fields) { |
328 UCX_FOREACH(elm, st->fields) { |
323 DavQLField *field = elm->data; |
329 DavQLField *field = elm->data; |
357 // get path string |
364 // get path string |
358 davqlerror_t error; |
365 davqlerror_t error; |
359 sstr_t path = dav_format_string(mp->allocator, st->path, ap, &error); |
366 sstr_t path = dav_format_string(mp->allocator, st->path, ap, &error); |
360 if(error) { |
367 if(error) { |
361 // TODO: cleanup |
368 // TODO: cleanup |
|
369 ucx_mempool_destroy(mp); |
362 return result; |
370 return result; |
363 } |
371 } |
364 |
372 |
365 int depth = st->depth == DAV_DEPTH_PLACEHOLDER ? va_arg(ap, int) : st->depth; |
373 int depth = st->depth == DAV_DEPTH_PLACEHOLDER ? va_arg(ap, int) : st->depth; |
366 |
374 |
367 UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap); |
375 UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap); |
368 if(st->where && !where) { |
376 if(st->where && !where) { |
|
377 // TODO: cleanup |
369 ucx_mempool_destroy(mp); |
378 ucx_mempool_destroy(mp); |
370 return result; |
379 return result; |
371 } |
380 } |
|
381 ucx_mempool_reg_destr(mp, where, (ucx_destructor)ucx_buffer_free); |
372 |
382 |
373 // compile order criterion |
383 // compile order criterion |
374 UcxList *ordercr = NULL; |
384 UcxList *ordercr = NULL; |
375 UCX_FOREACH(elm, st->orderby) { |
385 UCX_FOREACH(elm, st->orderby) { |
376 DavQLOrderCriterion *oc = elm->data; |
386 DavQLOrderCriterion *oc = elm->data; |
395 cr->descending = oc->descending; |
405 cr->descending = oc->descending; |
396 ordercr = ucx_list_append_a(mp->allocator, ordercr, cr); |
406 ordercr = ucx_list_append_a(mp->allocator, ordercr, cr); |
397 } else { |
407 } else { |
398 // error |
408 // error |
399 // TODO: cleanup |
409 // TODO: cleanup |
|
410 ucx_mempool_destroy(mp); |
400 return result; |
411 return result; |
401 } |
412 } |
402 } else if(dav_identifier2resprop(column->srctext, &resprop)) { |
413 } else if(dav_identifier2resprop(column->srctext, &resprop)) { |
403 DavOrderCriterion *cr = ucx_mempool_malloc(mp, sizeof(DavOrderCriterion)); |
414 DavOrderCriterion *cr = ucx_mempool_malloc(mp, sizeof(DavOrderCriterion)); |
404 cr->type = 0; |
415 cr->type = 0; |
406 cr->descending = oc->descending; |
417 cr->descending = oc->descending; |
407 ordercr = ucx_list_append_a(mp->allocator, ordercr, cr); |
418 ordercr = ucx_list_append_a(mp->allocator, ordercr, cr); |
408 } else { |
419 } else { |
409 // error |
420 // error |
410 // TODO: cleanup |
421 // TODO: cleanup |
|
422 ucx_mempool_destroy(mp); |
411 return result; |
423 return result; |
412 } |
424 } |
413 |
425 |
414 } else if(column->type == DAVQL_NUMBER) { |
426 } else if(column->type == DAVQL_NUMBER) { |
415 // TODO: implement |
427 // TODO: implement |
416 fprintf(stderr, "order by number not supported\n"); |
428 fprintf(stderr, "order by number not supported\n"); |
417 return result; |
429 return result; |
418 } else { |
430 } else { |
419 // something is broken |
431 // something is broken |
420 // TODO: cleanup |
432 // TODO: cleanup |
|
433 ucx_mempool_destroy(mp); |
421 return result; |
434 return result; |
422 } |
435 } |
423 } |
436 } |
424 |
437 |
425 DavResource *selroot = dav_resource_new(sn, path.ptr); |
438 DavResource *selroot = dav_resource_new(sn, path.ptr); |
431 r->depth = 0; |
444 r->depth = 0; |
432 stack = ucx_list_prepend(stack, r); |
445 stack = ucx_list_prepend(stack, r); |
433 |
446 |
434 // reuseable response buffer |
447 // reuseable response buffer |
435 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
448 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
|
449 if(!rpbuf) { |
|
450 // TODO: cleanup |
|
451 ucx_mempool_destroy(mp); |
|
452 return result; |
|
453 } |
|
454 ucx_mempool_reg_destr(mp, rpbuf, (ucx_destructor)ucx_buffer_free); |
436 |
455 |
437 result.result = selroot; |
456 result.result = selroot; |
438 result.status = 0; |
457 result.status = 0; |
439 |
458 |
440 // do a propfind request for each resource on the stack |
459 // do a propfind request for each resource on the stack |
459 while((r = get_propfind_response(parser, &response)) != 0) { |
478 while((r = get_propfind_response(parser, &response)) != 0) { |
460 if(r == -1) { |
479 if(r == -1) { |
461 // error |
480 // error |
462 result.status = -1; |
481 result.status = -1; |
463 // TODO: free resources |
482 // TODO: free resources |
|
483 cleanup_response(&response); |
464 break; |
484 break; |
465 } |
485 } |
466 |
486 |
467 // the propfind multistatus response contains responses |
487 // the propfind multistatus response contains responses |
468 // for the requested resource and all childs |
488 // for the requested resource and all childs |
471 // response is the currently requested resource |
491 // response is the currently requested resource |
472 // and not a child |
492 // and not a child |
473 |
493 |
474 // add properties |
494 // add properties |
475 add_properties(root, &response); |
495 add_properties(root, &response); |
|
496 cleanup_response(&response); |
476 |
497 |
477 if(root == selroot) { |
498 if(root == selroot) { |
478 // The current root is the root of the select query. |
499 // The current root is the root of the select query. |
479 // In this case we have to check the where clause. |
500 // In this case we have to check the where clause. |
480 // If root is not selroot, the where clause was |
501 // If root is not selroot, the where clause was |
498 } else { |
519 } else { |
499 DavResource *child = response2resource( |
520 DavResource *child = response2resource( |
500 sn, |
521 sn, |
501 &response, |
522 &response, |
502 root->path); |
523 root->path); |
|
524 cleanup_response(&response); |
503 // check where clause |
525 // check where clause |
504 DavQLStackObj where_result; |
526 DavQLStackObj where_result; |
505 if(!dav_exec_expr(where, child, &where_result)) { |
527 if(!dav_exec_expr(where, child, &where_result)) { |
506 if(where_result.data.integer != 0) { |
528 if(where_result.data.integer != 0) { |
507 if(!reset_properties(sn, &result, child, cfieldlist)) { |
529 if(!reset_properties(sn, &result, child, cfieldlist)) { |
524 dav_resource_free(child); |
546 dav_resource_free(child); |
525 } |
547 } |
526 } |
548 } |
527 } |
549 } |
528 } |
550 } |
529 |
551 destroy_propfind_parser(parser); |
530 } else { |
552 } else { |
531 dav_session_set_error(sn, ret, http_status); |
553 dav_session_set_error(sn, ret, http_status); |
532 result.result = NULL; |
554 result.result = NULL; |
533 result.status = -1; |
555 result.status = -1; |
534 dav_resource_free_all(selroot); |
556 dav_resource_free_all(selroot); |