1 /* |
1 /* |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 * |
3 * |
4 * Copyright 2016 Olaf Wintermann. All rights reserved. |
4 * Copyright 2018 Olaf Wintermann. All rights reserved. |
5 * |
5 * |
6 * Redistribution and use in source and binary forms, with or without |
6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions are met: |
7 * modification, are permitted provided that the following conditions are met: |
8 * |
8 * |
9 * 1. Redistributions of source code must retain the above copyright |
9 * 1. Redistributions of source code must retain the above copyright |
37 #include "utils.h" |
37 #include "utils.h" |
38 #include "methods.h" |
38 #include "methods.h" |
39 #include "session.h" |
39 #include "session.h" |
40 #include "resource.h" |
40 #include "resource.h" |
41 |
41 |
|
42 DavQLArgList* dav_ql_get_args(DavQLStatement *st, va_list ap) { |
|
43 DavQLArgList *args = malloc(sizeof(DavQLArgList)); |
|
44 if(!args) { |
|
45 return NULL; |
|
46 } |
|
47 args->first = NULL; |
|
48 |
|
49 DavQLArg *cur = NULL; |
|
50 UCX_FOREACH(elm, st->args) { |
|
51 intptr_t type = (intptr_t)elm->data; |
|
52 DavQLArg *arg = calloc(1, sizeof(DavQLArg)); |
|
53 if(!arg) { |
|
54 dav_ql_free_arglist(args); |
|
55 return NULL; |
|
56 } |
|
57 arg->type = type; |
|
58 switch(type) { |
|
59 case 'd': { |
|
60 arg->value.d = va_arg(ap, int); |
|
61 break; |
|
62 } |
|
63 case 'u': { |
|
64 arg->value.u = va_arg(ap, unsigned int); |
|
65 break; |
|
66 } |
|
67 case 's': { |
|
68 arg->value.s = va_arg(ap, char*); |
|
69 break; |
|
70 } |
|
71 case 't': { |
|
72 arg->value.t = va_arg(ap, time_t); |
|
73 break; |
|
74 } |
|
75 default: { |
|
76 free(arg); |
|
77 dav_ql_free_arglist(args); |
|
78 return NULL; |
|
79 } |
|
80 } |
|
81 if(cur) { |
|
82 cur->next = arg; |
|
83 } else { |
|
84 args->first = arg; |
|
85 } |
|
86 cur = arg; |
|
87 } |
|
88 args->current = args->first; |
|
89 return args; |
|
90 } |
|
91 |
|
92 void dav_ql_free_arglist(DavQLArgList *args) { |
|
93 DavQLArg *arg = args->first; |
|
94 while(arg) { |
|
95 DavQLArg *next = arg->next; |
|
96 free(arg); |
|
97 arg = next; |
|
98 } |
|
99 } |
|
100 |
|
101 static DavQLArg* arglist_get(DavQLArgList *args) { |
|
102 DavQLArg *a = args->current; |
|
103 if(a) { |
|
104 args->current = a->next; |
|
105 } |
|
106 return a; |
|
107 } |
|
108 |
|
109 int dav_ql_getarg_int(DavQLArgList *args) { |
|
110 DavQLArg *a = arglist_get(args); |
|
111 if(a && a->type == 'd') { |
|
112 return a->value.d; |
|
113 } |
|
114 return 0; |
|
115 } |
|
116 |
|
117 unsigned int dav_ql_getarg_uint(DavQLArgList *args) { |
|
118 DavQLArg *a = arglist_get(args); |
|
119 if(a && a->type == 'u') { |
|
120 return a->value.u; |
|
121 } |
|
122 return 0; |
|
123 } |
|
124 |
|
125 char* dav_ql_getarg_str(DavQLArgList *args) { |
|
126 DavQLArg *a = arglist_get(args); |
|
127 if(a && a->type == 's') { |
|
128 return a->value.s; |
|
129 } |
|
130 return ""; |
|
131 } |
|
132 |
|
133 time_t dav_ql_getarg_time(DavQLArgList *args) { |
|
134 DavQLArg *a = arglist_get(args); |
|
135 if(a && a->type == 't') { |
|
136 return a->value.t; |
|
137 } |
|
138 return 0; |
|
139 } |
|
140 |
|
141 |
42 DavResult dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { |
142 DavResult dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { |
43 va_list ap; |
143 va_list ap; |
44 va_start(ap, st); |
144 va_start(ap, st); |
45 DavResult result = dav_statement_execv(sn, st, ap); |
145 DavResult result = dav_statement_execv(sn, st, ap); |
46 va_end(ap); |
146 va_end(ap); |
64 } |
164 } |
65 |
165 |
66 return result; |
166 return result; |
67 } |
167 } |
68 |
168 |
69 sstr_t dav_format_string(UcxAllocator *a, sstr_t fstr, va_list ap, davqlerror_t *error) { |
169 sstr_t dav_format_string(UcxAllocator *a, sstr_t fstr, DavQLArgList *ap, davqlerror_t *error) { |
70 UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); |
170 UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); |
71 |
171 |
72 int placeholder = 0; |
172 int placeholder = 0; |
73 for(int i=0;i<fstr.length;i++) { |
173 for(int i=0;i<fstr.length;i++) { |
74 char c = fstr.ptr[i]; |
174 char c = fstr.ptr[i]; |
79 } else { |
179 } else { |
80 // detect placeholder type and insert arg |
180 // detect placeholder type and insert arg |
81 int err = 0; |
181 int err = 0; |
82 switch(c) { |
182 switch(c) { |
83 case 's': { |
183 case 's': { |
84 char *arg = va_arg(ap, char*); |
184 char *arg = dav_ql_getarg_str(ap); |
85 ucx_buffer_puts(buf, arg); |
185 ucx_buffer_puts(buf, arg); |
86 break; |
186 break; |
87 } |
187 } |
88 case 'd': { |
188 case 'd': { |
89 int arg = va_arg(ap, int); |
189 int arg = dav_ql_getarg_int(ap); |
90 ucx_bprintf(buf, "%d", arg); |
190 ucx_bprintf(buf, "%d", arg); |
91 break; |
191 break; |
92 } |
192 } |
93 case 'u': { |
193 case 'u': { |
94 unsigned int arg = va_arg(ap, unsigned int); |
194 unsigned int arg = dav_ql_getarg_uint(ap); |
95 ucx_bprintf(buf, "%u", arg); |
195 ucx_bprintf(buf, "%u", arg); |
96 break; |
196 break; |
97 } |
197 } |
98 case 't': { |
198 case 't': { |
99 // time arguments not supported for strings |
199 // time arguments not supported for strings |
336 UcxMempool *mp = ucx_mempool_new(128); |
436 UcxMempool *mp = ucx_mempool_new(128); |
337 DavResult result; |
437 DavResult result; |
338 result.result = NULL; |
438 result.result = NULL; |
339 result.status = 1; |
439 result.status = 1; |
340 |
440 |
|
441 DavQLArgList *args = dav_ql_get_args(st, ap); |
|
442 if(!args) { |
|
443 return result; |
|
444 } |
|
445 ucx_mempool_reg_destr(mp, args, (ucx_destructor)dav_ql_free_arglist); |
|
446 |
341 int isallprop; |
447 int isallprop; |
342 UcxBuffer *rqbuf = fieldlist2propfindrequest(sn, mp, st->fields, &isallprop); |
448 UcxBuffer *rqbuf = fieldlist2propfindrequest(sn, mp, st->fields, &isallprop); |
343 if(!rqbuf) { |
449 if(!rqbuf) { |
344 ucx_mempool_destroy(mp); |
450 ucx_mempool_destroy(mp); |
345 return result; |
451 return result; |
354 // compile field expression |
460 // compile field expression |
355 UcxBuffer *code = dav_compile_expr( |
461 UcxBuffer *code = dav_compile_expr( |
356 sn->context, |
462 sn->context, |
357 mp->allocator, |
463 mp->allocator, |
358 field->expr, |
464 field->expr, |
359 ap); |
465 args); |
360 if(!code) { |
466 if(!code) { |
361 // TODO: set error string |
467 // TODO: set error string |
362 return result; |
468 return result; |
363 } |
469 } |
364 ucx_mempool_reg_destr(mp, code, (ucx_destructor)ucx_buffer_free); |
470 ucx_mempool_reg_destr(mp, code, (ucx_destructor)ucx_buffer_free); |
384 } |
490 } |
385 } |
491 } |
386 |
492 |
387 // get path string |
493 // get path string |
388 davqlerror_t error; |
494 davqlerror_t error; |
389 sstr_t path = dav_format_string(mp->allocator, st->path, ap, &error); |
495 sstr_t path = dav_format_string(mp->allocator, st->path, args, &error); |
390 if(error) { |
496 if(error) { |
391 // TODO: cleanup |
497 // TODO: cleanup |
392 ucx_mempool_destroy(mp); |
498 ucx_mempool_destroy(mp); |
393 return result; |
499 return result; |
394 } |
500 } |
395 |
501 |
396 int depth = st->depth == DAV_DEPTH_PLACEHOLDER ? va_arg(ap, int) : st->depth; |
502 int depth = st->depth == DAV_DEPTH_PLACEHOLDER ? |
397 |
503 dav_ql_getarg_int(args) : st->depth; |
398 UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap); |
504 |
|
505 UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, args); |
399 if(st->where && !where) { |
506 if(st->where && !where) { |
400 // TODO: cleanup |
507 // TODO: cleanup |
401 ucx_mempool_destroy(mp); |
508 ucx_mempool_destroy(mp); |
402 return result; |
509 return result; |
403 } |
510 } |
641 switch(expr->type) { |
748 switch(expr->type) { |
642 default: break; |
749 default: break; |
643 case DAVQL_NUMBER: { |
750 case DAVQL_NUMBER: { |
644 cmd.type = DAVQL_CMD_INT; |
751 cmd.type = DAVQL_CMD_INT; |
645 if(src.ptr[0] == '%') { |
752 if(src.ptr[0] == '%') { |
646 cmd.data.integer = va_arg(ap, int); |
753 cmd.data.integer = dav_ql_getarg_int(ap); |
647 } else if(util_strtoint(src.ptr, &cmd.data.integer)) { |
754 } else if(util_strtoint(src.ptr, &cmd.data.integer)) { |
648 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
755 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
649 } else { |
756 } else { |
650 // error |
757 // error |
651 return -1; |
758 return -1; |
660 break; |
767 break; |
661 } |
768 } |
662 case DAVQL_TIMESTAMP: { |
769 case DAVQL_TIMESTAMP: { |
663 if(src.ptr[0] == '%') { |
770 if(src.ptr[0] == '%') { |
664 cmd.type = DAVQL_CMD_TIMESTAMP; |
771 cmd.type = DAVQL_CMD_TIMESTAMP; |
665 cmd.data.timestamp = va_arg(ap, time_t); |
772 cmd.data.timestamp = dav_ql_getarg_time(ap); |
666 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
773 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); |
667 } else { |
774 } else { |
668 // error |
775 // error |
669 return -1; |
776 return -1; |
670 } |
777 } |