implemented webdav copy and move method

Tue, 12 Jan 2016 19:17:46 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 12 Jan 2016 19:17:46 +0100
changeset 181
a8f8cdbf85df
parent 180
5b58389ab9dd
child 182
ca07f14f7bfe

implemented webdav copy and move method

dav/main.c file | annotate | diff | comparison | revisions
dav/main.h file | annotate | diff | comparison | revisions
libidav/methods.c file | annotate | diff | comparison | revisions
libidav/methods.h file | annotate | diff | comparison | revisions
libidav/resource.c file | annotate | diff | comparison | revisions
libidav/utils.c file | annotate | diff | comparison | revisions
libidav/utils.h file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
--- a/dav/main.c	Fri Oct 23 22:15:12 2015 +0200
+++ b/dav/main.c	Tue Jan 12 19:17:46 2016 +0100
@@ -106,6 +106,10 @@
         ret = cmd_remove(args);
     } else if(!strcasecmp(cmd, "mkdir") || !strcasecmp(cmd, "mkcol")) {
         ret = cmd_mkdir(args);
+    } else if(!strcasecmp(cmd, "copy") || !strcasecmp(cmd, "cp")) {
+        ret = cmd_move(args, true);
+    } else if(!strcasecmp(cmd, "move") || !strcasecmp(cmd, "mv")) {
+        ret = cmd_move(args, false);
     } else if(!strcasecmp(cmd, "date")) {
         ret = cmd_date(args);
     } else if(!strcasecmp(cmd, "set-property")) {
@@ -139,6 +143,8 @@
     fprintf(stderr, "        put [-pcR] [-k <key>] <url> <file>\n");
     fprintf(stderr, "        mkdir [-pc] [-k <key>] <url>\n");
     fprintf(stderr, "        remove [-pc] <url>\n");
+    fprintf(stderr, "        copy [-pc] <url> <url>\n");
+    fprintf(stderr, "        move [-pc] <url> <url>\n");
     fprintf(
             stderr,
             "        get-property [-pc] [-n <uri>] <url> <property>\n");
@@ -921,6 +927,42 @@
     return 0;
 }
 
+int cmd_move(CmdArgs *a, int cp) {
+    if(a->argc != 2) {
+        // TODO: change, when creation of multiple dirs is supported
+        fprintf(stderr, "Too %s arguments\n", a->argc < 2 ? "few":"many");
+        return -1;
+    }
+    
+    char *url1 = a->argv[0];
+    char *path1 = NULL;
+    Repository *repo1 = url2repo(url1, &path1);
+    
+    char *url2 = a->argv[1];
+    char *path2 = NULL;
+    Repository *repo2 = url2repo(url2, &path2);
+    
+    DavSession *sn = connect_to_repo(repo1);
+    if(set_session_config(sn, a)) {
+        return -1;
+    }
+    
+    if(repo1 == repo2) {
+        DavResource *res = dav_resource_new(sn, path1);
+        int err = cp ? dav_copy(res, path2) : dav_move(res, path2);
+        if(err) {
+            print_resource_error(sn, res->path);
+            fprintf(stderr, "Cannot %s resource.\n", cp ? "copy" : "move");
+            return -1;
+        }
+    } else {
+        fprintf(stderr, "Copy or Move not supported for differend hosts.\n");
+        return -1;
+    }
+    
+    return 0;
+}
+
 
 static size_t get_date_header_cb(void *header, int s, int n, void *data) {
     char **date_str = (char**)data;
--- a/dav/main.h	Fri Oct 23 22:15:12 2015 +0200
+++ b/dav/main.h	Tue Jan 12 19:17:46 2016 +0100
@@ -55,6 +55,8 @@
 int cmd_remove(CmdArgs *args);
 int cmd_mkdir(CmdArgs *args);
 
+int cmd_move(CmdArgs *args, int cp);
+
 int cmd_date(CmdArgs *args);
 
 int cmd_get_property(CmdArgs *args);
--- a/libidav/methods.c	Fri Oct 23 22:15:12 2015 +0200
+++ b/libidav/methods.c	Tue Jan 12 19:17:46 2016 +0100
@@ -741,14 +741,14 @@
         DavProperty *p = elm->data;
         if(strcmp(p->ns->name, "DAV:")) {
             snprintf(prefix, 8, "x%d", pfxnum++);
-            ucx_map_cstr_put(namespaces, p->ns->name, prefix);
+            ucx_map_cstr_put(namespaces, p->ns->name, strdup(prefix));
         }
     }
     UCX_FOREACH(elm, data->remove) {
         DavProperty *p = elm->data;
         if(strcmp(p->ns->name, "DAV:")) {
             snprintf(prefix, 8, "x%d", pfxnum++);
-            ucx_map_cstr_put(namespaces, p->ns->name, prefix);
+            ucx_map_cstr_put(namespaces, p->ns->name, strdup(prefix));
         }
     }
     
@@ -782,6 +782,9 @@
         UCX_FOREACH(elm, data->set) {
             DavProperty *property = elm->data;
             char *prefix = ucx_map_cstr_get(namespaces, property->ns->name);
+            if(!prefix) {
+                prefix = "D";
+            }
             
             s = S("<");
             ucx_buffer_write(s.ptr, 1, s.length, buf);
@@ -834,6 +837,8 @@
     s = S("</D:propertyupdate>\n");
     ucx_buffer_write(s.ptr, 1, s.length, buf);
     
+    // TODO: cleanup namespace map
+    
     return buf;
 }
 
@@ -968,3 +973,36 @@
     curl_easy_setopt(handle, CURLOPT_NOBODY, 0L);
     return ret;
 }
+
+
+CURLcode do_copy_move_request(CURL *handle, char *dest, _Bool copy, _Bool override) {
+    if(copy) {
+        curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "COPY");
+    } else {
+        curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MOVE");
+    }
+    curl_easy_setopt(handle, CURLOPT_PUT, 0L);  
+    curl_easy_setopt(handle, CURLOPT_UPLOAD, 0L);
+    
+    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, dummy_write);
+    curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL);
+    
+    struct curl_slist *headers = NULL;
+    //sstr_t deststr = ucx_sprintf("Destination: %s", dest);
+    sstr_t deststr = sstrcat(2, S("Destination: "), sstr(dest));
+    headers = curl_slist_append(headers, deststr.ptr);
+    if(override) {
+        headers = curl_slist_append(headers, "Overwrite: T");
+    } else {
+        headers = curl_slist_append(headers, "Overwrite: F");
+    }
+    curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+    
+    CURLcode ret = curl_easy_perform(handle);
+    free(deststr.ptr);
+    curl_slist_free_all(headers);
+    headers = NULL;
+    curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+    return ret;
+}
+
--- a/libidav/methods.h	Fri Oct 23 22:15:12 2015 +0200
+++ b/libidav/methods.h	Tue Jan 12 19:17:46 2016 +0100
@@ -96,6 +96,8 @@
 
 CURLcode do_head_request(CURL *handle);
 
+CURLcode do_copy_move_request(CURL *handle, char *dest, _Bool copy, _Bool override);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/libidav/resource.c	Fri Oct 23 22:15:12 2015 +0200
+++ b/libidav/resource.c	Tue Jan 12 19:17:46 2016 +0100
@@ -629,6 +629,7 @@
     if(data->set || data->remove) {
         UcxBuffer *request = create_proppatch_request(data);
         UcxBuffer *response = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND);
+        //printf("request:\n%.*s\n\n", request->pos, request->space);
 
         CURLcode ret = do_proppatch_request(sn->handle, request, response);
         int status = 0;
@@ -870,6 +871,35 @@
     }
 }
 
+static int dav_cp_mv(DavResource *res, char *newpath, _Bool copy, _Bool override) {
+    DavSession *sn = res->session;
+    CURL *handle = sn->handle;
+    util_set_url(sn, dav_resource_get_href(res));
+    
+    char *dest = dav_session_get_href(sn, newpath);
+    dav_session_free(sn, dest);
+    char *desturl = util_get_url(sn, dest);
+    
+    CURLcode ret = do_copy_move_request(handle, desturl, copy, override);
+    free(desturl);
+    int status = 0;
+    curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status);
+    if(ret == CURLE_OK && (status >= 200 && status < 300)) {
+        return 0;
+    } else {
+        dav_session_set_error(sn, ret, status);
+        return 1;
+    }
+}
+
+int dav_copy(DavResource *res, char *newpath) {
+    return dav_cp_mv(res, newpath, 1, 0);
+}
+
+int dav_move(DavResource *res, char *newpath) {
+    return dav_cp_mv(res, newpath, 0, 0);
+}
+
 
 int resource_add_crypto_info(DavSession *sn, char *href, char *name, char *hash) {
     if(!DAV_IS_ENCRYPTED(sn)) {
--- a/libidav/utils.c	Fri Oct 23 22:15:12 2015 +0200
+++ b/libidav/utils.c	Tue Jan 12 19:17:46 2016 +0100
@@ -377,7 +377,7 @@
     return url.ptr;
 }
 
-void util_set_url(DavSession *sn, char *href) {
+char* util_get_url(DavSession *sn, char *href) {
     sstr_t base = sstr(sn->base_url);
     sstr_t href_str = sstr(href);
     
@@ -385,9 +385,13 @@
     base.length -= strlen(base_path);
     
     sstr_t url = sstrcat(2, base, href_str);
-    
-    curl_easy_setopt(sn->handle, CURLOPT_URL, url.ptr);
-    free(url.ptr);
+    return url.ptr;
+}
+
+void util_set_url(DavSession *sn, char *href) {
+    char *url = util_get_url(sn, href);
+    curl_easy_setopt(sn->handle, CURLOPT_URL, url);
+    free(url);
 }
 
 char* util_path_to_url(DavSession *sn, char *path) {
--- a/libidav/utils.h	Fri Oct 23 22:15:12 2015 +0200
+++ b/libidav/utils.h	Tue Jan 12 19:17:46 2016 +0100
@@ -63,6 +63,7 @@
 char* util_url_decode(DavSession *sn, char *url);
 char* util_resource_name(char *url);
 char* util_concat_path(char *url_base, char *path);
+char* util_get_url(DavSession *sn, char *href);
 void util_set_url(DavSession *sn, char *href);
 
 void util_capture_header(CURL *handle, UcxMap* map);
--- a/libidav/webdav.h	Fri Oct 23 22:15:12 2015 +0200
+++ b/libidav/webdav.h	Tue Jan 12 19:17:46 2016 +0100
@@ -222,6 +222,9 @@
 int dav_create(DavResource *res);
 int dav_exists(DavResource *res);
 
+int dav_copy(DavResource *res, char *newpath);
+int dav_move(DavResource *res, char *newpath);
+
 char* dav_get_property(DavResource *res, char *name);
 char* dav_get_property_ns(DavResource *res, char *ns, char *name);
 void dav_set_property(DavResource *res, char *name, char *value);

mercurial