added mkdir command

Fri, 16 Aug 2013 12:41:30 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 16 Aug 2013 12:41:30 +0200
changeset 16
5dbef9e07376
parent 15
182af08b4813
child 17
11dffb40cd91

added mkdir command

dav/main.c file | annotate | diff | comparison | revisions
dav/main.h file | annotate | diff | comparison | revisions
dav/methods.c file | annotate | diff | comparison | revisions
dav/methods.h file | annotate | diff | comparison | revisions
dav/utils.c file | annotate | diff | comparison | revisions
dav/utils.h file | annotate | diff | comparison | revisions
dav/webdav.c file | annotate | diff | comparison | revisions
dav/webdav.h file | annotate | diff | comparison | revisions
--- 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] <url>\n");
     fprintf(stderr, "        get [-p] [-k <key>] [-o <file>] <url>\n");
     fprintf(stderr, "        put [-p] [-k <key>] <url> <file>\n");
+    fprintf(stderr, "        mkdir <url>\n");
+    fprintf(stderr, "        remove <url>\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;
+}
--- 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
 }
--- 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;
+}
--- 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
--- 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;
--- 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);
 
--- 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;
+    }
+}
--- 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
 }

mercurial