# HG changeset patch # User Olaf Wintermann # Date 1452622666 -3600 # Node ID a8f8cdbf85df04605c79d515a133c20b508654f9 # Parent 5b58389ab9ddcd7c733e3cc622d9c50c1404763b implemented webdav copy and move method diff -r 5b58389ab9dd -r a8f8cdbf85df dav/main.c --- 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 ] \n"); fprintf(stderr, " mkdir [-pc] [-k ] \n"); fprintf(stderr, " remove [-pc] \n"); + fprintf(stderr, " copy [-pc] \n"); + fprintf(stderr, " move [-pc] \n"); fprintf( stderr, " get-property [-pc] [-n ] \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; diff -r 5b58389ab9dd -r a8f8cdbf85df dav/main.h --- 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); diff -r 5b58389ab9dd -r a8f8cdbf85df libidav/methods.c --- 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("\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; +} + diff -r 5b58389ab9dd -r a8f8cdbf85df libidav/methods.h --- 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 diff -r 5b58389ab9dd -r a8f8cdbf85df libidav/resource.c --- 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)) { diff -r 5b58389ab9dd -r a8f8cdbf85df libidav/utils.c --- 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) { diff -r 5b58389ab9dd -r a8f8cdbf85df libidav/utils.h --- 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); diff -r 5b58389ab9dd -r a8f8cdbf85df libidav/webdav.h --- 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);