Sun, 15 Jan 2012 17:00:16 +0100
New configuration file parser
--- a/src/server/Makefile Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/Makefile Sun Jan 15 17:00:16 2012 +0100 @@ -41,29 +41,32 @@ include safs/objs.mk include webdav/objs.mk include daemon/objs.mk +include config/objs.mk -MAINOBJS = $(UCXOBJS) $(UTILOBJS) $(SAFOBJS) $(DAVOBJS) $(DAEMONOBJS) +MAINOBJS = $(UCXOBJS) $(UTILOBJS) $(SAFOBJS) $(DAVOBJS) $(DAEMONOBJS) $(CONFOBJS) -OBJ_DIRS = daemon safs ucx util webdav +OBJ_DIRS = daemon safs ucx util webdav config MK_OBJ_DIRS = $(OBJ_DIRS:%=$(OBJ_DIR)server/%) +MK_OBJ_DIRS += $(BUILD_ROOT)work/bin preparation: $(MK_OBJ_DIRS) - mkdir -p $(BUILD_ROOT)work/bin $(MK_OBJ_DIRS): mkdir -p $@ -$(MAIN_TARGET): $(DAEMONOBJS) $(UCXOBJS) $(UTILOBJS) $(SAFOBJS) $(DAVOBJS) +$(MAIN_TARGET): $(MAINOBJS) CC -o $(MAIN_TARGET) $(LDFLAGS) $(MAINOBJS) -$(DAEMONOBJS): $(UCXOBJS) +$(DAEMONOBJS): $(DAEMONSOURCE) cd daemon; $(MAKE) all -$(UCXOBJS): +$(UCXOBJS): $(UCXSOURCE) cd ucx; $(MAKE) all -$(UTILOBJS): +$(UTILOBJS): $(UTILSOURCE) cd util; $(MAKE) all -$(SAFOBJS): +$(SAFOBJS): $(SAFSOURCE) cd safs; $(MAKE) all -$(DAVOBJS): +$(CONFOBJS): $(CONFSOURCE) + cd config; $(MAKE) all +$(DAVOBJS): $(DAVSOURCE) cd webdav; $(MAKE) all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/Makefile Sun Jan 15 17:00:16 2012 +0100 @@ -0,0 +1,44 @@ +# +# 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. +# + +BUILD_ROOT = ../../../ +OBJ_DIR = $(BUILD_ROOT)build/ + +CFLAGS = -g +LDFLAGS = + +include objs.mk + +all: $(CONFOBJS) + +$(CONF_OBJPRE)%.o: %.c + cc -o $@ -c $(CFLAGS) $< + +$(CONF_OBJPRE)%.o: %.cpp + CC -o $@ -c $(CFLAGS) $< +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/conf.c Sun Jan 15 17:00:16 2012 +0100 @@ -0,0 +1,297 @@ +/* + * 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 "conf.h" + +#include <string.h> + +int cfg_parse_basic_file(ConfigParser *parser, FILE *in) { + parser->lines = NULL; + parser->mp = ucx_mempool_new(512); + + // one logical line over many lines + sstr_t mline; + mline.ptr = NULL; + mline.length = 0; + ConfigLine *start_line; + ConfigLine *end_line; + + // read file + sstr_t l; + while((l = cfg_readln(in)).ptr != NULL) { + // put the line to the list + ConfigLine *line = OBJ_NEW(parser->mp, ConfigLine); + line->line = sstrdub_mp(parser->mp, l); + line->object = NULL; + line->type = LINE_OTHER; + parser->lines = ucx_dlist_append(parser->lines, line); + + // check if the line contains something + l = cfg_trim_comment(l); + line->type = cfg_get_basic_type(l); + + if(line->type == LINE_OTHER) { + // check for multi line + if(mline.ptr != NULL) { + // concate lines + char *ptr = malloc(mline.length + l.length + 1); + memcpy(ptr, mline.ptr, mline.length); + memcpy(ptr + mline.length - 1, l.ptr, l.length); + mline.length += l.length; + free(mline.ptr); + mline.ptr = ptr; + mline.ptr[mline.length] = 0; + + end_line = line; + + line->type = LINE_MULTI; + } + if(l.ptr[l.length - 1] == '\\') { + if(mline.ptr == NULL) { + mline = sstrdub(l); + start_line = line; + } + } else { + // this line is complete so we can parse it + sstr_t ll; // we parse this line + + if(mline.ptr == NULL) { + // single line + ll = l; + start_line = line; + end_line = line; + } else { + ll = mline; + } + + // parse + int r = parser->parse(parser, start_line, end_line, ll); + + // clean up + if(mline.ptr != NULL) { + free(mline.ptr); + mline.ptr = NULL; + mline.length = 0; + start_line = NULL; + end_line = NULL; + } + + if(r != 0) { + return -1; + } + } + } + } + + return 0; +} + +sstr_t cfg_readln(FILE *file) { + sstr_t ns; + ns.ptr = NULL; + ns.length = 0; + + if(!feof(file)) { + char buf[512]; + buf[0] = 0; + int len = 512; + + if(fgets(buf, len, file) == NULL) { + return ns; + } + + if(*buf == 0) { + printf("???\n"); + return ns; + } + + char *ptr; + if((ptr = strrchr(buf, '\n'))) { + ptr[0] = 0; + } + + sstr_t line = sstr(buf); + return line; + } + + sstr_t s; + s.ptr = NULL; + s.length = 0; + return s; +} + +/* + * checks if the line contains only a comment or space + */ +int cfg_get_basic_type(sstr_t line) { + if(line.length == 0) { + return LINE_NOCONTENT; + } else if(line.ptr[0] == '#') { + return LINE_NOCONTENT; + } + return LINE_OTHER; +} + +/* + * removes a comment from the line + */ +sstr_t cfg_trim_comment(sstr_t line) { + sstr_t nl = line; + for(int i=0;i<line.length;i++) { + if(line.ptr[i] == '#') { + if(i > 0) { + nl.ptr = line.ptr + i - 1; + nl.length = i; + break; + } else { + nl.ptr = line.ptr; + nl.length = 0; + break; + } + } + } + return sstrtrim(nl); +} + +/* + * gets the first parameter in the params string and returns a new string + * containing the other parameters or an empty string, if there are no more + * parameters + */ +sstr_t cfg_param(sstr_t params, sstr_t *name, sstr_t *value) { + name->ptr = NULL; + name->length = 0; + value->ptr = NULL; + value->length = 0; + + // get name + int i; + for(i=0;i<params.length;i++) { + char c = params.ptr[i]; + if(c == '=') { + break; + } else if(c < 33) { + // no '=' means there is only a name, no value + name->ptr = params.ptr; + name->length = i; + + params.ptr = params.ptr + i; + params.length -= i; + return sstrtrim(params); + } + } + + name->ptr = params.ptr; + name->length = i; + i++; + + // get value + if(i>=params.length) { + sstr_t ns; + ns.ptr = NULL; + ns.length = 0; + return ns; + } + + int quote = 0; + value->ptr = params.ptr + i; + for(;i<params.length;i++) { + char c = params.ptr[i]; + if(c == '"') { + if(quote) { + break; // end of quoted value + } else { + quote = 1; + value->ptr++; + } + } else if(!quote && c < 33) { + break; // end of value + } + } + value->length = i - name->length - 2; + i++; + + if(value->length <= 0) { + value->length = 0; + value->ptr = NULL; + } + + // create new params string + params.ptr += i; + params.length -= i; + return sstrtrim(params); +} + +/* + * gets from a parameter list a value + */ +sstr_t cfg_param_get(UcxList *list, sstr_t name) { + while(list != NULL) { + ConfigParam *param = list->data; + if(!sstrcmp(param->name, name)) { + return param->value; + } + list = list->next; + } + sstr_t ns; + ns.ptr = NULL; + ns.length = 0; + return ns; +} + +/* + * gets the directive type number from a type string + * valid types are: + * AuthTrans 0 + * NameTrans 1 + * PathCheck 2 + * ObjectType 3 + * Service 4 + * AddLog 5 + * Init 6 + */ +int cfg_get_directive_type_num(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; + } else if(sstrcmp(type, sstr("Init")) == 0) { + dt = 6; + } + return dt; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/conf.h Sun Jan 15 17:00:16 2012 +0100 @@ -0,0 +1,98 @@ +/* + * 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. + */ + +#ifndef ACONF_H +#define ACONF_H + +#include <stdio.h> +#include <stdlib.h> + +#include "../ucx/list.h" +#include "../ucx/dlist.h" +#include "../ucx/map.h" +#include "../ucx/mempool.h" +#include "../ucx/string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// mempool malloc macro +#define OBJ_NEW(pool, type) (type*)ucx_mempool_malloc(pool, sizeof(type)) +#define OBJ_NEW_N(pool, type) (type*)ucx_mempool_calloc(pool, 1, sizeof(type)) + +// line types +#define LINE_OTHER 0 +#define LINE_DIRECTIVE 1 +#define LINE_BEGIN_TAG 2 +#define LINE_END_TAG 3 +#define LINE_MULTI 4 +#define LINE_NOCONTENT 5 // only comment or space +#define LINE_ERROR 6 // parse error on this line + +typedef struct _cfg_line { + sstr_t line; // raw line string + void *object; // pointer to data struct + int type; // type, see line types +} ConfigLine; + +typedef int (*cfg_parse_f)(void *, ConfigLine *, ConfigLine *, sstr_t); + +typedef struct _cfg_param { + sstr_t name; + sstr_t value; +} ConfigParam; + +typedef struct _cfg_parser { + UcxMempool *mp; + UcxDlist *lines; + cfg_parse_f parse; +} ConfigParser; + + +int cfg_parse_basic_file(ConfigParser *parser, FILE *in); + +sstr_t cfg_readln(FILE *file); + +int cfg_get_basic_type(sstr_t line); + +sstr_t cfg_trim_comment(sstr_t line); + +sstr_t cfg_param(sstr_t params, sstr_t *name, sstr_t *value); + +sstr_t cfg_param_get(UcxList *list, sstr_t name); + +int cfg_get_directive_type_num(sstr_t type); + + +#ifdef __cplusplus +} +#endif + +#endif /* ACONF_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/objconf.c Sun Jan 15 17:00:16 2012 +0100 @@ -0,0 +1,399 @@ +/* + * 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 "objconf.h" + +#include <string.h> + +/* dev notes: + * + * to free ObjectConfig, free: + * line dlist + * mempool + * object + */ + +ObjectConfig *load_object_config(char *file) { + FILE *in = fopen(file, "r"); + if(in == NULL) { + return NULL; + } + + ObjectConfig *conf = malloc(sizeof(ObjectConfig)); + conf->parser.parse = objconf_parse; + conf->file = file; + + int r = cfg_parse_basic_file((ConfigParser*)conf, in); + if(r != 0) { + // TODO: free + return NULL; + } + + return conf; +} + + + +int objconf_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line) { + ObjectConfig *conf = p; + + begin->type = objconf_get_line_type(line); + switch(begin->type) { + case LINE_BEGIN_TAG: { + ConfigTag *tag = objconf_parse_begin_tag(line, conf->parser.mp); + if(tag == NULL) { + fprintf(stderr, "Parse error!\n"); + exit(-1); // TODO: better error handling + } + tag->begin = begin; + tag->end = end; + tag->type_num = objconf_get_tag_type(tag->name); + //printf("line {%s}\n", sstrdub(ll).ptr); + if(objconf_on_begin_tag(conf, tag) != 0) { + fprintf(stderr, "1error!\n"); + exit(-1); + } + break; + } + case LINE_END_TAG: { + sstr_t tag = objconf_get_end_tag_name(line); + if(objconf_on_end_tag(conf, tag) != 0) { + fprintf(stderr, "2error!\n"); + exit(-1); + } + + break; + } + case LINE_DIRECTIVE: { + ConfigDirective *dir = objconf_parse_directive( + line, + conf->parser.mp); + dir->begin = begin; + dir->end = end; + if(objconf_on_directive(conf, dir) != 0) { + fprintf(stderr, "3error!\n"); + exit(-1); + } + } + } + return 0; +} + +int objconf_on_begin_tag(ObjectConfig *conf, ConfigTag *tag) { + if(tag->type_num != TAG_OBJECT) { + ConfigParserLevel *l = conf->levels->data; + if(l->tag->type_num != TAG_OBJECT) { + tag->parent = l->tag; + } + } + + + switch(tag->type_num) { + case TAG_OBJECT: { + ConfigObject *obj = OBJ_NEW_N(conf->parser.mp, ConfigObject); + obj->begin = tag->begin; + obj->end = tag->end; + + obj->name = cfg_param_get(tag->param, sstr("name")); + obj->ppath = cfg_param_get(tag->param, sstr("ppath")); + + conf->obj = obj; + conf->objects = ucx_dlist_append(conf->objects, obj); + + // create tree level object + ConfigParserLevel *lvl = OBJ_NEW(conf->parser.mp, ConfigParserLevel); + lvl->iftag = NULL; + lvl->levelnum = 1; + lvl->tag = tag; + conf->levels = ucx_list_prepend(conf->levels, lvl); + + break; + } + case TAG_IF: { + // create tree level object + ConfigParserLevel *last_lvl = conf->levels->data; + + ConfigParserLevel *lvl = OBJ_NEW(conf->parser.mp, ConfigParserLevel); + lvl->iftag = NULL; + lvl->levelnum = last_lvl->levelnum + 1; + lvl->tag = tag; + conf->levels = ucx_list_prepend(conf->levels, lvl); + last_lvl->iftag = tag; + + break; + } + case TAG_ELSEIF: { + } + case TAG_ELSE: { + // create tree level object + ConfigParserLevel *last_lvl = conf->levels->data; + tag->iftag = last_lvl->iftag; + + ConfigParserLevel *lvl = OBJ_NEW( + conf->parser.mp, + ConfigParserLevel); + + lvl->iftag = last_lvl->tag; + lvl->levelnum = last_lvl->levelnum + 1; + lvl->tag = tag; + conf->levels = ucx_list_prepend(conf->levels, lvl); + + break; + } + case TAG_CLIENT: { + // create tree level object + + // TODO + + break; + } + default: { + printf("unknown tag\n"); + return 1; + } + } + + return 0; +} + +int objconf_on_end_tag(ObjectConfig *conf, sstr_t tagname) { + int type = objconf_get_tag_type(tagname); + if(type == -1) { + fprintf(stderr, "unknown tag\n"); + return 1; + } else { + if(type == TAG_OBJECT) { + conf->obj = NULL; + } + + // remove level + conf->levels = ucx_list_remove(conf->levels, conf->levels); + } + + return 0; +} + +int objconf_on_directive(ObjectConfig *conf, ConfigDirective *dir) { + ConfigParserLevel *lvl = conf->levels->data; + + // check if we have a condition for the directive + // if the level tag is not an object tag, use it as condition + if(lvl->tag->type_num != TAG_OBJECT) { + dir->condition = lvl->tag; + } + + // add directive to current object + conf->obj->directives[dir->type_num] = ucx_dlist_append( + conf->obj->directives[dir->type_num], + dir); + + return 0; +} + +/* + * checks if the line contains a begin/end tag or a directive + */ +int objconf_get_line_type(sstr_t line) { + if(line.length < 3) { + // this line is to short to be correct + return LINE_ERROR; + } + + if(line.ptr[0] == '<') { + // start or end tag + // TODO: check for space between '<' and '/' + if(line.ptr[1] == '/') { + return LINE_END_TAG; + } else { + return LINE_BEGIN_TAG; + } + } else { + return LINE_DIRECTIVE; + } +} + +ConfigTag* objconf_parse_begin_tag(sstr_t line, UcxMempool *mp) { + if(line.length < 4) { + return NULL; // this line can't contain a valid tag + } + + if(line.ptr[0] != '<' || line.ptr[line.length - 1] != '>') { + return NULL; // syntax error + } + + sstr_t name; + name.ptr = line.ptr + 1; + int i; + for(i=1;i<line.length - 1;i++) { + if(line.ptr[i] < 33) { // char is space + name.length = i - 1; + break; + } + } + if(name.length < 1) { + return NULL; // syntax error + } + + // create tag object + ConfigTag *tag = OBJ_NEW(mp, ConfigTag); + tag->name = sstrdub_mp(mp, name); + tag->param = NULL; + + // parse parameters + sstr_t param_str; + param_str.ptr = line.ptr + i; + param_str.length = line.length - name.length - 2; + param_str = sstrtrim(param_str); + if(param_str.length <= 0) { + return tag; // no parameters + } + + sstr_t pname; + sstr_t pvalue; + for(;;) { + param_str = cfg_param(param_str, &pname, &pvalue); + if(pname.length <= 0) { + break; + } + + // create param object + ConfigParam *param = OBJ_NEW(mp, ConfigParam); + param->name = sstrdub_mp(mp, pname); + if(pvalue.length > 0) { + param->value = sstrdub_mp(mp, pvalue); + } else { + param->value.ptr = NULL; + param->value.length = 0; + } + + // add param to list + tag->param = ucx_list_append(tag->param, param); + } + + return tag; +} + +/* + * returns the name of the ending tag + * on error, this functions returns a zero length string + */ +sstr_t objconf_get_end_tag_name(sstr_t line) { + sstr_t ns; + ns.ptr = NULL; + ns.length = 0; + + if(line.length < 4) { + // minimum of 4 chars: </a> + return ns; + } + + sstr_t name; + name.ptr = line.ptr + 2; + name.length = line.length - 3; + + // check for </ > frame + if(line.ptr[0] != '<' + || line.ptr[1] != '/' + || line.ptr[line.length - 1] != '>') + { + return ns; + } + + return sstrtrim(name); +} + +/* + * parses a line containing a directive and returns a ConfigDirective object + * or NULL if an error occurs + */ +ConfigDirective* objconf_parse_directive(sstr_t line, UcxMempool *mp) { + if(line.length < 6) { + return NULL; // line too short + } + + sstr_t name; + + int i; + for(i=0;i<line.length;i++) { + if(line.ptr[i] < 33) { + break; + } + } + name.ptr = line.ptr; + name.length = i; + + // create directive object + ConfigDirective *directive = OBJ_NEW(mp, ConfigDirective); + directive->directive_type = sstrdub_mp(mp, name); + directive->type_num = cfg_get_directive_type_num(name); + directive->condition = NULL; // set later by main parsing function + directive->param = NULL; + + sstr_t param_str; + param_str.ptr = name.ptr + i; + param_str.length = line.length - i; + param_str = sstrtrim(param_str); + sstr_t pname; + sstr_t pvalue; + for(;;) { + param_str = cfg_param(param_str, &pname, &pvalue); + if(pname.length <= 0) { + break; + } + + // create param object + ConfigParam *param = OBJ_NEW(mp, ConfigParam); + param->name = sstrdub_mp(mp, pname); + if(pvalue.length > 0) { + param->value = sstrdub_mp(mp, pvalue); + } else { + param->value.ptr = NULL; + param->value.length = 0; + } + + // add param to list + directive->param = ucx_list_append(directive->param, param); + } + + return directive; +} + +int objconf_get_tag_type(sstr_t tag) { + if(!sstrcmp(tag, sstr("Object"))) { + return TAG_OBJECT; + } else if(!sstrcmp(tag, sstr("If"))) { + return TAG_IF; + } else if(!sstrcmp(tag, sstr("ElseIf"))) { + return TAG_ELSEIF; + } else if(!sstrcmp(tag, sstr("Else"))) { + return TAG_ELSE; + } else if(!sstrcmp(tag, sstr("Client"))) { + return TAG_CLIENT; + } + return -1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/objconf.h Sun Jan 15 17:00:16 2012 +0100 @@ -0,0 +1,126 @@ +/* + * 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. + */ + +#ifndef OBJCONF_H +#define OBJCONF_H + +#include "conf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TAG_OBJECT 0 +#define TAG_IF 1 +#define TAG_ELSEIF 2 +#define TAG_ELSE 3 +#define TAG_CLIENT 4 + + +typedef struct _conf_tag ConfigTag; +struct _conf_tag { + ConfigLine *begin; + ConfigLine *end; + + sstr_t name; + UcxList *param; + ConfigTag *parent; + ConfigTag *iftag; // only used by <ElseIf> and <Else> + int type_num; +}; + +typedef struct _conf_directive { + ConfigLine *begin; + ConfigLine *end; + + sstr_t directive_type; + UcxList *param; + ConfigTag *condition; + int type_num; +} ConfigDirective; + +typedef struct _conf_object { + ConfigLine *begin; + ConfigLine *end; + + sstr_t name; + sstr_t ppath; + ConfigTag *conditions; + // directives + UcxDlist *directives[6]; +} ConfigObject; + +/* + * representing a xml like level in the obj.conf tree + */ +typedef struct _conf_parser_level { + ConfigTag *iftag; // last if tag + ConfigTag *tag; // root of this level + int levelnum; +} ConfigParserLevel; + +typedef struct _obj_conf { + ConfigParser parser; + char *file; + UcxDlist *lines; + UcxDlist *conditions; + UcxDlist *objects; + + // private parser temp vars + ConfigObject *obj; // add directives to this object + UcxList *levels; // tree levels (stack) + +} ObjectConfig; + +ObjectConfig *load_object_config(char *file); + +int objconf_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line); + +int objconf_on_begin_tag(ObjectConfig *conf, ConfigTag *tag); + +int objconf_on_end_tag(ObjectConfig *conf, sstr_t tagname); + +int objconf_on_directive(ObjectConfig *conf, ConfigDirective *dir); + +int objconf_get_line_type(sstr_t line); + +ConfigTag* objconf_parse_begin_tag(sstr_t line, UcxMempool *mp); + +sstr_t objconf_get_end_tag_name(sstr_t line); + +ConfigDirective* objconf_parse_directive(sstr_t line, UcxMempool *mp); + +int objconf_get_tag_type(sstr_t tag); + + +#ifdef __cplusplus +} +#endif + +#endif /* OBJCONF_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/objs.mk Sun Jan 15 17:00:16 2012 +0100 @@ -0,0 +1,38 @@ +# +# 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. +# + +CONF_SRC_DIR = server/config/ + +CONF_OBJPRE = $(OBJ_DIR)$(CONF_SRC_DIR) + +CONFOBJ = objconf.o +CONFOBJ += conf.o + +CONFOBJS = $(CONFOBJ:%=$(CONF_OBJPRE)%) +CONFSOURCE = $(CONFOBJ:%.o=config/%.c) +
--- a/src/server/daemon/conf.c Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/daemon/conf.c Sun Jan 15 17:00:16 2012 +0100 @@ -46,6 +46,8 @@ #include "vserver.h" #include "../util/pblock.h" +#include "../config/objconf.h" + VirtualServer *default_vs; void load_init_conf(char *file) { @@ -163,40 +165,86 @@ HTTPObjectConfig* load_obj_conf(char *file) { printf("load_obj_conf\n"); - /* create object config */ - ObjectConfParser parser; - HTTPObjectConfig *conf = calloc(sizeof(HTTPObjectConfig), 1); - conf->pool = pool_create(); - parser.conf = conf; - - FILE *in = fopen("conf/obj.conf", "r"); - if(in == NULL) { - fprintf(stderr, "Cannot open conf/obj.conf\n"); + // new conf function test + ObjectConfig *cfg = load_object_config(file); + if(cfg == NULL) { return NULL; } - char buf[512]; - int len = 512; + /* create object config */ + HTTPObjectConfig *conf = calloc(sizeof(HTTPObjectConfig), 1); + conf->pool = pool_create(); + + /* convert ObjectConfig to HTTPObjectConfig */ - while(!feof(in)) { - fgets(buf, len, in); + /* 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; - if(*buf == 0) { - continue; + /* 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; } - char *ptr; - if((ptr = strrchr(buf, '\n'))) { - ptr[0] = 0; + /* 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); + } } - sstr_t line = string_trim(sstr(buf)); - if(line.length > 0) { - obj_conf_parse_line(&parser, line); - } + /* next */ + i++; + objlist = objlist->next; } + + + return conf; }
--- a/src/server/daemon/objs.mk Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/daemon/objs.mk Sun Jan 15 17:00:16 2012 +0100 @@ -45,4 +45,5 @@ DAEMONOBJ += ws-fn.o DAEMONOBJS = $(DAEMONOBJ:%=$(DMN_OBJPRE)%) +DAEMONSOURCE = $(DAEMONOBJ:%.o=daemon/%.c)
--- a/src/server/safs/objs.mk Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/safs/objs.mk Sun Jan 15 17:00:16 2012 +0100 @@ -35,4 +35,4 @@ SAFOBJ += service.o SAFOBJS = $(SAFOBJ:%=$(SAFS_OBJPRE)%) - +SAFSOURCE = $(SAFOBJ:%.o=safs/%.c)
--- a/src/server/ucx/list.c Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/ucx/list.c Sun Jan 15 17:00:16 2012 +0100 @@ -15,7 +15,7 @@ int ucx_list_equals(UcxList *l1, UcxList *l2, cmp_func fnc, void* data) { if (l1 == l2) return 1; - + while (l1 != NULL && l2 != NULL) { if (fnc == NULL) { if (l1->data != l2->data) return 0; @@ -25,7 +25,7 @@ l1 = l1->next; l2 = l2->next; } - + return (l1 == NULL && l2 == NULL); } @@ -41,7 +41,7 @@ UcxList *ucx_list_append(UcxList *l, void *data) { UcxList *nl = (UcxList*) malloc(sizeof(UcxList)); if (nl == NULL) return NULL; - + nl->data = data; nl->next = NULL; if (l == NULL) { @@ -56,7 +56,7 @@ UcxList *ucx_list_prepend(UcxList *l, void *data) { UcxList *nl = ucx_list_append(NULL, data); if (nl == NULL) return NULL; - + if (l != NULL) { nl->next = l; } @@ -75,7 +75,7 @@ UcxList *ucx_list_last(UcxList *l) { if (l == NULL) return NULL; - + UcxList *e = l; while (e->next != NULL) { e = e->next; @@ -91,13 +91,13 @@ e = e->next; index--; } - + return index == 0 ? e : NULL; } size_t ucx_list_size(UcxList *l) { if (l == NULL) return 0; - + UcxList *e = l; size_t s = 1; while (e->next != NULL) { @@ -110,8 +110,29 @@ void ucx_list_foreach(UcxList *l, ucx_callback fnc, void* data) { UcxList *e = l; + UcxList *n; while (e != NULL) { + n = e->next; fnc(e, data); - e = e->next; + e = n; } } + +/* list specific functions */ +UcxList *ucx_list_remove(UcxList *l, UcxList *e) { + if (e == l) { + l = e->next; + free(e); + } else { + UcxList *f = l; + while (f->next != NULL && f->next != e) { + f = f->next; + } + /* perform remove iff this element is found in this list */ + if (f->next == e) { + f->next = e->next; + free(e); + } + } + return l; +}
--- a/src/server/ucx/list.h Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/ucx/list.h Sun Jan 15 17:00:16 2012 +0100 @@ -1,5 +1,5 @@ /* - * + * */ #ifndef LIST_H @@ -30,6 +30,8 @@ size_t ucx_list_size(UcxList *l); void ucx_list_foreach(UcxList *l, ucx_callback fnc, void *data); +/* list specific functions */ +UcxList *ucx_list_remove(UcxList *l, UcxList *e); #ifdef __cplusplus }
--- a/src/server/ucx/objs.mk Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/ucx/objs.mk Sun Jan 15 17:00:16 2012 +0100 @@ -37,4 +37,5 @@ UCXOBJ += string.o UCXOBJS = $(UCXOBJ:%=$(UCX_OBJPRE)%) +UCXSOURCE = $(UCXOBJ:%.o=ucx/%.c)
--- a/src/server/ucx/string.c Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/ucx/string.c Sun Jan 15 17:00:16 2012 +0100 @@ -10,6 +10,7 @@ #include <stdarg.h> #include "string.h" +#include "mempool.h" sstr_t sstr (char *s) { sstr_t string; @@ -97,3 +98,40 @@ return newstring; } + + +// webserver extension +sstr_t sstrtrim(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; +} + +sstr_t sstrdub_mp(UcxMempool *mp, sstr_t s) { + sstr_t newstring; + newstring.ptr = ucx_mempool_malloc(mp, s.length + 1); + newstring.length = s.length; + newstring.ptr[newstring.length] = 0; + + memcpy(newstring.ptr, s.ptr, s.length); + + return newstring; +}
--- a/src/server/ucx/string.h Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/ucx/string.h Sun Jan 15 17:00:16 2012 +0100 @@ -8,6 +8,8 @@ #ifndef _SSTRING_H #define _SSTRING_H +#include "mempool.h" + #define S(s) { s, sizeof(s)-1 } #define ST(s) sstrn(s, sizeof(s)-1) @@ -71,6 +73,9 @@ sstr_t sstrdub(sstr_t s); +sstr_t sstrtrim(sstr_t string); +sstr_t sstrdub_mp(UcxMempool *mp, sstr_t s); + #ifdef __cplusplus } #endif
--- a/src/server/util/objs.mk Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/util/objs.mk Sun Jan 15 17:00:16 2012 +0100 @@ -33,7 +33,7 @@ UTILOBJ = io.o UTILOBJ += netbuf.o UTILOBJ += object.o -UTILOBJ += pblock.o +# UTILOBJ += pblock.o UTILOBJ += plist.o UTILOBJ += pool.o UTILOBJ += shexp.o @@ -41,8 +41,15 @@ UTILOBJ += system.o UTILOBJ += systhr.o UTILOBJ += thrpool.o -UTILOBJ += uri.o +#UTILOBJ += uri.o UTILOBJ += util.o UTILOBJS = $(UTILOBJ:%=$(UTIL_OBJPRE)%) +UTILSOURCE = $(UTILOBJ:%.o=util/%.c) +# add cpp files +UTILOBJS += $(UTIL_OBJPRE)pblock.o +UTILOBJS += $(UTIL_OBJPRE)uri.o + +UTILSOURCE += util/pblock.cpp +UTILSOURCE += util/uri.cpp
--- a/src/server/webdav/objs.mk Sat Jan 14 14:33:38 2012 +0100 +++ b/src/server/webdav/objs.mk Sun Jan 15 17:00:16 2012 +0100 @@ -30,9 +30,14 @@ DAV_OBJPRE = $(OBJ_DIR)$(DAV_SRC_DIR) -DAVOBJ = davparser.o -DAVOBJ += saxhandler.o -DAVOBJ += webdav.o +DAVOBJ = webdav.o DAVOBJS = $(DAVOBJ:%=$(DAV_OBJPRE)%) +DAVSOURCE = $(DAVOBJ:%.o=webdav/%.c) +# add cpp files +DAVOBJS += $(DAV_OBJPRE)saxhandler.o +DAVOBJS += $(DAV_OBJPRE)davparser.o + +DAVSOURCE += webdav/saxhandler.cpp +DAVSOURCE += webdav/davparser.cpp