Sun, 15 Jan 2012 17:00:16 +0100
New configuration file parser
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2011 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 "../public/nsapi.h" #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/mman.h> #include "../ucx/string.h" #include "httplistener.h" #include "conf.h" #include "func.h" #include "vserver.h" #include "../util/pblock.h" #include "../config/objconf.h" VirtualServer *default_vs; void load_init_conf(char *file) { printf("load_init_conf\n"); pool_handle_t *pool = pool_create(); FILE *in = fopen("conf/init.conf", "r"); if(in == NULL) { fprintf(stderr, "Cannot open conf/init.conf\n"); return; } char buf[512]; buf[0] = 0; int len = 512; while(!feof(in)) { fgets(buf, len, in); if(*buf == 0) { continue; } char *ptr; if((ptr = strrchr(buf, '\n'))) { ptr[0] = 0; } sstr_t line = string_trim(sstr(buf)); if(line.length > 0) { sstr_t type; directive *d = parse_directive(pool, line, &type); if(sstrcmp(type, sstr("Init"))) { d->func->func(d->param, NULL, NULL); } } } } void load_server_conf(char *file) { printf("load_server_conf\n"); ListenerConfig *conf = malloc(sizeof(ListenerConfig)); conf->port = 9090; conf->nacceptors = 1; conf->name = "default"; http_listener_new(conf); // virtual server default_vs = vs_new(); // load obj.conf default_vs->objects = load_obj_conf("conf/obj.conf"); default_vs->default_obj_name = "default"; // begin objset test /* httpd_objset *objset = default_vs->objset; for(int i=0;i<objset->pos;i++) { httpd_object *obj = objset->obj[i]; printf("<object [%s]>\n", obj->name); for(int j=0;j<obj->nd;j++) { dtable *dt; switch(j) { case NSAPIAuthTrans: { printf(" Get AuthTrans Directives\n"); dt = object_get_dtable(obj, NSAPIAuthTrans); break; } case NSAPINameTrans: { printf(" Get NameTrans Directives\n"); dt = object_get_dtable(obj, NSAPINameTrans); break; } case NSAPIPathCheck: { printf(" Get PathCheck Directives\n"); dt = object_get_dtable(obj, NSAPIPathCheck); break; } case NSAPIService: { printf(" Get Service Directives\n"); dt = object_get_dtable(obj, NSAPIService); break; } default: { printf("j: %d\n", j); dt = object_get_dtable(obj, j); break; } } if(dt != NULL) { printf(" dtable[%d].length = %d\n", dt, dt->ndir); } else { continue; } for(int k=0;k<dt->ndir;k++) { directive *d = dt->directive[k]; if(d == NULL) { printf("d is null\n"); } else { printf(" Directive[%d].name = %s\n", d, d->func->name); } } } } */ // end objset test } VirtualServer* conf_get_default_vs() { return default_vs; } HTTPObjectConfig* load_obj_conf(char *file) { printf("load_obj_conf\n"); // new conf function test ObjectConfig *cfg = load_object_config(file); if(cfg == NULL) { return NULL; } /* create object config */ HTTPObjectConfig *conf = calloc(sizeof(HTTPObjectConfig), 1); conf->pool = pool_create(); /* convert ObjectConfig to HTTPObjectConfig */ /* add objects */ conf->nobj = ucx_dlist_size(cfg->objects); conf->objects = calloc(1, sizeof(httpd_object*)); UcxDlist *objlist = cfg->objects; int i = 0; while(objlist != NULL) { ConfigObject *cob = objlist->data; /* get name and ppath */ char *name = NULL; char *ppath = NULL; if(cob->name.length > 0) { name = sstrdub(cob->name).ptr; } if(cob->ppath.length > 0) { ppath = sstrdub(cob->ppath).ptr; } /* create and add object */ httpd_object *obj = object_new(name); obj->path = NULL; conf->objects[i] = obj; /* add directives */ for(int i=0;i<6;i++) { UcxDlist *dirs = cob->directives[i]; while(dirs != NULL) { ConfigDirective *cfgdir = dirs->data; directive *d = malloc(sizeof(directive)); d->cond = NULL; d->param = pblock_create_pool(conf->pool, 8); /* add params */ UcxList *param = cfgdir->param; while(param != NULL) { ConfigParam *p = param->data; pblock_nvlinsert( p->name.ptr, p->name.length, p->value.ptr, p->value.length, d->param); param = param->next; } /* get function */ char *func_name = pblock_findval("fn", d->param); d->func = get_function(func_name); dirs = dirs->next; /* add function to dtable */ object_add_directive(obj, d, cfgdir->type_num); } } /* next */ i++; objlist = objlist->next; } return conf; } void obj_conf_parse_line(ObjectConfParser *parser, sstr_t line) { //printf("{%s}[%d]\n", line.ptr, line.length); if(line.ptr[0] == '#') { return; } if(line.length < 3) { // to short for everything fprintf(stderr, "obj.conf: line to short \"%s\"\n", line.ptr); return; } // TODO: ersetzen if(line.ptr[0] == '<') { if(line.ptr[1] == '/') { // end tag if(line.ptr[2] == 'O' && parser->obj != NULL) { // end of Object httpobjconf_add_object(parser->conf, parser->obj); parser->obj = NULL; return; } } else { // new tag httpd_object *obj = parse_new_object_tag(line); parser->obj = obj; } } else { // directive sstr_t dtype; directive *d = parse_directive(parser->conf->pool, line, &dtype); int dt = get_directive_type_from_string(dtype); object_add_directive(parser->obj, d, dt); } } /* utils */ sstr_t string_trim(sstr_t string) { sstr_t newstr = string; int nsoff = 0; int l = 1; for(int i=0;i<string.length;i++) { char c = string.ptr[i]; if(l) { /* leading whitespace */ if(c > 32) { l = 0; nsoff = i; newstr.ptr = &string.ptr[i]; newstr.length = string.length - nsoff; } } else { /* trailing whitespace */ if(c > 32) { newstr.length = (i - nsoff) + 1; } } } return newstr; } httpd_object* parse_new_object_tag(sstr_t line) { int i = 0; int b = 0; sstr_t name; sstr_t value; char *obj_name = NULL; char *obj_ppath = NULL; for(;i<line.length;i++) { if(line.ptr[i] < 33) { b = 1; } else if(b == 1) { break; } } if(!b || line.ptr[i] < 33) { printf("1\n"); return NULL; } b = 0; /* parse name=value params */ for(;i<line.length;i++) { if(line.ptr[i] == '>') { break; } /* get name */ name.ptr = line.ptr + i; for(;i<line.length;i++) { if(line.ptr[i] == '=') { b = 1; i++; break; } } if(!b) { printf("2\n"); return NULL; } name.length = line.ptr + i - name.ptr - 1; if(line.ptr[i] == '\"') { i++; // TODO: Bug wenn end of line - wird nicht erkannt! } value.ptr = line.ptr + i; for(;i<line.length;i++) { char c = line.ptr[i]; if(c < 33 || c == '\"' || c == '>') { b = 1; break; } } if(!b) { printf("3\n"); return NULL; } value.length = line.ptr + i - value.ptr; if(sstrcmp(name, sstrn("name", 4)) == 0) { obj_name = sstrdub(value).ptr; } else if (sstrcmp(name, sstrn("ppath", 5)) == 0) { obj_ppath = sstrdub(value).ptr; } /* printf("name: [%d]{", name.length); fwrite(name.ptr, 1, name.length, stdout); printf("}\n"); printf("value: [%d]{", value.length); fwrite(value.ptr, 1, value.length, stdout); printf("}\n"); */ char c = line.ptr[i]; if(c == '>') { break; } else { i++; } } if(obj_name != NULL || obj_ppath != NULL) { httpd_object *o = object_new(obj_name); o->path = obj_ppath; return o; } return NULL; } directive* parse_directive(pool_handle_t *pool, sstr_t line, sstr_t *type) { int i = 0; int b = 0; sstr_t directive_type = line; directive *directive = malloc(sizeof(directive)); directive->cond = NULL; directive->param = pblock_create_pool(pool, 8); for(;i<line.length;i++) { if(line.ptr[i] < 33) { b = 1; directive_type.length = i; if(directive_type.length <= 0) { fprintf(stderr, "parse error: cannot parse directive\n"); return NULL; } } else if(b == 1) { break; } } /* parse name=value params */ sstr_t name; sstr_t value; for(;i<line.length;i++) { /* get name */ name.ptr = line.ptr + i; for(;i<line.length;i++) { if(line.ptr[i] == '=') { b = 1; i++; break; } } if(!b) { printf("2\n"); return NULL; } name.length = line.ptr + i - name.ptr - 1; if(line.ptr[i] == '\"') { i++; // TODO: Bug wenn end of line - wird nicht erkannt! } value.ptr = line.ptr + i; for(;i<line.length;i++) { char c = line.ptr[i]; if(c < 33 || c == '\"') { b = 1; break; } } if(!b) { printf("3\n"); return NULL; } value.length = line.ptr + i - value.ptr; name = string_trim(name); value = string_trim(value); /* insert name and value into directive pblock */ pblock_nvlinsert( name.ptr, name.length, value.ptr, value.length, directive->param); } /* get function */ char *func_name = pblock_findval("fn", directive->param); directive->func = get_function(func_name); *type = directive_type; return directive; } int get_directive_type_from_string(sstr_t type) { /* get nsapi function type */ int dt = -1; if(sstrcmp(type, sstr("AuthTrans")) == 0) { dt = 0; } else if(sstrcmp(type, sstr("NameTrans")) == 0) { dt = 1; } else if(sstrcmp(type, sstr("PathCheck")) == 0) { dt = 2; } else if(sstrcmp(type, sstr("ObjectType")) == 0) { dt = 3; } else if(sstrcmp(type, sstr("Service")) == 0) { dt = 4; } else if(sstrcmp(type, sstr("AddLog")) == 0) { dt = 5; } return dt; }