dav/davql.c

changeset 27
e584c351b402
parent 17
11dffb40cd91
child 28
4e46c65711ef
equal deleted inserted replaced
26:146171b57e69 27:e584c351b402
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <string.h>
31 32
32 #include "davql.h" 33 #include "davql.h"
33 #include "methods.h" 34 #include "methods.h"
34 #include "webdav.h"
35 #include "utils.h" 35 #include "utils.h"
36 36
37 DavQuery dav_ql_parse(char *query, va_list ap) { 37 DavQuery dav_ql_parse(char *query, va_list ap) {
38 DavQuery davquery; 38 DavQuery davquery;
39 davquery.command = DAV_QUERY_ERROR; 39 davquery.command = DAV_QUERY_ERROR;
100 } else { 100 } else {
101 ucx_buffer_putc(fbuf, c); 101 ucx_buffer_putc(fbuf, c);
102 } 102 }
103 } 103 }
104 104
105 // condition
106 DavQOp *condition = NULL;
107 size_t oplen = 0;
108 if(cond.ptr) {
109 //printf("cond: {%.*s}\n", cond.length, cond.ptr);
110 UcxList *ops = NULL;
111 if(dav_parse_condition(&ops, cond, ap)) {
112 // TODO: error
113 printf("parse error\n");
114 return NULL;
115 }
116 oplen = ucx_list_size(ops);
117 condition = calloc(sizeof(DavQOp), oplen);
118 int l = 0;
119 UCX_FOREACH(elm, ops) {
120 condition[l] = *(DavQOp*)elm->data;
121 free(elm->data);
122 l++;
123 }
124 ucx_list_free(ops);
125 }
126
105 DavGetQuery *getquery = malloc(sizeof(DavGetQuery)); 127 DavGetQuery *getquery = malloc(sizeof(DavGetQuery));
106 getquery->properties = sstrdup(property_query); 128 getquery->properties = sstrdup(property_query);
107 getquery->from = sstrn(fbuf->space, fbuf->pos); 129 getquery->from = sstrn(fbuf->space, fbuf->pos);
108 // TODO: condition 130 if(condition) {
131 getquery->condition = condition;
132 getquery->condlen = oplen;
133 } else {
134 getquery->condition = NULL;
135 getquery->condlen = 0;
136 }
109 return getquery; 137 return getquery;
110 } 138 }
111 139
112 void free_get_query(DavGetQuery *q) { 140 void free_get_query(DavGetQuery *q) {
113 free(q->from.ptr); 141 free(q->from.ptr);
135 *depth = 1; 163 *depth = 1;
136 } 164 }
137 165
138 return 0; 166 return 0;
139 } 167 }
168
169 int dav_parse_condition(UcxList **ops, sstr_t cond, va_list ap) {
170 sstr_t token;
171 DavQOp *op1 = NULL; // level 1 operator
172 DavQOp *op2 = NULL; // level 2 operator
173 DavQOp *op3 = NULL; // level 3 operator
174 while((token = condition_parser_next_token(&cond)).length > 0) {
175 //printf("token: {%.*s}[%d]\n", token.length, token.ptr, token.length);
176 int64_t type = 0;
177 int tkop = condition_operator_type(token, &type);
178 DavQOp *operation = malloc(sizeof(DavQOp));
179 if(tkop > 0) {
180 // operator token
181 operation->type = DAVQOP_OPERATOR;
182 operation->val = NULL;
183 operation->intval = type;
184 switch(tkop) {
185 case 1: {
186 // operators: + - / * not
187 // add operation after next non operator token
188 op1 = operation;
189 break;
190 }
191 case 2: {
192 // operators: < > == != <= >=
193 if(op2) {
194 *ops = ucx_list_append(*ops, op2);
195 }
196 op2 = operation;
197 break;
198 }
199 case 3: {
200 // operators: and or xor
201 if(op2) {
202 *ops = ucx_list_append(*ops, op2);
203 op2 = NULL;
204 }
205 if(op3) {
206 *ops = ucx_list_append(*ops, op3);
207 }
208 op3 = operation;
209 break;
210 }
211 }
212 } else {
213 if(token.ptr[0] == '"' || token.ptr[0] == '\'') {
214 operation->type = DAVQOP_STRING;
215 operation->val = token.ptr+1;
216 operation->intval = token.length-2;
217 } else if(!sstrcmp(token, S("true")) ||
218 !sstrcmp(token, S("false")))
219 {
220 operation->type = DAVQOP_INTEGER;
221 operation->val = NULL;
222 operation->intval = util_getboolean(token.ptr);
223 } else if(token.length == 2 && token.ptr[0] == '%') {
224 switch(token.ptr[1]) {
225 case 's': {
226 char *arg = va_arg(ap, char*);
227 operation->type = DAVQOP_STRING;
228 operation->val = arg;
229 operation->intval = strlen(arg);
230 break;
231 }
232 case 'd': {
233 operation->type = DAVQOP_INTEGER;
234 operation->val = NULL;
235 operation->intval = va_arg(ap, int);
236 break;
237 }
238 case 't': {
239 operation->type = DAVQOP_INTEGER;
240 operation->val = NULL;
241 operation->intval = va_arg(ap, time_t);
242 break;
243 }
244 default: {
245 operation->type = DAVQOP_STRING;
246 operation->val = token.ptr;
247 operation->intval = token.length;
248 }
249 }
250 } else {
251 sstr_t d = sstrdup(token);
252 char *end;
253 int64_t val = strtoll(d.ptr, &end, 0);
254 int intval = strlen(end) == 0 ? 1 : 0;
255 free(d.ptr);
256 if(intval) {
257 operation->type = DAVQOP_INTEGER;
258 operation->val = NULL;
259 operation->intval = val;
260 } else {
261 if(!sstrcmp(token, S("contentlength"))) {
262 operation->type = DAVQOP_RESPROP;
263 } else if(!sstrcmp(token, S("lastmodified"))) {
264 operation->type = DAVQOP_RESPROP;
265 } else if(!sstrcmp(token, S("creationdate"))) {
266 operation->type = DAVQOP_RESPROP;
267 } else if(!sstrcmp(token, S("name"))) {
268 operation->type = DAVQOP_RESPROP;
269 } else if(!sstrcmp(token, S("path"))) {
270 operation->type = DAVQOP_RESPROP;
271 } else {
272 operation->type = DAVQOP_PROPERTY;
273 }
274 operation->val = token.ptr;
275 operation->intval = token.length;
276 }
277 }
278
279 // add operation
280 *ops = ucx_list_append(*ops, operation);
281 if(op1) {
282 // add level 1 operator
283 *ops = ucx_list_append(*ops, op1);
284 op1 = NULL;
285 }
286 }
287 }
288 if(op1) {
289 *ops = ucx_list_append(*ops, op1);
290 }
291 if(op2) {
292 *ops = ucx_list_append(*ops, op2);
293 }
294 if(op3) {
295 *ops = ucx_list_append(*ops, op3);
296 }
297 return 0;
298 }
299
300 sstr_t condition_parser_next_token(sstr_t *str) {
301 sstr_t s = *str;
302 sstr_t t;
303 t.ptr = NULL;
304 t.length = 0;
305 // remove leading space
306 int i;
307 for(i=0;i<s.length;i++) {
308 if(s.ptr[i] > 32) {
309 break;
310 }
311 }
312 s.length -= i;
313 s.ptr += i;
314
315 if(s.length == 0) {
316 *str = s;
317 return t;
318 }
319
320 // check for single char operators
321 switch(s.ptr[0]) {
322 case '<':
323 case '>':
324 case '+':
325 case '-':
326 case '*':
327 case '/': {
328 t.ptr = s.ptr;
329 t.length = 1;
330 str->ptr = s.ptr + 1;
331 str->length = s.length - 1;
332 return t;
333 }
334 }
335
336 if(s.length > 1) {
337 // check for double char operators
338 int16_t op = *(int16_t*)s.ptr;
339 if(op == '==' || op == '!=' || op == '>=' || op == '=<') {
340 t.ptr = s.ptr;
341 t.length = 2;
342 str->ptr = s.ptr + 2;
343 str->length = s.length - 2;
344 return t;
345 }
346 } else {
347 t.ptr = s.ptr;
348 t.length = 1;
349 str->ptr = s.ptr + 1;
350 str->length = s.length - 1;
351 return t;
352 }
353
354 // TODO: brackets
355
356 // check for string literal
357 if(s.ptr[0] == '\'' || s.ptr[0] == '"') {
358 for(i=1;i<s.length;i++) {
359 if(s.ptr[0] == s.ptr[i]) {
360 i++;
361 break;
362 }
363 }
364 t.ptr = s.ptr;
365 t.length = i;
366 str->ptr = s.ptr + i;
367 str->length = s.length - i;
368 return t;
369 }
370
371 for(i=0;i<s.length;i++) {
372 char c = s.ptr[i];
373 if((c < 33) || (c > 41 && c < 48) || (c > 59 && c < 63)) {
374 break;
375 }
376 }
377 t.ptr = s.ptr;
378 t.length = i;
379 str->ptr = s.ptr + i;
380 str->length = s.length - i;
381 return t;
382 }
383
384 int condition_operator_type(sstr_t token, int64_t *type) {
385 // returns the operator level and sets the type
386
387 if(token.ptr[0] == '"' || token.ptr[0] == '\'' || token.ptr[0] == '(') {
388 return 0;
389 }
390
391 if(token.length == 1) {
392 switch(token.ptr[0]) {
393 case '+': *type = 1; return 1;
394 case '-': *type = 2; return 1;
395 case '*': *type = 3; return 1;
396 case '/': *type = 4; return 1;
397 case '<': *type = 5; return 2;
398 case '>': *type = 6; return 2;
399 }
400 }
401 if(!sstrcmp(token, S("not"))) {
402 *type = 0;
403 return 1;
404 }
405
406 if(!sstrcmp(token, S("=="))) {
407 *type = 7;
408 return 2;
409 }
410 if(!sstrcmp(token, S("!="))) {
411 *type = 8;
412 return 2;
413 }
414 if(!sstrcmp(token, S("<="))) {
415 *type = 9;
416 return 2;
417 }
418 if(!sstrcmp(token, S(">="))) {
419 *type = 10;
420 return 2;
421 }
422
423 if(!sstrcmp(token, S("and"))) {
424 *type = 11;
425 return 3;
426 }
427 if(!sstrcmp(token, S("or"))) {
428 *type = 12;
429 return 3;
430 }
431 if(!sstrcmp(token, S("xor"))) {
432 *type = 13;
433 return 3;
434 }
435
436 return 0;
437 }
438
439 int condition_eval(DavResource *res, DavQOp *cond, size_t len) {
440 DavQOp stack[128];
441 int stackpos = 0;
442 for(int i=0;i<len;i++) {
443 DavQOp op = cond[i];
444 switch(op.type) {
445 case DAVQOP_OPERATOR: {
446 if(op.intval == 0) {
447 // not operator
448 if(stackpos < 1) {
449 // error
450 printf("no data on stack\n");
451 return NULL;
452 }
453 int pos = stackpos-1;
454 if(stack[pos].type == DAVQOP_INTEGER) {
455 printf("not %" PRId64 "\n", stack[pos].intval);
456 stack[pos].intval = !stack[pos].intval;
457 } else {
458 // error
459 printf("wrong value for 'not' operator\n");
460 return NULL;
461 }
462 } else {
463 DavQOp val1 = stack[stackpos-2];
464 DavQOp val2 = stack[stackpos-1];
465 DavQOp result;
466 if(val1.type == DAVQOP_INTEGER) {
467 if(val2.type == DAVQOP_INTEGER) {
468 result = compare_intint(
469 op.intval,
470 val1.intval,
471 val2.intval);
472 } else {
473 result = compare_intstr(op.intval, val1, val2);
474 }
475 } else {
476 if(val2.type == DAVQOP_INTEGER) {
477 result = compare_strint(op.intval, val1, val2);
478 } else {
479 result = compare_strstr(op.intval, val1, val2);
480 }
481 }
482 stack[stackpos-2] = result;
483 stackpos--;
484 }
485 break;
486 }
487 case DAVQOP_STRING:
488 case DAVQOP_INTEGER:
489 case DAVQOP_TIME: {
490 if(op.type == DAVQOP_STRING) {
491 printf("put on stack: '%s'\n", op.val);
492 } else {
493 printf("put on stack[%d]: %" PRId64 "\n", stackpos, op.intval);
494 }
495 stack[stackpos++] = op;
496 break;
497 }
498 case DAVQOP_PROPERTY: {
499 sstr_t pname = sstrn(op.val, op.intval);
500 pname = sstrdup(pname);
501 char *property_value = dav_get_property(res, pname.ptr);
502 free(pname.ptr);
503 DavQOp value;
504 value.type = DAVQOP_STRING;
505 if(property_value) {
506 printf("put on stack: \"%s\"\n", property_value);
507 value.val = property_value;
508 value.intval = strlen(property_value);
509 } else {
510 printf("put on stack: null string\n");
511 value.val = NULL;
512 value.intval = 0;
513 }
514 stack[stackpos++] = value;
515 break;
516 }
517 case DAVQOP_RESPROP: {
518 sstr_t name = sstrn(op.val, op.intval);
519 DavQOp value;
520 value.type = DAVQOP_INTEGER;
521 value.val = NULL;
522 if(!sstrcmp(name, S("contentlength"))) {
523 printf("put contentlength\n");
524 value.intval = res->contentlength;
525 } else if(!sstrcmp(name, S("lastmodified"))) {
526 printf("put getlastmodified\n");
527 value.intval = res->lastmodified;
528 } else if(!sstrcmp(name, S("creationdate"))) {
529 value.intval = res->creationdate;
530 } else if(!sstrcmp(name, S("name"))) {
531 value.type = DAVQOP_STRING;
532 value.val = res->name;
533 value.intval = strlen(res->name);
534 } else if(!sstrcmp(name, S("path"))) {
535 value.type = DAVQOP_STRING;
536 value.val = res->path;
537 value.intval = strlen(res->path);
538 }
539 stack[stackpos++] = value;
540 break;
541 }
542 }
543 }
544 if(stackpos != 1) {
545 return 0;
546 }
547 DavQOp result = stack[0];
548 printf("result: %" PRId64 "\n", result.intval);
549 return (int)result.intval;
550 }
551
552 DavQOp compare_intint(int op, int64_t v1, int64_t v2) {
553 DavQOp res;
554 res.type = DAVQOP_INTEGER;
555 res.val = NULL;
556 res.intval = 0;
557 switch(op) {
558 case 5: {
559 // <
560 printf("compare: %" PRId64 " < %" PRId64 "\n", v1, v2);
561 res.intval = v1 < v2;
562 break;
563 }
564 case 6: {
565 // >
566 printf("compare: %" PRId64 " > %" PRId64 "\n", v1, v2);
567 res.intval = v1 > v2;
568 break;
569 }
570 case 7: {
571 // ==
572 printf("compare: %" PRId64 " == %" PRId64 "\n", v1, v2);
573 res.intval = v1 == v2;
574 break;
575 }
576 case 8: {
577 // !=
578 printf("compare: %" PRId64 " != %" PRId64 "\n", v1, v2);
579 res.intval = v1 != v2;
580 break;
581 }
582 case 9: {
583 // <=
584 printf("compare: %" PRId64 " <= %" PRId64 "\n", v1, v2);
585 res.intval = v1 <= v2;
586 break;
587 }
588 case 10: {
589 // >=
590 printf("compare: %" PRId64 " >= %" PRId64 "\n", v1, v2);
591 res.intval = v1 >= v2;
592 break;
593 }
594 case 11: {
595 // and
596 printf("compare: %" PRId64 " and %" PRId64 "\n", v1, v2);
597 res.intval = v1 && v2;
598 break;
599 }
600 case 12: {
601 // or
602 printf("compare: %" PRId64 " or %" PRId64 "\n", v1, v2);
603 res.intval = v1 || v2;
604 break;
605 }
606 case 13: {
607 // xor
608 printf("compare: %" PRId64 " xor %" PRId64 "\n", v1, v2);
609 res.intval = v1 ^ v2;
610 break;
611 }
612 }
613 return res;
614 }
615
616 DavQOp compare_strint(int op, DavQOp v1, DavQOp v2) {
617 // TODO
618 }
619
620 DavQOp compare_intstr(int op, DavQOp v1, DavQOp v2) {
621 // TODO
622 }
623
624 DavQOp compare_strstr(int op, DavQOp v1, DavQOp v2) {
625 DavQOp res;
626 res.type = DAVQOP_INTEGER;
627 res.val = NULL;
628 res.intval = 0;
629 sstr_t s1 = sstrn(v1.val, v1.intval);
630 sstr_t s2 = sstrn(v2.val, v2.intval);
631 switch(op) {
632 case 5: {
633 // <
634 printf("str compare: %.*s < %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
635 res.intval = s1.length < s2.length;
636 break;
637 }
638 case 6: {
639 // >
640 printf("str compare: %.*s > %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
641 res.intval = s1.length > s2.length;
642 break;
643 }
644 case 7: {
645 // ==
646 printf("str compare: %.*s == %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
647 res.intval = sstrcmp(s1, s2) == 0;
648 break;
649 }
650 case 8: {
651 // !=
652 printf("str compare: %.*s != %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
653 res.intval = sstrcmp(s1, s2) != 0;
654 break;
655 }
656 case 9: {
657 // <=
658 printf("str compare: %.*s <= %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
659 res.intval = s1.length <= s2.length;
660 break;
661 }
662 case 10: {
663 // >=
664 printf("str compare: %.*s >= %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
665 res.intval = s1.length >= s2.length;
666 break;
667 }
668 case 11: {
669 // and
670 printf("str compare: %.*s and %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
671 res.intval = s1.ptr && s2.ptr;
672 break;
673 }
674 case 12: {
675 // or
676 printf("str compare: %.*s or %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
677 res.intval = s1.ptr || s2.ptr;
678 break;
679 }
680 case 13: {
681 // xor
682 printf("str compare: %.*s xor %.*s\n", s1.length, s1.ptr, s2.length, s2.ptr);
683 res.intval = (int)s1.ptr ^ (int)s2.ptr;
684 break;
685 }
686 }
687 return res;
688 }

mercurial