Sun, 08 Jan 2012 15:46:47 +0100
Added webdav code
--- 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} };