# HG changeset patch # User Olaf Wintermann # Date 1376649690 -7200 # Node ID 5dbef9e07376489954e7360026b515c4f0c0663a # Parent 182af08b48133754e7aadd59eecd3db96ac64b02 added mkdir command diff -r 182af08b4813 -r 5dbef9e07376 dav/main.c --- a/dav/main.c Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/main.c Fri Aug 16 12:41:30 2013 +0200 @@ -68,18 +68,27 @@ return -1; } - if(!strcmp(cmd, "list") || !strcmp(cmd, "ls")) { - return cmd_list(args); - } else if(!strcmp(cmd, "get")) { - return cmd_get(args); - } else if(!strcmp(cmd, "put")) { - return cmd_put(args); - } else if(!strcmp(cmd, "remove") || !strcmp(cmd, "rm")) { - return cmd_remove(args); + int ret = -1; + if(!strcasecmp(cmd, "list") || !strcasecmp(cmd, "ls")) { + ret = cmd_list(args); + } else if(!strcasecmp(cmd, "get")) { + ret = cmd_get(args); + } else if(!strcasecmp(cmd, "put")) { + ret = cmd_put(args); + } else if( + !strcasecmp(cmd, "remove") || + !strcasecmp(cmd, "rm") || + !strcasecmp(cmd, "delete")) + { + ret = cmd_remove(args); + } else if(!strcasecmp(cmd, "mkdir") || !strcasecmp(cmd, "mkcol")) { + ret = cmd_mkdir(args); + } else { + print_usage(argv[0]); } + dav_context_destroy(ctx); - print_usage(argv[0]); - return -1; + return ret; } void print_usage(char *cmd) { @@ -88,6 +97,8 @@ fprintf(stderr, " list [-alt] \n"); fprintf(stderr, " get [-p] [-k ] [-o ] \n"); fprintf(stderr, " put [-p] [-k ] \n"); + fprintf(stderr, " mkdir \n"); + fprintf(stderr, " remove \n"); fprintf(stderr, "\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, @@ -156,6 +167,15 @@ fprintf(stderr, "Access forbidden.\n"); break; } + case DAV_METHOD_NOT_ALLOWED: { + fprintf(stderr, "Method not allowed.\n"); + } + case DAV_CONFLICT: { + fprintf( + stderr, + "Missing intermediate collections for resource %s.\n", + res_url); + } } free(res_url); } @@ -530,3 +550,38 @@ return 0; } + +int cmd_mkdir(CmdArgs *a) { + if(a->argc < 1) { + fprintf(stderr, "Too few arguments\n"); + return -1; + } + + DavSession *sn = NULL; + char *url = a->argv[0]; + char *root = NULL; + char *path = NULL; + url_get_parts(url, &root, &path); + + Repository *repo = get_repository(root); + if(repo) { + sn = dav_session_new_auth(ctx, repo->url, repo->user, repo->password); + } else { + sn = dav_session_new(ctx, root); + } + + DavResource *res = dav_resource_new(sn, path); + if(!res) { + fprintf(stderr, "error\n"); + return -1; + } + res->iscollection = 1; + + if(dav_create(res)) { + print_resource_error(sn, res->path); + fprintf(stderr, "Cannot create collection.\n"); + return -1; + } + + return 0; +} diff -r 182af08b4813 -r 5dbef9e07376 dav/main.h --- a/dav/main.h Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/main.h Fri Aug 16 12:41:30 2013 +0200 @@ -46,6 +46,7 @@ int cmd_get(CmdArgs *args); int cmd_put(CmdArgs *args); int cmd_remove(CmdArgs *args); +int cmd_mkdir(CmdArgs *args); #ifdef __cplusplus } diff -r 182af08b4813 -r 5dbef9e07376 dav/methods.c --- a/dav/methods.c Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/methods.c Fri Aug 16 12:41:30 2013 +0200 @@ -453,11 +453,11 @@ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, dummy_write); curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL); - CURLcode res = curl_easy_perform(handle); + CURLcode ret = curl_easy_perform(handle); if(buf) { ucx_buffer_free(buf); } - return res; + return ret; } CURLcode do_delete_request(CURL *handle, UcxBuffer *response) { @@ -469,6 +469,19 @@ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ucx_buffer_write); curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); - CURLcode res = curl_easy_perform(handle); - return res; + CURLcode ret = curl_easy_perform(handle); + return ret; } + +CURLcode do_mkcol_request(CURL *handle) { + curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MKCOL"); + curl_easy_setopt(handle, CURLOPT_PUT, 0L); + curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L); + curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); + + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, dummy_write); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL); + + CURLcode ret = curl_easy_perform(handle); + return ret; +} diff -r 182af08b4813 -r 5dbef9e07376 dav/methods.h --- a/dav/methods.h Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/methods.h Fri Aug 16 12:41:30 2013 +0200 @@ -61,6 +61,8 @@ CURLcode do_delete_request(CURL *handle, UcxBuffer *response); +CURLcode do_mkcol_request(CURL *handle); + #ifdef __cplusplus } #endif diff -r 182af08b4813 -r 5dbef9e07376 dav/utils.c --- a/dav/utils.c Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/utils.c Fri Aug 16 12:41:30 2013 +0200 @@ -152,6 +152,17 @@ return url.ptr; } +char* util_parent_path(char *path) { + char *name = util_resource_name(path); + size_t namelen = strlen(name); + size_t pathlen = strlen(path); + size_t parentlen = pathlen - namelen; + char *parent = malloc(parentlen + 1); + memcpy(parent, path, parentlen); + parent[parentlen] = '\0'; + return parent; +} + char* util_xml_get_text(xmlNode *elm) { xmlNode *node = elm->children; diff -r 182af08b4813 -r 5dbef9e07376 dav/utils.h --- a/dav/utils.h Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/utils.h Fri Aug 16 12:41:30 2013 +0200 @@ -42,6 +42,7 @@ char* util_url_path(char *url); char* util_resource_name(char *url); char* util_concat_path(char *url_base, char *path); +char* util_parent_path(char *path); int util_getboolean(char *v); diff -r 182af08b4813 -r 5dbef9e07376 dav/webdav.c --- a/dav/webdav.c Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/webdav.c Fri Aug 16 12:41:30 2013 +0200 @@ -35,6 +35,7 @@ #include "webdav.h" #include "methods.h" #include "ucx/buffer.h" +#include "ucx/utils.h" #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) @@ -66,6 +67,24 @@ return context; } +void dav_context_destroy(DavContext *ctx) { + // destroy all sessions assoziated with this context + UCX_FOREACH(elm, ctx->sessions) { + dav_session_destroy(elm->data); + } + + UcxMapIterator i = ucx_map_iterator(ctx->namespaces); + UcxKey k; + DavNamespace *ns; + UCX_MAP_FOREACH(k, ns, i) { + free(ns->prefix); + free(ns->name); + free(ns); + } + ucx_map_free(ctx->namespaces); + free(ctx); +} + int dav_add_namespace(DavContext *context, char *prefix, char *name) { DavNamespace *namespace = malloc(sizeof(DavNamespace)); if(!namespace) { @@ -109,6 +128,8 @@ sn->mp = ucx_mempool_new(1024); sn->allocator = ucx_mempool_allocator(sn->mp); + context->sessions = ucx_list_append(context->sessions, sn); + return sn; } @@ -140,12 +161,31 @@ case 401: sn->error = DAV_UNAUTHORIZED; break; case 403: sn->error = DAV_FORBIDDEN; break; case 404: sn->error = DAV_NOT_FOUND; break; + case 405: sn->error = DAV_METHOD_NOT_ALLOWED; break; + case 409: sn->error = DAV_CONFLICT; break; } } else { sn->error = DAV_ERROR; } } +void dav_session_destroy(DavSession *sn) { + // remove session from context + UcxList *sessions = sn->context->sessions; + ssize_t i = ucx_list_find(sessions, sn, ucx_ptrcmp, NULL); + if(i > 0) { + UcxList *elm = ucx_list_get(sessions, i); + if(elm) { + sn->context->sessions = ucx_list_remove(sessions, elm); + } + } + + ucx_mempool_destroy(sn->mp); + curl_easy_cleanup(sn->handle); + free(sn->base_url); + free(sn); +} + DavResource* dav_get(DavSession *sn, char *path, char *properties) { char *url = util_concat_path(sn->base_url, path); @@ -514,3 +554,43 @@ return 1; } } + +int dav_create(DavResource *res) { + char *url = util_concat_path(res->session->base_url, res->path); + char *parent = util_parent_path(res->path); + + DavSession *sn = res->session; + DavResource *parent_res = dav_get(sn, parent, NULL); + if(!parent_res && sn->error == DAV_NOT_FOUND) { + parent_res = dav_resource_new(sn, parent); + parent_res->iscollection = 1; + int r = dav_create(parent_res); + if(r) { + free(parent); + return r; + } + } else if(parent_res && !res->iscollection) { + sn->error = DAV_FORBIDDEN; + return 1; + } else if(sn->error != DAV_OK) { + return 1; + } + + CURL *handle = res->session->handle; + curl_easy_setopt(handle, CURLOPT_URL, url); + free(url); + free(parent); + + // TODO: check iscollection and create empty resource or collection + + CURLcode ret = do_mkcol_request(handle); + int status = 0; + curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); + if(ret == CURLE_OK && (status >= 200 && status < 300)) { + res->session->error = DAV_OK; + return 0; + } else { + session_set_error(res->session, ret, status); + return 1; + } +} diff -r 182af08b4813 -r 5dbef9e07376 dav/webdav.h --- a/dav/webdav.h Thu Aug 15 11:23:25 2013 +0200 +++ b/dav/webdav.h Fri Aug 16 12:41:30 2013 +0200 @@ -57,7 +57,9 @@ DAV_ERROR, DAV_NOT_FOUND, DAV_UNAUTHORIZED, - DAV_FORBIDDEN + DAV_FORBIDDEN, + DAV_METHOD_NOT_ALLOWED, + DAV_CONFLICT }; typedef enum DavError DavError; @@ -94,7 +96,8 @@ }; struct DavContext { - UcxMap *namespaces; + UcxMap *namespaces; + UcxList *sessions; }; struct dav_content_data { @@ -133,6 +136,7 @@ }; DavContext* dav_context_new(); +void dav_context_destroy(DavContext *ctx); int dav_add_namespace(DavContext *context, char *prefix, char *ns); DavNamespace* dav_get_namespace(DavContext *context, char *prefix); @@ -142,6 +146,8 @@ void session_set_error(DavSession *sn, CURLcode c, int status); +void dav_session_destroy(DavSession *sn); + DavResource* dav_get(DavSession *sn, char *path, char *properties); UcxList* parse_properties_string(DavContext *context, sstr_t str); @@ -171,6 +177,7 @@ int dav_get_content(DavResource *res, void *stream, dav_write_func write_func); int dav_delete(DavResource *res); +int dav_create(DavResource *res); #ifdef __cplusplus }