# HG changeset patch # User Olaf Wintermann # Date 1580579071 -3600 # Node ID e59abb21058485b7bdcf73561388cd1de826672e # Parent 1a29b1d8d9d89d959092d21a325bb5111ef0cd6f add minimal mkcol implementation and prepare delete diff -r 1a29b1d8d9d8 -r e59abb210584 src/server/public/webdav.h --- a/src/server/public/webdav.h Sun Jan 26 11:50:35 2020 +0100 +++ b/src/server/public/webdav.h Sat Feb 01 18:44:31 2020 +0100 @@ -320,6 +320,40 @@ WSBool); /* + * int opt_mkcol( + * Session *sn, + * Request *rq, + * const char *path, + * WSBool *out_created + * + * Optional mkcol callback that is called before vfs_mkdir. If the function + * sets out_created to TRUE, vfs_mkdir will not be executed. + */ + int (*opt_mkcol)( + Session *, + Request *, + const char *, + WSBool *); + + /* + * int opt_delete( + * Session *sn, + * Request *rq, + * const char *path, + * WSBool *out_deleted + * + * Optional delete callback that is called once before any VFS deletions. + * When the callback sets out_deleted to TRUE, no VFS unlink operations + * will be done. + * + */ + int (*opt_delete)( + Session *, + Request *, + const char *, + WSBool *); + + /* * See the WS_WEBDAV_* macros for informations about the settings */ uint32_t settings; diff -r 1a29b1d8d9d8 -r e59abb210584 src/server/test/webdav.c --- a/src/server/test/webdav.c Sun Jan 26 11:50:35 2020 +0100 +++ b/src/server/test/webdav.c Sat Feb 01 18:44:31 2020 +0100 @@ -123,6 +123,8 @@ backend2_propfind_finish, backend2_proppatch_do, backend2_proppatch_finish, + NULL, // opt_mkcol + NULL, // opt_delete 0, NULL }; @@ -221,6 +223,8 @@ backend1_propfind_finish, backend1_proppatch_do, backend1_proppatch_finish, + NULL, // opt_mkcol + NULL, // opt_delete 0, &backend2 }; diff -r 1a29b1d8d9d8 -r e59abb210584 src/server/webdav/webdav.c --- a/src/server/webdav/webdav.c Sun Jan 26 11:50:35 2020 +0100 +++ b/src/server/webdav/webdav.c Sat Feb 01 18:44:31 2020 +0100 @@ -66,6 +66,8 @@ default_backend.propfind_finish = default_propfind_finish; default_backend.proppatch_do = default_proppatch_do; default_backend.proppatch_finish = default_proppatch_finish; + default_backend.opt_mkcol = NULL; + default_backend.opt_delete = NULL; default_backend.settings = WS_WEBDAV_PROPFIND_USE_VFS; } @@ -444,15 +446,64 @@ } int webdav_mkcol(pblock *pb, Session *sn, Request *rq) { - return REQ_ABORTED; + UcxBuffer *reqbuf; + VFSContext *vfs; + char *path; + + if(webdav_init_vfs_op(sn, rq, &reqbuf, &vfs, &path)) { + return REQ_ABORTED; + } + + int ret = REQ_PROCEED; + if(vfs_mkdir(vfs, path)) { + protocol_status(sn, rq, util_errno2status(vfs->vfs_errno), NULL); + return REQ_ABORTED; + } + + protocol_status(sn, rq, 201, NULL); + + // cleanup and return + if(reqbuf) { + ucx_buffer_free(reqbuf); + } + return ret; } int webdav_post(pblock *pb, Session *sn, Request *rq) { return REQ_ABORTED; } +static int webdav_delete_collection( + Session *sn, + Request *rq, + VFSContext *vfs, + const char *path) +{ + +} + int webdav_delete(pblock *pb, Session *sn, Request *rq) { - return REQ_ABORTED; + UcxBuffer *reqbuf; + VFSContext *vfs; + char *path; + + if(webdav_init_vfs_op(sn, rq, &reqbuf, &vfs, &path)) { + return REQ_ABORTED; + } + + int ret = REQ_PROCEED; + + // TODO + + if(ret == REQ_PROCEED) { + protocol_status(sn, rq, 200, NULL); + } + + // cleanup and return + if(reqbuf) { + ucx_buffer_free(reqbuf); + } + return ret; } int webdav_put(pblock *pb, Session *sn, Request *rq) { @@ -484,6 +535,51 @@ } +int webdav_init_vfs_op( + Session *sn, + Request *rq, + UcxBuffer **out_reqbuf, + VFSContext **out_vfs, + char **out_path) +{ + *out_reqbuf = NULL; + *out_vfs = NULL; + *out_path = NULL; + + // create VFS context + VFSContext *vfs = vfs_request_context(sn, rq); + if(!vfs) { + return REQ_ABORTED; + } + + // read request body, if it exists + char *expect = pblock_findkeyval(pb_key_expect, rq->headers); + if(expect) { + if(!strcasecmp(expect, "100-continue")) { + if(http_send_continue(sn)) { + return REQ_ABORTED; + } + } + } + + UcxBuffer *reqbody = NULL; + if(sn->inbuf) { + reqbody = rqbody2buffer(sn, rq); + if(!reqbody) { + return REQ_ABORTED; + } + } + + // requested uri and path + char *path = pblock_findkeyval(pb_key_path, rq->vars); + + *out_reqbuf = reqbody; + *out_vfs = vfs; + *out_path = path; + + return REQ_PROCEED; +} + /* ------------------------ default webdav backend ------------------------ */ int default_propfind_init( diff -r 1a29b1d8d9d8 -r e59abb210584 src/server/webdav/webdav.h --- a/src/server/webdav/webdav.h Sun Jan 26 11:50:35 2020 +0100 +++ b/src/server/webdav/webdav.h Sat Feb 01 18:44:31 2020 +0100 @@ -82,6 +82,25 @@ int webdav_acl(pblock *pb, Session *sn, Request *rq); int webdav_search (pblock *pb, Session *sn, Request *rq); +/* + * Initialize a WebDAV VFS operation + * + * sn: WS Session + * rq: WS Request + * out_reqbuf: func returns a pointer to the request body or NULL + * out_vfs: func returns a pointer to the newly created VFSContext + * out_path: func returns a pointer to the path string + * + * return: on success REQ_PROCEED + * on error REQ_ABORTED + */ +int webdav_init_vfs_op( + Session *sn, + Request *rq, + UcxBuffer **out_reqbuf, + VFSContext **out_vfs, + char **out_path); + int default_propfind_init( WebdavPropfindRequest *rq, const char* path,