Added webdav code

Sun, 08 Jan 2012 15:46:47 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 08 Jan 2012 15:46:47 +0100
changeset 13
1fdbf4170ef4
parent 12
34aa8001ea53
child 14
b8bf95b39952

Added webdav code

src/server/Makefile file | annotate | diff | comparison | revisions
src/server/conf.c file | annotate | diff | comparison | revisions
src/server/conf.h file | annotate | diff | comparison | revisions
src/server/davparser.cpp file | annotate | diff | comparison | revisions
src/server/davparser.h file | annotate | diff | comparison | revisions
src/server/dlist.c file | annotate | diff | comparison | revisions
src/server/dlist.h file | annotate | diff | comparison | revisions
src/server/object.c file | annotate | diff | comparison | revisions
src/server/objs.mk file | annotate | diff | comparison | revisions
src/server/saxhandler.cpp file | annotate | diff | comparison | revisions
src/server/saxhandler.h file | annotate | diff | comparison | revisions
src/server/ucx.h file | annotate | diff | comparison | revisions
src/server/webdav.c file | annotate | diff | comparison | revisions
src/server/webdav.h file | annotate | diff | comparison | revisions
src/server/ws-fn.c file | annotate | diff | comparison | revisions
--- a/src/server/Makefile	Fri Dec 30 17:50:05 2011 +0100
+++ b/src/server/Makefile	Sun Jan 08 15:46:47 2012 +0100
@@ -30,7 +30,7 @@
 OBJ_DIR = $(BUILD_ROOT)build/
 
 CFLAGS  = -I/usr/include/mps -g
-LDFLAGS = -L/usr/lib/mps -R/usr/lib/mps -lplds4 -lplc4 -lnspr4 -lpthread -ldl -lposix4  -lsocket -lnsl -lgen -lm -lsendfile -pg
+LDFLAGS = -L/usr/lib/mps -R/usr/lib/mps -lplds4 -lplc4 -lnspr4 -lpthread -ldl -lposix4  -lsocket -lnsl -lgen -lm -lsendfile -lxerces-c -pg
 
 MAIN_TARGET = $(BUILD_ROOT)work/bin/webservd
 
--- a/src/server/conf.c	Fri Dec 30 17:50:05 2011 +0100
+++ b/src/server/conf.c	Sun Jan 08 15:46:47 2012 +0100
@@ -50,6 +50,42 @@
 
 void load_init_conf(char *file) {
     printf("load_init_conf\n");
+    if(1) {
+        return;
+    }
+
+    pool_handle_t *pool = pool_create();
+
+    FILE *in = fopen("conf/obj.conf", "r");
+    if(in == NULL) {
+        fprintf(stderr, "Cannot open conf/obj.conf\n");
+        return;
+    }
+
+    char buf[512];
+    int  len = 512;
+
+    while(!feof(in)) {
+        fgets(buf, len, in);
+
+        if(*buf == 0) {
+            continue;
+        }
+
+        char *ptr;
+        if((ptr = strrchr(buf, '\n'))) {
+            ptr[0] = 0;
+        }
+
+        sstr_t line = string_trim(sstr(buf));
+        if(line.length > 0) {
+            sstr_t type;
+            directive *d = parse_directive(pool, line, &type);
+            if(sstrcmp(type, sstr("Init"))) {
+                d->func->func(d->param, NULL, NULL);
+            }
+        }
+    }
 }
 
 void load_server_conf(char *file) {
@@ -196,7 +232,10 @@
         }
     } else {
         // directive
-        parse_directive(parser, line);
+        sstr_t dtype;
+        directive *d = parse_directive(parser->conf->pool, line, &dtype);
+        int dt = get_directive_type_from_string(dtype);
+        object_add_directive(parser->obj, d, dt);
     }
 }
 
@@ -319,7 +358,7 @@
     return NULL;
 }
 
-void parse_directive(ObjectConfParser *parser, sstr_t line) {
+directive* parse_directive(pool_handle_t *pool, sstr_t line, sstr_t *type) {
     int i = 0;
     int b = 0;
 
@@ -327,7 +366,7 @@
     
     directive *directive = malloc(sizeof(directive));
     directive->cond = NULL;
-    directive->param = pblock_create_pool(parser->conf->pool, 8);
+    directive->param = pblock_create_pool(pool, 8);
 
     for(;i<line.length;i++) {
         if(line.ptr[i] < 33) {
@@ -335,7 +374,7 @@
             directive_type.length = i;
             if(directive_type.length <= 0) {
                 fprintf(stderr, "parse error: cannot parse directive\n");
-                return;
+                return NULL;
             }
         } else if(b == 1) {
             break;
@@ -357,7 +396,7 @@
         }
         if(!b) {
             printf("2\n");
-            return;
+            return NULL;
         }
         name.length = line.ptr + i - name.ptr - 1;
 
@@ -374,7 +413,7 @@
         }
         if(!b) {
             printf("3\n");
-            return;
+            return NULL;
         }
         value.length = line.ptr + i - value.ptr;
 
@@ -394,22 +433,25 @@
     char *func_name = pblock_findval("fn", directive->param);
     directive->func = get_function(func_name);
 
+    *type = directive_type;
+    return directive;
+}
+
+int get_directive_type_from_string(sstr_t type) {
     /* get nsapi function type */
     int dt = -1;
-    if(sstrcmp(directive_type, sstr("AuthTrans")) == 0) {
+    if(sstrcmp(type, sstr("AuthTrans")) == 0) {
         dt = 0;
-    } else if(sstrcmp(directive_type, sstr("NameTrans")) == 0) {
+    } else if(sstrcmp(type, sstr("NameTrans")) == 0) {
         dt = 1;
-    } else if(sstrcmp(directive_type, sstr("PathCheck")) == 0) {
+    } else if(sstrcmp(type, sstr("PathCheck")) == 0) {
         dt = 2;
-    } else if(sstrcmp(directive_type, sstr("ObjectType")) == 0) {
+    } else if(sstrcmp(type, sstr("ObjectType")) == 0) {
         dt = 3;
-    } else if(sstrcmp(directive_type, sstr("Service")) == 0) {
+    } else if(sstrcmp(type, sstr("Service")) == 0) {
         dt = 4;
-    } else if(sstrcmp(directive_type, sstr("AddLog")) == 0) {
-        //dt = 5;
-        return;
+    } else if(sstrcmp(type, sstr("AddLog")) == 0) {
+        dt = 5;
     }
-
-    object_add_directive(parser->obj, directive, dt);
+    return dt;
 }
--- a/src/server/conf.h	Fri Dec 30 17:50:05 2011 +0100
+++ b/src/server/conf.h	Sun Jan 08 15:46:47 2012 +0100
@@ -59,7 +59,9 @@
 
 httpd_object* parse_new_object_tag(sstr_t line);
 
-void parse_directive(ObjectConfParser *parser, sstr_t line);
+directive* parse_directive(pool_handle_t *pool, sstr_t line, sstr_t *type);
+
+int get_directive_type_from_string(sstr_t dt);
 
 
 #ifdef	__cplusplus
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/davparser.cpp	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,91 @@
+/*
+ * 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 "davparser.h"
+
+#include "pool.h"
+#include "pblock.h"
+
+#include "saxhandler.h"
+
+#include <xercesc/sax2/SAX2XMLReader.hpp>
+#include <xercesc/sax2/XMLReaderFactory.hpp>
+#include <xercesc/sax2/DefaultHandler.hpp>
+#include <xercesc/util/XMLString.hpp>
+#include <xercesc/framework/MemBufInputSource.hpp>
+
+XERCES_CPP_NAMESPACE_USE;
+
+int xcinit = 0;
+
+PropfindRequest* dav_parse_propfind(
+        Session *sn,
+        Request *rq,
+        char *xml,
+        size_t len)
+{
+    if(!xcinit) {
+        /* TODO: create webdav module init function */
+        XMLPlatformUtils::Initialize();
+        xcinit = 1;
+    }
+    PropfindRequest *davrq = (PropfindRequest*)pool_malloc(
+            sn->pool,
+            sizeof(PropfindRequest));
+    davrq->allprop = 0;
+    davrq->propname = 0;
+    davrq->properties = NULL;
+    // create xml parser
+    SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
+    parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
+
+    PropfindHandler handler(davrq, sn->pool);
+    parser->setContentHandler(&handler);
+    parser->setErrorHandler(&handler);
+
+    MemBufInputSource source((XMLByte*)xml, (XMLSize_t)len, "wsid");
+    try {
+        parser->parse(source);
+    }
+    catch (const XMLException& e) {
+        printf("XMLException\n");
+        
+    }
+    catch (const SAXParseException& e) {
+        printf("SAXParseException\n");
+        
+    }
+    catch (...) {
+        printf("davaparser Exception\n");
+    }
+
+    
+    
+
+    return davrq;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/davparser.h	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,53 @@
+/*
+ * 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 DAVPARSER_H
+#define	DAVPARSER_H
+
+#include "nsapi.h"
+
+#include "dlist.h"
+#include <inttypes.h>
+#include "webdav.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+PropfindRequest* dav_parse_propfind(
+        Session *sn,
+        Request *rq,
+        char *xml,
+        size_t len);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* DAVPARSER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/dlist.c	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,102 @@
+#include "dlist.h"
+
+void ucx_dlist_free(UcxDlist *l) {
+    UcxDlist *e = l, *f;
+    while (e != NULL) {
+        f = e;
+        e = e->next;
+        free(f);
+    }
+}
+
+UcxDlist *ucx_dlist_append(UcxDlist *l, void *data)  {
+    UcxDlist *nl = (UcxDlist*) malloc(sizeof(UcxDlist));
+    if (nl == NULL) return NULL;
+
+    nl->data = data;
+    nl->next = NULL;
+    if (l == NULL) {
+        return nl;
+    } else {
+        UcxDlist *t = ucx_dlist_last(l);
+        t->next = nl;
+        nl->prev = t;
+        return l;
+    }
+}
+
+UcxDlist *ucx_dlist_prepend(UcxDlist *l, void *data) {
+    UcxDlist *nl = ucx_dlist_append(NULL, data);
+    if (nl == NULL) return NULL;
+
+    if (l != NULL) {
+        nl->next = l;
+        l->prev = nl;
+    }
+    return nl;
+}
+
+UcxDlist *ucx_dlist_concat(UcxDlist *l1, UcxDlist *l2) {
+    if (l1 == NULL) {
+        return l2;
+    } else {
+        UcxDlist *last = ucx_dlist_last(l1);
+        last->next = l2;
+        l2->prev = last;
+        return l1;
+    }
+}
+
+UcxDlist *ucx_dlist_last(UcxDlist *l) {
+    if (l == NULL) return NULL;
+
+    UcxDlist *e = l;
+    while (e->next != NULL) {
+        e = e->next;
+    }
+    return e;
+}
+
+UcxDlist *ucx_dlist_get(UcxDlist *l, int index) {
+    if (l == NULL) return NULL;
+
+    UcxDlist *e = l;
+    while (e->next != NULL && index > 0) {
+        e = e->next;
+        index--;
+    }
+
+    return index == 0 ? e : NULL;
+}
+
+size_t ucx_dlist_size(UcxDlist *l) {
+    if (l == NULL) return 0;
+
+    UcxDlist *e = l;
+    size_t s = 1;
+    while (e->next != NULL) {
+        e = e->next;
+        s++;
+    }
+
+    return s;
+}
+
+void ucx_dlist_foreach(UcxDlist *l, ucx_callback fnc, void* data) {
+    UcxDlist *e = l;
+    while (e != NULL) {
+        fnc(e, data);
+        e = e->next;
+    }
+}
+
+/* dlist specific functions */
+UcxDlist *ucx_dlist_first(UcxDlist *l) {
+    if (l == NULL) return NULL;
+
+    UcxDlist *e = l;
+    while (e->prev != NULL) {
+        e = e->prev;
+    }
+    return e;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/dlist.h	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,39 @@
+/*
+ *
+ */
+
+#ifndef DLIST_H
+#define	DLIST_H
+
+#include "ucx.h"
+#include <stddef.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct UcxDlist UcxDlist;
+struct UcxDlist {
+    void     *data;
+    UcxDlist *next;
+    UcxDlist *prev;
+};
+
+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);
+void ucx_dlist_foreach(UcxDlist *l, ucx_callback fnc, void* data);
+
+/* dlist specific functions */
+UcxDlist *ucx_dlist_first(UcxDlist *l);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* DLIST_H */
+
--- a/src/server/object.c	Fri Dec 30 17:50:05 2011 +0100
+++ b/src/server/object.c	Sun Jan 08 15:46:47 2012 +0100
@@ -59,14 +59,16 @@
     dtable *l = object_get_dtable(obj, dt);
     // allocate space for the new directive
 
-    l->dirs = realloc(l->dirs, (l->ndir+1)*sizeof(void*));
+    //l->dirs = realloc(l->dirs, (l->ndir+1)*sizeof(void*));
     /* TODO: aus irgend einem Grund funktioniert realloc nicht. warum?? */
     
     directive **drs = malloc((l->ndir+1)*sizeof(void*));
     for(int i=0;i<l->ndir;i++) {
         drs[i] = l->dirs[i];
     }
-    free(l->dirs);
+    if(l->dirs != NULL) {
+        free(l->dirs);
+    }
     l->dirs = drs;
 
     // add directive
--- a/src/server/objs.mk	Fri Dec 30 17:50:05 2011 +0100
+++ b/src/server/objs.mk	Sun Jan 08 15:46:47 2012 +0100
@@ -62,6 +62,10 @@
 MOBJ += shexp.o
 MOBJ += objecttype.o
 MOBJ += strbuf.o
+MOBJ += webdav.o
+MOBJ += davparser.o
+MOBJ += dlist.o
+MOBJ += saxhandler.o
 
 MAINOBJS = $(MOBJ:%=$(OBJPRE)%)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/saxhandler.cpp	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,128 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sstring.h"
+#include "dlist.h"
+#include "pool.h"
+
+#include "saxhandler.h"
+
+using std;
+
+PropfindHandler::PropfindHandler(PropfindRequest *rq, pool_handle_t *p) {
+    davrq = rq;
+    pool  = p;
+
+    davPropTag = false;
+    property = NULL;
+}
+
+PropfindHandler::~PropfindHandler() {
+    
+}
+
+void PropfindHandler::startElement(
+        const XMLCh *const uri,
+        const XMLCh* const localname,
+        const XMLCh* const qname,
+        const Attributes& attrs)
+{
+    char *ns  = XMLString::transcode(uri);
+    char *name = XMLString::transcode(localname);
+    
+    if(!strcmp(ns, "DAV:") && !strcmp(name, "prop")) {
+        davPropTag = true;
+    } else if(davPropTag && property == NULL) {
+        //property = (DavProperty*)pool_malloc(pool, sizeof(DavProperty));
+        property = (DavProperty*)malloc(sizeof(DavProperty));
+        /* Ultra TODO: pool_malloc makes big mistakes!! */
+
+        size_t nslen = strlen(ns);
+        size_t namelen = strlen(name);
+        if(nslen > 0) {
+            property->xmlns = (char*)pool_malloc(pool, nslen + 1);
+            property->xmlns[nslen] = 0;
+            memcpy(property->xmlns, ns, nslen);
+        } else {
+            property->xmlns = NULL;
+        }
+
+        if(namelen > 0) {
+            property->name = (char*)pool_malloc(pool, namelen + 1);
+            property->name[namelen] = 0;
+            memcpy(property->name, name, namelen);
+        } else {
+            property->name = NULL;
+        }
+    }
+
+    XMLString::release(&ns);
+    XMLString::release(&name);
+}
+
+
+void PropfindHandler::endElement(
+        const XMLCh* const   uri,
+        const XMLCh* const   localname,
+        const XMLCh* const   qname)
+{
+    char *ns  = XMLString::transcode(uri);
+    char *name = XMLString::transcode(localname);
+
+    if(property != NULL) {
+        const char *xmlns = (property->xmlns) ? property->xmlns : "";
+        
+        if(!strcmp(ns, xmlns) && !strcmp(name, property->name)) {
+            // add property to DavRequest
+            UcxDlist *elm = (UcxDlist*)pool_malloc(pool, sizeof(UcxDlist));
+            elm->prev = NULL;
+            elm->next = NULL;
+            elm->data = property;
+            //printf("saxhandler: add property: {%s}\n", property->name);
+            davrq->properties = ucx_dlist_concat(davrq->properties, elm);
+            
+            property = NULL;
+        }
+    }
+
+    XMLString::release(&ns);
+    XMLString::release(&name);
+}
+
+void PropfindHandler::startDocument() {
+    
+}
+
+void PropfindHandler::endDocument() {
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/saxhandler.h	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,67 @@
+/*
+ * 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 SAXHANDLER_H
+#define	SAXHANDLER_H
+
+#include "davparser.h"
+
+#include <xercesc/sax2/DefaultHandler.hpp>
+
+using namespace xercesc;
+
+class PropfindHandler : public DefaultHandler {
+public:
+    PropfindHandler(PropfindRequest *rq, pool_handle_t *p);
+    virtual ~PropfindHandler();
+
+    void startElement(
+        const XMLCh* const   uri,
+        const XMLCh* const   localname,
+        const XMLCh* const   qname,
+        const Attributes&    attrs);
+    
+    void endElement(
+        const XMLCh* const   uri,
+        const XMLCh* const   localname,
+        const XMLCh* const   qname);
+
+    void startDocument();
+
+    void endDocument();
+
+private:
+    PropfindRequest *davrq;
+    pool_handle_t   *pool;
+
+    bool            davPropTag;
+    DavProperty     *property;
+};
+
+#endif	/* SAXHANDLER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx.h	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,24 @@
+/*
+ * File:   ucx.h
+ * Author: olaf
+ *
+ * Created on 31. Dezember 2011, 17:17
+ */
+
+#ifndef UCX_H
+#define	UCX_H
+
+#include <stdlib.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef int(*ucx_callback)(void*,void*);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* UCX_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/webdav.c	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,256 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "webdav.h"
+#include "sstring.h"
+#include "pool.h"
+#include "pblock.h"
+
+#include "davparser.h"
+
+int webdav_service(pblock *pb, Session *sn, Request *rq) {
+    /* TODO:
+     * Dies ist die Implementierung für PROPFIND. Es sollte für jede webdav-
+     * Methode eine eigene Service-Funktion geben. Solange die anderen
+     * Methoden nicht implementiert werden, behandelt webdav_service nur
+     * PROPFIND.
+     */
+
+    /* TODO: clean up if errors occurs */
+
+    /* Get request body which contains the webdav XML request */
+    char   *xml_body;
+    size_t xml_len = 0;
+
+    char *ctlen = pblock_findkeyval(pb_key_content_length, rq->headers);
+    if(ctlen) {
+        xml_len = atoi(ctlen);
+    } else {
+        /* invalid request */
+        return REQ_ABORTED;
+    }
+
+    xml_body = pool_malloc(sn->pool, xml_len + 1);
+    xml_body[xml_len] = 0;
+    if(!xml_body) {
+        /* server error */
+        return REQ_ABORTED;
+    }
+
+    /* TODO: bug with multi reads */
+    int r = 0;
+    char *xb = xml_body;
+    size_t xl = xml_len;
+    while((r = netbuf_getbytes(sn->inbuf, xb, xl)) != NETBUF_EOF) {
+        xb += r;
+        xl -= xml_len;
+    }
+
+    PropfindRequest *davrq = dav_parse_propfind(sn, rq, xml_body, xml_len);
+    davrq->sn = sn;
+    davrq->rq = rq;
+    davrq->propertyBackend = create_property_backend();
+    davrq->notFoundProps = NULL;
+    davrq->forbiddenProps = NULL;
+    davrq->out = sbuf_new(512);
+
+    /* write header */
+    sbuf_puts(davrq->out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+    sbuf_puts(davrq->out, "<D:multistatus xmlns:D=\"DAV:\">\n");
+
+    /* get stat of file */
+    char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars);
+    char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
+
+    struct stat st;
+    if(stat(ppath, &st) != 0) {
+        perror("webdav_service: stat");
+        return REQ_ABORTED;
+    }
+    /* TODO: check for more modes */
+    if(S_ISDIR(st.st_mode)) {
+        DIR *dir = opendir(ppath);
+        if(dir == NULL) {
+            protocol_status(sn, rq, 500, NULL);
+            printf("webdav_service: DIR is null\n");
+            return REQ_ABORTED;
+        }
+
+        struct dirent *f;
+        while((f = readdir(dir)) != NULL) {
+            if(strcmp(f->d_name, ".") == 0 || strcmp(f->d_name, "..") == 0) {
+                continue;
+            }
+
+            sstr_t filename = sstr(f->d_name);
+            sstr_t _path = sstr(ppath);
+            sstr_t _uri = sstr(uri);
+
+            sstr_t newuri;
+            newuri.length = filename.length + _uri.length;
+            newuri.ptr = alloca(newuri.length + 1);
+            newuri = sstrncat(2, newuri, _uri, filename);
+
+            sstr_t newpath;
+            newpath.length = _path.length + filename.length;
+            newpath.ptr = alloca(newpath.length + 1);
+            newpath = sstrncat(2, newpath, _path, filename);
+
+            davrq->path = newpath.ptr;
+            davrq->uri = newuri.ptr;
+            dav_create_response(davrq);
+        }
+    }
+    davrq->path = ppath;
+    davrq->uri = uri;
+    dav_create_response(davrq);
+
+    sbuf_puts(davrq->out, "</D:multistatus>\n");
+
+    /* send buffer to client */
+    pblock_removekey(pb_key_content_type, rq->srvhdrs);
+    pblock_nvinsert("content-type", "text/xml", rq->srvhdrs);
+    pblock_nninsert("content-length", davrq->out->length, rq->srvhdrs);
+
+    protocol_status(sn, rq, 207, NULL);
+    http_start_response(sn, rq);
+
+    net_write(sn->csd, davrq->out->ptr, davrq->out->length);
+
+    return REQ_PROCEED;
+}
+
+int dav_foreach_reqprop(UcxDlist *list, PropfindRequest *davrq) {
+    DavProperty *prop = list->data;
+    int error = 0;
+    
+    char *str = davrq->propertyBackend->get_property(
+            davrq->propertyBackend,
+            davrq,
+            davrq->path,
+            prop->xmlns,
+            prop->name,
+            &error);
+    if(str == NULL) {
+        UcxDlist **dl = NULL;
+        if(error == 404) {
+            dl = &davrq->notFoundProps;
+        } else {
+            dl = &davrq->forbiddenProps;
+        }
+        *dl = ucx_dlist_append(*dl, prop);
+    } else {
+        //printf("dav property: {%s|%s::%s\n", prop->xmlns, prop->name, str);
+        sbuf_puts(davrq->out, "<D:");
+        sbuf_puts(davrq->out, prop->name);
+        sbuf_puts(davrq->out, ">");
+        sbuf_puts(davrq->out, str);
+        sbuf_puts(davrq->out, "</D:");
+        sbuf_puts(davrq->out, prop->name);
+        sbuf_puts(davrq->out, ">\n");
+    }
+    return 0;
+}
+
+void dav_create_response(PropfindRequest *davrq) {
+    sbuf_puts(davrq->out, "<D:response>\n");
+
+    sbuf_puts(davrq->out, "<D:href>");
+    sbuf_puts(davrq->out, davrq->uri);
+    sbuf_puts(davrq->out, "</D:href>\n");
+
+    sbuf_puts(davrq->out, "<D:propstat>\n<D:prop>\n");
+    
+    ucx_dlist_foreach(
+            davrq->properties,
+            (ucx_callback)dav_foreach_reqprop,
+            davrq);
+
+    sbuf_puts(davrq->out, "</D:prop>\n<D:status>HTTP/1.1 200 OK</D:status>\n");
+    sbuf_puts(davrq->out, "</D:propstat>\n");
+
+    /* 404 props */
+    sbuf_puts(davrq->out, "<D:propstat>\n<D:prop>\n");
+    UcxDlist *dl = davrq->notFoundProps;
+    while(dl != NULL) {
+        DavProperty *nfp = dl->data;
+        sbuf_puts(davrq->out, "<D:");
+        sbuf_puts(davrq->out, nfp->name);
+        sbuf_puts(davrq->out, " />\n");
+        dl = dl->next;
+    }
+    sbuf_puts(davrq->out, "</D:prop>\n");
+    sbuf_puts(davrq->out, "<D:status>HTTP/1.1 404 Not Found</D:status>\n");
+    sbuf_puts(davrq->out, "</D:propstat>\n");
+
+    /* end */
+    sbuf_puts(davrq->out, "</D:response>\n");
+    
+}
+
+char* dav_get_property(
+        DAVPropertyBackend *b,
+        PropfindRequest *davrq,
+        char *path,
+        char *xmlns,
+        char *name,
+        int *error)
+{
+    DAVDefaultBackend *be = (DAVDefaultBackend*)b;
+    *error = 200;
+
+    if(strcmp(name, "getcontentlength") == 0) {
+        struct stat s;
+        if(stat(davrq->path, &s) != 0) {
+            *error = 403; /* really? */
+            return NULL;
+        }
+        if(S_ISDIR(s.st_mode)) {
+            *error = 404;
+            return NULL;
+        }
+        char *buf = pool_malloc(davrq->sn->pool, 24);
+        sprintf(buf, "%d", s.st_size);
+        return buf;
+    }
+
+    *error = 404;
+    return NULL;
+}
+
+DAVPropertyBackend* create_property_backend() {
+    DAVDefaultBackend *backend = malloc(sizeof(DAVDefaultBackend));
+    backend->backend.get_property = dav_get_property;
+    backend->path = NULL;
+    backend->s = 0;
+    return (DAVPropertyBackend*)backend;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/webdav.h	Sun Jan 08 15:46:47 2012 +0100
@@ -0,0 +1,115 @@
+/*
+ * 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 WEBDAV_H
+#define	WEBDAV_H
+
+#include "nsapi.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include "map.h"
+#include "dlist.h"
+#include "strbuf.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct PropfindResponse PropfindResponse;
+typedef struct DAVPropertyBackend DAVPropertyBackend;
+
+typedef struct PropfindRequest   PropfindRequest;
+typedef struct DavProperty       DavProperty;
+
+struct PropfindRequest {
+    Session            *sn;
+    Request            *rq;
+
+    UcxDlist           *properties; /* DavProperty list */
+    int8_t             allprop;
+    int8_t             propname;
+
+    UcxDlist           *notFoundProps;
+    UcxDlist           *forbiddenProps;
+    DAVPropertyBackend *propertyBackend;
+
+    char               *path;
+    char               *uri;
+
+    sbuf_t             *out;
+};
+
+struct DavProperty {
+    char *xmlns;
+    char *name;
+};
+
+typedef char*(*prop_get_func)(
+        DAVPropertyBackend*,
+        PropfindRequest*,
+        char*,
+        char*,
+        char*,
+        int*);
+
+struct DAVPropertyBackend {
+    prop_get_func get_property;
+};
+
+int webdav_service(pblock *pb, Session *sn, Request *rq);
+
+void dav_create_response(PropfindRequest *davrq);
+
+int dav_foreach_reqprop(UcxDlist *list, PropfindRequest *davrq);
+
+char* dav_get_property(
+        DAVPropertyBackend *b,
+        PropfindRequest *davrq,
+        char *path,
+        char *xmlns,
+        char *name,
+        int *error);
+
+DAVPropertyBackend* create_property_backend();
+
+typedef struct {
+    DAVPropertyBackend backend;
+    char *path;
+    struct stat st;
+    int s;
+} DAVDefaultBackend;
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* WEBDAV_H */
+
--- a/src/server/ws-fn.c	Fri Dec 30 17:50:05 2011 +0100
+++ b/src/server/ws-fn.c	Sun Jan 08 15:46:47 2012 +0100
@@ -31,6 +31,7 @@
 #include "nametrans.h"
 #include "objecttype.h"
 #include "service.h"
+#include "webdav.h"
 
 struct FuncStruct webserver_funcs[] = {
     { "test-nametrans", test_nametrans, NULL, 0 },
@@ -39,5 +40,6 @@
     { "send-file", send_file, NULL, 0},
     { "common-index", service_index, NULL, 0},
     { "service-hello", service_hello, NULL, 0},
+    { "webdav-service", webdav_service, NULL, 0},
     {NULL, NULL, NULL, 0}
 };

mercurial