Fri, 23 Oct 2015 17:28:09 +0200
implemented range requests
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2013 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <ucx/string.h> #include "../public/nsapi.h" #include "object.h" #include "pool.h" #include "../daemon/func.h" httpd_object* object_new(pool_handle_t *pool, char *name) { // TODO: Speicherverwaltung httpd_object *obj = pool_malloc(pool, sizeof(httpd_object)); obj->pool = pool; obj->name = name; obj->path = NULL; // create directive table obj->dt = pool_calloc(pool, NUM_NSAPI_TYPES - 1, sizeof(struct dtable)); obj->nd = NUM_NSAPI_TYPES - 1; return obj; } void object_free(httpd_object *obj) { //free(obj->name); //free(obj->dt); } void object_add_directive(httpd_object *obj, directive *dir, int dt) { dtable *l = object_get_dtable(obj, dt); // allocate space for the new directive //l->dirs = realloc(l->dirs, (l->ndir+1)*sizeof(void*)); // TODO: use realloc directive **drs = pool_malloc(obj->pool, (l->ndir+1)*sizeof(void*)); for(int i=0;i<l->ndir;i++) { drs[i] = l->dirs[i]; } if(l->dirs != NULL) { pool_free(obj->pool, l->dirs); } l->dirs = drs; // add directive l->dirs[l->ndir] = dir; l->ndir++; } /* objset functions */ httpd_objset* objset_create(pool_handle_t *pool) { httpd_objset *os = pool_malloc(pool, sizeof(httpd_objset)); os->obj = pool_calloc(pool, 2, sizeof(void*)); os->pos = 0; return os; } void objset_add_object(pool_handle_t *p, httpd_objset *os, httpd_object *obj) { if(os->pos != 0 && os->pos % 2 == 0) { os->obj = pool_realloc(p, os->obj, (os->pos + 2) * sizeof(void*)); } os->obj[os->pos] = obj; os->pos++; } void httpobjconf_add_object(HTTPObjectConfig *conf, httpd_object *obj) { conf->nobj++; conf->objects = realloc(conf->objects, conf->nobj * sizeof(void*)); conf->objects[conf->nobj - 1] = obj; } void nsapi_context_next_stage(NSAPIContext *context) { context->dtable_index = 0; context->objset_index = -1; context->last_req_code = REQ_NOACTION; } Condition* condition_from_str(pool_handle_t *pool, char *expr, size_t len) { Condition *cond = pool_malloc(pool, sizeof(Condition)); cond->expression = NULL; cond->parent = NULL; cond->index = 0; printf("Expression: {"); fwrite(expr, len, 1, stdout); printf("}\n"); cond->expression = expression_from_str(pool, expr, len); return cond; } Expression* expression_from_str(pool_handle_t *pool, char *expr, size_t len) { char str_qc = 0; // 0 or the quote char char c_brace = 0; int brace_count = 0; Expression *expression = pool_malloc(pool, sizeof(Expression)); ZERO(expression, sizeof(Expression)); Expression *ex = expression; /* * 0: first operand * 1: second operand * 2: next expression */ int optoken = 0; int token_start = 0; // index of token begin int i; for(i=0;i<=len;i++) { char c = i == len ? ' ' : expr[i]; if(brace_count > 0) { if(c == c_brace) { char *token = expr + token_start; int token_len = i - token_start; printf("Token {"); fwrite(token, token_len, 1, stdout); printf("}\n"); // reset token_start token_start = -1; } } else { if((c == '(' || c == '[') && !str_qc) { brace_count++; if(brace_count == 1) { if(c == '(') { c_brace = ')'; } else { c_brace = ']'; } token_start = i+1; } } else if(c == str_qc) { str_qc = 0; } else if(c == '\'' || c == '\"') { if(token_start != -1) { // error printf("error: token_start != -1"); return NULL; } token_start = i; str_qc = c; } else if(c < 33 && token_start != -1 && !str_qc) { char *token = expr + token_start; int token_len = i - token_start; //printf("Token {"); //fwrite(token, token_len, 1, stdout); //printf("}[%u]\n", token_len); int token_type = expr_token_type(token, token_len); switch(optoken) { case 0: { // first operand if(token_type == 1) { ex->optype[1] = EXPR_OP_NULL; ex->opdata[1] = NULL; ex->expr_operator = expr_operator( token, token_len); break; } else { expr_set_op(pool, &ex->optype[0], &ex->opdata[0], token, token_len); } optoken++; break; } case 1: { // second operand if(token_type == 1) { Operator op = expr_operator( token, token_len); if(op != OP_AND && op != OP_OR && op != OP_XOR) { ex->expr_operator = op; break; } // else: jump to case 2 } else if(ex->expr_operator != 0) { expr_set_op(pool, &ex->optype[1], &ex->opdata[1], token, token_len); optoken++; break; } else { // syntax error fprintf(stderr, "expr: missing operator(1)\n"); return NULL; } } case 2: { // next if(token_type == 1) { ex->next_operator = expr_operator( token, token_len); optoken = 0; Expression *next_expr = pool_malloc( pool, sizeof(Expression)); ZERO(next_expr, sizeof(Expression)); ex->next = next_expr; ex = next_expr; break; } else { // syntax error fprintf(stderr, "expr: missing operator(2)\n"); return NULL; } } } // reset token_start token_start = -1; } else if(c > 32 && token_start == -1) { token_start = i; } } } return expression; } Operator expr_operator(char *token, size_t len) { if(!strncmp(token, "not", len) || !strncmp(token, "!", len)) { return OP_NOT; } else if(!strncmp(token, "and", len) || !strncmp(token, "&&", len)) { return OP_AND; } else if(!strncmp(token, "or", len) || !strncmp(token, "||", len)) { return OP_OR; } else if(!strncmp(token, "xor", len) || !strncmp(token, "^", len)) { return OP_XOR; } else if(!strncmp(token, "=", len)) { return OP_WILDCARD; } else if(!strncmp(token, "=~", len)) { return OP_REGEX; } else if(!strncmp(token, "!~", len)) { return OP_NREGEX; } else if(!strncmp(token, "+", len)) { return OP_ADD; } else if(!strncmp(token, "-", len)) { return OP_SUB; } else if(!strncmp(token, ".", len)) { return OP_CAT; } else if(!strncmp(token, "defined", len)) { return OP_DEF; } else if(!strncmp(token, "-d", len)) { return OP_DEXISTS; } else if(!strncmp(token, "-e", len)) { return OP_FDEXISTS; } else if(!strncmp(token, "-f", len)) { return OP_FEXISTS; } else if(!strncmp(token, "-l", len)) { return OP_LEXISTS; } else if(!strncmp(token, "-r", len)) { return OP_READABLE; } else if(!strncmp(token, "-s", len)) { return OP_FSIZE; } else if(!strncmp(token, "-U", len)) { return OP_UMAP; } else if(!strncmp(token, "<", len)) { return OP_LESS; } else if(!strncmp(token, "<=", len)) { return OP_LESSEQ; } else if(!strncmp(token, ">", len)) { return OP_GREATER; } else if(!strncmp(token, ">=", len)) { return OP_GREATEREQ; } else if(!strncmp(token, "lt", len)) { return OP_STRLESS; } else if(!strncmp(token, "le", len)) { return OP_STRLESSEQ; } else if(!strncmp(token, "gt", len)) { return OP_GREATER; } else if(!strncmp(token, "ge", len)) { return OP_STRGREATEREQ; } else if(!strncmp(token, "==", len)) { return OP_EQUAL; } else if(!strncmp(token, "!=", len)) { return OP_NOTEQUAL; } else if(!strncmp(token, "eq", len)) { return OP_STREQUAL; } else if(!strncmp(token, "ne", len)) { return OP_STRNOTEQUAL; } return OP_NOOP; } int expr_token_type(char *token, size_t len) { char c = token[0]; if(c == '$' || c == '"' || c == '\'') { return 0; } else { if(expr_operator(token, len) == OP_NOOP) { return 0; } else { return 1; } } } void expr_set_op(pool_handle_t *pool, OperandType *type, void **val, char *token, size_t len) { char c = token[0]; if(c == '$') { *type = EXPR_OP_VAR; sstr_t s = sstrn(token+1, len-1); s = sstrdup_pool(pool, s); *val = s.ptr; } else if(c == '"' || c == '\'') { *type = EXPR_OP_STRING; sstr_t s = sstrn(token+1, len-2); //s = sstrdup_pool(pool, s); *val = s.ptr; } } int condition_evaluate(Condition *condition, Session *sn, Request *rq) { return expression_evaluate(condition->expression, sn, rq); } int expression_evaluate(Expression *ex, Session *sn, Request *rq) { int ret = 0; int last_eval = 0; Operator expr_lconn = OP_NOOP; // logical connective between 2 expressions while(ex) { int eval = 0; if(!ex->opdata[1]) { /* * Only one operand. Can be: * boolean with or without not operator * defined operator * file/directory/link exists operator */ int not_op = 0; switch(ex->expr_operator) { case OP_NOT: { not_op = 1; } case OP_NOOP: { // must be boolean // TODO } } } else { void *ops[2]; VarType types[2]; for(int i=0;i<2;i++) { switch(ex->optype[i]) { case EXPR_OP_STRING: { ops[i] = ex->opdata[i]; types[i] = VAR_STRING; break; } case EXPR_OP_VAR: { if(!expr_get_var(ex->opdata[i], sn, rq, &ops[i], &types[i])); break; } } } if(types[0] != types[1]) { fprintf(stderr, "Condition: incompatible types\n"); return 0; } if(types[0] == VAR_STRING) { switch(ex->expr_operator) { case OP_WILDCARD: { eval = !shexp_match(ops[0], ops[1]); break; } case OP_STREQUAL: { eval = !strcmp(ops[0], ops[1]); break; } } } } // evaluate logical connective between last 2 expressions switch(expr_lconn) { case OP_AND: { if(!last_eval || !eval) { return 0; } break; } case OP_OR: { if(!last_eval && !eval) { return 0; } } case OP_XOR: { if(last_eval == eval) { return 0; } } } last_eval = eval; // switch to next expression if(ex->next) { expr_lconn = ex->next_operator; } ex = ex->next; } return last_eval; } int expr_get_var(char *var, Session *sn, Request *rq, void **val, VarType *t) { if(!strcmp(var, "path")) { char *ppath = pblock_findval("ppath", rq->vars); if(ppath) { *t = VAR_STRING; *val = ppath; return 1; } } else if(!strcmp(var, "uri")) { char *uri = pblock_findval("uri", rq->reqpb); if(uri) { *t = VAR_STRING; *val = uri; return 1; } } *val = NULL; *t = 0; return 0; }