New configuration file parser

Sun, 15 Jan 2012 17:00:16 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 15 Jan 2012 17:00:16 +0100
changeset 16
a9bbd82d2dce
parent 15
cff9c4101dd7
child 17
d2a97bbeb57d

New configuration file parser

src/server/Makefile file | annotate | diff | comparison | revisions
src/server/config/Makefile file | annotate | diff | comparison | revisions
src/server/config/conf.c file | annotate | diff | comparison | revisions
src/server/config/conf.h file | annotate | diff | comparison | revisions
src/server/config/objconf.c file | annotate | diff | comparison | revisions
src/server/config/objconf.h file | annotate | diff | comparison | revisions
src/server/config/objs.mk file | annotate | diff | comparison | revisions
src/server/daemon/conf.c file | annotate | diff | comparison | revisions
src/server/daemon/objs.mk file | annotate | diff | comparison | revisions
src/server/safs/objs.mk file | annotate | diff | comparison | revisions
src/server/ucx/list.c file | annotate | diff | comparison | revisions
src/server/ucx/list.h file | annotate | diff | comparison | revisions
src/server/ucx/objs.mk file | annotate | diff | comparison | revisions
src/server/ucx/string.c file | annotate | diff | comparison | revisions
src/server/ucx/string.h file | annotate | diff | comparison | revisions
src/server/util/objs.mk file | annotate | diff | comparison | revisions
src/server/webdav/objs.mk file | annotate | diff | comparison | revisions
--- 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

mercurial