diff -r 1fdbf4170ef4 -r b8bf95b39952 src/server/webdav.c --- a/src/server/webdav.c Sun Jan 08 15:46:47 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,256 +0,0 @@ -/* - * 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 -#include -#include - -#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, "\n"); - sbuf_puts(davrq->out, "\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, "\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, "out, prop->name); - sbuf_puts(davrq->out, ">"); - sbuf_puts(davrq->out, str); - sbuf_puts(davrq->out, "out, prop->name); - sbuf_puts(davrq->out, ">\n"); - } - return 0; -} - -void dav_create_response(PropfindRequest *davrq) { - sbuf_puts(davrq->out, "\n"); - - sbuf_puts(davrq->out, ""); - sbuf_puts(davrq->out, davrq->uri); - sbuf_puts(davrq->out, "\n"); - - sbuf_puts(davrq->out, "\n\n"); - - ucx_dlist_foreach( - davrq->properties, - (ucx_callback)dav_foreach_reqprop, - davrq); - - sbuf_puts(davrq->out, "\nHTTP/1.1 200 OK\n"); - sbuf_puts(davrq->out, "\n"); - - /* 404 props */ - sbuf_puts(davrq->out, "\n\n"); - UcxDlist *dl = davrq->notFoundProps; - while(dl != NULL) { - DavProperty *nfp = dl->data; - sbuf_puts(davrq->out, "out, nfp->name); - sbuf_puts(davrq->out, " />\n"); - dl = dl->next; - } - sbuf_puts(davrq->out, "\n"); - sbuf_puts(davrq->out, "HTTP/1.1 404 Not Found\n"); - sbuf_puts(davrq->out, "\n"); - - /* end */ - sbuf_puts(davrq->out, "\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; -}