diff -r 5dee29c7c530 -r 37ff8bf54b89 src/server/webdav/webdav.c
--- a/src/server/webdav/webdav.c Sat Feb 25 12:43:26 2012 +0100
+++ b/src/server/webdav/webdav.c Sun Feb 26 19:51:14 2012 +0100
@@ -38,13 +38,10 @@
#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.
- */
+ return webdav_propfind(pb, sn, rq);
+}
+int webdav_propfind(pblock *pb, Session *sn, Request *rq) {
/* TODO: clean up if errors occurs */
/* Get request body which contains the webdav XML request */
@@ -61,6 +58,9 @@
}
xml_body = pool_malloc(sn->pool, xml_len + 1);
+ if(xml_body == NULL) {
+ return REQ_ABORTED;
+ }
xml_body[xml_len] = 0;
if(!xml_body) {
/* server error */
@@ -77,182 +77,198 @@
xl -= xml_len;
}
+ /*
+ * get requested properties and initialize some stuff
+ */
PropfindRequest *davrq = dav_parse_propfind(sn, rq, xml_body, xml_len);
davrq->sn = sn;
davrq->rq = rq;
+ davrq->out = sbuf_new(512);
davrq->propertyBackend = create_property_backend();
- davrq->notFoundProps = NULL;
- davrq->forbiddenProps = NULL;
- davrq->out = sbuf_new(512);
-
- /* write header */
+
+ /* write xml response header */
sbuf_puts(davrq->out, "\n");
sbuf_puts(davrq->out, "\n");
-
- /* get stat of file */
+
+ /* begin multistatus response */
+ int is_dir = 0;
+ char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
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");
+ perror("webdav_propfind: stat");
return REQ_ABORTED;
- }
- /* TODO: check for more modes */
+ }
+
+ /*
+ * if the requested webdav resource(file) is a directory, we create
+ * a response for every child
+ */
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");
+ printf("webdav_propfind: 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 _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);
+
+ /* child response */
+ dav_resource_response(davrq, newpath, newuri);
}
}
- davrq->path = ppath;
- davrq->uri = uri;
- dav_create_response(davrq);
-
+
+ /* create the response for the requested resource */
+ dav_resource_response(davrq, sstr(ppath), sstr(uri));
+
+ /* end xml */
sbuf_puts(davrq->out, "\n");
-
- /* send buffer to client */
+
+ /* send the xml response to the client */
+ protocol_status(sn, rq, 207, "Multi Status");
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);
+
+ pblock_nvinsert("connection", "close", rq->srvhdrs);
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;
+void dav_resource_response(PropfindRequest *davrq, sstr_t path, sstr_t uri) {
+ printf("dav_resource_response %s %s\n", sstrdub(path).ptr, sstrdub(uri).ptr);
+
+ sbuf_puts(davrq->out, "\n");
+ sbuf_puts(davrq->out, "");
+ sbuf_append(davrq->out, uri);
+ sbuf_puts(davrq->out, "\n");
- 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");
+ davrq->propertyBackend->propfind(davrq->propertyBackend, davrq, path.ptr);
+
+ if(davrq->prop) {
+ /*
+ * there are some properties written, so we close the
+ * prop and propstat tag
+ */
+ sbuf_puts(davrq->out, "\n");
+ sbuf_puts(davrq->out, "HTTP/1.1 200 OK\n");
+ 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;
+ if(davrq->notFoundProps != NULL) {
+ sbuf_puts(davrq->out, "\n\n");
+ DAV_FOREACH(elm, davrq->notFoundProps) {
+ DavProperty *prop = (DavProperty*)elm->data;
+ sbuf_puts(davrq->out, "out, prop->name);
+ sbuf_puts(davrq->out, " />\n");
+ }
+ sbuf_puts(davrq->out, "\n");
+ sbuf_puts(davrq->out, "HTTP/1.1 404 Not Found\n");
+ sbuf_puts(davrq->out, "\n");
}
- 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");
+ /* reset */
+ davrq->prop = 0;
+ davrq->notFoundProps = NULL;
+ davrq->forbiddenProps = NULL;
+
}
-char* dav_get_property(
- DAVPropertyBackend *b,
+void dav_propfind_add_str_prop(
PropfindRequest *davrq,
- char *path,
- char *xmlns,
- char *name,
- int *error)
+ DavProperty* prop,
+ char *str,
+ size_t len)
{
- DAVDefaultBackend *be = (DAVDefaultBackend*)b;
- *error = 200;
+ if(!davrq->prop) {
+ sbuf_puts(davrq->out, "\n\n");
+ davrq->prop = 1;
+ }
+
+ sbuf_puts(davrq->out, "out, prop->name);
+ sbuf_puts(davrq->out, ">");
+
+ sbuf_append(davrq->out, sstrn(str, len));
+
+ sbuf_puts(davrq->out, "out, prop->name);
+ sbuf_puts(davrq->out, ">\n");
+}
- 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;
+void dav_propfind_add_prop_error(
+ PropfindRequest *davrq,
+ DavProperty *prop,
+ int error)
+{
+ davrq->notFoundProps = ucx_dlist_append(davrq->notFoundProps, prop);
}
+
+
+
+/* WebDAV Default Backend */
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;
+ DAVPropertyBackend *pb = malloc(sizeof(DAVPropertyBackend));
+ if(pb == NULL) {
+ //
+ }
+ pb->propfind = dav_rq_propfind;
+ return pb;
}
+
+void dav_rq_propfind(DAVPropertyBackend *b, PropfindRequest *rq ,char *path) {
+ struct stat st;
+ if(stat(path, &st) != 0) {
+ perror("dav_be_propfind");
+ fprintf(stderr, "Cannot get stat of file: %s\n", path);
+ }
+
+ DAV_FOREACH(elm, rq->properties) {
+ DavProperty *prop = (DavProperty*)elm->data;
+
+ char *s = prop->name;
+ if(!strcmp(s, "resourcetype")) {
+ if(S_ISDIR(st.st_mode)) {
+ dav_propfind_add_str_prop(rq, prop, "", 15);
+ } else {
+ dav_propfind_add_str_prop(rq, prop, NULL, 0);
+ }
+ } else if(!strcmp(s, "getcontentlength") && !S_ISDIR(st.st_mode)) {
+ char buf[32];
+ size_t n = snprintf(buf, 32, "%d", st.st_size);
+ dav_propfind_add_str_prop(rq, prop, buf, n);
+ } else {
+ dav_propfind_add_prop_error(rq, prop, 404);
+ }
+ }
+}