UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <cx/string.h> 30 #include <cx/linked_list.h> 31 #include <cx/array_list.h> 32 #include <cx/compare.h> 33 34 #include "../public/nsapi.h" 35 36 #include "object.h" 37 #include "util.h" 38 #include "pool.h" 39 #include "../daemon/func.h" 40 41 42 43 httpd_object* object_new(pool_handle_t *pool, char *name) { 44 httpd_object *obj = pool_malloc(pool, sizeof(httpd_object)); 45 obj->pool = pool; 46 obj->name = name; 47 obj->path = NULL; 48 49 // create directive table 50 obj->dt = pool_calloc(pool, NUM_NSAPI_TYPES - 1, sizeof(struct dtable)); 51 obj->nd = NUM_NSAPI_TYPES - 1; 52 53 return obj; 54 } 55 56 void object_free(httpd_object *obj) { 57 //free(obj->name); 58 //free(obj->dt); 59 } 60 61 62 int object_add_directive(httpd_object *obj, directive *dir, int dt) { 63 dtable *l = object_get_dtable(obj, dt); 64 // allocate space for the new directive 65 if(l->ndir >= l->alloc) { 66 l->alloc += 8; 67 directive **drs = pool_realloc(obj->pool, l->dirs, (l->alloc)*sizeof(void*)); 68 if(!drs) { 69 l->alloc -= 8; 70 return -1; 71 } 72 l->dirs = drs; 73 } 74 75 // add directive 76 l->dirs[l->ndir++] = dir; 77 return 0; 78 } 79 80 81 /* objset functions */ 82 httpd_objset* objset_create(pool_handle_t *pool) { 83 httpd_objset *os = pool_malloc(pool, sizeof(httpd_objset)); 84 85 os->obj = pool_calloc(pool, 2, sizeof(void*)); 86 os->pos = 0; 87 88 return os; 89 } 90 91 void objset_add_object(pool_handle_t *p, httpd_objset *os, httpd_object *obj) { 92 if(os->pos != 0 && os->pos % 2 == 0) { 93 os->obj = pool_realloc(p, os->obj, (os->pos + 2) * sizeof(void*)); 94 } 95 os->obj[os->pos] = obj; 96 os->pos++; 97 } 98 99 void httpobjconf_add_object(HTTPObjectConfig *conf, httpd_object *obj) { 100 conf->nobj++; 101 conf->objects = realloc(conf->objects, conf->nobj * sizeof(void*)); 102 conf->objects[conf->nobj - 1] = obj; 103 } 104 105 106 void nsapi_context_next_stage(NSAPIContext *context) { 107 context->dtable_index = 0; 108 context->objset_index = -1; 109 context->last_req_code = REQ_NOACTION; 110 } 111 112 113 /* ------------------------------ Expression ------------------------------ */ 114 115 Expression* condition_create(pool_handle_t *pool, CxList *tokens) { 116 size_t pos = 0; 117 NSAPIExpression *expression = expr_parse_logical_expr(pool, tokens, &pos); 118 if(!expression || pos != tokens->size) { 119 return NULL; 120 } 121 122 return NULL; 123 } 124 125 126 typedef struct { 127 pool_handle_t *pool; 128 CxList *op_stack; 129 CxList *ex_stack; 130 CxList *tokens; 131 size_t *pos; 132 WSBool expect_value; 133 WSBool expect_arg; 134 } ExprParser; 135 136 typedef struct { 137 NSAPIExpressionOperator operator; 138 cxstring identifier; 139 int expect_value; 140 int open_parenthesis; 141 } ExprOpStackItem; 142 143 static void expr_free(pool_handle_t *pool, NSAPIExpression *expr) { 144 if(expr->left) { 145 expr_free(pool, expr->left); 146 } 147 if(expr->right) { 148 expr_free(pool, expr->right); 149 } 150 if(expr->type == NSAPI_EXPRESSION_STRING && expr->value.str.ptr) { 151 pool_free(pool, (char*)expr->value.str.ptr); 152 } else if(expr->type == NSAPI_EXPRESSION_VARIABLE && expr->value.var.ptr) { 153 pool_free(pool, (char*)expr->value.var.ptr); 154 } 155 pool_free(pool, expr); 156 } 157 158 static NSAPIExpressionOperator expr_operator(cxstring token) { 159 if(!cx_strcmp(token, cx_str(","))) { 160 return NSAPI_EXPRESSION_ARG; 161 } else if(!cx_strcmp(token, cx_str("+"))) { 162 return NSAPI_EXPRESSION_ADD; 163 } else if(!cx_strcmp(token, cx_str("-"))) { 164 return NSAPI_EXPRESSION_SUB; 165 } else if(!cx_strcmp(token, cx_str("*"))) { 166 return NSAPI_EXPRESSION_MUL; 167 } else if(!cx_strcmp(token, cx_str("/"))) { 168 return NSAPI_EXPRESSION_DIV; 169 } else if(!cx_strcmp(token, cx_str("%"))) { 170 return NSAPI_EXPRESSION_MOD; 171 } else if(!cx_strcmp(token, cx_str("."))) { 172 return NSAPI_EXPRESSION_STRCAT; 173 } else if(!cx_strcmp(token, cx_str("not")) || !cx_strcmp(token, cx_str("!"))) { 174 return NSAPI_EXPRESSION_NOT; 175 } else if(!cx_strcmp(token, cx_str("and")) || !cx_strcmp(token, cx_str("&&"))) { 176 return NSAPI_EXPRESSION_AND; 177 } else if(!cx_strcmp(token, cx_str("or")) || !cx_strcmp(token, cx_str("||"))) { 178 return NSAPI_EXPRESSION_OR; 179 } else if(!cx_strcmp(token, cx_str("xor")) || !cx_strcmp(token, cx_str("^"))) { 180 return NSAPI_EXPRESSION_XOR; 181 } else if(!cx_strcmp(token, cx_str("=="))) { 182 return NSAPI_EXPRESSION_EQ; 183 } else if(!cx_strcmp(token, cx_str("!="))) { 184 return NSAPI_EXPRESSION_NEQ; 185 } else if(!cx_strcmp(token, cx_str(">"))) { 186 return NSAPI_EXPRESSION_GT; 187 } else if(!cx_strcmp(token, cx_str("<"))) { 188 return NSAPI_EXPRESSION_LT; 189 } else if(!cx_strcmp(token, cx_str(">="))) { 190 return NSAPI_EXPRESSION_GE; 191 } else if(!cx_strcmp(token, cx_str("<="))) { 192 return NSAPI_EXPRESSION_LE; 193 } else if(!cx_strcmp(token, cx_str("="))) { 194 return NSAPI_EXPRESSION_WILDCARD_MATCH; 195 } else if(!cx_strcmp(token, cx_str("=~"))) { 196 return NSAPI_EXPRESSION_REGEX_MATCH; 197 } else if(!cx_strcmp(token, cx_str("!~"))) { 198 return NSAPI_EXPRESSION_REGEX_MISMATCH; 199 } else if(!cx_strcmp(token, cx_str("defined"))) { 200 return NSAPI_EXPRESSION_VALUE_DEFINED; 201 } else if(!cx_strcmp(token, cx_str("-d"))) { 202 return NSAPI_EXPRESSION_DIR_EXISTS; 203 } else if(!cx_strcmp(token, cx_str("-e"))) { 204 return NSAPI_EXPRESSION_FILE_DIR_EXISTS; 205 } else if(!cx_strcmp(token, cx_str("-f"))) { 206 return NSAPI_EXPRESSION_FILE_EXISTS; 207 } else if(!cx_strcmp(token, cx_str("-l"))) { 208 return NSAPI_EXPRESSION_SYMLINK_EXISTS; 209 } else if(!cx_strcmp(token, cx_str("-r"))) { 210 return NSAPI_EXPRESSION_FILE_READABLE; 211 } else if(!cx_strcmp(token, cx_str("-s"))) { 212 return NSAPI_EXPRESSION_FILE_SIZE; 213 } 214 return NSAPI_EXPRESSION_NOOP; 215 } 216 217 static int token_is_int(cxstring token) { 218 if(token.length == 0) { 219 return 0; 220 } 221 222 size_t start = 0; 223 if(token.ptr[0] == '-' || token.ptr[0] == '+') { 224 if(token.length < 2) { 225 return 0; 226 } 227 start++; 228 } 229 230 for(size_t i=start;i<token.length;i++) { 231 if(!isdigit(token.ptr[i])) { 232 return 0; 233 } 234 } 235 return 1; 236 } 237 238 static int expr_set_value(pool_handle_t *pool, NSAPIExpression *expr, cxstring token) { 239 if(token.length >= 2 && token.ptr[0] == '\"' && token.ptr[token.length-1] == '\"') { 240 expr->value.str = cx_strcast(cx_strdup_a(pool_allocator(pool), cx_strsubsl(token, 1, token.length-2))); 241 expr->type = NSAPI_EXPRESSION_STRING; 242 } else if(token.length >= 2 && token.ptr[0] == '$' && isalpha(token.ptr[1])) { 243 expr->value.var = cx_strcast(cx_strdup_a(pool_allocator(pool), cx_strsubs(token, 1))); 244 expr->type = NSAPI_EXPRESSION_VARIABLE; 245 } else if(token_is_int(token)) { 246 if(!util_strtoint(token.ptr, &expr->value.i)) { 247 return 1; 248 } 249 expr->type = NSAPI_EXPRESSION_INT; 250 } else if(!strcmp(token.ptr, "true")) { 251 expr->type = NSAPI_EXPRESSION_BOOL; 252 expr->value.b = 1; 253 } else if(!strcmp(token.ptr, "false")) { 254 expr->type = NSAPI_EXPRESSION_BOOL; 255 expr->value.b = 0; 256 } else { 257 return 1; 258 } 259 // TODO: double 260 return 0; 261 } 262 263 cxstring expr_next_token(CxList *tokens, size_t *pos) { 264 cxstring *token = cxListAt(tokens, *pos); 265 if(token) { 266 (*pos)++; 267 return *token; 268 } 269 return (cxstring){NULL, 0}; 270 } 271 272 NSAPIExpression* expr_parser_pop(ExprParser *parser) { 273 CxList *stack = parser->ex_stack; 274 if(stack->size == 0) { 275 return NULL; 276 } 277 NSAPIExpression *ret = *((NSAPIExpression**)cxListAt(stack, stack->size-1)); 278 cxListRemove(stack, stack->size-1); 279 return ret; 280 } 281 282 // takes items from ex_stack and adds a new operator expression to ex_stack 283 static int expr_add_operator(ExprParser *parser, ExprOpStackItem *op) { 284 NSAPIExpression *exp = pool_malloc(parser->pool, sizeof(NSAPIExpression)); 285 exp->operator = op->operator; 286 // op->expect_value == TRUE means, that the operator was found in a case 287 // a value was expected. 288 // For example: 1 + - 2 289 // After + a value is expected, but there is the - operator 290 // in that case, the - operator is a unary expression 291 if(op->expect_value) { 292 // We expected a value but got an operator? This must be an unary operator 293 294 if(op->operator == NSAPI_EXPRESSION_ARG && !parser->expect_arg) { 295 // simplify unary arg 296 pool_free(parser->pool, exp); 297 parser->expect_value = TRUE; 298 parser->expect_arg = FALSE; 299 return 0; 300 } 301 302 exp->type = NSAPI_EXPRESSION_UNARY; 303 exp->left = expr_parser_pop(parser); 304 exp->right = NULL; 305 } else if(exp->operator == NSAPI_EXPRESSION_CALL) { 306 // identifiers are added as call, but if they land here, it is 307 // actually just an identifier 308 exp->operator = NSAPI_EXPRESSION_NOOP; 309 exp->left = NULL; 310 exp->right = NULL; 311 exp->type = NSAPI_EXPRESSION_IDENTIFIER; 312 exp->value.identifier = op->identifier; 313 } else { 314 // binary operator 315 exp->type = NSAPI_EXPRESSION_BINARY; 316 exp->right = expr_parser_pop(parser); 317 exp->left = expr_parser_pop(parser); 318 } 319 320 if(!exp->left && !exp->right && exp->operator != NSAPI_EXPRESSION_NOOP) { 321 return 1; // error 322 } 323 324 cxListAdd(parser->ex_stack, &exp); 325 326 parser->expect_value = TRUE; 327 parser->expect_arg = FALSE; 328 return 0; 329 } 330 331 static int expr_add_func(ExprParser *parser, ExprOpStackItem *func) { 332 NSAPIExpression *exp = pool_malloc(parser->pool, sizeof(NSAPIExpression)); 333 if(!exp) { 334 return 1; 335 } 336 exp->type = NSAPI_EXPRESSION_IDENTIFIER; 337 exp->operator = NSAPI_EXPRESSION_CALL; 338 exp->left = NULL; 339 exp->right = NULL; 340 exp->value.str = func->identifier; 341 342 if(parser->ex_stack->size > 0) { 343 NSAPIExpression *top = *((NSAPIExpression**)cxListAt(parser->ex_stack, parser->ex_stack->size - 1)); 344 if(top && top->operator == NSAPI_EXPRESSION_ARG) { 345 exp->left = top; 346 cxListRemove(parser->ex_stack, parser->ex_stack->size - 1); 347 } 348 } 349 350 if(cxListAdd(parser->ex_stack, &exp)) { 351 return 1; 352 } 353 parser->expect_value = FALSE; 354 return 0; 355 } 356 357 // converts the token to a value expression (int, bool, str, ...) 358 // and adds it to parser->ex_stack 359 // sets parser->expect_value to false 360 static int expr_add_value(ExprParser *parser, cxstring token) { 361 NSAPIExpression *exp = pool_malloc(parser->pool, sizeof(NSAPIExpression)); 362 ZERO(exp, sizeof(NSAPIExpression)); 363 if(expr_set_value(parser->pool, exp, token)) { 364 return 1; 365 } 366 367 cxListAdd(parser->ex_stack, &exp); 368 if(parser->expect_arg) { 369 ExprOpStackItem argList; 370 argList.expect_value = TRUE; 371 argList.identifier = (cxstring){NULL, 0}; 372 argList.open_parenthesis = FALSE; 373 argList.operator = NSAPI_EXPRESSION_ARG; 374 if(expr_add_operator(parser, &argList)) { 375 return 1; 376 } 377 } 378 379 parser->expect_value = FALSE; 380 parser->expect_arg = FALSE; 381 return 0; 382 } 383 384 static int token_is_identifier(cxstring token) { 385 if(token.length == 0) { 386 return 0; 387 } 388 389 if(!isalpha(token.ptr[0])) { 390 return 0; 391 } 392 393 for(int i=1;i<token.length;i++) { 394 if(!isalnum(token.ptr[i])) { 395 return 0; 396 } 397 } 398 399 if(!cx_strcmp(token, cx_str("true")) || !cx_strcmp(token, cx_str("false"))) { 400 return 0; 401 } 402 403 return 1; 404 } 405 406 407 static NSAPIExpression* expr_parse_expr(ExprParser *parser) { 408 CxList *op_stack = parser->op_stack; 409 CxList *ex_stack = parser->ex_stack; 410 411 // Shunting yard algorithm 412 cxstring token = expr_next_token(parser->tokens, parser->pos); 413 for(;token.ptr;token=expr_next_token(parser->tokens, parser->pos)) { 414 NSAPIExpressionOperator op = expr_operator(token); 415 if(op != NSAPI_EXPRESSION_NOOP) { 416 ExprOpStackItem new_op; 417 new_op.operator = op; 418 new_op.identifier = (cxstring){NULL,0}; 419 new_op.expect_value = parser->expect_value; 420 new_op.open_parenthesis = FALSE; 421 while(op_stack->size > 0) { 422 ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1); 423 if(stack_item->operator == NSAPI_EXPRESSION_NOOP) { 424 break; 425 } 426 // check presedence 427 if(op >= stack_item->operator) { 428 break; 429 } 430 if(expr_add_operator(parser, stack_item)) { 431 return NULL; 432 } 433 cxListRemove(op_stack, op_stack->size-1); 434 } 435 cxListAdd(op_stack, &new_op); 436 parser->expect_value = TRUE; 437 parser->expect_arg = FALSE; 438 } else if(token.length == 1 && token.ptr[0] == '(') { 439 ExprOpStackItem *prev_op = NULL; 440 if(op_stack->size > 0) { 441 prev_op = cxListAt(op_stack, op_stack->size - 1); 442 } 443 444 if(prev_op && prev_op->operator == NSAPI_EXPRESSION_CALL) { 445 // function call open parenthesis 446 // we don't need to add a new op stack item, just mark function 447 // call as open parenthesis 448 prev_op->open_parenthesis = TRUE; 449 parser->expect_arg = TRUE; 450 } else { 451 ExprOpStackItem new_op; 452 new_op.operator = NSAPI_EXPRESSION_NOOP; 453 new_op.identifier = (cxstring){NULL,0}; 454 new_op.expect_value = 0; 455 new_op.open_parenthesis = TRUE; 456 cxListAdd(op_stack, &new_op); 457 } 458 parser->expect_value = TRUE; 459 } else if(token.length == 1 && token.ptr[0] == ')') { 460 int found_open_bracket = FALSE; 461 ExprOpStackItem stack_item; 462 while(op_stack->size > 0) { 463 ExprOpStackItem *stack_item_ptr = cxListAt(op_stack, op_stack->size-1); 464 stack_item = *stack_item_ptr; 465 cxListRemove(op_stack, op_stack->size-1); 466 if(stack_item.open_parenthesis) { 467 found_open_bracket = TRUE; 468 break; 469 } else { 470 if(expr_add_operator(parser, &stack_item)) { 471 return NULL; 472 } 473 } 474 } 475 if(!found_open_bracket) { 476 return NULL; 477 } 478 if(stack_item.operator == NSAPI_EXPRESSION_CALL) { 479 if(expr_add_func(parser, &stack_item)) { 480 return NULL; 481 } 482 } 483 parser->expect_value = FALSE; 484 parser->expect_arg = FALSE; 485 } else if(token_is_identifier(token)) { 486 ExprOpStackItem new_op; 487 new_op.operator = NSAPI_EXPRESSION_CALL; 488 new_op.identifier = token; 489 new_op.expect_value = 0; 490 new_op.open_parenthesis = FALSE; 491 cxListAdd(op_stack, &new_op); 492 parser->expect_value = FALSE; 493 parser->expect_arg = FALSE; 494 } else { 495 if(expr_add_value(parser, token)) { 496 return NULL; 497 } 498 } 499 } 500 501 while(op_stack->size > 0) { 502 ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1); 503 if(stack_item->open_parenthesis) { 504 return NULL; 505 } 506 if(expr_add_operator(parser, stack_item)) { 507 return NULL; 508 } 509 cxListRemove(op_stack, op_stack->size-1); 510 } 511 512 if(ex_stack->size != 1) { 513 return NULL; 514 } 515 516 NSAPIExpression **ret = cxListAt(ex_stack, 0); 517 return *ret; 518 } 519 520 NSAPIExpression* expr_parse_logical_expr(pool_handle_t *pool, CxList *tokens, size_t *pos) { 521 CxList *op_stack = cxArrayListCreate(pool_allocator(pool), NULL, sizeof(ExprOpStackItem), 32); 522 CxList *ex_stack = cxArrayListCreate(pool_allocator(pool), NULL, sizeof(NSAPIExpression*), 32); 523 524 ExprParser parser; 525 parser.pool = pool; 526 parser.op_stack = op_stack; 527 parser.ex_stack = ex_stack; 528 parser.tokens = tokens; 529 parser.pos = pos; 530 parser.expect_value = TRUE; 531 parser.expect_arg = FALSE; 532 533 NSAPIExpression *ret = expr_parse_expr(&parser); 534 cxListDestroy(op_stack); 535 cxListDestroy(ex_stack); 536 537 return ret; 538 } 539 540 541 542 int condition_evaluate(Condition *condition, Session *sn, Request *rq) { 543 return 1; 544 } 545