ucx update

Fri, 21 Jun 2013 12:10:44 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 21 Jun 2013 12:10:44 +0200
changeset 71
069c152f6272
parent 70
4e6e812c1d97
child 72
9b888965f3ee
child 74
5bc6d078fb2c

ucx update

src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/ucx/allocator.c file | annotate | diff | comparison | revisions
src/server/ucx/allocator.h file | annotate | diff | comparison | revisions
src/server/ucx/buffer.c file | annotate | diff | comparison | revisions
src/server/ucx/buffer.h file | annotate | diff | comparison | revisions
src/server/ucx/dlist.c file | annotate | diff | comparison | revisions
src/server/ucx/dlist.h 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/logging.c file | annotate | diff | comparison | revisions
src/server/ucx/logging.h file | annotate | diff | comparison | revisions
src/server/ucx/mempool.c file | annotate | diff | comparison | revisions
src/server/ucx/mempool.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/ucx/test.c file | annotate | diff | comparison | revisions
src/server/ucx/test.h file | annotate | diff | comparison | revisions
src/server/ucx/utils.c file | annotate | diff | comparison | revisions
src/server/ucx/utils.h file | annotate | diff | comparison | revisions
src/server/util/io.c file | annotate | diff | comparison | revisions
src/server/util/pblock.cpp file | annotate | diff | comparison | revisions
src/server/util/pool.c file | annotate | diff | comparison | revisions
src/server/webdav/saxhandler.cpp file | annotate | diff | comparison | revisions
--- a/src/server/daemon/config.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/daemon/config.c	Fri Jun 21 12:10:44 2013 +0200
@@ -251,7 +251,7 @@
     uint32_t ref = ws_atomic_dec32(&cfg->ref);
     if(ref == 0) {
         // TODO: free configuration
-        printf("free ServerConfiguration %d\n", cfg);
+        printf("free ServerConfiguration %"PRIxPTR"\n", (intptr_t)cfg);
     }
 }
 
@@ -462,7 +462,7 @@
         name = sstrdup(name);
         
         AuthDB *authdb = create_ldap_authdb(name.ptr, &conf);
-        printf("authdb: %d\n", authdb);
+        printf("authdb: %"PRIxPTR"\n", (intptr_t)authdb);
         ucx_map_sstr_put(cfg->authdbs, name, authdb);
         
         // TODO: create_ldap_authdb should copy the strings
@@ -506,7 +506,7 @@
         // add keyfile authdb
         Keyfile *keyfile = f->data;
         keyfile->authdb.name = sstrdup(name).ptr;
-        printf("authdb: %d\n", keyfile);
+        printf("authdb: %"PRIxPTR"\n", (intptr_t)keyfile);
         ucx_map_sstr_put(cfg->authdbs, name, keyfile);
     }
 
@@ -641,7 +641,7 @@
 void object_conf_unref(HTTPObjectConfig *conf) {
     uint32_t ref = ws_atomic_dec32(&conf->ref);
     if(ref == 0) {
-        printf("free HTTPObjectConfig %x\n", conf);
+        printf("free HTTPObjectConfig %"PRIxPTR"\n", (intptr_t)conf);
         pool_destroy(conf->pool);
     }
 }
@@ -770,7 +770,7 @@
 void mime_conf_unref(MimeMap *conf) {
     uint32_t ref = ws_atomic_dec32(&conf->ref);
     if(ref == 0) {
-        printf("free MimeConfig %x\n", conf);
+        printf("free MimeConfig %"PRIxPTR"\n", (intptr_t)conf);
         UcxMapIterator i = ucx_map_iterator(conf->map);
         char *str;
         UCX_MAP_FOREACH(str, i) {
--- a/src/server/ucx/allocator.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/allocator.c	Fri Jun 21 12:10:44 2013 +0200
@@ -1,3 +1,31 @@
+/*
+ * 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 <stdlib.h>
 #include "allocator.h"
 
--- a/src/server/ucx/allocator.h	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/allocator.h	Fri Jun 21 12:10:44 2013 +0200
@@ -1,6 +1,36 @@
+/*
+ * 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.
+ */
+
 #ifndef ALLOCATOR_H
 #define	ALLOCATOR_H
 
+#include "ucx.h"
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/buffer.c	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,260 @@
+/*
+ * 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 "buffer.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags) {
+    UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
+    if (buffer) {
+        buffer->flags = flags;
+        if (!space) {
+            buffer->space = (char*)malloc(size);
+            if (!buffer->space) {
+                free(buffer);
+                return NULL;
+            }
+            memset(buffer->space, 0, size);
+            buffer->flags |= UCX_BUFFER_AUTOFREE;
+        } else {
+            buffer->space = (char*)space;
+        }
+        buffer->capacity = size;
+        buffer->size = 0;
+
+        buffer->pos = 0;
+    }
+
+    return buffer;
+}
+
+void ucx_buffer_free(UcxBuffer *buffer) {
+    if ((buffer->flags & UCX_BUFFER_AUTOFREE) == UCX_BUFFER_AUTOFREE) {
+        free(buffer->space);
+    }
+    free(buffer);
+}
+
+UcxBuffer* ucx_buffer_extract(
+        UcxBuffer *src, size_t start, size_t length, int flags) {
+    if(src->size == 0) {
+        return NULL;
+    }
+    if (length == 0) {
+        length = src->size - start;
+    }
+    if (start+length > src->size) {
+        return NULL;
+    }
+
+    UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
+    if (dst) {
+        dst->space = (char*)malloc(length);
+        if (!dst->space) {
+            free(dst);
+            return NULL;
+        }
+        dst->capacity = length;
+        dst->size = length;
+        dst->flags = flags | UCX_BUFFER_AUTOFREE;
+        dst->pos = 0;
+        memcpy(dst->space, src->space+start, length);
+    }
+    return dst;
+}
+
+int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
+    size_t npos = 0;
+    switch (whence) {
+    case SEEK_SET:
+        npos = 0;
+        break;
+    case SEEK_CUR:
+        npos = buffer->pos;
+        break;
+    case SEEK_END:
+        npos = buffer->size;
+        break;
+    }
+
+    npos += offset;
+    
+    if (npos > buffer->size) {
+        return -1;
+    } else {
+        buffer->pos = npos;
+        return 0;
+    }
+
+}
+
+int ucx_buffer_eof(UcxBuffer *buffer) {
+    return buffer->pos >= buffer->size;
+}
+
+int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
+    size_t newcap = buffer->capacity;
+    while (buffer->pos + len > newcap) newcap <<= 1;
+    
+    char *newspace = (char*)realloc(buffer->space, newcap);
+    if (newspace) {
+        memset(newspace+buffer->size, 0, newcap-buffer->size);
+        buffer->space = newspace;
+        buffer->capacity = newcap;
+    } else {
+        return -1;
+    }
+    
+    return 0;
+}
+
+size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
+        UcxBuffer *buffer) {
+    size_t len = size * nitems;
+    if (buffer->pos + len > buffer->capacity) {
+        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
+            if(ucx_buffer_extend(buffer, len)) {
+                return -1;
+            }
+        } else {
+            len = buffer->capacity - buffer->pos;
+            if (size > 1) len -= len%size;
+        }
+    }
+    
+    if (len <= 0) {
+        return len;
+    }
+    
+    memcpy(buffer->space + buffer->pos, ptr, len);
+    buffer->pos += len;
+    if(buffer->pos > buffer->size) {
+        buffer->size = buffer->pos;
+    }
+    
+    return len / size;
+}
+
+size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
+        UcxBuffer *buffer) {
+    size_t len = size * nitems;
+    if (buffer->pos + len > buffer->size) {
+        len = buffer->size - buffer->pos;
+        if (size > 1) len -= len%size;
+    }
+    
+    if (len <= 0) {
+        return len;
+    }
+    
+    memcpy(ptr, buffer->space + buffer->pos, len);
+    buffer->pos += len;
+    
+    return len / size;
+}
+
+int ucx_buffer_putc(UcxBuffer *buffer, int c) {
+    if(buffer->pos >= buffer->capacity) {
+        if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
+            if(ucx_buffer_extend(buffer, 1)) {
+                return EOF;
+            }
+        } else {
+            return EOF;
+        }
+    }
+    
+    c &= 0xFF;
+    buffer->space[buffer->pos] = (char) c;
+    buffer->pos++;
+    if(buffer->pos > buffer->size) {
+        buffer->size = buffer->pos;
+    }
+    return c;
+}
+
+int ucx_buffer_getc(UcxBuffer *buffer) {
+    if (ucx_buffer_eof(buffer)) {
+        return EOF;
+    } else {
+        int c = buffer->space[buffer->pos];
+        buffer->pos++;
+        return c;
+    }
+}
+
+size_t ucx_buffer_generic_copy(void *s1, void *s2,
+        read_func readfnc, write_func writefnc, size_t bufsize) {
+    size_t ncp = 0;
+    char *buf = (char*)malloc(bufsize);
+    if(buf == NULL) {
+        return 0;
+    }
+    
+    size_t r;
+    while((r = readfnc(buf, 1, bufsize, s1)) != 0) {
+        r = writefnc(buf, 1, r, s2);
+        ncp += r;
+        if(r == 0) {
+            break;
+        }
+    }
+    
+    free(buf);
+    return ncp;
+}
+
+size_t ucx_buffer_generic_ncopy(void *s1, void *s2,
+        read_func readfnc, write_func writefnc, size_t bufsize, size_t n) {
+    if(n == 0) {
+        return 0;
+    }
+    
+    size_t ncp = 0;
+    char *buf = (char*)malloc(bufsize);
+    if(buf == NULL) {
+        return 0;
+    }
+    
+    size_t r;
+    size_t rn = bufsize > n ? n : bufsize;
+    while((r = readfnc(buf, 1, rn, s1)) != 0) {
+        r = writefnc(buf, 1, r, s2);
+        ncp += r;
+        n -= r;
+        rn = bufsize > n ? n : bufsize;
+        if(r == 0 || n == 0) {
+            break;
+        }
+    }
+    
+    free(buf);
+    return ncp;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/buffer.h	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#ifndef BUFFER_H
+#define	BUFFER_H
+
+#include "ucx.h"
+#include <sys/types.h>
+#include <stdio.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* no autoextend or autofree behaviour */
+#define UCX_BUFFER_DEFAULT      0x00
+/* the buffer shall free the occupied memory space */
+#define UCX_BUFFER_AUTOFREE     0x01
+/* the buffer may automatically double its size on write operations */
+#define UCX_BUFFER_AUTOEXTEND   0x02
+
+/* the user shall not modify values, but may get the latest pointer */
+typedef struct {
+    char *space;
+    size_t pos;
+    size_t capacity;
+    size_t size;
+    int flags;
+} UcxBuffer;
+
+/* if space is NULL, new space is allocated and the autofree flag is enforced */
+UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags);
+void ucx_buffer_free(UcxBuffer* buffer);
+
+/*
+ * the autofree flag is enforced for the new buffer
+ * if length is zero, the whole remaining buffer shall be extracted
+ * the position of the new buffer is set to zero
+ */
+UcxBuffer* ucx_buffer_extract(UcxBuffer *src,
+        size_t start, size_t length, int flags);
+#define ucx_buffer_clone(src,flags) \
+    ucx_buffer_extract(src, 0, 0, flags)
+
+/*
+ * Moves the position of the buffer to a new position relative to whence.
+ *
+ * SEEK_SET marks the start of the buffer
+ * SEEK_CUR marks the current position
+ * SEEK_END marks the first 0-byte in the buffer
+ *
+ * ucx_buffer_seek returns 0 on success and -1 if the new position is beyond the
+ * bounds of the allocated buffer. In that case the position of the buffer
+ * remains unchanged.
+ *
+ */
+int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence);
+
+#define ucx_buffer_clear(buffer)    memset(buffer->space, 0, buffer->size); \
+                                    buffer->size = 0; buffer->pos = 0;
+
+/*
+ * returns non-zero, if the current buffer position has exceeded the last
+ * available byte of the underlying buffer
+ *
+ */
+int ucx_buffer_eof(UcxBuffer *buffer);
+
+
+int ucx_buffere_extend(UcxBuffer *buffer, size_t len);
+
+size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
+        UcxBuffer *buffer);
+
+size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
+        UcxBuffer *buffer);
+
+int ucx_buffer_putc(UcxBuffer *b, int c);
+int ucx_buffer_getc(UcxBuffer *b);
+
+
+/*
+ * copies all bytes from s1 to s2
+ * uses the read function r to read from s1 und writes the data using the
+ * write function w to s2
+ * returns the number of bytes copied
+ */
+size_t ucx_buffer_generic_copy(void *s1, void *s2, read_func r, write_func w,
+        size_t bufsize);
+
+size_t ucx_buffer_generic_ncopy(void *s1, void *s2, read_func r, write_func w,
+        size_t bufsize, size_t n);
+
+#define UCX_DEFAULT_BUFFER_SIZE 0x1000
+
+#define ucx_buffer_copy(s1,s2,r,w) \
+    ucx_buffer_generic_copy(s1, s2, (read_func)r, (write_func)w, \
+    UCX_DEFAULT_BUFFER_SIZE)
+
+#define ucx_buffer_ncopy(s1,s2,r,w, n) \
+    ucx_buffer_generic_ncopy(s1, s2, (read_func)r, (write_func)w, \
+    UCX_DEFAULT_BUFFER_SIZE, n)
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* BUFFER_H */
+
--- a/src/server/ucx/dlist.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/dlist.c	Fri Jun 21 12:10:44 2013 +0200
@@ -1,3 +1,31 @@
+/*
+ * 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 "dlist.h"
 
 UcxDlist *ucx_dlist_clone(UcxDlist *l, copy_func fnc, void *data) {
@@ -13,7 +41,8 @@
     return ret;
 }
 
-int ucx_dlist_equals(UcxDlist *l1, UcxDlist *l2, cmp_func fnc, void* data) {
+int ucx_dlist_equals(const UcxDlist *l1, const UcxDlist *l2,
+        cmp_func fnc, void* data) {
     if (l1 == l2) return 1;
     
     while (l1 != NULL && l2 != NULL) {
@@ -77,32 +106,41 @@
     }
 }
 
-UcxDlist *ucx_dlist_last(UcxDlist *l) {
+UcxDlist *ucx_dlist_last(const UcxDlist *l) {
     if (l == NULL) return NULL;
     
-    UcxDlist *e = l;
+    const UcxDlist *e = l;
     while (e->next != NULL) {
         e = e->next;
     }
-    return e;
+    return (UcxDlist*)e;
 }
 
-UcxDlist *ucx_dlist_get(UcxDlist *l, int index) {
+UcxDlist *ucx_dlist_get(const UcxDlist *l, int index) {
     if (l == NULL) return NULL;
 
-    UcxDlist *e = l;
+    const UcxDlist *e = l;
     while (e->next != NULL && index > 0) {
         e = e->next;
         index--;
     }
     
-    return index == 0 ? e : NULL;
+    return (UcxDlist*)(index == 0 ? e : NULL);
 }
 
-size_t ucx_dlist_size(UcxDlist *l) {
+int ucx_dlist_contains(UcxDlist *l, void *elem, cmp_func fnc, void *cmpdata) {
+    UCX_FOREACH(UcxDlist*, l, e) {
+        if (!fnc(elem, e->data, cmpdata)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+size_t ucx_dlist_size(const UcxDlist *l) {
     if (l == NULL) return 0;
     
-    UcxDlist *e = l;
+    const UcxDlist *e = l;
     size_t s = 1;
     while (e->next != NULL) {
         e = e->next;
@@ -113,14 +151,15 @@
 }
 
 UcxDlist *ucx_dlist_sort_merge(int length,
-        UcxDlist* ls, UcxDlist* rs, UcxDlist* le, UcxDlist* re,
+        UcxDlist* restrict ls, UcxDlist* restrict le, UcxDlist* restrict re,
         cmp_func fnc, void* data) {
-    UcxDlist *sorted[length];
+
+    UcxDlist** sorted = (UcxDlist**) malloc(sizeof(UcxDlist*)*length);
     UcxDlist *rc, *lc;
 
-    lc = ls; rc = rs;
+    lc = ls; rc = le;
     int n = 0;
-    while (lc != le && rc != re) {
+    while (lc && lc != le && rc != re) {
         if (fnc(lc->data, rc->data, data) <= 0) {
             sorted[n] = lc;
             lc = lc->next;
@@ -130,12 +169,12 @@
         }
         n++;
     }
-    while (lc != le) {
+    while (lc && lc != le) {
         sorted[n] = lc;
         lc = lc->next;
         n++;
     }
-    while (rc != re) {
+    while (rc && rc != re) {
         sorted[n] = rc;
         rc = rc->next;
         n++;
@@ -149,7 +188,9 @@
     }
     sorted[length-1]->next = NULL;
 
-    return sorted[0];
+    UcxDlist *ret = sorted[0];
+    free(sorted);
+    return ret;
 }
 
 UcxDlist *ucx_dlist_sort(UcxDlist *l, cmp_func fnc, void *data) {
@@ -160,7 +201,7 @@
     UcxDlist *lc;
     int ln = 1;
 
-    UcxDlist *ls = l, *le;
+    UcxDlist *restrict ls = l, *restrict le, *restrict re;
     lc = ls;
     while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
         lc = lc->next;
@@ -168,13 +209,12 @@
     }
     le = lc->next;
 
-    UcxDlist *rs = le, *re;
-    if (rs == NULL) {
+    if (le == NULL) {
         return l; // this list is already sorted :)
     } else {
         UcxDlist *rc;
         int rn = 1;
-        rc = rs;
+        rc = le;
         while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
             rc = rc->next;
             rn++;
@@ -190,27 +230,26 @@
 
         // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
         UcxDlist *sorted = ucx_dlist_sort_merge(ln+rn,
-                ls, rs, le, re,
+                ls, le, re,
                 fnc, data);
 
         // merge sorted list with (also sorted) remainder
         l = ucx_dlist_sort_merge(ln+rn+remainder_length,
-                sorted, remainder, NULL, NULL,
-                fnc, data);
+                sorted, remainder, NULL, fnc, data);
 
         return l;
     }
 }
 
 /* dlist specific functions */
-UcxDlist *ucx_dlist_first(UcxDlist *l) {
+UcxDlist *ucx_dlist_first(const UcxDlist *l) {
     if (l == NULL) return NULL;
     
-    UcxDlist *e = l;
+    const UcxDlist *e = l;
     while (e->prev != NULL) {
         e = e->prev;
     }
-    return e;
+    return (UcxDlist *)e;
 }
 
 UcxDlist *ucx_dlist_remove(UcxDlist *l, UcxDlist *e) {
--- a/src/server/ucx/dlist.h	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/dlist.h	Fri Jun 21 12:10:44 2013 +0200
@@ -1,5 +1,29 @@
-/* 
- * 
+/*
+ * 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.
  */
 
 #ifndef DLIST_H
@@ -20,20 +44,22 @@
 };
 
 UcxDlist *ucx_dlist_clone(UcxDlist *l, copy_func fnc, void* data);
-int ucx_dlist_equals(UcxDlist *l1, UcxDlist *l2, cmp_func fnc, void* data);
+int ucx_dlist_equals(const UcxDlist *l1, const UcxDlist *l2,
+        cmp_func fnc, void* data);
 
 void ucx_dlist_free(UcxDlist *l);
 UcxDlist *ucx_dlist_append(UcxDlist *l, void *data);
 UcxDlist *ucx_dlist_prepend(UcxDlist *l, void *data);
 UcxDlist *ucx_dlist_concat(UcxDlist *l1, UcxDlist *l2);
-UcxDlist *ucx_dlist_last(UcxDlist *l);
-UcxDlist *ucx_dlist_get(UcxDlist *l, int index);
-size_t ucx_dlist_size(UcxDlist *l);
+UcxDlist *ucx_dlist_last(const UcxDlist *l);
+UcxDlist *ucx_dlist_get(const UcxDlist *l, int index);
+size_t ucx_dlist_size(const UcxDlist *l);
+int ucx_dlist_contains(UcxDlist *l, void *elem, cmp_func fnc, void *cmpdata);
 
 UcxDlist *ucx_dlist_sort(UcxDlist *l, cmp_func fnc, void *data);
 
 /* dlist specific functions */
-UcxDlist *ucx_dlist_first(UcxDlist *l);
+UcxDlist *ucx_dlist_first(const UcxDlist *l);
 UcxDlist *ucx_dlist_remove(UcxDlist *l, UcxDlist *e);
 
 #ifdef	__cplusplus
--- a/src/server/ucx/list.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/list.c	Fri Jun 21 12:10:44 2013 +0200
@@ -1,3 +1,31 @@
+/*
+ * 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 "list.h"
 
 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
@@ -13,7 +41,8 @@
     return ret;
 }
 
-int ucx_list_equals(UcxList *l1, UcxList *l2, cmp_func fnc, void* data) {
+int ucx_list_equals(const UcxList *l1, const UcxList *l2,
+        cmp_func fnc, void* data) {
     if (l1 == l2) return 1;
     
     while (l1 != NULL && l2 != NULL) {
@@ -73,32 +102,41 @@
     }
 }
 
-UcxList *ucx_list_last(UcxList *l) {
+UcxList *ucx_list_last(const UcxList *l) {
     if (l == NULL) return NULL;
     
-    UcxList *e = l;
+    const UcxList *e = l;
     while (e->next != NULL) {
         e = e->next;
     }
-    return e;
+    return (UcxList*)e;
 }
 
-UcxList *ucx_list_get(UcxList *l, int index) {
+UcxList *ucx_list_get(const UcxList *l, int index) {
     if (l == NULL) return NULL;
 
-    UcxList *e = l;
+    const UcxList *e = l;
     while (e->next != NULL && index > 0) {
         e = e->next;
         index--;
     }
     
-    return index == 0 ? e : NULL;
+    return (UcxList*)(index == 0 ? e : NULL);
 }
 
-size_t ucx_list_size(UcxList *l) {
+int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) {
+    UCX_FOREACH(UcxList*, l, e) {
+        if (!fnc(elem, e->data, cmpdata)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+size_t ucx_list_size(const UcxList *l) {
     if (l == NULL) return 0;
     
-    UcxList *e = l;
+    const UcxList *e = l;
     size_t s = 1;
     while (e->next != NULL) {
         e = e->next;
@@ -109,14 +147,15 @@
 }
 
 UcxList *ucx_list_sort_merge(int length,
-        UcxList* ls, UcxList* rs, UcxList* le, UcxList* re,
+        UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re,
         cmp_func fnc, void* data) {
-    UcxList *sorted[length];
+
+    UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length);
     UcxList *rc, *lc;
 
-    lc = ls; rc = rs;
+    lc = ls; rc = le;
     int n = 0;
-    while (lc != le && rc != re) {
+    while (lc && lc != le && rc != re) {
         if (fnc(lc->data, rc->data, data) <= 0) {
             sorted[n] = lc;
             lc = lc->next;
@@ -126,12 +165,12 @@
         }
         n++;
     }
-    while (lc != le) {
+    while (lc && lc != le) {
         sorted[n] = lc;
         lc = lc->next;
         n++;
     }
-    while (rc != re) {
+    while (rc && rc != re) {
         sorted[n] = rc;
         rc = rc->next;
         n++;
@@ -143,7 +182,9 @@
     }
     sorted[length-1]->next = NULL;
 
-    return sorted[0];
+    UcxList *ret = sorted[0];
+    free(sorted);
+    return ret;
 }
 
 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
@@ -154,7 +195,7 @@
     UcxList *lc;
     int ln = 1;
 
-    UcxList *ls = l, *le;
+    UcxList *restrict ls = l, *restrict le, *restrict re;
     lc = ls;
     while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
         lc = lc->next;
@@ -162,13 +203,12 @@
     }
     le = lc->next;
 
-    UcxList *rs = le, *re;
-    if (rs == NULL) {
+    if (le == NULL) {
         return l; // this list is already sorted :)
     } else {
         UcxList *rc;
         int rn = 1;
-        rc = rs;
+        rc = le;
         while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
             rc = rc->next;
             rn++;
@@ -184,13 +224,12 @@
 
         // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
         UcxList *sorted = ucx_list_sort_merge(ln+rn,
-                ls, rs, le, re,
+                ls, le, re,
                 fnc, data);
 
         // merge sorted list with (also sorted) remainder
         l = ucx_list_sort_merge(ln+rn+remainder_length,
-                sorted, remainder, NULL, NULL,
-                fnc, data);
+                sorted, remainder, NULL, fnc, data);
 
         return l;
     }
--- a/src/server/ucx/list.h	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/list.h	Fri Jun 21 12:10:44 2013 +0200
@@ -1,5 +1,29 @@
 /*
- * 
+ * 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.
  */
 
 #ifndef LIST_H
@@ -19,15 +43,17 @@
 };
 
 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data);
-int ucx_list_equals(UcxList *l1, UcxList *l2, cmp_func fnc, void *data);
+int ucx_list_equals(const UcxList *l1, const UcxList *l2,
+        cmp_func fnc, void *data);
 
 void ucx_list_free(UcxList *l);
 UcxList *ucx_list_append(UcxList *l, void *data);
 UcxList *ucx_list_prepend(UcxList *l, void *data);
 UcxList *ucx_list_concat(UcxList *l1, UcxList *l2);
-UcxList *ucx_list_last(UcxList *l);
-UcxList *ucx_list_get(UcxList *l, int index);
-size_t ucx_list_size(UcxList *l);
+UcxList *ucx_list_last(const UcxList *l);
+UcxList *ucx_list_get(const UcxList *l, int index);
+size_t ucx_list_size(const UcxList *l);
+int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata);
 
 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/logging.c	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,102 @@
+/*
+ * 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 "logging.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask) {
+    UcxLogger *logger = (UcxLogger*) malloc(sizeof(UcxLogger));
+    if (logger != NULL) {
+        logger->stream = stream;
+        logger->writer = (write_func)fwrite;
+        logger->dateformat = (char*) "%F %T %z ";
+        logger->level = level;
+        logger->mask = mask;
+        logger->levels = ucx_map_new(8);
+        
+        unsigned int l;
+        l = UCX_LOGGER_ERROR;
+        ucx_map_int_put(logger->levels, l, (void*) "[ERROR]");
+        l = UCX_LOGGER_WARN;
+        ucx_map_int_put(logger->levels, l, (void*) "[WARNING]");
+        l = UCX_LOGGER_INFO;
+        ucx_map_int_put(logger->levels, l, (void*) "[INFO]");
+        l = UCX_LOGGER_TRACE;
+        ucx_map_int_put(logger->levels, l, (void*) "[TRACE]");
+    }
+
+    return logger;
+}
+
+void ucx_logger_free(UcxLogger *logger) {
+    ucx_map_free(logger->levels);
+    free(logger);
+}
+
+void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file,
+        const unsigned int line, const char *format, ...) {
+    if (level <= logger->level) {
+        const size_t max = 4096; // estimated maximum message length
+        char msg[max];
+        char *text;
+        size_t k = 0;
+        size_t n;
+        
+        if ((logger->mask & UCX_LOGGER_LEVEL) > 0) {
+            text = (char*) ucx_map_int_get(logger->levels, level);
+            n = strlen(text);
+            memcpy(msg+k, text, n);
+            k += n;
+            msg[k++] = ' ';
+        }
+        if ((logger->mask & UCX_LOGGER_TIMESTAMP) > 0) {
+            time_t now = time(NULL);
+            k += strftime(msg+k, 128, logger->dateformat, localtime(&now));
+        }
+        if ((logger->mask & UCX_LOGGER_SOURCE) > 0) {
+            n = strlen(file);
+            memcpy(msg+k, file, n);
+            k += n;
+            k += sprintf(msg+k, ":%d ", line);
+        }
+        
+        msg[k++] = '-'; msg[k++] = ' ';
+        
+        va_list args;
+        va_start (args, format);
+        k += vsnprintf(msg+k, max-k-1, format, args);
+        va_end (args);        
+        
+        msg[k++] = '\n';
+        
+        logger->writer(msg, 1, k, logger->stream);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/logging.h	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#include "ucx.h"
+#include "map.h"
+#include "string.h"
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* leave enough space for custom log levels */
+#define UCX_LOGGER_ERROR        0x00
+#define UCX_LOGGER_WARN         0x10
+#define UCX_LOGGER_INFO         0x20
+#define UCX_LOGGER_TRACE        0x30
+
+#define UCX_LOGGER_LEVEL        0x01
+#define UCX_LOGGER_TIMESTAMP    0x02
+#define UCX_LOGGER_SOURCE       0x04
+
+typedef struct {
+    void *stream;
+    write_func writer;
+    char *dateformat;
+    unsigned int level;
+    unsigned int mask;
+    UcxMap* levels;
+} UcxLogger;
+
+UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask);
+void ucx_logger_free(UcxLogger* logger);
+
+void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file,
+        const unsigned int line, const char* format, ...);
+#define ucx_logger_log(logger, level, ...) \
+    ucx_logger_logf(logger, level, __FILE__, __LINE__, __VA_ARGS__)
+#define ucx_logger_error(logger, ...) \
+    ucx_logger_log(logger, UCX_LOGGER_ERROR, __VA_ARGS__)
+#define ucx_logger_info(logger, ...) \
+    ucx_logger_log(logger, UCX_LOGGER_INFO, __VA_ARGS__)
+#define ucx_logger_warn(logger, ...) \
+    ucx_logger_log(logger, UCX_LOGGER_WARN, __VA_ARGS__)
+#define ucx_logger_trace(logger, ...) \
+    ucx_logger_log(logger, UCX_LOGGER_TRACE, __VA_ARGS__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LOGGING_H */
--- a/src/server/ucx/mempool.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/mempool.c	Fri Jun 21 12:10:44 2013 +0200
@@ -1,11 +1,38 @@
 /*
+ * 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 <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include <errno.h>
+#ifdef __cplusplus
+#define __STDC_FORMAT_MACROS
+#endif
+#include <inttypes.h>
 
 #include "mempool.h"
 
@@ -28,7 +55,7 @@
     UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool));
     if (pool == NULL) return NULL;
     
-    pool->data = malloc(n * sizeof(void*));
+    pool->data = (void**) malloc(n * sizeof(void*));
     if (pool->data == NULL) {
         free(pool);
         return NULL;
@@ -40,9 +67,9 @@
 }
 
 int ucx_mempool_chcap(UcxMempool *pool, size_t newcap) {
-    void **data = realloc(pool->data, newcap*sizeof(void*));
+    void **data = (void**) realloc(pool->data, newcap*sizeof(void*));
     if (data == NULL) {
-        return ENOMEM;
+        return 1;
     } else {
         pool->data = data; 
         pool->size = newcap;
@@ -79,13 +106,14 @@
     char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor));
     if (newm == NULL) return NULL;
     if (mem != newm) {
-        for(int i=0;i<pool->ndata;i++) {
+        for(size_t i=0 ; i < pool->ndata ; i++) {
             if(pool->data[i] == mem) {
                 pool->data[i] = newm;
                 return newm + sizeof(ucx_destructor);
             }
         }
-        fprintf(stderr, "FATAL: %8x not in mpool %8x\n", ptr, pool);
+        fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
+          (intptr_t)ptr, (intptr_t)pool);
         exit(1);
     } else {
         return newm + sizeof(ucx_destructor);
@@ -94,7 +122,7 @@
 
 void ucx_mempool_free(UcxMempool *pool) {
     ucx_memchunk *chunk;
-    for(int i=0;i<pool->ndata;i++) {
+    for(size_t i=0 ; i<pool->ndata ; i++) {
         chunk = (ucx_memchunk*) pool->data[i];
         if(chunk->destructor != NULL) {
             chunk->destructor(&chunk->c);
--- a/src/server/ucx/mempool.h	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/mempool.h	Fri Jun 21 12:10:44 2013 +0200
@@ -1,10 +1,35 @@
-/* 
+/*
+ * 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.
  */
 
 #ifndef MPOOL_H
 #define	MPOOL_H
 
+#include "ucx.h"
 #include <stddef.h>
 #include "allocator.h"
 
--- a/src/server/ucx/objs.mk	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/objs.mk	Fri Jun 21 12:10:44 2013 +0200
@@ -36,6 +36,8 @@
 UCXOBJ += mempool.o
 UCXOBJ += string.o
 UCXOBJ += allocator.o
+UCXOBJ += utils.o
+UCXOBJ += buffer.o
 
 UCXOBJS = $(UCXOBJ:%=$(UCX_OBJPRE)%)
 UCXSOURCE = $(UCXOBJ:%.o=ucx/%.c)
--- a/src/server/ucx/string.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/string.c	Fri Jun 21 12:10:44 2013 +0200
@@ -1,36 +1,57 @@
 /*
- * File:   sstring.c
- * Author: olaf
+ * 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.
  *
- * Created on 17. Juni 2010, 13:27
+ *   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 <stdlib.h>
-#include <strings.h>
+#include <string.h>
 #include <stdarg.h>
 
 #include "string.h"
 
-sstr_t sstr (char *s) {
+sstr_t sstr(char *s) {
     sstr_t string;
     string.ptr = s;
     string.length = strlen(s);
     return string;
 }
 
-sstr_t sstrn (char *s, size_t n) {
+sstr_t sstrn(char *s, size_t n) {
     sstr_t string;
     string.ptr = s;
     string.length = n;
     return string;
 }
 
-size_t sstrnlen (size_t n, sstr_t s, ...) {
+size_t sstrnlen(size_t n, sstr_t s, ...) {
     va_list ap;
     size_t size = s.length;
     va_start(ap, s);
 
-    for (int i=0;i<n-1;i++) {
+    for (size_t i = 0 ; i < n-1 ; i++) {
         sstr_t str = va_arg(ap, sstr_t);
         size += str.length;
     }
@@ -39,22 +60,7 @@
     return size;
 }
 
-sstr_t sstrcat (sstr_t s, ...) {
-    va_list ap;
-    va_start(ap, s);
-    s.ptr[0] = 0;
-
-    sstr_t str = va_arg (ap, sstr_t);
-    while (str.ptr != NULL) {
-        s.ptr = strncat (s.ptr, str.ptr, s.length);
-        str = va_arg (ap, sstr_t);
-    }
-    va_end(ap);
-
-    return s;
-}
-
-sstr_t sstrncat (size_t n, sstr_t s, sstr_t c1, ...) {
+sstr_t sstrncat(size_t n, sstr_t s, sstr_t c1, ...) {
     va_list ap;
     va_start(ap, c1);
     s.ptr[0] = 0;
@@ -66,7 +72,7 @@
     memcpy(ptr, c1.ptr, cplen);
     len -= cplen;
     ptr += cplen;
-    for (int i=0;i<n-1;i++) {
+    for (size_t i = 0 ; i < n-1 ; i++) {
         sstr_t str = va_arg (ap, sstr_t);
         cplen = str.length > len ? len : str.length;
         if(cplen <= 0) {
@@ -78,15 +84,16 @@
         ptr += cplen;
     }
     va_end(ap);
+    s.length = ptr - s.ptr;
 
     return s;
 }
 
-sstr_t sstrsubs (sstr_t s, size_t start) {
+sstr_t sstrsubs(sstr_t s, size_t start) {
     return sstrsubsl (s, start, s.length-start);
 }
 
-sstr_t sstrsubsl (sstr_t s, size_t start, size_t length) {
+sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) {
     sstr_t new_sstr;
     if (start >= s.length) {
         return s;
@@ -110,16 +117,15 @@
 
     /* special case: exact match - no processing needed */
     if (s.length == d.length && strncmp(s.ptr, d.ptr, s.length) == 0) {
-        result = malloc(sizeof(sstr_t));
-        result[0] = sstrn("", 0);
-        return result;
+        *n = 0;
+        return NULL;
     }
     sstr_t sv = sstrdup(s);
 
-    for (int i = 0 ; i < s.length ; i++) {
+    for (size_t i = 0 ; i < s.length ; i++) {
         if (sv.ptr[i] == d.ptr[0]) {
             _Bool match = 1;
-            for (int j = 1 ; j < d.length ; j++) {
+            for (size_t j = 1 ; j < d.length ; j++) {
                 if (j+i < s.length) {
                     match &= (sv.ptr[i+j] == d.ptr[j]);
                 } else {
@@ -129,7 +135,7 @@
             }
             if (match) {
                 (*n)++;
-                for (int j = 0 ; j < d.length ; j++) {
+                for (size_t j = 0 ; j < d.length ; j++) {
                     sv.ptr[i+j] = 0;
                 }
                 i += d.length;
@@ -137,12 +143,12 @@
         }
         if ((*n) == nmax) break;
     }
-    result = malloc(sizeof(sstr_t) * (*n));
+    result = (sstr_t*) malloc(sizeof(sstr_t) * (*n));
 
     char *pptr = sv.ptr;
-    for (int i = 0 ; i < *n ; i++) {
+    for (size_t i = 0 ; i < *n ; i++) {
         size_t l = strlen(pptr);
-        char* ptr = malloc(l + 1);
+        char* ptr = (char*) malloc(l + 1);
         memcpy(ptr, pptr, l);
         ptr[l] = 0;
 
@@ -162,16 +168,57 @@
 sstr_t sstrdup(sstr_t s) {
     sstr_t newstring;
     newstring.ptr = (char*) malloc(s.length + 1);
-    if (newstring.ptr != NULL) {
+    newstring.length = 0;
+    if (newstring.ptr) {
         newstring.length = s.length;
         newstring.ptr[newstring.length] = 0;
 
         memcpy(newstring.ptr, s.ptr, s.length);
+    } else {
+        newstring.length = 0;
     }
 
     return newstring;
 }
 
+sstr_t sstrtrim(sstr_t string) {
+    sstr_t newstr = string;
+    if (string.length == 0) {
+        return newstr;
+    }
+    
+    size_t i;
+    for(i=0;i<string.length;i++) {
+        char c = string.ptr[i];
+        if(c > 32) {
+            break;
+        }
+    }
+    newstr.ptr = &string.ptr[i];
+    newstr.length = string.length - i;
+    
+    if(newstr.length == 0) {
+        return newstr;
+    }
+    
+    i = newstr.length - 1;
+    for(;;) {
+        char c = newstr.ptr[i];
+        if(c > 32) {
+            break;
+        }
+        if(i > 0) {
+            i--;
+        } else {
+            break;
+        }
+    }
+    newstr.length = i + 1;
+    
+    return newstr;
+}
+
+
 // webserver extension
 
 int sstr_startswith(sstr_t string, sstr_t cmp) {
@@ -183,30 +230,6 @@
     }
 }
 
-sstr_t sstrtrim(sstr_t string) {
-    sstr_t newstr = string;
-    int i;
-    for(i=0;i<string.length;i++) {
-        char c = string.ptr[i];
-        if(c > 32) {
-            break;
-        }
-    }
-    
-    newstr.ptr = &string.ptr[i];
-    newstr.length = string.length - i;
-    
-    for(i=newstr.length-1;i>=0;i--) {
-        char c = newstr.ptr[i];
-        if(c > 32) {
-            break;
-        }
-    }
-    newstr.length = i + 1;
-    
-    return newstr;
-}
-
 sstr_t sstrdup_mp(UcxMempool *pool, sstr_t s) {
     sstr_t newstring;
     newstring.ptr = (char*)ucx_mempool_malloc(pool, s.length + 1);
--- a/src/server/ucx/string.h	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/ucx/string.h	Fri Jun 21 12:10:44 2013 +0200
@@ -1,21 +1,42 @@
 /*
- * File:   sstring.h
- * Author: olaf
+ * 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.
  *
- * Created on 17. Juni 2010, 13:26
+ *   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 _SSTRING_H
 #define	_SSTRING_H
 
+#include "ucx.h"
+#include "mempool.h"
+#include "../public/nsapi.h"
 #include <stddef.h>
 
-#include "mempool.h"
-#include "../util/pool.h"
-
 /* use macros for literals only */
-#define S(s) { s, sizeof(s)-1 }
-#define ST(s) sstrn(s, sizeof(s)-1)
+#define S(s) { (char*)s, sizeof(s)-1 }
+#define ST(s) sstrn((char*)s, sizeof(s)-1)
 
 #ifdef	__cplusplus
 extern "C" {
@@ -31,7 +52,7 @@
  *
  * s  null terminated string
  */
-sstr_t sstr (char *s);
+sstr_t sstr(char *s);
 
 /*
  * creates a new sstr_t from a string and length
@@ -39,7 +60,7 @@
  * s  string
  * n  length of string
  */
-sstr_t sstrn (char *s, size_t n);
+sstr_t sstrn(char *s, size_t n);
 
 
 /*
@@ -49,7 +70,7 @@
  * s    string
  * ...  strings
  */
-size_t sstrnlen (size_t n, sstr_t s, ...);
+size_t sstrnlen(size_t n, sstr_t s, ...);
 
 
 /*
@@ -59,18 +80,18 @@
  * s    new string with enough memory allocated
  * ...  strings
  */
-sstr_t sstrncat (size_t n, sstr_t s, sstr_t c1, ...);
+sstr_t sstrncat(size_t n, sstr_t s, sstr_t c1, ...);
 
 
 /*
  *
  */
-sstr_t sstrsubs (sstr_t s, size_t start);
+sstr_t sstrsubs(sstr_t s, size_t start);
 
 /*
  *
  */
-sstr_t sstrsubsl (sstr_t s, size_t start, size_t length);
+sstr_t sstrsubsl(sstr_t s, size_t start, size_t length);
 
 /*
  * splits s into n parts
@@ -94,9 +115,10 @@
 
 sstr_t sstrdup(sstr_t s);
 
+sstr_t sstrtrim(sstr_t string);
+
 // webserver extension
 int sstr_startswith(sstr_t string, sstr_t cmp);
-sstr_t sstrtrim(sstr_t string);
 sstr_t sstrdup_mp(UcxMempool *pool, sstr_t s);
 sstr_t sstrdup_pool(pool_handle_t *pool, sstr_t s);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/test.c	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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 "test.h"
+
+UcxTestSuite* ucx_test_suite_new() {
+    UcxTestSuite* suite = (UcxTestSuite*) malloc(sizeof(UcxTestSuite));
+    if (suite != NULL) {
+        suite->success = 0;
+        suite->failure = 0;
+        suite->tests = NULL;
+    }
+    return suite;
+}
+
+void ucx_test_suite_free(UcxTestSuite* suite) {
+    UcxTestList *l = suite->tests;
+    while (l != NULL) {
+        UcxTestList *e = l;
+        l = l->next;
+        free(e);
+    }
+    free(suite);
+}
+
+int ucx_test_register(UcxTestSuite* suite, UcxTest test) {
+    if (suite->tests) {
+        UcxTestList *newelem = (UcxTestList*) malloc(sizeof(UcxTestList));
+        if (newelem) {
+            newelem->test = test;
+            newelem->next = NULL;
+            
+            UcxTestList *last = suite->tests;
+            while (last->next) {
+                last = last->next;
+            }
+            last->next = newelem;
+            
+            return EXIT_SUCCESS;
+        } else {
+            return EXIT_FAILURE;
+        }
+    } else {
+        suite->tests = (UcxTestList*) malloc(sizeof(UcxTestList));
+        if (suite->tests) {
+            suite->tests->test = test;
+            suite->tests->next = NULL;
+            
+            return EXIT_SUCCESS;
+        } else {
+            return EXIT_FAILURE;
+        }
+    }
+}
+
+void ucx_test_run(UcxTestSuite* suite, FILE* output) {
+    suite->success = 0;
+    suite->failure = 0;
+    UCX_FOREACH (UcxTestList*, suite->tests, e) {
+        e->test(suite, output);
+    }
+    fwrite("\nAll test completed.\n", 1, 21, output);
+    fprintf(output, "  Total:   %d\n  Success: %d\n  Failure: %d\n",
+            suite->success+suite->failure, suite->success, suite->failure);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/test.h	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+ 
+/*
+ *
+ * Usage of this test framework:
+ *
+ * **** IN HEADER FILE: ****
+ *
+ * UCX_TEST_DECLARE(function_name)
+ *
+ * **** IN SOURCE FILE: ****
+ *
+ * UCX_TEST_IMPLEMENT(function_name) {
+ *  <memory allocation and other stuff here>
+ *  UCX_TEST_BEGIN
+ *  <tests with UCX_TEST_ASSERT here>
+ *  UCX_TEST_END
+ *  <cleanup of memory here>
+ * }
+ *
+ * PLEASE NOTE: if a test fails, a longjump is performed
+ * back to the UCX_TEST_BEGIN macro!
+ *
+ * You may use multiple BEGIN-END blocks if you are aware of the
+ * longjmp behaviour.
+ *
+ */
+
+#ifndef TEST_H
+#define	TEST_H
+
+#include "ucx.h"
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#ifndef __FUNCTION__
+#define __FUNCTION__ __func__
+#endif
+
+typedef struct UcxTestList UcxTestList;
+typedef struct UcxTestSuite UcxTestSuite;
+typedef void(*UcxTest)(UcxTestSuite*,FILE*);
+    
+struct UcxTestList{
+    UcxTest test;
+    UcxTestList *next;
+};
+
+struct UcxTestSuite {
+    unsigned int success;
+    unsigned int failure;
+    UcxTestList *tests;
+};
+
+UcxTestSuite* ucx_test_suite_new();
+void ucx_test_suite_free(UcxTestSuite*);
+
+int ucx_test_register(UcxTestSuite*, UcxTest);
+void ucx_test_run(UcxTestSuite*, FILE*);
+
+#define UCX_TEST_DECLARE(name) void name(UcxTestSuite*,FILE *)
+#define UCX_TEST_IMPLEMENT(name) void name(UcxTestSuite* _suite_,FILE *_output_)
+
+#define UCX_TEST_BEGIN fwrite("Running ", 1, 8, _output_);\
+        fwrite(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\
+        fwrite("... ", 1, 4, _output_);\
+        jmp_buf _env_; \
+        if (!setjmp(_env_)) {
+
+#define UCX_TEST_ASSERT(condition,message) if (!(condition)) { \
+        fwrite(message".\n", 1, 2+strlen(message), _output_); \
+        _suite_->failure++; \
+        longjmp(_env_, 1);\
+    }
+
+#define UCX_TEST_SUBROUTINE(name,...) void name(UcxTestSuite* _suite_,\
+        FILE *_output_, jmp_buf _env_, __VA_ARGS__)
+#define UCX_TEST_CALL_SUBROUTINE(name,...) \
+        name(_suite_,_output_,_env_,__VA_ARGS__);
+
+#define UCX_TEST_END fwrite("success.\n", 1, 9, _output_); _suite_->success++;}
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* TEST_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/utils.c	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,100 @@
+/*
+ * 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 "utils.h"
+#include "math.h"
+
+/* COPY FUCNTIONS */
+void* ucx_strcpy(void* s, void* data) {
+    char *str = (char*) s;
+    size_t n = 1+strlen(str);
+    char *cpy = (char*) malloc(n);
+    memcpy(cpy, str, n);
+    return cpy;
+}
+
+void* ucx_memcpy(void* m, void* n) {
+    size_t k = *((size_t*)n);
+    void *cpy = malloc(k);
+    memcpy(cpy, m, k);
+    return cpy;
+}
+
+/* COMPARE FUNCTION */
+
+int ucx_strcmp(void *s1, void *s2, void *data) {
+    return strcmp((char*)s1, (char*)s2);
+}
+
+int ucx_strncmp(void *s1, void *s2, void *n) {
+    return strncmp((char*)s1, (char*)s2, *((size_t*) n));
+}
+
+int ucx_intcmp(void *i1, void *i2, void *data) {
+   int a = *((int*) i1);
+   int b = *((int*) i2);
+   if (a == b) {
+       return 0;
+   } else {
+       return a < b ? -1 : 1;
+   }
+}
+
+int ucx_floatcmp(void *f1, void *f2, void *epsilon) {
+   float a = *((float*) f1);
+   float b = *((float*) f2);
+   float e = !epsilon ? 1e-6f : *((float*)epsilon);
+   if (fabsf(a - b) < e) {
+       return 0;
+   } else {
+       return a < b ? -1 : 1;
+   }
+}
+
+int ucx_doublecmp(void *d1, void *d2, void *epsilon) {
+   double a = *((float*) d1);
+   double b = *((float*) d2);
+   double e = !epsilon ? 1e-14 : *((double*)epsilon);
+   if (fabs(a - b) < e) {
+       return 0;
+   } else {
+       return a < b ? -1 : 1;
+   }
+}
+
+int ucx_ptrcmp(void *ptr1, void *ptr2, void *data) {
+    if (ptr1 == ptr2) {
+        return 0;
+    } else {
+        return ptr1 < ptr2 ? -1 : 1;
+    }
+}
+
+int ucx_memcmp(void *ptr1, void *ptr2, void *n) {
+    return memcmp(ptr1, ptr2, *((size_t*)n));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/utils.h	Fri Jun 21 12:10:44 2013 +0200
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#ifndef COMPARATOR_H
+#define	COMPARATOR_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include "ucx.h"
+#include <string.h>
+
+/**
+ * Copies a string.
+ * @param s the string to copy
+ * @param data omitted
+ * @return a pointer to a copy of s1 that can be passed to free(void*)
+ */
+void *ucx_strcpy(void *s, void *data);
+
+/**
+ * Copies a memory area.
+ * @param m a pointer to the memory area
+ * @param n a pointer to the size_t containing the size of the memory area
+ * @return a pointer to a copy of the specified memory area that can
+ * be passed to free(void*)
+ */
+void *ucx_memcpy(void *m, void *n);
+
+/**
+ * Wraps the strcmp function.
+ * @param s1 string one
+ * @param s2 string two
+ * @param data omitted
+ * @return the result of strcmp(s1, s2)
+ */
+int ucx_strcmp(void *s1, void *s2, void *data);
+
+/**
+ * Wraps the strncmp function.
+ * @param s1 string one
+ * @param s2 string two
+ * @param n a pointer to the size_t containing the third strncmp parameter
+ * @return the result of strncmp(s1, s2, *n)
+ */
+int ucx_strncmp(void *s1, void *s2, void *n);
+
+/**
+ * Compares two integers of type int.
+ * @param i1 pointer to integer one
+ * @param i2 pointer to integer two
+ * @param data omitted
+ * @return -1, if *i1 is less than *i2, 0 if both are equal,
+ * 1 if *i1 is greater than *i2
+ */
+
+int ucx_intcmp(void *i1, void *i2, void *data);
+
+/**
+ * Compares two real numbers of type float.
+ * @param f1 pointer to float one
+ * @param f2 pointer to float two
+ * @param if provided: a pointer to precision (default: 1e-6f)
+ * @return -1, if *f1 is less than *f2, 0 if both are equal,
+ * 1 if *f1 is greater than *f2
+ */
+
+int ucx_floatcmp(void *f1, void *f2, void *data);
+
+/**
+ * Compares two real numbers of type double.
+ * @param f1 pointer to double one
+ * @param f2 pointer to double two
+* @param if provided: a pointer to precision (default: 1e-14)
+ * @return -1, if *d1 is less than *d2, 0 if both are equal,
+ * 1 if *d1 is greater than *d2
+ */
+
+int ucx_doublecmp(void *d1, void *d2, void *data);
+
+/**
+ * Compares two pointers.
+ * @param ptr1 pointer one
+ * @param ptr2 pointer two
+ * @param data omitted
+ * @return -1 if ptr1 is less than ptr2, 0 if both are equal,
+ * 1 if ptr1 is greater than ptr2
+ */
+int ucx_ptrcmp(void *ptr1, void *ptr2, void *data);
+
+/**
+ * Compares two memory areas.
+ * @param ptr1 pointer one
+ * @param ptr2 pointer two
+ * @param n a pointer to the size_t containing the third parameter for memcmp
+ * @return the result of memcmp(ptr1, ptr2, *n)
+ */
+int ucx_memcmp(void *ptr1, void *ptr2, void *n);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* COMPARATOR_H */
+
--- a/src/server/util/io.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/util/io.c	Fri Jun 21 12:10:44 2013 +0200
@@ -95,7 +95,7 @@
         struct iovec io[2];
         char chunk_len[16];
         io[0].iov_base = chunk_len;
-        io[0].iov_len = snprintf(chunk_len, 16, "\n%zx\r\n", nbytes);
+        io[0].iov_len = snprintf(chunk_len, 16, "\r\n%zx\r\n", nbytes);
         io[1].iov_base = buf;
         io[1].iov_len = nbytes;
         ssize_t r = writev(st->fd, io, 2);
@@ -114,7 +114,7 @@
         for(int i=0;i<iovcnt;i++) {
             len += iovec[i].iov_len;
         }
-        io[0].iov_len = snprintf(chunk_len, 16, "\n%zx\r\n", len);
+        io[0].iov_len = snprintf(chunk_len, 16, "\r\n%zx\r\n", len);
         memcpy(io + 1, iovec, iovcnt * sizeof(struct iovec));
         ssize_t r = writev(st->fd, io, iovcnt + 1);
         return r - io[0].iov_len;
@@ -137,7 +137,7 @@
     ssize_t ret = 0;
     off_t fileoffset = sfd->offset;
     if(sfd->fd->fd != -1) {
-#ifdef OSX
+#ifdef BSD
         struct iovec hdvec;
         hdvec.iov_base = (void*)sfd->header;
         hdvec.iov_len = sfd->hlen;
@@ -151,8 +151,19 @@
         hdtr.trl_cnt = 1;
         
         off_t len = sfd->len;
-        ret = sendfile(sfd->fd->fd, st->fd, sfd->offset, &len, &hdtr, 0);
-#else
+#ifdef OSX
+        ret = sendfile(sfd->fd->fd, st->fd, fileoffset, &len, &hdtr, 0);
+#else // BSD
+        ret = sendfile(
+                sfd->fd->fd,
+                st->fd,
+                fileoffset,
+                sfd->len,
+                &hdtr,
+                NULL,
+                0);
+#endif
+#else // Solaris/Linux
         ret = sendfile(st->fd, sfd->fd->fd, &fileoffset, sfd->len);
 #endif
     } else {
--- a/src/server/util/pblock.cpp	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/util/pblock.cpp	Fri Jun 21 12:10:44 2013 +0200
@@ -333,7 +333,7 @@
     /* Check to see if name corresponds to a pb_key */
     CListConstIterator<pb_key> iter(&_hashKeys.Find(hashval));
     const pb_key *key;
-    while (key = ++iter) {
+    while((key = ++iter)) {
         if (key->hashval == hashval && !strcmp(key->name, name))
             return key;
     }
@@ -1127,7 +1127,7 @@
 
 /* ---------------------------- pblock_pb2env ----------------------------- */
 
-/*
+
 NSAPI_PUBLIC char **pblock_pb2env(const pblock *pb, char **env)
 {
     PListStruct_t *pl = PBTOPL(pb);
@@ -1138,13 +1138,15 @@
     int pos;
 
     /* Find out how many there are. */
-    /*
+    
     ppval = (PLValueStruct_t **)(pl->pl_ppval);
 
     for (i = 0, nval = 0; i < pl->pl_initpi; ++i) {
         if (ppval[i]) ++nval;
     }
-
+    
+    // TODO: implement util_env_create and util_env_str
+    /*
     env = util_env_create(env, nval, &pos);
 
     for (i = 0; i < pl->pl_initpi; ++i) {
@@ -1154,10 +1156,11 @@
         }
     }
     env[pos] = NULL;
+    */
 
     return env;
 }
-*/
+
 
 /* ---------------------------- pblock_replace ---------------------------- */
 
--- a/src/server/util/pool.c	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/util/pool.c	Fri Jun 21 12:10:44 2013 +0200
@@ -179,9 +179,8 @@
 static void 
 _free_block(block_t *block)
 {
+#ifdef POOL_ZERO_DEBUG
     long blen = block->end - block->data;
-
-#ifdef POOL_ZERO_DEBUG
     memset(block->data, POOL_ZERO_DEBUG, blen);
 #endif /* POOL_ZERO_DEBUG */
 
@@ -458,7 +457,7 @@
     }
 
     {
-        pool_t **ppool;
+        //pool_t **ppool;
 
         /* Remove from the known pools list */
         // NOTICE: known pools list removed
--- a/src/server/webdav/saxhandler.cpp	Thu Jun 20 14:07:46 2013 +0200
+++ b/src/server/webdav/saxhandler.cpp	Fri Jun 21 12:10:44 2013 +0200
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <iostream>
 
 #include "../ucx/string.h"
 #include "../ucx/dlist.h"

mercurial