diff -r 7072a2b4ae35 -r 649eb328674a libidav/davqlexec.c --- a/libidav/davqlexec.c Tue Jun 02 10:07:20 2015 +0200 +++ b/libidav/davqlexec.c Tue Jun 02 20:57:23 2015 +0200 @@ -33,17 +33,19 @@ #include #include "davqlexec.h" #include "utils.h" +#include "methods.h" +#include "session.h" -DavQLResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { +DavResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { va_list ap; va_start(ap, st); - DavQLResult *result = dav_statement_execv(sn, st, ap); + DavResult *result = dav_statement_execv(sn, st, ap); va_end(ap); return result; } -DavQLResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) { - DavQLResult *result = dav_session_malloc(sn, sizeof(DavQLResult)); +DavResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) { + DavResult *result = dav_session_malloc(sn, sizeof(DavResult)); result->result = NULL; result->status = 1; @@ -57,7 +59,7 @@ sstr_t path = dav_format_string(sn->mp->allocator, st->path, ap, &error); if(st->type == DAVQL_SELECT) { - dav_exec_get(sn, st, path.ptr, ap); + *result = dav_exec_select(sn, st, path.ptr, ap); } else { // TODO } @@ -126,23 +128,128 @@ return sstrdup_a(a, sstrn(buf->space, buf->size)); } -void dav_exec_get(DavSession *sn, DavQLStatement *st, char* path, va_list ap) { - // execute a davql get statement +/* + * execute a davql select statement + */ +DavResult dav_exec_select(DavSession *sn, DavQLStatement *st, char* path, va_list ap) { UcxMempool *mp = ucx_mempool_new(128); // TODO: get property list + UcxBuffer *rqbuf = create_allprop_propfind_request(); - UcxBuffer *bcode = dav_compile_expr(mp->allocator, st->where, ap); + UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap); + + DavResource *selroot = dav_resource_new(sn, path); + DavResult result; + result.result = selroot; + result.status = 0; + - //print_bytecode(bcode); + UcxList *stack = NULL; // stack with DavResource* elements + // initialize the stack with the requested resource + DavQLRes *r = ucx_mempool_malloc(mp, sizeof(DavQLRes)); + r->resource = selroot; + r->depth = 0; + stack = ucx_list_prepend(stack, r); + + // reuseable response buffer + UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); - DavResource *res = dav_resource_new(sn, "/test.txt"); - dav_set_property_ns(res, "DAV:", "string", "value"); - dav_set_property_ns(res, "DAV:", "integer", "1337"); - res->lastmodified = 100; + // do a propfind request for each resource on the stack + while(stack) { + DavQLRes *sr = stack->data; // get first element from the stack + stack = ucx_list_remove(stack, stack); // remove first element + DavResource *root = sr->resource; + + util_set_url(sn, dav_resource_get_href(sr->resource)); + CURLcode ret = do_propfind_request(sn->handle, rqbuf, rpbuf); + int http_status = 0; + curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &http_status); + + if(ret == CURLE_OK && http_status == 207) { + // propfind request successful, now parse the response + char *url = "http://url/"; + PropfindParser *parser = create_propfind_parser(rpbuf, url); + ResponseTag response; + int r; + while((r = get_propfind_response(parser, &response)) != 0) { + if(r == -1) { + // error + result.status = -1; + // TODO: free resources + break; + } + + // the propfind multistatus response contains responses + // for the requsted resource and all childs + // determine if the response is a child or not + if(hrefeq(sn, root->href, response.href)) { + // response is the currently requested resource + // and not a child + + // add properties + add_properties(root, &response); + + if(root == selroot) { + // The current root is the root of the select query. + // In this case we have to check the where clause. + // If root is not selroot, the where clause was + // already checked for the resource before it was + // added to the stack. + DavQLStackObj where_result; + if(!dav_exec_expr(where, root, &where_result)) { + if(where_result.data.integer != 0) { + continue; + } + } else { + result.status = -1; + } + dav_resource_free_all(selroot); + ucx_list_free(stack); + break; + } + } else { + DavResource *child = response2resource( + sn, + &response, + root->path); + // check where clause + DavQLStackObj where_result; + if(!dav_exec_expr(where, child, &where_result)) { + if(where_result.data.integer != 0) { + resource_add_child(root, child); + if(child->iscollection && + (st->depth < 0 || st->depth > sr->depth+1)) + { + DavQLRes *rs = ucx_mempool_malloc( + mp, + sizeof(DavQLRes)); + rs->resource = child; + rs->depth = sr->depth + 1; + stack = ucx_list_prepend(stack, rs); + } + } else { + dav_resource_free(child); + } + } + } + } + + } else { + dav_session_set_error(sn, ret, http_status); + result.status = -1; + dav_resource_free_all(selroot); + break; + } + + // reset response buffer + ucx_buffer_seek(rpbuf, SEEK_SET, 0); + } - DavQLStackObj result; - dav_exec_expr(bcode, res, &result); + ucx_mempool_destroy(mp); + + result.result = selroot; + return result; } static int count_func_args(DavQLExpression *expr) { @@ -159,21 +266,7 @@ return count; } -static int identifier2propname(UcxAllocator *a, sstr_t id, DavPropName *propname) { - ssize_t count; - sstr_t *s = sstrsplit_a(a, id, S(":"), &count); - if(count == 2) { - sstr_t ns = s[0]; - sstr_t name = s[1]; - propname->ns = ns.ptr; - propname->name = name.ptr; - return 0; - } else { - return 1; - } -} - -static int add_cmd(UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) { +static int add_cmd(DavContext *ctx, UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) { if(!expr) { return 0; } @@ -219,7 +312,17 @@ cmd.type = DAVQL_CMD_RES_IDENTIFIER; if(propertyname.length > 0) { cmd.type = DAVQL_CMD_PROP_IDENTIFIER; - if(identifier2propname(a, src, &cmd.data.property)) { + char *ns; + char *name; + dav_get_property_namespace( + ctx, + sstrdup_a(a, src).ptr, + &ns, + &name); + if(ns && name) { + cmd.data.property.ns = ns; + cmd.data.property.name = name; + } else { // error return -1; } @@ -253,27 +356,29 @@ break; } case DAVQL_UNARY: { - numcmd += add_cmd(a, bcode, expr->left, ap); + numcmd += add_cmd(ctx, a, bcode, expr->left, ap); switch(expr->op) { case DAVQL_ADD: { - cmd.type = DAVQL_CMD_OP_UNARY_ADD; + // noop + numcmd = 0; break; } case DAVQL_SUB: { cmd.type = DAVQL_CMD_OP_UNARY_SUB; + ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); break; } case DAVQL_NEG: { cmd.type = DAVQL_CMD_OP_UNARY_NEG; + ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); break; } } - ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); break; } case DAVQL_BINARY: { - numcmd += add_cmd(a, bcode, expr->left, ap); - numcmd += add_cmd(a, bcode, expr->right, ap); + numcmd += add_cmd(ctx, a, bcode, expr->left, ap); + numcmd += add_cmd(ctx, a, bcode, expr->right, ap); switch(expr->op) { case DAVQL_ADD: { cmd.type = DAVQL_CMD_OP_BINARY_ADD; @@ -309,13 +414,13 @@ } case DAVQL_LOGICAL: { if(expr->left && expr->right && expr->op != DAVQL_LOR) { - numcmd += add_cmd(a, bcode, expr->left, ap); - numcmd += add_cmd(a, bcode, expr->right, ap); + numcmd += add_cmd(ctx, a, bcode, expr->left, ap); + numcmd += add_cmd(ctx, a, bcode, expr->right, ap); } switch(expr->op) { case DAVQL_NOT: { - numcmd += add_cmd(a, bcode, expr->left, ap); + numcmd += add_cmd(ctx, a, bcode, expr->left, ap); cmd.type = DAVQL_CMD_OP_LOGICAL_NOT; ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); break; @@ -326,13 +431,13 @@ break; } case DAVQL_LOR: { - int nleft = add_cmd(a, bcode, expr->left, ap); + int nleft = add_cmd(ctx, a, bcode, expr->left, ap); cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L; DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos); ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); - int nright = add_cmd(a, bcode, expr->right, ap); + int nright = add_cmd(ctx, a, bcode, expr->right, ap); or_l->data.integer = nright + 1; cmd.type = DAVQL_CMD_OP_LOGICAL_OR; @@ -393,7 +498,7 @@ case DAVQL_FUNCCALL: { switch(expr->op) { case DAVQL_CALL: { - int nright = add_cmd(a, bcode, expr->right, ap); + int nright = add_cmd(ctx, a, bcode, expr->right, ap); // TODO: count args DavQLExpression *funcid = expr->left; if(!funcid && funcid->type != DAVQL_IDENTIFIER) { @@ -417,8 +522,8 @@ } case DAVQL_ARGLIST: { numcmd = 0; - numcmd += add_cmd(a, bcode, expr->left, ap); - numcmd += add_cmd(a, bcode, expr->right, ap); + numcmd += add_cmd(ctx, a, bcode, expr->left, ap); + numcmd += add_cmd(ctx, a, bcode, expr->right, ap); break; } } @@ -428,13 +533,13 @@ return numcmd; } -UcxBuffer* dav_compile_expr(UcxAllocator *a, DavQLExpression *lexpr, va_list ap) { +UcxBuffer* dav_compile_expr(DavContext *ctx, UcxAllocator *a, DavQLExpression *lexpr, va_list ap) { UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); if(!bcode) { return NULL; } - if(add_cmd(a, bcode, lexpr, ap) <= 0) { + if(add_cmd(ctx, a, bcode, lexpr, ap) <= 0) { ucx_buffer_free(bcode); return NULL; } @@ -678,15 +783,15 @@ } } - for(int i=0;i