diff -r f4d93355b054 -r f727a21497bb src/server/webdav/webdav.c --- 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) {