added put method

Mon, 27 Feb 2012 17:20:42 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 27 Feb 2012 17:20:42 +0100
changeset 27
05b7576dca2b
parent 26
37ff8bf54b89
child 28
f387669912e8

added put method

src/server/daemon/main.c file | annotate | diff | comparison | revisions
src/server/util/date.c file | annotate | diff | comparison | revisions
src/server/util/date.h file | annotate | diff | comparison | revisions
src/server/util/objs.mk file | annotate | diff | comparison | revisions
src/server/webdav/webdav.c file | annotate | diff | comparison | revisions
src/server/webdav/webdav.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/main.c	Sun Feb 26 19:51:14 2012 +0100
+++ b/src/server/daemon/main.c	Mon Feb 27 17:20:42 2012 +0100
@@ -37,6 +37,7 @@
 #include "../util/pool.h"
 #include "../public/nsapi.h"
 #include "../util/plist.h"
+#include "../util/date.h"
 
 #include "webserver.h"
 
@@ -47,7 +48,10 @@
 int std_pipe_fds[2];
 
 void test() {
-    
+    time_t t = time(NULL);
+    pool_handle_t *pool = pool_create();
+    sstr_t date = date_format_http(t, pool);
+    printf("%s\n", date.ptr);
 }
 
 /*
@@ -86,7 +90,7 @@
 }
 
 int main(int argc, char **argv) {
-    //test();
+    test();
 
     /* if the -c parameter is specified, we don't create a daemon */
     int d = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/util/date.c	Mon Feb 27 17:20:42 2012 +0100
@@ -0,0 +1,110 @@
+/*
+ * 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 <stdlib.h>
+#include "pool.h"
+
+#include "date.h"
+
+char *date_wkday[] = {
+    "Sun",
+    "Mon",
+    "Tue",
+    "Wed",
+    "Thu",
+    "Fri",
+    "Sat"
+};
+
+char *date_month[] = {
+    "Jan",
+    "Feb",
+    "Mar",
+    "Apr",
+    "May",
+    "Jun",
+    "Jul",
+    "Aug",
+    "Sep",
+    "Oct",
+    "Nov",
+    "Dec"
+};
+
+sstr_t date_format_http(time_t t, pool_handle_t *pool) {
+    sstr_t d;
+    d.ptr = NULL;
+    d.length = 0;
+    
+    struct tm date;
+    gmtime_r(&t, &date);
+    
+    char *str = pool_malloc(pool, 32);
+    snprintf(
+            str,
+            32,
+            "%s, %02d %s %d %02d:%02d:%02d GMT",
+            date_wkday[date.tm_wday],
+            date.tm_mday,
+            date_month[date.tm_mon],
+            1900 + date.tm_year,
+            date.tm_hour,
+            date.tm_min,
+            date.tm_sec);
+    
+    d.length = 29;
+    d.ptr = str;
+    
+    return d;
+}
+
+sstr_t date_format_iso8601(time_t t, pool_handle_t *pool) {
+    sstr_t d;
+    d.ptr = NULL;
+    d.length = 0;
+    
+    struct tm date;
+    gmtime_r(&t, &date);
+    
+    char *str = pool_malloc(pool, 24);
+    snprintf(
+            str,
+            24,
+            "%d-%02d-%02dT%02d:%02d:%02dZ",
+            1900 + date.tm_year,
+            date.tm_mon + 1,
+            date.tm_mday,
+            date.tm_hour,
+            date.tm_min,
+            date.tm_sec);
+    
+    d.length = 20;
+    d.ptr = str;
+    
+    return d;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/util/date.h	Mon Feb 27 17:20:42 2012 +0100
@@ -0,0 +1,52 @@
+/*
+ * 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 DATE_H
+#define	DATE_H
+
+#include "../public/nsapi.h"
+
+#include <time.h>
+
+#include "../ucx/string.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+sstr_t date_format_http(time_t t, pool_handle_t *pool);
+
+sstr_t date_format_iso8601(time_t t, pool_handle_t *pool);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* DATE_H */
+
--- a/src/server/util/objs.mk	Sun Feb 26 19:51:14 2012 +0100
+++ b/src/server/util/objs.mk	Mon Feb 27 17:20:42 2012 +0100
@@ -41,6 +41,7 @@
 UTILOBJ += systhr.o
 UTILOBJ += thrpool.o
 UTILOBJ += util.o
+UTILOBJ += date.o
 
 UTILOBJS = $(UTILOBJ:%=$(UTIL_OBJPRE)%)
 UTILSOURCE = $(UTILOBJ:%.o=util/%.c)
--- a/src/server/webdav/webdav.c	Sun Feb 26 19:51:14 2012 +0100
+++ b/src/server/webdav/webdav.c	Mon Feb 27 17:20:42 2012 +0100
@@ -34,11 +34,74 @@
 #include "../ucx/string.h"
 #include "../util/pool.h"
 #include "../util/pblock.h"
+#include "../util/date.h"
 
 #include "davparser.h"
 
 int webdav_service(pblock *pb, Session *sn, Request *rq) {
-    return webdav_propfind(pb, sn, rq);
+    char *method = pblock_findkeyval(pb_key_method, rq->reqpb);
+    if(method == NULL) {
+        return REQ_ABORTED;
+    }
+    
+    if(!strcmp(method, "PROPFIND")) {
+        return webdav_propfind(pb, sn, rq);
+    } else if(!strcmp(method, "PUT")) {
+        return webdav_put(pb, sn, rq);
+    }
+    
+    return REQ_NOACTION;
+}
+
+int webdav_put(pblock *pb, Session *sn, Request *rq) {
+    int length = 0;
+    
+    char *ctlen = pblock_findkeyval(pb_key_content_length, rq->headers);
+    if(ctlen) {
+        length = atoi(ctlen);
+    } else {
+        /* invalid request */
+        printf("invalid request\n");
+        return REQ_ABORTED;
+    }
+    
+    printf("PUT length: %d\n", length);
+    
+    int status = 204;
+    if(length >= 0) {
+        char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars);
+        
+        FILE *out = fopen(ppath, "w");
+        if(out == NULL) {
+            fprintf(stderr, "fopen(%s, \"w\") failed\n", ppath);
+            return REQ_ABORTED;
+        }
+        setvbuf(out, NULL, _IONBF, 0);
+        
+        size_t l = (length > 4096) ? (4096) : (length);
+        char *buffer = malloc(l);
+        
+        int r;
+        int r2 = 0;
+        while(r2 < length) {
+            r = netbuf_getbytes(sn->inbuf, buffer, l);
+            if(r == NETBUF_EOF) {
+                break;
+            }
+            fwrite(buffer, 1, r, out);
+            
+            r2 += r;
+        }
+        
+        fclose(out);
+    }
+    
+    protocol_status(sn, rq, status, NULL);
+    pblock_removekey(pb_key_content_type, rq->srvhdrs);
+    pblock_nninsert("content-length", 0, rq->srvhdrs);
+    http_start_response(sn, rq);
+    
+    return REQ_PROCEED;
 }
 
 int webdav_propfind(pblock *pb, Session *sn, Request *rq) {
@@ -68,13 +131,13 @@
         return REQ_ABORTED;
     }
 
-    /* TODO: bug with multiple reads */
+    /* get request body */
     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;
+        xl -= r;
     }
 
     /*
@@ -91,7 +154,6 @@
     sbuf_puts(davrq->out, "<D:multistatus xmlns:D=\"DAV:\">\n");
     
     /* 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);
     
@@ -122,16 +184,36 @@
             sstr_t filename = sstr(f->d_name);
             sstr_t _path = sstr(ppath); 
             sstr_t _uri = sstr(uri);
+            sstr_t ps;
+            sstr_t us;
+            ps.length = 0;
+            ps.ptr = NULL;
+            us.length = 0;
+            us.ptr = NULL;
+            if(_path.ptr[_path.length - 1] != '/') {
+                ps = sstrn("/", 1);
+            }
+            if(_uri.ptr[_uri.length - 1] != '/') {
+                us = sstrn("/", 1);
+            }
             
             sstr_t newuri;
-            newuri.length = filename.length + _uri.length;
+            newuri.length = filename.length + _uri.length + us.length;
             newuri.ptr = alloca(newuri.length + 1);
-            newuri = sstrncat(2, newuri, _uri, filename);
+            if(us.length == 1) {
+                newuri = sstrncat(3, newuri, _uri, us, filename);
+            } else {
+                newuri = sstrncat(2, newuri, _uri, filename);
+            }
             
             sstr_t newpath;
-            newpath.length = _path.length + filename.length;
+            newpath.length = _path.length + filename.length + ps.length;
             newpath.ptr = alloca(newpath.length + 1);
-            newpath = sstrncat(2, newpath, _path, filename);
+            if(ps.length == 1) {
+                newpath = sstrncat(3, newpath, _path, ps, filename);
+            } else {
+                newpath = sstrncat(2, newpath, _path, filename);
+            }
             
             /* child response */
             dav_resource_response(davrq, newpath, newuri);
@@ -267,6 +349,12 @@
             char buf[32];
             size_t n = snprintf(buf, 32, "%d", st.st_size);
             dav_propfind_add_str_prop(rq, prop, buf, n);
+        } else if(!strcmp(s, "getlastmodified")) {
+            sstr_t s = date_format_http(st.st_mtim.tv_sec, rq->sn->pool);
+            dav_propfind_add_str_prop(rq, prop, s.ptr, s.length);
+        } else if(!strcmp(s, "creationdate")) {
+            sstr_t s = date_format_iso8601(st.st_ctim.tv_sec, rq->sn->pool);
+            dav_propfind_add_str_prop(rq, prop, s.ptr, s.length);
         } else {
             dav_propfind_add_prop_error(rq, prop, 404);
         }
--- a/src/server/webdav/webdav.h	Sun Feb 26 19:51:14 2012 +0100
+++ b/src/server/webdav/webdav.h	Mon Feb 27 17:20:42 2012 +0100
@@ -94,6 +94,7 @@
 };
 
 int webdav_service(pblock *pb, Session *sn, Request *rq);
+int webdav_put(pblock *pb, Session *sn, Request *rq);
 int webdav_propfind(pblock *pb, Session *sn, Request *rq);
 
 void dav_resource_response(PropfindRequest *rq, sstr_t path, sstr_t uri);

mercurial