src/server/webdav/webdav.c

branch
webdav
changeset 251
f727a21497bb
parent 249
3b302093945c
child 252
5653a9626cc0
--- a/src/server/webdav/webdav.c	Sun Jun 07 17:18:59 2020 +0200
+++ b/src/server/webdav/webdav.c	Sat Jul 11 17:58:00 2020 +0200
@@ -397,7 +397,7 @@
             default: return REQ_ABORTED;
         }
     }
-    
+     
     WebdavBackend *dav =  rq->davCollection ?
                               rq->davCollection : &default_backend;
     
@@ -600,7 +600,65 @@
 }
 
 int webdav_put(pblock *pb, Session *sn, Request *rq) {
-    return REQ_ABORTED;
+    char *path = pblock_findkeyval(pb_key_path, rq->vars);
+
+    VFSContext *vfs = vfs_request_context(sn, rq);
+    if(!vfs) {
+        protocol_status(sn, rq, PROTOCOL_SERVER_ERROR, NULL);
+        return REQ_ABORTED;
+    }
+    
+    struct stat s;
+    int create_file = 0;
+    if(vfs_stat(vfs, path, &s)) {
+        if(vfs->vfs_errno == ENOENT) {
+            create_file = O_CREAT;
+        } else {
+            protocol_status(sn, rq, util_errno2status(vfs->vfs_errno), NULL);
+            return REQ_ABORTED;
+        }
+    }
+    
+    if(S_ISDIR(s.st_mode)) {
+        // PUT on collections is not allowed
+        protocol_status(sn, rq, PROTOCOL_METHOD_NOT_ALLOWED, NULL);
+        return REQ_ABORTED;
+    }
+    
+    SYS_FILE fd = vfs_open(vfs, path, O_RDONLY | create_file);
+    if(!fd) {
+        // if it fails, vfs_open sets http status code
+        return REQ_ABORTED;
+    }
+    
+    // TODO: check permissions, lock, ...
+    
+    // all checks done
+    
+    char *expect = pblock_findkeyval(pb_key_expect, rq->headers);
+    if(expect) {
+        if(!strcasecmp(expect, "100-continue")) {
+            if(http_send_continue(sn)) {
+                return REQ_ABORTED;
+            }
+        }
+    }
+    
+    char in[4096];
+    int r;
+    while((r = netbuf_getbytes(sn->inbuf, in, 2048)) > 0) {
+        int w = 0;
+        while(w < r) {
+            w += system_fwrite(fd, in, r);
+        }
+    }
+    
+    system_fclose(fd);
+    
+    int status = create_file ? PROTOCOL_CREATED : PROTOCOL_NO_CONTENT;
+    protocol_status(sn, rq, status, NULL);
+    
+    return REQ_PROCEED;
 }
 
 int webdav_copy(pblock *pb, Session *sn, Request *rq) {

mercurial