78 { "DAV:", "getetag" }, |
78 { "DAV:", "getetag" }, |
79 { DAV_NS, "status" }, |
79 { DAV_NS, "status" }, |
80 { DAV_NS, "finfo" }, |
80 { DAV_NS, "finfo" }, |
81 { DAV_NS, "tags" }, |
81 { DAV_NS, "tags" }, |
82 { DAV_NS, "xattributes" }, |
82 { DAV_NS, "xattributes" }, |
|
83 { DAV_NS, "content-hash" }, |
83 { DAV_NS, "split" } |
84 { DAV_NS, "split" } |
84 }; |
85 }; |
85 static size_t numdefprops = 6; |
86 static size_t numdefprops = 6; |
86 |
87 |
87 /* |
88 /* |
2040 { |
2041 { |
2041 DavPropName properties[] = { |
2042 DavPropName properties[] = { |
2042 {"DAV:", "getetag"}, |
2043 {"DAV:", "getetag"}, |
2043 {DAV_NS, "tags"}, |
2044 {DAV_NS, "tags"}, |
2044 {DAV_NS, "version-collection"}, |
2045 {DAV_NS, "version-collection"}, |
|
2046 {DAV_NS, "content-hash"}, |
2045 {DAV_NS, "split" } |
2047 {DAV_NS, "split" } |
2046 }; |
2048 }; |
2047 int err = dav_load_prop(remote, properties, 4); |
2049 int err = dav_load_prop(remote, properties, 4); |
2048 |
2050 |
2049 if(res->restore) { |
2051 if(res->restore) { |
2051 } |
2053 } |
2052 |
2054 |
2053 int ret = 0; |
2055 int ret = 0; |
2054 if(err == 0) { |
2056 if(err == 0) { |
2055 char *etag = dav_get_string_property(remote, "D:getetag"); |
2057 char *etag = dav_get_string_property(remote, "D:getetag"); |
2056 if(!res->etag) { |
2058 char *hash = dav_get_string_property(remote, "idav:content-hash"); |
|
2059 if(hash || res->hash) { |
|
2060 if(!nullstrcmp(hash, res->hash)) { |
|
2061 ret = 1; |
|
2062 } |
|
2063 } else if(!res->etag) { |
2057 // the resource is on the server and the client has no etag |
2064 // the resource is on the server and the client has no etag |
2058 ret = 1; |
2065 ret = 1; |
2059 } else if(etag) { |
2066 } else if(etag) { |
2060 sstr_t e = sstr(etag); |
2067 sstr_t e = sstr(etag); |
2061 if(sstrprefix(e, S("W/"))) { |
2068 if(sstrprefix(e, S("W/"))) { |
2733 // temporarly disable name encryption, because we don't need it for |
2740 // temporarly disable name encryption, because we don't need it for |
2734 // part names |
2741 // part names |
2735 uint32_t session_flags = res->session->flags; |
2742 uint32_t session_flags = res->session->flags; |
2736 res->session->flags ^= DAV_SESSION_ENCRYPT_NAME; |
2743 res->session->flags ^= DAV_SESSION_ENCRYPT_NAME; |
2737 |
2744 |
|
2745 DAV_SHA_CTX *sha = dav_hash_init(); |
|
2746 |
2738 while((r = fread(buffer, 1, blocksize, in)) > 0) { |
2747 while((r = fread(buffer, 1, blocksize, in)) > 0) { |
|
2748 dav_hash_update(sha, buffer, r); |
|
2749 |
2739 int upload_block = 0; |
2750 int upload_block = 0; |
2740 char *block_hash = dav_create_hash(buffer, r); |
2751 char *block_hash = dav_create_hash(buffer, r); |
2741 if(blockindex >= local->numparts) { |
2752 if(blockindex >= local->numparts) { |
2742 // we don't have a hash for this block, therefore it must be new |
2753 // we don't have a hash for this block, therefore it must be new |
2743 upload_block = 1; |
2754 upload_block = 1; |
2794 ucx_map_free_content(updated_parts_map, (ucx_destructor)filepart_free); |
2805 ucx_map_free_content(updated_parts_map, (ucx_destructor)filepart_free); |
2795 ucx_map_free(updated_parts_map); |
2806 ucx_map_free(updated_parts_map); |
2796 return NULL; |
2807 return NULL; |
2797 } |
2808 } |
2798 |
2809 |
|
2810 // set content-hash |
|
2811 char content_hash[DAV_SHA256_DIGEST_LENGTH]; |
|
2812 dav_hash_final(sha, content_hash); |
|
2813 char *hash_hex = util_hexstr(content_hash, DAV_SHA256_DIGEST_LENGTH); |
|
2814 dav_set_string_property_ns(res, DAV_NS, "content-hash", hash_hex); |
|
2815 local->hash = hash_hex; |
|
2816 |
|
2817 // get etags from uploaded resources |
|
2818 // also delete everything, that is not part of the file |
2799 UcxList *updated_parts = NULL; |
2819 UcxList *updated_parts = NULL; |
2800 DavResource *parts = dav_query(res->session, "select D:getetag from %s order by name", res->path); |
2820 DavResource *parts = dav_query(res->session, "select D:getetag from %s order by name", res->path); |
2801 if(!parts) { |
2821 if(!parts) { |
2802 print_resource_error(res->session, parts->path); |
2822 print_resource_error(res->session, parts->path); |
2803 *err = 1; |
2823 *err = 1; |
2930 if(!issplit) { |
2950 if(!issplit) { |
2931 // regular file upload |
2951 // regular file upload |
2932 dav_set_content(res, in, (dav_read_func)myread, (dav_seek_func)file_seek); |
2952 dav_set_content(res, in, (dav_read_func)myread, (dav_seek_func)file_seek); |
2933 dav_set_content_length(res, s.st_size); |
2953 dav_set_content_length(res, s.st_size); |
2934 } else { |
2954 } else { |
|
2955 // set split property |
|
2956 char blocksize_str[32]; |
|
2957 snprintf(blocksize_str, 32, "%zu", split_blocksize); |
|
2958 dav_set_string_property_ns(res, DAV_NS, "split", blocksize_str); |
|
2959 |
2935 // splitted/partial upload |
2960 // splitted/partial upload |
2936 parts = upload_parts( |
2961 parts = upload_parts( |
2937 local, |
2962 local, |
2938 res, |
2963 res, |
2939 in, |
2964 in, |