Mon, 06 May 2013 13:44:27 +0200
some fixes and new public APIs
--- a/src/server/daemon/acl.h Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/acl.h Mon May 06 13:44:27 2013 +0200 @@ -29,164 +29,12 @@ #ifndef ACL_H #define ACL_H -#include "../public/nsapi.h" -#include "authdb.h" +#include "../public/acl.h" #ifdef __cplusplus extern "C" { #endif -// ACLListHandle typedef in nsapi.h -typedef struct ACLListElm ACLListElm; -typedef struct ACLList ACLList; - -typedef struct WSAcl WSAcl; -typedef struct WSAce WSAce; - -/* - * a wrapper struct for acls - */ -struct ACLListHandle { - AuthDB *defaultauthdb; - ACLListElm *listhead; - ACLListElm *listtail; -}; - -struct ACLListElm { - ACLList *acl; - ACLListElm *next; -}; - -/* - * abstract ACL - */ -typedef int(*acl_check_f)(ACLList*, User*, int); -struct ACLList { - AuthDB *authdb; - char *authprompt; - int isextern; - /* int check(ACLList *acl, User *user, int access_mask) */ - int(*check)(ACLList *acl, User *user, int access_mask); -}; - -/* - * a webserver access control list - * - * Access control is determined by the ace field. The ece field is a separat - * list for audit and alarm entries. - */ -struct WSAcl { - ACLList acl; - WSAce **ace; // access control entries - WSAce **ece; // event control entries (audit/alarm entries) - int acenum; // number of aces - int ecenum; // number of eces -}; - - -struct WSAce { - char *who; // user or group name - uint32_t access_mask; - uint16_t flags; - uint16_t type; -}; - - -/* - * access permissions - */ -#define ACL_READ_DATA 0x0001 -#define ACL_WRITE_DATA 0x0002 -#define ACL_APPEND 0x0002 -#define ACL_ADD_FILE 0x0004 -#define ACL_ADD_SUBDIRECTORY 0x0004 -#define ACL_READ_XATTR 0x0008 -#define ACL_WRITE_XATTR 0x0010 -#define ACL_EXECUTE 0x0020 -#define ACL_DELETE_CHILD 0x0040 -#define ACL_DELETE 0x0040 -#define ACL_READ_ATTRIBUTES 0x0080 -#define ACL_WRITE_ATTRIBUTES 0x0100 -#define ACL_LIST 0x0200 -#define ACL_READ_ACL 0x0400 -#define ACL_WRITE_ACL 0x0800 -#define ACL_WRITE_OWNER 0x1000 -#define ACL_SYNCHRONIZE 0x2000 -#define ACL_READ \ - (ACL_READ_DATA|ACL_READ_XATTR|ACL_READ_ATTRIBUTES) -#define ACL_WRITE \ - (ACL_WRITE_DATA|ACL_WRITE_XATTR|ACL_WRITE_ATTRIBUTES) - -/* - * ace flags - */ -#define ACL_FILE_INHERIT 0x0001 -#define ACL_DIR_INHERIT 0x0002 -#define ACL_NO_PROPAGATE 0x0004 -#define ACL_INHERIT_ONLY 0x0008 -#define ACL_SUCCESSFUL_ACCESS_FLAG 0x0010 -#define ACL_FAILED_ACCESS_ACE_FLAG 0x0020 -#define ACL_IDENTIFIER_GROUP 0x0040 -#define ACL_OWNER 0x1000 -#define ACL_GROUP 0x2000 -#define ACL_EVERYONE 0x4000 - -/* - * ace type - */ -#define ACL_TYPE_ALLOWED 0x01 -#define ACL_TYPE_DENIED 0x02 -#define ACL_TYPE_AUDIT 0x03 -#define ACL_TYPE_ALARM 0x04 - - -/* - * public API - */ - -// list -void acllist_append(Session *sn, Request *rq, ACLList *acl); -void acllist_prepend(Session *sn, Request *rq, ACLList *acl); - -/* - * gets a access mask from open flags - */ -uint32_t acl_oflag2mask(int oflags); - -/* - * authenticates the user with the user database specified in the acl list - */ -User* acllist_getuser(Session *sn, Request *rq, ACLListHandle *list); - -/* - * sets the status to 403 or 401 and sets www-authenticate - * - * use this only if a ACL denies access - */ -void acl_set_error_status(Session *sn, Request *rq, ACLList *acl, User *user); - -/* - * acl_evaluate - * - * Evaluates all ACLs in rq->acllist. It combines rq->aclreqaccess and - * access_mask. If access is denied and no user is authenticated it sets the - * www-authenticate header and the status to 401 Unauthorized. - * - * returns REQ_PROCEED if access is allowed or REQ_ABORTED if access is denied - */ -int acl_evaluate(Session *sn, Request *rq, int access_mask); - -/* - * acl_evallist - * - * evalutes all ACLs in acllist - * - * returns NULL if access is allowed or a pointer to the ACLList which - * denied access - */ -ACLList* acl_evallist(ACLListHandle *acllist, User *user, int access_mask); - - // private int wsacl_affects_user(WSAce *ace, User *user); int wsacl_check(WSAcl *acl, User *user, int access_mask);
--- a/src/server/daemon/authdb.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/authdb.c Mon May 06 13:44:27 2013 +0200 @@ -30,5 +30,5 @@ #include <stdlib.h> #include "../ucx/map.h" -#include "authdb.h" +#include "../public/auth.h"
--- a/src/server/daemon/authdb.h Tue Mar 19 17:38:32 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2013 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 AUTHDB_H -#define AUTHDB_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct auth_db AuthDB; -typedef struct user User; - -/* - * get a user from the authentication database - * - * param1: authentication database - * param2: user - */ -typedef User*(*authdb_get_user_f)(AuthDB*, char*); - -struct auth_db { - char *name; - /* User* get_user(AuthDB *db, char *username) */ - authdb_get_user_f get_user; -}; - -/* - * verify the users password - * - * param1: user - * param2: password - */ -typedef int(*user_verify_passwd_f)(User*, char*); - -/* - * check if the user is a member of a given group - * - * param1: user - * param2: group - */ -typedef int(*user_check_group_f)(User*, char*); - -/* - * free the user object - */ -typedef void(*user_free_f)(User*); - -struct user { - char *name; - /* int verify_password(User *user, char *password) */ - user_verify_passwd_f verify_password; - /* int check_group(User *user, char *group) */ - user_check_group_f check_group; - /* void free(User*) */ - user_free_f free; -}; - - - - -#ifdef __cplusplus -} -#endif - -#endif /* AUTHDB_H */ -
--- a/src/server/daemon/httprequest.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/httprequest.c Mon May 06 13:44:27 2013 +0200 @@ -121,7 +121,7 @@ request->request_line.length, rq->rq.reqpb); - /* Pass method as "method" in reqpb, and also as method_num */ + // Pass method as "method" in reqpb, and also as method_num pblock_kvinsert( pb_key_method, request->method.ptr, @@ -131,7 +131,7 @@ //rqRq.rq.method_num = rqHdr->GetMethodNumber(); //PR_ASSERT(rqRq.rq.method_num != -1 || iStatus); - /* Pass protocol as "protocol" in reqpb, and also in protv_num */ + // Pass protocol as "protocol" in reqpb, and also in protv_num pblock_kvinsert( pb_key_protocol, request->httpv.ptr, @@ -156,7 +156,7 @@ } absPath.length = i; - /* Pass any query as 'query' in reqpb */ + // Pass any query as 'query' in reqpb pblock_kvinsert( pb_key_query, query.ptr, @@ -167,25 +167,29 @@ } } - /* Get abs_path part of request URI, and canonicalize the path */ + // Get abs_path part of request URI, and canonicalize the path absPath.ptr = util_canonicalize_uri( pool, absPath.ptr, absPath.length, (int*)&absPath.length); - /* Decode the abs_path */ - // TODO: decode abs_path (done?) - - /* Pass the abs_path as 'uri' in reqpb */ - pblock_kvinsert( - pb_key_uri, - absPath.ptr, - absPath.length, - rq->rq.reqpb); + // Decode the abs_path + if(util_uri_unescape_strict(absPath.ptr)) { + // Pass the abs_path as 'uri' in reqpb + pblock_kvinsert( + pb_key_uri, + absPath.ptr, + absPath.length, + rq->rq.reqpb); + } else { + // TODO: log error + printf("unescape failed\n"); + pblock_kvinsert(pb_key_uri, "/", 1, rq->rq.reqpb); + } // pass http header to the NSAPI request structure - int hlen = request->headers->len; + int hlen = request->headers->len; HeaderArray *ha = request->headers; for(int i=0;i<=hlen;i++) { if(i == hlen) { @@ -224,7 +228,7 @@ netbuf *nb = request->netbuf; - /* create new netbuf */ + // create new netbuf NetIOStream *net_io = (NetIOStream*)net_stream_from_fd( pool, request->connection->fd);
--- a/src/server/daemon/ldap_auth.h Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/ldap_auth.h Mon May 06 13:44:27 2013 +0200 @@ -29,7 +29,7 @@ #ifndef LDAP_AUTH_H #define LDAP_AUTH_H -#include "authdb.h" +#include "../public/auth.h" #include <ldap.h> #ifdef __cplusplus
--- a/src/server/daemon/request.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/request.c Mon May 06 13:44:27 2013 +0200 @@ -99,6 +99,7 @@ // new rq->status_num = -1; rq->vfs = NULL; + rq->davCollection = NULL; return 0; }
--- a/src/server/daemon/vfs.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/vfs.c Mon May 06 13:44:27 2013 +0200 @@ -32,8 +32,11 @@ #include <sys/types.h> #include "../util/pool.h" +#include "../ucx/map.h" #include "vfs.h" +static UcxMap *vfs_map; + static VFS_IO sys_file_io = { sys_file_read, sys_file_write, @@ -45,6 +48,21 @@ sys_dir_close }; +int vfs_init() { + vfs_map = ucx_map_new(16); + if(!vfs_map) { + return -1; + } + return 0; +} + +void vfs_add(char *name, VFS *vfs) { + if(!vfs_map) { + vfs_init(); + } + ucx_map_cstr_put(vfs_map, name, vfs); +} + VFSContext* vfs_request_context(Session *sn, Request *rq) { VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext)); ctx->sn = sn;
--- a/src/server/daemon/vfs.h Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/vfs.h Mon May 06 13:44:27 2013 +0200 @@ -29,95 +29,15 @@ #ifndef VFS_H #define VFS_H -#include "../public/nsapi.h" -#include "acl.h" +#include "../public/vfs.h" #ifdef __cplusplus extern "C" { #endif -typedef struct VFS_IO VFS_IO; -typedef struct VFS_DIRIO VFS_DIRIO; -typedef struct VFSFile VFSFile; -typedef struct VFSDir VFSDir; -typedef struct VFSEntry VFSEntry; - -#define VFS_DIR VFSDir* -#define VFS_ENTRY VFSEntry - -struct VFS { - SYS_FILE (*open)(VFSContext *ctx, char *path, int oflags); - int (*stat)(VFSContext *ctx, char *path, struct stat *buf); - int (*fstat)(VFSContext *ctx, SYS_FILE fd, struct stat *buf); - VFS_DIR (*opendir)(VFSContext *ctx, char *path); - int (*mkdir)(VFSContext *ctx, char *path); - int (*unlink)(VFSContext *ctx, char *path); -}; - -struct VFSContext { - Session *sn; - Request *rq; - VFS *vfs; - pool_handle_t *pool; - User *user; - ACLListHandle *acllist; - uint32_t aclreqaccess; - int vfs_errno; -}; - -struct VFSFile { - VFSContext *ctx; - VFS_IO *io; // IO functions - void *data; // private data used by the VFSFile implementation - int fd; // native file descriptor if available, or -1 -}; +// private +int vfs_init(); -struct VFSDir { - VFSContext *ctx; - VFS_DIRIO *io; - void *data; // private data used by the VFSDir implementation - int fd; // native file descriptor if available, or -1 -}; - -struct VFSEntry { - char *name; - struct stat stat; - void *stat_extra; - int stat_errno; -}; - -struct VFS_IO { - ssize_t (*read)(SYS_FILE fd, void *buf, size_t nbyte); - ssize_t (*write)(SYS_FILE fd, const void *buf, size_t nbyte); - void (*close)(SYS_FILE fd); -}; - -struct VFS_DIRIO { - int (*readdir)(VFS_DIR dir, VFS_ENTRY *entry, int getstat); - void (*close)(VFS_DIR dir); -}; - -/* - * creates a VFSContext for a Request - * vfs calls will do ACL checks - */ -VFSContext* vfs_request_context(Session *sn, Request *rq); - -SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags); -SYS_FILE vfs_openRO(VFSContext *ctx, char *path); -SYS_FILE vfs_openWO(VFSContext *ctx, char *path); -SYS_FILE vfs_openRW(VFSContext *ctx, char *path); -int vfs_stat(VFSContext *ctx, char *path, struct stat *buf); -int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf); -void vfs_close(SYS_FILE fd); -VFS_DIR vfs_opendir(VFSContext *ctx, char *path); -int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry); -int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry); -void vfs_closedir(VFS_DIR dir); -int vfs_mkdir(VFSContext *ctx, char *path); -int vfs_unlink(VFSContext *ctx, char *path); - -// private typedef int(*vfs_op_f)(VFSContext *, char *); int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access);
--- a/src/server/daemon/webserver.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/webserver.c Mon May 06 13:44:27 2013 +0200 @@ -39,6 +39,7 @@ #include <sys/stat.h> #include "../public/nsapi.h" +#include "../public/auth.h" #include "../util/systhr.h" #include "../util/io.h" #include "../util/util.h" @@ -47,7 +48,6 @@ #include "config.h" #include "configmanager.h" #include "httplistener.h" -#include "authdb.h" #include "webserver.h" #include "log.h"
--- a/src/server/daemon/ws-fn.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/daemon/ws-fn.c Mon May 06 13:44:27 2013 +0200 @@ -50,6 +50,8 @@ { "common-index", service_index, NULL, 0}, { "service-hello", service_hello, NULL, 0}, { "send-options", send_options, NULL, 0}, + { "webdav-init", webdav_init, NULL, 0}, + { "webdav-setcollection", webdav_setcollection, NULL, 0}, { "webdav-service", webdav_service, NULL, 0}, { "admin-index", adm_index, NULL, 0}, { "auth-basic", auth_basic, NULL, 0 },
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/public/acl.h Mon May 06 13:44:27 2013 +0200 @@ -0,0 +1,194 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 WS_ACL_H +#define WS_ACL_H + +#include "nsapi.h" +#include "auth.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ACLListHandle typedef in nsapi.h +typedef struct ACLListElm ACLListElm; +typedef struct ACLList ACLList; + +typedef struct WSAcl WSAcl; +typedef struct WSAce WSAce; + +/* + * a wrapper struct for acls + */ +struct ACLListHandle { + AuthDB *defaultauthdb; + ACLListElm *listhead; + ACLListElm *listtail; +}; + +struct ACLListElm { + ACLList *acl; + ACLListElm *next; +}; + +/* + * abstract ACL + */ +typedef int(*acl_check_f)(ACLList*, User*, int); +struct ACLList { + AuthDB *authdb; + char *authprompt; + int isextern; + /* int check(ACLList *acl, User *user, int access_mask) */ + int(*check)(ACLList *acl, User *user, int access_mask); +}; + +/* + * a webserver access control list + * + * Access control is determined by the ace field. The ece field is a separat + * list for audit and alarm entries. + */ +struct WSAcl { + ACLList acl; + WSAce **ace; // access control entries + WSAce **ece; // event control entries (audit/alarm entries) + int acenum; // number of aces + int ecenum; // number of eces +}; + + +struct WSAce { + char *who; // user or group name + uint32_t access_mask; + uint16_t flags; + uint16_t type; +}; + + +/* + * access permissions + */ +#define ACL_READ_DATA 0x0001 +#define ACL_WRITE_DATA 0x0002 +#define ACL_APPEND 0x0002 +#define ACL_ADD_FILE 0x0004 +#define ACL_ADD_SUBDIRECTORY 0x0004 +#define ACL_READ_XATTR 0x0008 +#define ACL_WRITE_XATTR 0x0010 +#define ACL_EXECUTE 0x0020 +#define ACL_DELETE_CHILD 0x0040 +#define ACL_DELETE 0x0040 +#define ACL_READ_ATTRIBUTES 0x0080 +#define ACL_WRITE_ATTRIBUTES 0x0100 +#define ACL_LIST 0x0200 +#define ACL_READ_ACL 0x0400 +#define ACL_WRITE_ACL 0x0800 +#define ACL_WRITE_OWNER 0x1000 +#define ACL_SYNCHRONIZE 0x2000 +#define ACL_READ \ + (ACL_READ_DATA|ACL_READ_XATTR|ACL_READ_ATTRIBUTES) +#define ACL_WRITE \ + (ACL_WRITE_DATA|ACL_WRITE_XATTR|ACL_WRITE_ATTRIBUTES) + +/* + * ace flags + */ +#define ACL_FILE_INHERIT 0x0001 +#define ACL_DIR_INHERIT 0x0002 +#define ACL_NO_PROPAGATE 0x0004 +#define ACL_INHERIT_ONLY 0x0008 +#define ACL_SUCCESSFUL_ACCESS_FLAG 0x0010 +#define ACL_FAILED_ACCESS_ACE_FLAG 0x0020 +#define ACL_IDENTIFIER_GROUP 0x0040 +#define ACL_OWNER 0x1000 +#define ACL_GROUP 0x2000 +#define ACL_EVERYONE 0x4000 + +/* + * ace type + */ +#define ACL_TYPE_ALLOWED 0x01 +#define ACL_TYPE_DENIED 0x02 +#define ACL_TYPE_AUDIT 0x03 +#define ACL_TYPE_ALARM 0x04 + + +/* + * public API + */ + +// list +void acllist_append(Session *sn, Request *rq, ACLList *acl); +void acllist_prepend(Session *sn, Request *rq, ACLList *acl); + +/* + * gets a access mask from open flags + */ +uint32_t acl_oflag2mask(int oflags); + +/* + * authenticates the user with the user database specified in the acl list + */ +User* acllist_getuser(Session *sn, Request *rq, ACLListHandle *list); + +/* + * sets the status to 403 or 401 and sets www-authenticate + * + * use this only if a ACL denies access + */ +void acl_set_error_status(Session *sn, Request *rq, ACLList *acl, User *user); + +/* + * acl_evaluate + * + * Evaluates all ACLs in rq->acllist. It combines rq->aclreqaccess and + * access_mask. If access is denied and no user is authenticated it sets the + * www-authenticate header and the status to 401 Unauthorized. + * + * returns REQ_PROCEED if access is allowed or REQ_ABORTED if access is denied + */ +int acl_evaluate(Session *sn, Request *rq, int access_mask); + +/* + * acl_evallist + * + * evalutes all ACLs in acllist + * + * returns NULL if access is allowed or a pointer to the ACLList which + * denied access + */ +ACLList* acl_evallist(ACLListHandle *acllist, User *user, int access_mask); + +#ifdef __cplusplus +} +#endif + +#endif /* WS_ACL_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/public/auth.h Mon May 06 13:44:27 2013 +0200 @@ -0,0 +1,92 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 WS_AUTH_H +#define WS_AUTH_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct auth_db AuthDB; +typedef struct user User; + +/* + * get a user from the authentication database + * + * param1: authentication database + * param2: user + */ +typedef User*(*authdb_get_user_f)(AuthDB*, char*); + +struct auth_db { + char *name; + /* User* get_user(AuthDB *db, char *username) */ + authdb_get_user_f get_user; +}; + +/* + * verify the users password + * + * param1: user + * param2: password + */ +typedef int(*user_verify_passwd_f)(User*, char*); + +/* + * check if the user is a member of a given group + * + * param1: user + * param2: group + */ +typedef int(*user_check_group_f)(User*, char*); + +/* + * free the user object + */ +typedef void(*user_free_f)(User*); + +struct user { + char *name; + /* int verify_password(User *user, char *password) */ + user_verify_passwd_f verify_password; + /* int check_group(User *user, char *group) */ + user_check_group_f check_group; + /* void free(User*) */ + user_free_f free; +}; + + + + +#ifdef __cplusplus +} +#endif + +#endif /* WS_AUTH_H */ +
--- a/src/server/public/nsapi.h Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/public/nsapi.h Mon May 06 13:44:27 2013 +0200 @@ -1001,6 +1001,8 @@ uint32_t aclreqaccess; /* new - required access rights */ VFS *vfs; /* new - virtual file system */ + + void *davCollection; int request_is_cacheable; /* */ int directive_is_cacheable; /* set by SAFs with no external side effects that make decisions based solely on URI and path */ @@ -1083,6 +1085,11 @@ #define ISMOPTIONS(r) ((r)->method_num == METHOD_OPTIONS) +// new type +typedef struct _thread_pool threadpool_t; +typedef struct _threadpool_job threadpool_job; +typedef void*(*job_callback_f)(void *data); + /* --- End type definitions --- */ /* --- Begin dispatch vector table definition --- */ @@ -1259,6 +1266,42 @@ #define pblock_fr INTpblock_fr #define pblock_replace INTpblock_replace + +// pool +NSAPI_PUBLIC pool_handle_t *INTpool_create(void); + +NSAPI_PUBLIC void *INTpool_mark(pool_handle_t *pool_handle); + +NSAPI_PUBLIC void INTpool_recycle(pool_handle_t *pool_handle, void *mark); + +NSAPI_PUBLIC void INTpool_destroy(pool_handle_t *pool_handle); + +NSAPI_PUBLIC int INTpool_enabled(void); + +NSAPI_PUBLIC void *INTpool_malloc(pool_handle_t *pool_handle, size_t size ); + +NSAPI_PUBLIC void INTpool_free(pool_handle_t *pool_handle, void *ptr ); + +NSAPI_PUBLIC +void *INTpool_calloc(pool_handle_t *pool_handle, size_t nelem, size_t elsize); + +NSAPI_PUBLIC +void *INTpool_realloc(pool_handle_t *pool_handle, void *ptr, size_t size ); + +NSAPI_PUBLIC +char *INTpool_strdup(pool_handle_t *pool_handle, const char *orig_str ); + +#define pool_create INTpool_create +#define pool_mark INTpool_mark +#define pool_recycle INTpool_recycle +#define pool_destroy INTpool_destroy +#define pool_enabled INTpool_enabled +#define pool_malloc INTpool_malloc +#define pool_free INTpool_free +#define pool_calloc INTpool_calloc +#define pool_realloc INTpool_realloc +#define pool_strdup INTpool_strdup + // func util functions FuncStruct* func_resolve(pblock *pb, Session *sn, Request *rq); int func_exec (pblock *pb, Session *sn, Request *rq); @@ -1324,6 +1367,12 @@ #define util_errno2status util_errno2status +// threadpool +threadpool_t* threadpool_new(int n); +void* threadpool_func(void *data); +threadpool_job* threadpool_get_job(threadpool_t *pool); +void threadpool_run(threadpool_t *pool, job_callback_f func, void *data); + /* end new macro and function definitions */ #define SYS_STDERR STDERR_FILENO
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/public/vfs.h Mon May 06 13:44:27 2013 +0200 @@ -0,0 +1,130 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 WS_VFS_H +#define WS_VFS_H + +#include "nsapi.h" +#include "acl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct VFS_IO VFS_IO; +typedef struct VFS_DIRIO VFS_DIRIO; +typedef struct VFSFile VFSFile; +typedef struct VFSDir VFSDir; +typedef struct VFSEntry VFSEntry; + +#define VFS_DIR VFSDir* +#define VFS_ENTRY VFSEntry + +struct VFS { + SYS_FILE (*open)(VFSContext *ctx, char *path, int oflags); + int (*stat)(VFSContext *ctx, char *path, struct stat *buf); + int (*fstat)(VFSContext *ctx, SYS_FILE fd, struct stat *buf); + VFS_DIR (*opendir)(VFSContext *ctx, char *path); + int (*mkdir)(VFSContext *ctx, char *path); + int (*unlink)(VFSContext *ctx, char *path); +}; + +struct VFSContext { + Session *sn; + Request *rq; + VFS *vfs; + pool_handle_t *pool; + User *user; + ACLListHandle *acllist; + uint32_t aclreqaccess; + int vfs_errno; +}; + +struct VFSFile { + VFSContext *ctx; + VFS_IO *io; // IO functions + void *data; // private data used by the VFSFile implementation + int fd; // native file descriptor if available, or -1 +}; + +struct VFSDir { + VFSContext *ctx; + VFS_DIRIO *io; + void *data; // private data used by the VFSDir implementation + int fd; // native file descriptor if available, or -1 +}; + +struct VFSEntry { + char *name; + struct stat stat; + void *stat_extra; + int stat_errno; +}; + +struct VFS_IO { + ssize_t (*read)(SYS_FILE fd, void *buf, size_t nbyte); + ssize_t (*write)(SYS_FILE fd, const void *buf, size_t nbyte); + void (*close)(SYS_FILE fd); +}; + +struct VFS_DIRIO { + int (*readdir)(VFS_DIR dir, VFS_ENTRY *entry, int getstat); + void (*close)(VFS_DIR dir); +}; + +/* + * registers a new VFS + */ +void vfs_add(char *name, VFS *vfs); + +/* + * creates a VFSContext for a Request + * vfs calls will do ACL checks + */ +VFSContext* vfs_request_context(Session *sn, Request *rq); + +SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags); +SYS_FILE vfs_openRO(VFSContext *ctx, char *path); +SYS_FILE vfs_openWO(VFSContext *ctx, char *path); +SYS_FILE vfs_openRW(VFSContext *ctx, char *path); +int vfs_stat(VFSContext *ctx, char *path, struct stat *buf); +int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf); +void vfs_close(SYS_FILE fd); +VFS_DIR vfs_opendir(VFSContext *ctx, char *path); +int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry); +int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry); +void vfs_closedir(VFS_DIR dir); +int vfs_mkdir(VFSContext *ctx, char *path); +int vfs_unlink(VFSContext *ctx, char *path); + +#ifdef __cplusplus +} +#endif + +#endif /* WS_VFS_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/public/webdav.h Mon May 06 13:44:27 2013 +0200 @@ -0,0 +1,319 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 WS_WEBDAV_H +#define WS_WEBDAV_H + +#include "nsapi.h" + +#include <sys/file.h> +#include <sys/stat.h> +#include <inttypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DavCollection DavCollection; + +typedef struct PropfindResponse PropfindResponse; +typedef struct PersistenceManager PersistenceManager; + +typedef struct PropfindRequest PropfindRequest; +typedef struct ProppatchRequest ProppatchRequest; +typedef struct DavProperty DavProperty; + +typedef struct Propstat Propstat; + +typedef struct XmlNs XmlNs; +typedef struct XmlNsMap XmlNsMap; + +typedef struct XmlData XmlData; +typedef struct XmlElement XmlElement; + +typedef uint8_t xmlch_t; + +typedef struct UcxDlist List; +typedef struct UcxMap Map; + +typedef struct _strbuf Buffer; + +struct DavCollection { + PersistenceManager *mgr; + // callbacks +}; + +struct PropfindRequest { + Session *sn; + Request *rq; + + XmlNsMap *nsmap; + + List *properties; /* DavProperty list, requested props */ + int8_t allprop; + int8_t propname; + + int8_t prop; + int8_t isdir; + List *notFoundProps; + List *forbiddenProps; + PersistenceManager *persistencemgr; + void *mgrdata; + + char *path; + char *uri; + + Buffer *out; +}; + +struct ProppatchRequest { + Session *sn; + Request *rq; + + List *setProps; /* XmlElement list, set props */ + List *removeProps; /* DavProperty list, remove props */ + + Propstat *propstat; + XmlNsMap *nsmap; + + PersistenceManager *backend; + + char *path; + + Buffer *out; +}; + +struct Propstat { + List *okprop; /* properties with status 200 OK */ + Map *map; /* all other properties */ + pool_handle_t *pool; +}; + +struct DavProperty { + XmlNs *xmlns; + char *name; +}; + +struct XmlData { + XmlNsMap *nsmap; + XmlElement *elm; +}; + +struct XmlElement { + XmlNs *xmlns; + char *name; + void *content; /* xmlch* or UcxDlist* */ + size_t ctlen; /* content string length. If 0, content is a UcxDlist */ +}; + +struct XmlNs { + char *xmlns; + char *prefix; + int nslen; + int prelen; +}; + +struct XmlNsMap { + Map *map; + pool_handle_t *pool; + int num; +}; + +typedef void(*dav_propfind_begin_f)(PersistenceManager*, PropfindRequest*); +typedef void(*dav_propfind_end_f)(PersistenceManager*, PropfindRequest*); +typedef void(*dav_propfind_f)(PersistenceManager*,PropfindRequest*,char*); +typedef void(*dav_proppatch_f)(PersistenceManager*,ProppatchRequest*); +struct PersistenceManager { + void(*propfind_begin)(PersistenceManager *mgr, PropfindRequest *rq); + void(*propfind_end)(PersistenceManager *mgr, PropfindRequest *rq); + + /* + * void propfind(PersistenceManager *mgr, PropfindRequest *rq, char *path) + * + * Gets all requested properties for a WebDAV resource(file). This function + * should add properties with dav_propfind_add_str_prop or + * dav_prop_add_xml_prop. Unavailable properties should be added with + * dav_propfind_add_prop_error + * + * + * mgr: WebDAV Persistence Manager + * rq: current PropfindRequest object + * path: the webdav resource path + */ + void(*propfind)(PersistenceManager *mgr, PropfindRequest *rq, char *path); + + /* + * void proppatch(PersistenceManager *mgr, ProppatchRequest *rq) + * + * Sets properties for a WebDAV resource. It should add all properties to + * the propstat object (member of the ProppatchRequest). + * + * mgr: WebDAV backend + * path: current ProppatchRequest object + */ + void(*proppatch)(PersistenceManager *mgr, ProppatchRequest *rq); + + /* + * bool + * if true, some properties are get from the VFS and not from this + * persistence manager + */ + int vfs_props; +}; + +void webdav_add_persistence_manager(char *name, PersistenceManager *mgr); + +int webdav_service(pblock *pb, Session *sn, Request *rq); +int webdav_put(pblock *pb, Session *sn, Request *rq); +int webdav_delete(pblock *pb, Session *sn, Request *rq); +int webdav_mkcol(pblock *pb, Session *sn, Request *rq); +int webdav_copy(pblock *pb, Session *sn, Request *rq); +int webdav_move(pblock *pb, Session *sn, Request *rq); +int webdav_propfind(pblock *pb, Session *sn, Request *rq); +int webdav_proppatch(pblock *pb, Session *sn, Request *rq); + + +/* + * dav_propfind_add_str_prop + * + * Adds a string property to the current WebDAV resource response + */ +void dav_propfind_add_str_prop( + PropfindRequest *rq, + DavProperty* prop, + char *str, + size_t len); + +//void dav_propfind_add_xml_prop(); + +/* + * dav_propfind_add_prop_error + * + * Adds a unavailable property to the response + * + * rq: propfind request object + * prop: unavailable property + * error: HTTP status code + */ +void dav_propfind_add_prop_error( + PropfindRequest *rq, + DavProperty *prop, + int error); + + + +/*---------------------------------- utils ----------------------------------*/ + +/* + * XmlNsMap + * + * a map containing xml namespaces + * + * key: namespace uri + * value: XmlNs object, containing namespace uri and the prefix + */ + +XmlNsMap* xmlnsmap_create(pool_handle_t *pool); + +void xmlnsmap_free(XmlNsMap *map); + +/* + * Puts a namespace in the map. If the namespace is already in the map, the + * available XmlNs object is returned + */ +XmlNs* xmlnsmap_put(XmlNsMap *map, char *ns); + +/* + * Gets a namespace from the map. Returns NULL if the namespace is not in the + * map + */ +XmlNs* xmlnsmap_get(XmlNsMap *map, char *ns); + + + +/* + * XmlElement + * + * representing a xml element + */ + +/* + * adds a xml element to a parent element + */ +void xmlelm_add_child(XmlElement *parent, XmlElement *child); + +/* + * writes an xml element to an output buffer + * if wv is true, it writes the complete value of the element + */ +void xmlelm_write(XmlElement *elm, Buffer *out, int wv); + + +/* + * PropstatMap + * + * A map containing multiple propstat objects + * + * key: status code: int + * value: prop list: UcxDlist* (list of XmlElement*) + */ + + +/* + * creates a new Propstat + */ +Propstat* propstat_create(pool_handle_t *pool); + + +/* + * adds a property to the propstat map + * + * propstat: propstat object + * status: http status code + * prop: WebDAV property + */ +void propstat_add(Propstat *propstat, int status, XmlElement *prop); + +/* + * writes the propstat object to an output buffer + * if wv is true, it writes the values of the 'OK' properties + * + * propstat: propstat object + * out: output buffer + * wv: property output mode + */ +void propstat_write(Propstat *propstat, Buffer *out, int wv); + + + +#ifdef __cplusplus +} +#endif + +#endif /* WS_WEBDAV_H */ +
--- a/src/server/safs/auth.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/safs/auth.c Mon May 06 13:44:27 2013 +0200 @@ -33,7 +33,7 @@ #include <strings.h> -#include "../daemon/authdb.h" +#include "../public/auth.h" #include "../daemon/config.h" #include "../daemon/session.h"
--- a/src/server/safs/init.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/safs/init.c Mon May 06 13:44:27 2013 +0200 @@ -50,7 +50,8 @@ /* load lib */ void *lib = dlopen(shlib, RTLD_GLOBAL | RTLD_NOW); if(lib == NULL) { - fprintf(stderr, "Cannot load library %s\n", shlib); + fprintf(stderr, "Cannot load library %s %s\n", shlib, dlerror()); + return REQ_ABORTED; }
--- a/src/server/safs/service.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/safs/service.c Mon May 06 13:44:27 2013 +0200 @@ -61,11 +61,28 @@ } /* get stat */ - if (vfs_fstat(vfs, fd, s) != 0) { + if(vfs_fstat(vfs, fd, s) != 0) { //perror("prepare_service_file: stat"); protocol_status(sn, rq, 500, NULL); return NULL; } + + // check if the file is a directory + if(S_ISDIR(s->st_mode)) { + pblock_nvinsert("content-length", "0", rq->srvhdrs); + pblock_removekey(pb_key_content_type, rq->srvhdrs); + char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); + size_t urilen = strlen(uri); + char *location = pool_malloc(sn->pool, urilen + 2); + memcpy(location, uri, urilen); + location[urilen] = '/'; + location[urilen+1] = '\0'; + pblock_kvinsert(pb_key_location, location, urilen + 1, rq->srvhdrs); + protocol_status(sn, rq, 302, NULL); + http_start_response(sn, rq); + vfs_close(fd); + return fd; + } /* add content-length header*/ char contentLength[32]; @@ -89,14 +106,16 @@ return REQ_ABORTED; } - // send file - sendfiledata sfd; - sfd.fd = fd; - sfd.len = s.st_size; - sfd.offset = 0; - sfd.header = NULL; - sfd.trailer = NULL; - net_sendfile(sn->csd, &sfd); + if(!S_ISDIR(s.st_mode)) { + // send file + sendfiledata sfd; + sfd.fd = fd; + sfd.len = s.st_size; + sfd.offset = 0; + sfd.header = NULL; + sfd.trailer = NULL; + net_sendfile(sn->csd, &sfd); + } vfs_close(fd);
--- a/src/server/util/pool.h Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/util/pool.h Mon May 06 13:44:27 2013 +0200 @@ -84,6 +84,7 @@ NSAPI_PUBLIC int INTpool_service_debug(pblock *pb, Session *sn, Request *rq); #endif +/* NSAPI_PUBLIC pool_handle_t *INTpool_create(void); NSAPI_PUBLIC void *INTpool_mark(pool_handle_t *pool_handle); @@ -107,6 +108,8 @@ NSAPI_PUBLIC char *INTpool_strdup(pool_handle_t *pool_handle, const char *orig_str ); +*/ + #ifdef DEBUG NSAPI_PUBLIC void INTpool_assert(pool_handle_t *pool_handle, const void *ptr); #endif @@ -127,17 +130,6 @@ #define POOL_ASSERT(pool, ptr) #endif -#define pool_create INTpool_create -#define pool_mark INTpool_mark -#define pool_recycle INTpool_recycle -#define pool_destroy INTpool_destroy -#define pool_enabled INTpool_enabled -#define pool_malloc INTpool_malloc -#define pool_free INTpool_free -#define pool_calloc INTpool_calloc -#define pool_realloc INTpool_realloc -#define pool_strdup INTpool_strdup - #endif /* INTNSAPI */ #endif /* !BASE_POOL_H_ */
--- a/src/server/util/thrpool.h Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/util/thrpool.h Mon May 06 13:44:27 2013 +0200 @@ -29,6 +29,7 @@ #ifndef THREADPOOL_H #define THREADPOOL_H +#include "../public/nsapi.h" #include <pthread.h> #ifdef __cplusplus @@ -36,34 +37,24 @@ #endif typedef struct _pool_queue pool_queue_t; -typedef struct _thread_pool { +struct _thread_pool { pthread_mutex_t queue_lock; pthread_mutex_t avlbl_lock; pthread_cond_t available; + pool_queue_t *queue; int queue_len; - pool_queue_t *queue; -} threadpool_t; +}; -typedef void*(*job_callback_f)(void *data); -typedef struct _threadpool_job { +struct _threadpool_job { job_callback_f callback; void *data; -} threadpool_job; +}; struct _pool_queue { threadpool_job *job; pool_queue_t *next; }; - -threadpool_t* threadpool_new(int n); - -void* threadpool_func(void *data); - -threadpool_job* threadpool_get_job(threadpool_t *pool); - -void threadpool_run(threadpool_t *pool, job_callback_f func, void *data); - #ifdef __cplusplus } #endif
--- a/src/server/util/util.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/util/util.c Mon May 06 13:44:27 2013 +0200 @@ -192,6 +192,32 @@ return 500; } +NSAPI_PUBLIC int util_uri_unescape_strict(char *s) +{ + char *t, *u, t1, t2; + int rv = 1; + + for(t = s, u = s; *t; ++t, ++u) { + if (*t == '%') { + t1 = t[1] & 0xdf; /* [a-f] -> [A-F] */ + if ((t1 < 'A' || t1 > 'F') && (t[1] < '0' || t[1] > '9')) + rv = 0; + + t2 = t[2] & 0xdf; /* [a-f] -> [A-F] */ + if ((t2 < 'A' || t2 > 'F') && (t[2] < '0' || t[2] > '9')) + rv = 0; + + *u = ((t[1] >= 'A' ? ((t[1] & 0xdf) - 'A')+10 : (t[1] - '0'))*16) + + (t[2] >= 'A' ? ((t[2] & 0xdf) - 'A')+10 : (t[2] - '0')); + t += 2; + } + else if (u != t) + *u = *t; + } + *u = *t; + + return rv; +} NSAPI_PUBLIC sstr_t util_path_append(pool_handle_t *pool, char *path, char *ch) { @@ -211,6 +237,7 @@ newstr.ptr = pool_malloc(pool, newstr.length + 1); if(!newstr.ptr) { // TODO: error + newstr.length = 0; return newstr; } if(s.length == 1) {
--- a/src/server/webdav/davparser.cpp Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/webdav/davparser.cpp Mon May 06 13:44:27 2013 +0200 @@ -58,12 +58,15 @@ sn->pool, 1, sizeof(PropfindRequest)); + davrq->nsmap = xmlnsmap_create(sn->pool); + xmlnsmap_put(davrq->nsmap, (char*)"DAV:"); davrq->allprop = 0; davrq->propname = 0; davrq->prop = 0; davrq->properties = NULL; davrq->forbiddenProps = NULL; davrq->notFoundProps = NULL; + davrq->mgrdata = NULL; // create xml parser SAX2XMLReader* parser = XMLReaderFactory::createXMLReader(); parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); @@ -117,7 +120,7 @@ 1, sizeof(PropfindRequest)); davrq->nsmap = xmlnsmap_create(sn->pool); - + xmlnsmap_put(davrq->nsmap, (char*)"DAV:"); // create xml parser
--- a/src/server/webdav/objs.mk Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/webdav/objs.mk Mon May 06 13:44:27 2013 +0200 @@ -31,6 +31,7 @@ DAV_OBJPRE = $(OBJ_DIR)$(DAV_SRC_DIR) DAVOBJ = webdav.o +DAVOBJ += persistence.o DAVOBJS = $(DAVOBJ:%=$(DAV_OBJPRE)%) DAVSOURCE = $(DAVOBJ:%.o=webdav/%.c)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/webdav/persistence.c Mon May 06 13:44:27 2013 +0200 @@ -0,0 +1,59 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> + +#include "persistence.h" + +PersistenceManager* create_property_database() { + PropertyDatabase *mgr = malloc(sizeof(PropertyDatabase)); + mgr->mgr.propfind_begin = (dav_propfind_begin_f)pdb_propfind_begin; + mgr->mgr.propfind_end = (dav_propfind_end_f)pdb_propfind_end; + mgr->mgr.propfind = (dav_propfind_f)pdb_propfind; + mgr->mgr.proppatch = (dav_proppatch_f)pdb_proppatch; + return (PersistenceManager*)mgr; +} + +void pdb_propfind_begin(PropertyDatabase *mgr, PropfindRequest *rq) { + +} + +void pdb_propfind_end(PropertyDatabase *mgr, PropfindRequest *rq) { + +} + +void pdb_propfind(PropertyDatabase *mgr, PropfindRequest *rq, char *path) { + +} + +void pdb_proppatch(PropertyDatabase *mgr, ProppatchRequest *rq) { + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/webdav/persistence.h Mon May 06 13:44:27 2013 +0200 @@ -0,0 +1,53 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 PERSISTENCE_H +#define PERSISTENCE_H + +#include "webdav.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct PropertyDatabase { + PersistenceManager mgr; +} PropertyDatabase; + +PersistenceManager* create_property_database(); +void pdb_propfind_begin(PropertyDatabase *mgr, PropfindRequest *rq); +void pdb_propfind_end(PropertyDatabase *mgr, PropfindRequest *rq); +void pdb_propfind(PropertyDatabase *mgr, PropfindRequest *rq, char *path); +void pdb_proppatch(PropertyDatabase *mgr, ProppatchRequest *rq); + +#ifdef __cplusplus +} +#endif + +#endif /* PERSISTENCE_H */ +
--- a/src/server/webdav/saxhandler.cpp Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/webdav/saxhandler.cpp Mon May 06 13:44:27 2013 +0200 @@ -88,9 +88,10 @@ size_t nslen = strlen(ns); size_t namelen = strlen(name); if(nslen > 0) { - property->xmlns = (char*)pool_malloc(pool, nslen + 1); - property->xmlns[nslen] = 0; - memcpy(property->xmlns, ns, nslen); + //property->xmlns = (char*)pool_malloc(pool, nslen + 1); + //property->xmlns[nslen] = 0; + property->xmlns = xmlnsmap_put(davrq->nsmap, ns); + //memcpy(property->xmlns, ns, nslen); } else { property->xmlns = NULL; } @@ -118,7 +119,7 @@ char *name = XMLString::transcode(localname); if(property != NULL) { - const char *xmlns = (property->xmlns) ? property->xmlns : ""; + const char *xmlns = (property->xmlns) ? property->xmlns->xmlns : ""; if(!strcmp(ns, xmlns) && !strcmp(name, property->name)) { // add property to DavRequest @@ -181,7 +182,7 @@ davPropTag = true; } else if(davPropTag) { newElement = (XmlElement*)pool_calloc(pool, 1, sizeof(XmlElement)); - newElement->name = sstr(pool_strdup(pool, name)); + newElement->name = pool_strdup(pool, name); newElement->xmlns = xmlnsmap_put(davrq->nsmap, ns); /* @@ -276,6 +277,7 @@ for(int i=0;i<length;i++) { str[i] = chars[i]; } + str[length] = 0; currentElm->content = str; currentElm->ctlen = length;
--- a/src/server/webdav/webdav.c Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/webdav/webdav.c Mon May 06 13:44:27 2013 +0200 @@ -41,6 +41,39 @@ #include "../daemon/protocol.h" #include "davparser.h" +#include "persistence.h" + +static UcxMap *pmgr_map; // char*, PersistenceManager + +int webdav_init(pblock *pb, Session *sn, Request *rq) { + pmgr_map = ucx_map_new(8); + PersistenceManager *defaultmgr = create_property_backend(); + ucx_map_cstr_put(pmgr_map, "default", defaultmgr); + return REQ_PROCEED; +} + +void webdav_add_persistence_manager(char *name, PersistenceManager *mgr) { + if(!pmgr_map) { + webdav_init(NULL, NULL, NULL); + } + ucx_map_cstr_put(pmgr_map, name, mgr); +} + +int webdav_setcollection(pblock *pb, Session *sn, Request *rq) { + //char *name = pblock_findkeyval(pb_key_name, pb); + char *db = pblock_findval("db", pb); + + if(!db) { + db = "default"; + } + + // setup DavCollection + DavCollection *dav = pool_malloc(sn->pool, sizeof(DavCollection)); + dav->mgr = ucx_map_cstr_get(pmgr_map, db); + rq->davCollection = dav; + + return REQ_NOACTION; +} int webdav_service(pblock *pb, Session *sn, Request *rq) { char *method = pblock_findkeyval(pb_key_method, rq->reqpb); @@ -217,26 +250,30 @@ /* * get requested properties and initialize some stuff */ + DavCollection *collection = rq->davCollection; + 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(); - - /* write xml response header */ - sbuf_puts(davrq->out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); - sbuf_puts(davrq->out, "<D:multistatus xmlns:D=\"DAV:\">\n"); + davrq->persistencemgr = collection->mgr; /* begin multistatus response */ char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); + davrq->uri = uri; + davrq->path = ppath; VFSContext *vfs = vfs_request_context(sn, rq); struct stat st; if(vfs_stat(vfs, ppath, &st) != 0) { return REQ_ABORTED; - } + } + + // begin propfind + davrq->isdir = S_ISDIR(st.st_mode); + davrq->persistencemgr->propfind_begin(davrq->persistencemgr, davrq); /* * if the requested webdav resource(file) is a directory, we create @@ -257,26 +294,49 @@ } } - /* create the response for the requested resource */ + // create the response for the requested resource dav_resource_response(davrq, sstr(ppath), sstr(uri)); - /* end xml */ + // end propfind + davrq->persistencemgr->propfind_begin(davrq->persistencemgr, davrq); + + // end xml sbuf_puts(davrq->out, "</D:multistatus>\n"); - /* send the xml response to the client */ + //printf("%s\n", davrq->out->ptr); + + // write xml response header + sbuf_t *out = sbuf_new(256); + sbuf_puts(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); + sbuf_puts(out, "<D:multistatus"); + UcxMapIterator nsiter = ucx_map_iterator(davrq->nsmap->map); + XmlNs *ns; + UCX_MAP_FOREACH(ns, nsiter) { + sbuf_puts(out, " xmlns:"); + sbuf_puts(out, ns->prefix); + sbuf_puts(out, "=\""); + sbuf_puts(out, ns->xmlns); + sbuf_puts(out, "\""); + } + sbuf_puts(out, ">\n"); + + // 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); + pblock_nninsert( + "content-length", + out->length + davrq->out->length, + rq->srvhdrs); - //pblock_nvinsert("connection", "close", rq->srvhdrs); http_start_response(sn, rq); - //printf("%s\n", davrq->out->ptr); - ssize_t nr = net_write(sn->csd, davrq->out->ptr, davrq->out->length); - //printf("net_write returned: %d\n", r); + // write content + size_t nr; + nr = net_write(sn->csd, out->ptr, out->length); + nr = net_write(sn->csd, davrq->out->ptr, davrq->out->length); - + sbuf_free(out); dav_free_propfind(davrq); return REQ_PROCEED; @@ -292,7 +352,7 @@ return REQ_ABORTED; } - /* Get request body which contains the webdav XML request */ + // Get request body which contains the webdav XML request char *xml_body; size_t xml_len = 0; @@ -300,7 +360,7 @@ if(ctlen) { xml_len = atoi(ctlen); } else { - /* invalid request */ + // invalid request printf("invalid request\n"); return REQ_ABORTED; } @@ -311,12 +371,12 @@ } xml_body[xml_len] = 0; if(!xml_body) { - /* server error */ + // server error printf("server error\n"); return REQ_ABORTED; } - /* get request body */ + // get request body int r = 0; char *xb = xml_body; size_t xl = xml_len; @@ -328,17 +388,15 @@ /* * parse the xml request and create the proppatch object */ + DavCollection *collection = rq->davCollection; + ProppatchRequest *davrq = dav_parse_proppatch(sn, rq, xml_body, xml_len); davrq->sn = sn; davrq->rq = rq; davrq->out = sbuf_new(512); - davrq->backend = create_property_backend(); + davrq->backend = collection->mgr; davrq->propstat = propstat_create(sn->pool); - /* TODO: create prefixes for every namespace */ - XmlNs *ns = xmlnsmap_get(davrq->nsmap, "DAV:"); - ns->prefix = "D"; - ns->prelen = 1; /* * begin multistatus response @@ -350,9 +408,19 @@ */ /* write xml response header */ - /* TODO: add possible xml namespaces */ sbuf_puts(davrq->out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); - sbuf_puts(davrq->out, "<D:multistatus xmlns:D=\"DAV:\">\n"); + //sbuf_puts(davrq->out, "<D:multistatus xmlns:D=\"DAV:\">\n"); + sbuf_puts(davrq->out, "<D:multistatus"); + UcxMapIterator nsiter = ucx_map_iterator(davrq->nsmap->map); + XmlNs *ns; + UCX_MAP_FOREACH(ns, nsiter) { + sbuf_puts(davrq->out, " xmlns:"); + sbuf_puts(davrq->out, ns->prefix); + sbuf_puts(davrq->out, "=\""); + sbuf_puts(davrq->out, ns->xmlns); + sbuf_puts(davrq->out, "\""); + } + sbuf_puts(davrq->out, ">\n"); sbuf_puts(davrq->out, "<D:response>\n<D:href>"); sbuf_puts(davrq->out, uri); @@ -391,7 +459,11 @@ sbuf_append(davrq->out, uri); sbuf_puts(davrq->out, "</D:href>\n"); - davrq->propertyBackend->propfind(davrq->propertyBackend, davrq, path.ptr); + if(davrq->persistencemgr->vfs_props) { + // get some DAV properties from the file system + dav_rq_propfind(davrq->persistencemgr, davrq, path.ptr); + } + davrq->persistencemgr->propfind(davrq->persistencemgr, davrq, path.ptr); if(davrq->prop) { /* @@ -407,7 +479,10 @@ sbuf_puts(davrq->out, "<D:propstat>\n<D:prop>\n"); DAV_FOREACH(elm, davrq->notFoundProps) { DavProperty *prop = (DavProperty*)elm->data; - sbuf_puts(davrq->out, "<D:"); + sbuf_put(davrq->out, '<'); + sbuf_puts(davrq->out, prop->xmlns->prefix); + sbuf_put(davrq->out, ':'); + sbuf_puts(davrq->out, prop->name); sbuf_puts(davrq->out, " />\n"); } @@ -436,13 +511,17 @@ davrq->prop = 1; } - sbuf_puts(davrq->out, "<D:"); + sbuf_put(davrq->out, '<'); + sbuf_puts(davrq->out, prop->xmlns->prefix); + sbuf_put(davrq->out, ':'); sbuf_puts(davrq->out, prop->name); - sbuf_puts(davrq->out, ">"); + sbuf_put(davrq->out, '>'); sbuf_append(davrq->out, sstrn(str, len)); - sbuf_puts(davrq->out, "</D:"); + sbuf_puts(davrq->out, "</"); + sbuf_puts(davrq->out, prop->xmlns->prefix); + sbuf_put(davrq->out, ':'); sbuf_puts(davrq->out, prop->name); sbuf_puts(davrq->out, ">\n"); } @@ -460,16 +539,19 @@ /* WebDAV Default Backend */ -static DAVPropertyBackend dav_file_backend = { +static PersistenceManager dav_file_backend = { + NULL, + NULL, dav_rq_propfind, - dav_rq_proppatch + dav_rq_proppatch, + 0 }; -DAVPropertyBackend* create_property_backend() { +PersistenceManager* create_property_backend() { return &dav_file_backend; } -void dav_rq_propfind(DAVPropertyBackend *b, PropfindRequest *rq ,char *path) { +void dav_rq_propfind(PersistenceManager *b, PropfindRequest *rq ,char *path) { struct stat st; if(stat(path, &st) != 0) { perror("dav_be_propfind"); @@ -478,7 +560,7 @@ if(rq->allprop) { DavProperty prop; - prop.xmlns = "DAV:"; + prop.xmlns = xmlnsmap_get(rq->nsmap, "DAV:"); prop.name = "resourcetype"; if(S_ISDIR(st.st_mode)) { @@ -531,7 +613,7 @@ } } -void dav_rq_proppatch(DAVPropertyBackend *b, ProppatchRequest *rq) { +void dav_rq_proppatch(PersistenceManager *b, ProppatchRequest *rq) { DAV_FOREACH(p, rq->setProps) { XmlElement *prop = (XmlElement*)p->data; propstat_add(rq->propstat, 403, prop); @@ -557,6 +639,17 @@ } map->map = uxm; map->pool = pool; + map->num = 0; + + // create DAV: namespace + XmlNs *ns = pool_malloc(map->pool, sizeof(XmlNs)); + ns->xmlns = "DAV:"; + ns->prefix = "D"; + ns->nslen = 4; + ns->prelen = 1; + + ucx_map_cstr_put(uxm, "DAV:", ns); + return map; } @@ -575,13 +668,16 @@ return NULL; } - xmlns->xmlns = ns; - xmlns->nslen = strlen(ns); + sstr_t newns = sstrdup(sstr(ns)); - xmlns->prefix = NULL; - xmlns->prelen = 0; + xmlns->xmlns = newns.ptr; + xmlns->nslen = newns.length; + + xmlns->prefix = pool_calloc(map->pool, 1, 8); + xmlns->prelen = snprintf(xmlns->prefix, 7, "x%d", map->num); ucx_map_cstr_put(map->map, ns, xmlns); /* TODO: check return value */ + map->num++; return xmlns; } @@ -598,11 +694,11 @@ } } -void xmlelm_write(XmlElement *elm, sbuf_t *out, int wv) { +void xmlelm_write(XmlElement *elm, Buffer *out, int wv) { sbuf_append(out, sstrn("<", 1)); sbuf_append(out, sstrn(elm->xmlns->prefix, elm->xmlns->prelen)); sbuf_append(out, sstrn(":", 1)); - sbuf_append(out, elm->name); + sbuf_append(out, sstr(elm->name)); if(wv) { if(elm->ctlen == 0) { @@ -616,7 +712,7 @@ sbuf_append(out, sstrn("</", 2)); sbuf_append(out, sstrn(elm->xmlns->prefix, elm->xmlns->prelen)); sbuf_append(out, sstrn(":", 1)); - sbuf_append(out, elm->name); + sbuf_append(out, sstr(elm->name)); sbuf_append(out, sstrn(">", 1)); } } else { @@ -625,7 +721,7 @@ sbuf_append(out, sstrn("</", 2)); sbuf_append(out, sstrn(elm->xmlns->prefix, elm->xmlns->prelen)); sbuf_append(out, sstrn(":", 1)); - sbuf_append(out, elm->name); + sbuf_append(out, sstr(elm->name)); sbuf_append(out, sstrn(">", 1)); } } else { @@ -659,7 +755,7 @@ } } -void propstat_write(Propstat *propstat, sbuf_t *out, int wv) { +void propstat_write(Propstat *propstat, Buffer *out, int wv) { if(propstat->okprop) { sbuf_puts(out, "<D:propstat>\n<D:prop>\n");
--- a/src/server/webdav/webdav.h Tue Mar 19 17:38:32 2013 +0100 +++ b/src/server/webdav/webdav.h Mon May 06 13:44:27 2013 +0200 @@ -29,12 +29,7 @@ #ifndef WEBDAV_H #define WEBDAV_H -#include "../public/nsapi.h" - -#include <sys/file.h> -#include <sys/stat.h> - -#include <inttypes.h> +#include "../public/webdav.h" #include "../ucx/map.h" #include "../ucx/dlist.h" @@ -46,251 +41,18 @@ #define DAV_FOREACH(elem, list) \ for (UcxDlist *elem = list ; elem != NULL ; elem = elem->next) - -typedef struct PropfindResponse PropfindResponse; -typedef struct DAVPropertyBackend DAVPropertyBackend; -typedef struct PropfindRequest PropfindRequest; -typedef struct ProppatchRequest ProppatchRequest; -typedef struct DavProperty DavProperty; - -typedef struct Propstat Propstat; - -typedef struct XmlNs XmlNs; -typedef struct XmlNsMap XmlNsMap; - -typedef struct XmlData XmlData; -typedef struct XmlElement XmlElement; - -typedef uint8_t xmlch_t; - - -struct PropfindRequest { - Session *sn; - Request *rq; - - UcxDlist *properties; /* DavProperty list, requested props */ - int8_t allprop; - int8_t propname; - - int8_t prop; - UcxDlist *notFoundProps; - UcxDlist *forbiddenProps; - DAVPropertyBackend *propertyBackend; - - char *path; - char *uri; - - sbuf_t *out; -}; - -struct ProppatchRequest { - Session *sn; - Request *rq; - - UcxDlist *setProps; /* XmlElement list, set props */ - UcxDlist *removeProps; /* DavProperty list, remove props */ - - Propstat *propstat; - XmlNsMap *nsmap; - - DAVPropertyBackend *backend; - - - sbuf_t *out; -}; - -struct Propstat { - UcxDlist *okprop; /* properties with status 200 OK */ - UcxMap *map; /* all other properties */ - pool_handle_t *pool; -}; - -struct DavProperty { - char *xmlns; - char *name; -}; - -struct XmlData { - XmlNsMap *nsmap; - XmlElement *elm; -}; - -struct XmlElement { - XmlNs *xmlns; - sstr_t name; - void *content; /* xmlch* or UcxDlist* */ - size_t ctlen; /* content string length. If 0, content is a UcxDlist */ -}; - -struct XmlNs { - char *xmlns; - char *prefix; - int nslen; - int prelen; -}; - -struct XmlNsMap { - UcxMap *map; - pool_handle_t *pool; -}; - -/* - * dav_propfind_f - * - * Gets all requested properties for a WebDAV resource(file). This function - * should add properties with dav_propfind_add_str_prop or - * dav_prop_add_xml_prop. Unavailable properties should be added with - * dav_propfind_add_prop_error - * - * - * arg0: property backend - * arg1: current PropfindRequest object - * arg2: the webdav resource path - */ -typedef void(*dav_propfind_f)(DAVPropertyBackend*,PropfindRequest*,char*); - -/* - * dav_proppatch_f - * - * Sets properties for a WebDAV resource. It should add all properties to the - * propstat object (member of the ProppatchRequest). - * - * arg0: WebDAV backend - * arg1: current ProppatchRequest object - */ -typedef void(*dav_proppatch_f)(DAVPropertyBackend*,ProppatchRequest*); - -struct DAVPropertyBackend { - dav_propfind_f propfind; - dav_proppatch_f proppatch; -}; - -int webdav_service(pblock *pb, Session *sn, Request *rq); -int webdav_put(pblock *pb, Session *sn, Request *rq); -int webdav_delete(pblock *pb, Session *sn, Request *rq); -int webdav_mkcol(pblock *pb, Session *sn, Request *rq); -int webdav_copy(pblock *pb, Session *sn, Request *rq); -int webdav_move(pblock *pb, Session *sn, Request *rq); -int webdav_propfind(pblock *pb, Session *sn, Request *rq); -int webdav_proppatch(pblock *pb, Session *sn, Request *rq); +int webdav_init(pblock *pb, Session *sn, Request *rq); +int webdav_setcollection(pblock *pb, Session *sn, Request *rq); void dav_resource_response(PropfindRequest *rq, sstr_t path, sstr_t uri); -/* - * dav_propfind_add_str_prop - * - * Adds a string property to the current WebDAV resource response - */ -void dav_propfind_add_str_prop( - PropfindRequest *rq, - DavProperty* prop, - char *str, - size_t len); - -//void dav_propfind_add_xml_prop(); - -/* - * dav_propfind_add_prop_error - * - * Adds a unavailable property to the response - * - * rq: propfind request object - * prop: unavailable property - * error: HTTP status code - */ -void dav_propfind_add_prop_error( - PropfindRequest *rq, - DavProperty *prop, - int error); - -DAVPropertyBackend* create_property_backend(); -void dav_rq_propfind(DAVPropertyBackend *b, PropfindRequest *rq, char *path); -void dav_rq_proppatch(DAVPropertyBackend *b, ProppatchRequest *rq); - -/*---------------------------------- utils ----------------------------------*/ - -/* - * XmlNsMap - * - * a map containing xml namespaces - * - * key: namespace uri - * value: XmlNs object, containing namespace uri and the prefix - */ - -XmlNsMap* xmlnsmap_create(pool_handle_t *pool); - -void xmlnsmap_free(XmlNsMap *map); - -/* - * Puts a namespace in the map. If the namespace is already in the map, the - * available XmlNs object is returned - */ -XmlNs* xmlnsmap_put(XmlNsMap *map, char *ns); - -/* - * Gets a namespace from the map. Returns NULL if the namespace is not in the - * map - */ -XmlNs* xmlnsmap_get(XmlNsMap *map, char *ns); - - - -/* - * XmlElement - * - * representing a xml element - */ +PersistenceManager* create_property_backend(); +void dav_rq_propfind(PersistenceManager *b, PropfindRequest *rq, char *path); +void dav_rq_proppatch(PersistenceManager *b, ProppatchRequest *rq); -/* - * adds a xml element to a parent element - */ -void xmlelm_add_child(XmlElement *parent, XmlElement *child); - -/* - * writes an xml element to an output buffer - * if wv is true, it writes the complete value of the element - */ -void xmlelm_write(XmlElement *elm, sbuf_t *out, int wv); - - -/* - * PropstatMap - * - * A map containing multiple propstat objects - * - * key: status code: int - * value: prop list: UcxDlist* (list of XmlElement*) - */ - - -/* - * creates a new Propstat - */ -Propstat* propstat_create(pool_handle_t *pool); - - -/* - * adds a property to the propstat map - * - * propstat: propstat object - * status: http status code - * prop: WebDAV property - */ -void propstat_add(Propstat *propstat, int status, XmlElement *prop); - -/* - * writes the propstat object to an output buffer - * if wv is true, it writes the values of the 'OK' properties - * - * propstat: propstat object - * out: output buffer - * wv: property output mode - */ -void propstat_write(Propstat *propstat, sbuf_t *out, int wv); #ifdef __cplusplus }