31 #include <string.h> |
31 #include <string.h> |
32 |
32 |
33 #include <ucx/utils.h> |
33 #include <ucx/utils.h> |
34 #include "davqlexec.h" |
34 #include "davqlexec.h" |
35 #include "utils.h" |
35 #include "utils.h" |
36 |
36 #include "methods.h" |
37 DavQLResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { |
37 #include "session.h" |
|
38 |
|
39 DavResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { |
38 va_list ap; |
40 va_list ap; |
39 va_start(ap, st); |
41 va_start(ap, st); |
40 DavQLResult *result = dav_statement_execv(sn, st, ap); |
42 DavResult *result = dav_statement_execv(sn, st, ap); |
41 va_end(ap); |
43 va_end(ap); |
42 return result; |
44 return result; |
43 } |
45 } |
44 |
46 |
45 DavQLResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) { |
47 DavResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) { |
46 DavQLResult *result = dav_session_malloc(sn, sizeof(DavQLResult)); |
48 DavResult *result = dav_session_malloc(sn, sizeof(DavResult)); |
47 result->result = NULL; |
49 result->result = NULL; |
48 result->status = 1; |
50 result->status = 1; |
49 |
51 |
50 // make sure the statement was successfully parsed |
52 // make sure the statement was successfully parsed |
51 if(st->type == DAVQL_ERROR) { |
53 if(st->type == DAVQL_ERROR) { |
124 *error = DAVQL_OK; |
126 *error = DAVQL_OK; |
125 |
127 |
126 return sstrdup_a(a, sstrn(buf->space, buf->size)); |
128 return sstrdup_a(a, sstrn(buf->space, buf->size)); |
127 } |
129 } |
128 |
130 |
129 void dav_exec_get(DavSession *sn, DavQLStatement *st, char* path, va_list ap) { |
131 /* |
130 // execute a davql get statement |
132 * execute a davql select statement |
|
133 */ |
|
134 DavResult dav_exec_select(DavSession *sn, DavQLStatement *st, char* path, va_list ap) { |
131 UcxMempool *mp = ucx_mempool_new(128); |
135 UcxMempool *mp = ucx_mempool_new(128); |
132 |
136 |
133 // TODO: get property list |
137 // TODO: get property list |
134 |
138 UcxBuffer *rqbuf = create_allprop_propfind_request(); |
135 UcxBuffer *bcode = dav_compile_expr(mp->allocator, st->where, ap); |
139 |
136 |
140 UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap); |
137 //print_bytecode(bcode); |
141 |
138 |
142 DavResource *selroot = dav_resource_new(sn, path); |
139 DavResource *res = dav_resource_new(sn, "/test.txt"); |
143 DavResult result; |
140 dav_set_property_ns(res, "DAV:", "string", "value"); |
144 result.result = selroot; |
141 dav_set_property_ns(res, "DAV:", "integer", "1337"); |
145 result.status = 0; |
142 res->lastmodified = 100; |
146 |
143 |
147 |
144 DavQLStackObj result; |
148 UcxList *stack = NULL; // stack with DavResource* elements |
145 dav_exec_expr(bcode, res, &result); |
149 // initialize the stack with the requested resource |
|
150 DavQLRes *r = ucx_mempool_malloc(mp, sizeof(DavQLRes)); |
|
151 r->resource = selroot; |
|
152 r->depth = 0; |
|
153 stack = ucx_list_prepend(stack, r); |
|
154 |
|
155 // reuseable response buffer |
|
156 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); |
|
157 |
|
158 // do a propfind request for each resource on the stack |
|
159 while(stack) { |
|
160 DavQLRes *sr = stack->data; // get first element from the stack |
|
161 stack = ucx_list_remove(stack, stack); // remove first element |
|
162 DavResource *root = sr->resource; |
|
163 |
|
164 util_set_url(sn, dav_resource_get_href(sr->resource)); |
|
165 CURLcode ret = do_propfind_request(sn->handle, rqbuf, rpbuf); |
|
166 int http_status = 0; |
|
167 curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &http_status); |
|
168 |
|
169 if(ret == CURLE_OK && http_status == 207) { |
|
170 // propfind request successful, now parse the response |
|
171 char *url = "http://url/"; |
|
172 PropfindParser *parser = create_propfind_parser(rpbuf, url); |
|
173 ResponseTag response; |
|
174 int r; |
|
175 while((r = get_propfind_response(parser, &response)) != 0) { |
|
176 if(r == -1) { |
|
177 // error |
|
178 result.status = -1; |
|
179 // TODO: free resources |
|
180 break; |
|
181 } |
|
182 |
|
183 // the propfind multistatus response contains responses |
|
184 // for the requsted resource and all childs |
|
185 // determine if the response is a child or not |
|
186 if(hrefeq(sn, root->href, response.href)) { |
|
187 // response is the currently requested resource |
|
188 // and not a child |
|
189 |
|
190 // add properties |
|
191 add_properties(root, &response); |
|
192 |
|
193 if(root == selroot) { |
|
194 // The current root is the root of the select query. |
|
195 // In this case we have to check the where clause. |
|
196 // If root is not selroot, the where clause was |
|
197 // already checked for the resource before it was |
|
198 // added to the stack. |
|
199 DavQLStackObj where_result; |
|
200 if(!dav_exec_expr(where, root, &where_result)) { |
|
201 if(where_result.data.integer != 0) { |
|
202 continue; |
|
203 } |
|
204 } else { |
|
205 result.status = -1; |
|
206 } |
|
207 dav_resource_free_all(selroot); |
|
208 ucx_list_free(stack); |
|
209 break; |
|
210 } |
|
211 } else { |
|
212 DavResource *child = response2resource( |
|
213 sn, |
|
214 &response, |
|
215 root->path); |
|
216 // check where clause |
|
217 DavQLStackObj where_result; |
|
218 if(!dav_exec_expr(where, child, &where_result)) { |
|
219 if(where_result.data.integer != 0) { |
|
220 resource_add_child(root, child); |
|
221 if(child->iscollection && |
|
222 (st->depth < 0 || st->depth > sr->depth+1)) |
|
223 { |
|
224 DavQLRes *rs = ucx_mempool_malloc( |
|
225 mp, |
|
226 sizeof(DavQLRes)); |
|
227 rs->resource = child; |
|
228 rs->depth = sr->depth + 1; |
|
229 stack = ucx_list_prepend(stack, rs); |
|
230 } |
|
231 } else { |
|
232 dav_resource_free(child); |
|
233 } |
|
234 } |
|
235 } |
|
236 } |
|
237 |
|
238 } else { |
|
239 dav_session_set_error(sn, ret, http_status); |
|
240 result.status = -1; |
|
241 dav_resource_free_all(selroot); |
|
242 break; |
|
243 } |
|
244 |
|
245 // reset response buffer |
|
246 ucx_buffer_seek(rpbuf, SEEK_SET, 0); |
|
247 } |
|
248 |
|
249 ucx_mempool_destroy(mp); |
|
250 |
|
251 result.result = selroot; |
|
252 return result; |
146 } |
253 } |
147 |
254 |
148 static int count_func_args(DavQLExpression *expr) { |
255 static int count_func_args(DavQLExpression *expr) { |
149 int count = 0; |
256 int count = 0; |
150 DavQLExpression *arg = expr->right; |
257 DavQLExpression *arg = expr->right; |
217 case DAVQL_IDENTIFIER: { |
310 case DAVQL_IDENTIFIER: { |
218 sstr_t propertyname = sstrchr(src, ':'); |
311 sstr_t propertyname = sstrchr(src, ':'); |
219 cmd.type = DAVQL_CMD_RES_IDENTIFIER; |
312 cmd.type = DAVQL_CMD_RES_IDENTIFIER; |
220 if(propertyname.length > 0) { |
313 if(propertyname.length > 0) { |
221 cmd.type = DAVQL_CMD_PROP_IDENTIFIER; |
314 cmd.type = DAVQL_CMD_PROP_IDENTIFIER; |
222 if(identifier2propname(a, src, &cmd.data.property)) { |
315 char *ns; |
|
316 char *name; |
|
317 dav_get_property_namespace( |
|
318 ctx, |
|
319 sstrdup_a(a, src).ptr, |
|
320 &ns, |
|
321 &name); |
|
322 if(ns && name) { |
|
323 cmd.data.property.ns = ns; |
|
324 cmd.data.property.name = name; |
|
325 } else { |
223 // error |
326 // error |
224 return -1; |
327 return -1; |
225 } |
328 } |
226 } else if(!sstrcmp(src, S("name"))) { |
329 } else if(!sstrcmp(src, S("name"))) { |
227 cmd.data.resprop = DAVQL_RES_NAME; |
330 cmd.data.resprop = DAVQL_RES_NAME; |
251 } |
354 } |
252 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
355 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
253 break; |
356 break; |
254 } |
357 } |
255 case DAVQL_UNARY: { |
358 case DAVQL_UNARY: { |
256 numcmd += add_cmd(a, bcode, expr->left, ap); |
359 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); |
257 switch(expr->op) { |
360 switch(expr->op) { |
258 case DAVQL_ADD: { |
361 case DAVQL_ADD: { |
259 cmd.type = DAVQL_CMD_OP_UNARY_ADD; |
362 // noop |
|
363 numcmd = 0; |
260 break; |
364 break; |
261 } |
365 } |
262 case DAVQL_SUB: { |
366 case DAVQL_SUB: { |
263 cmd.type = DAVQL_CMD_OP_UNARY_SUB; |
367 cmd.type = DAVQL_CMD_OP_UNARY_SUB; |
|
368 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
264 break; |
369 break; |
265 } |
370 } |
266 case DAVQL_NEG: { |
371 case DAVQL_NEG: { |
267 cmd.type = DAVQL_CMD_OP_UNARY_NEG; |
372 cmd.type = DAVQL_CMD_OP_UNARY_NEG; |
268 break; |
373 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
269 } |
374 break; |
270 } |
375 } |
271 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
376 } |
272 break; |
377 break; |
273 } |
378 } |
274 case DAVQL_BINARY: { |
379 case DAVQL_BINARY: { |
275 numcmd += add_cmd(a, bcode, expr->left, ap); |
380 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); |
276 numcmd += add_cmd(a, bcode, expr->right, ap); |
381 numcmd += add_cmd(ctx, a, bcode, expr->right, ap); |
277 switch(expr->op) { |
382 switch(expr->op) { |
278 case DAVQL_ADD: { |
383 case DAVQL_ADD: { |
279 cmd.type = DAVQL_CMD_OP_BINARY_ADD; |
384 cmd.type = DAVQL_CMD_OP_BINARY_ADD; |
280 break; |
385 break; |
281 } |
386 } |
307 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
412 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
308 break; |
413 break; |
309 } |
414 } |
310 case DAVQL_LOGICAL: { |
415 case DAVQL_LOGICAL: { |
311 if(expr->left && expr->right && expr->op != DAVQL_LOR) { |
416 if(expr->left && expr->right && expr->op != DAVQL_LOR) { |
312 numcmd += add_cmd(a, bcode, expr->left, ap); |
417 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); |
313 numcmd += add_cmd(a, bcode, expr->right, ap); |
418 numcmd += add_cmd(ctx, a, bcode, expr->right, ap); |
314 } |
419 } |
315 |
420 |
316 switch(expr->op) { |
421 switch(expr->op) { |
317 case DAVQL_NOT: { |
422 case DAVQL_NOT: { |
318 numcmd += add_cmd(a, bcode, expr->left, ap); |
423 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); |
319 cmd.type = DAVQL_CMD_OP_LOGICAL_NOT; |
424 cmd.type = DAVQL_CMD_OP_LOGICAL_NOT; |
320 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
425 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
321 break; |
426 break; |
322 } |
427 } |
323 case DAVQL_LAND: { |
428 case DAVQL_LAND: { |
324 cmd.type = DAVQL_CMD_OP_LOGICAL_AND; |
429 cmd.type = DAVQL_CMD_OP_LOGICAL_AND; |
325 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
430 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
326 break; |
431 break; |
327 } |
432 } |
328 case DAVQL_LOR: { |
433 case DAVQL_LOR: { |
329 int nleft = add_cmd(a, bcode, expr->left, ap); |
434 int nleft = add_cmd(ctx, a, bcode, expr->left, ap); |
330 |
435 |
331 cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L; |
436 cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L; |
332 DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos); |
437 DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos); |
333 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
438 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
334 |
439 |
335 int nright = add_cmd(a, bcode, expr->right, ap); |
440 int nright = add_cmd(ctx, a, bcode, expr->right, ap); |
336 or_l->data.integer = nright + 1; |
441 or_l->data.integer = nright + 1; |
337 |
442 |
338 cmd.type = DAVQL_CMD_OP_LOGICAL_OR; |
443 cmd.type = DAVQL_CMD_OP_LOGICAL_OR; |
339 cmd.data.integer = 0; |
444 cmd.data.integer = 0; |
340 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
445 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
415 numcmd += nright; |
520 numcmd += nright; |
416 break; |
521 break; |
417 } |
522 } |
418 case DAVQL_ARGLIST: { |
523 case DAVQL_ARGLIST: { |
419 numcmd = 0; |
524 numcmd = 0; |
420 numcmd += add_cmd(a, bcode, expr->left, ap); |
525 numcmd += add_cmd(ctx, a, bcode, expr->left, ap); |
421 numcmd += add_cmd(a, bcode, expr->right, ap); |
526 numcmd += add_cmd(ctx, a, bcode, expr->right, ap); |
422 break; |
527 break; |
423 } |
528 } |
424 } |
529 } |
425 break; |
530 break; |
426 } |
531 } |
427 } |
532 } |
428 return numcmd; |
533 return numcmd; |
429 } |
534 } |
430 |
535 |
431 UcxBuffer* dav_compile_expr(UcxAllocator *a, DavQLExpression *lexpr, va_list ap) { |
536 UcxBuffer* dav_compile_expr(DavContext *ctx, UcxAllocator *a, DavQLExpression *lexpr, va_list ap) { |
432 UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); |
537 UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); |
433 if(!bcode) { |
538 if(!bcode) { |
434 return NULL; |
539 return NULL; |
435 } |
540 } |
436 |
541 |
437 if(add_cmd(a, bcode, lexpr, ap) <= 0) { |
542 if(add_cmd(ctx, a, bcode, lexpr, ap) <= 0) { |
438 ucx_buffer_free(bcode); |
543 ucx_buffer_free(bcode); |
439 return NULL; |
544 return NULL; |
440 } |
545 } |
441 |
546 |
442 return bcode; |
547 return bcode; |