# HG changeset patch # User Olaf Wintermann # Date 1539278985 -7200 # Node ID ff477f1f776563a68601f3ac622843440166cdb3 # Parent 7bb47ddc1b5edb075e275533c420e39d518af964 fixes redirects diff -r 7bb47ddc1b5e -r ff477f1f7765 dav/main.c --- a/dav/main.c Sun Oct 07 09:14:03 2018 +0200 +++ b/dav/main.c Thu Oct 11 19:29:45 2018 +0200 @@ -1137,7 +1137,7 @@ if(e->type == TAR_TYPE_FILE) { fprintf(stderr, "put: %s\n", e->path); DavResource *res = dav_resource_new(sn, newpath); - dav_set_content(res, tar, (dav_read_func)tar_fread); + dav_set_content(res, tar, (dav_read_func)tar_fread, (dav_seek_func)tar_seek); dav_set_content_length(res, (size_t)e->size); if(dav_store(res)) { @@ -1178,6 +1178,11 @@ return ret; } +static int file_seek(FILE *f, curl_off_t offset, int origin) { + int ret = fseek(f, offset, origin); + return ret == 0 ? CURL_SEEKFUNC_OK : CURL_SEEKFUNC_CANTSEEK; +} + int put_file(Repository *repo, CmdArgs *a, DavSession *sn, char *path, char *name, FILE *in, off_t len) { DavResource *res = dav_query(sn, "select - from %s", path); @@ -1212,7 +1217,7 @@ return ret; } - dav_set_content(res, in, (dav_read_func)fread); + dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)file_seek); if(len > 0 && len < 0x7d000000) { dav_set_content_length(res, (size_t)len); } diff -r 7bb47ddc1b5e -r ff477f1f7765 dav/sync.c --- a/dav/sync.c Sun Oct 07 09:14:03 2018 +0200 +++ b/dav/sync.c Thu Oct 11 19:29:45 2018 +0200 @@ -1749,6 +1749,16 @@ return tags; } +static int file_seek(FILE *f, curl_off_t offset, int origin) { + int ret = fseek(f, offset, origin); + return ret == 0 ? CURL_SEEKFUNC_OK : CURL_SEEKFUNC_CANTSEEK; +} + +size_t myread(void *ptr, size_t size, size_t nmemb, FILE *f) { + size_t ret = fread(ptr, size, nmemb, f); + return ret; +} + int sync_put_resource( SyncDirectory *dir, DavResource *res, @@ -1772,7 +1782,7 @@ return -1; } - dav_set_content(res, in, (dav_read_func)fread); + dav_set_content(res, in, (dav_read_func)myread, (dav_seek_func)file_seek); if(dir->tagconfig) { UcxList *tags = sync_get_file_tags(dir, local, NULL); @@ -1807,7 +1817,7 @@ if(up_res) { // the new content length must be equal or greater than the file size if(up_res->contentlength < s.st_size) { - fprintf(stderr, "Incomplete Upload: %s", local_path); + fprintf(stderr, "Incomplete Upload: %s\n", local_path); ret = -1; // try to set the resource status to 'broken' sync_set_status(res, "broken"); diff -r 7bb47ddc1b5e -r ff477f1f7765 dav/tar.c --- a/dav/tar.c Sun Oct 07 09:14:03 2018 +0200 +++ b/dav/tar.c Thu Oct 11 19:29:45 2018 +0200 @@ -314,6 +314,10 @@ return r; } +int tar_seek(TarInputStream *stream, long offset, int whence) { + return fseek(stream->file, offset, whence); +} + int tar_inputstream_close(TarInputStream *tar) { if(tar->cur_entry.path) { free(tar->cur_entry.path); diff -r 7bb47ddc1b5e -r ff477f1f7765 dav/tar.h --- a/dav/tar.h Sun Oct 07 09:14:03 2018 +0200 +++ b/dav/tar.h Thu Oct 11 19:29:45 2018 +0200 @@ -122,6 +122,7 @@ TarInputStream* tar_inputstream_open(FILE *f); TarEntry* tar_read_entry(TarInputStream *tar); size_t tar_fread(void *ptr, size_t s, size_t n, TarInputStream *stream); +int tar_seek(TarInputStream *stream, long offset, int whence); int tar_inputstream_close(TarInputStream *tar); diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/crypto.c --- a/libidav/crypto.c Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/crypto.c Thu Oct 11 19:29:45 2018 +0200 @@ -137,7 +137,7 @@ } -AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func) { +AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func, dav_seek_func seek_func) { unsigned char *iv = malloc(16); if(!RAND_bytes(iv, 16)) { free(iv); @@ -148,6 +148,7 @@ SHA256_Init(&enc->sha256); enc->stream = stream; enc->read = read_func; + enc->seek = seek_func; enc->tmp = NULL; enc->tmplen = 0; enc->tmpoff = 0; @@ -199,7 +200,7 @@ if(in_len != 0) { outlen = len + 32; out = malloc(outlen + ivl); - if(enc->iv) { + if(ivl > 0) { memcpy(out, enc->iv, ivl); } EVP_EncryptUpdate(enc->ctx, out + ivl, &outlen, in, in_len); @@ -218,9 +219,7 @@ enc->tmplen = outlen + ivl; enc->tmpoff = 0; - if(enc->iv) { - free(enc->iv); - enc->iv = NULL; + if(enc->ivlen > 0) { enc->ivlen = 0; } @@ -241,6 +240,18 @@ free(enc); } +int aes_encrypter_reset(AESEncrypter *enc, curl_off_t offset, int origin) { + if(origin != SEEK_SET || offset != 0 || !enc->seek) { + return CURL_SEEKFUNC_CANTSEEK; + } + + enc->ivlen = 16; + if(enc->seek(enc->stream, 0, SEEK_SET) != 0) { + return CURL_SEEKFUNC_FAIL; + } + return CURL_SEEKFUNC_OK; +} + char* aes_encrypt(char *in, size_t len, DavKey *key) { unsigned char iv[16]; @@ -468,7 +479,7 @@ } -AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func) { +AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func, dav_seek_func seek_func) { unsigned char *iv = malloc(16); if(dav_rand_bytes(iv, 16)) { return NULL; @@ -490,6 +501,7 @@ CC_SHA256_Init(&enc->sha256); enc->stream = stream; enc->read = read_func; + enc->seek = seek_func; enc->tmp = NULL; enc->tmplen = 0; enc->tmpoff = 0; @@ -531,7 +543,7 @@ if(in_len != 0) { outlen = len + 32; out = malloc(outlen + ivl); - if(enc->iv) { + if(ivl > 0) { memcpy(out, enc->iv, ivl); } @@ -555,9 +567,7 @@ enc->tmplen = outlen + ivl; enc->tmpoff = 0; - if(enc->iv) { - free(enc->iv); - enc->iv = NULL; + if(enc->ivlen > 0) { enc->ivlen = 0; } @@ -566,6 +576,18 @@ return aes_read(buf, s, n, enc); } +int aes_encrypter_reset(AESEncrypter *enc, curl_off_t offset, int origin) { + if(origin != SEEK_SET || offset != 0 || !enc->seek) { + return CURL_SEEKFUNC_CANTSEEK; + } + + enc->ivlen = 16; + if(enc->seek(enc->stream, 0, SEEK_SET) != 0) { + return CURL_SEEKFUNC_FAIL; + } + return CURL_SEEKFUNC_OK; +} + void aes_encrypter_close(AESEncrypter *enc) { if(enc->tmp) { free(enc->tmp); diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/crypto.h --- a/libidav/crypto.h Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/crypto.h Thu Oct 11 19:29:45 2018 +0200 @@ -85,6 +85,7 @@ size_t ivlen; void *stream; dav_read_func read; + dav_seek_func seek; char *tmp; size_t tmplen; size_t tmpoff; @@ -98,9 +99,10 @@ void aes_decrypter_shutdown(AESDecrypter *dec); void aes_decrypter_close(AESDecrypter *dec); -AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func); +AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func, dav_seek_func seek_func); size_t aes_read(void *buf, size_t s, size_t n, AESEncrypter *enc); void aes_encrypter_close(AESEncrypter *enc); +int aes_encrypter_reset(AESEncrypter *enc, curl_off_t offset, int origin); char* aes_encrypt(char *in, size_t len, DavKey *key); char* aes_decrypt(char *in, size_t *len, DavKey *key); diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/davqlexec.c --- a/libidav/davqlexec.c Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/davqlexec.c Thu Oct 11 19:29:45 2018 +0200 @@ -602,6 +602,9 @@ //printf("rpbuf: %s %s\n%.*s\n\n", sr->resource->path, sr->resource->href, rpbuf->pos, rpbuf->space); if(ret == CURLE_OK && http_status == 207) { + // in case of an redirect we have to adjust resource->href + dav_set_effective_href(sn, root); + // propfind request successful, now parse the response char *url = "http://url/"; PropfindParser *parser = create_propfind_parser(rpbuf, url); diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/methods.c --- a/libidav/methods.c Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/methods.c Thu Oct 11 19:29:45 2018 +0200 @@ -40,6 +40,11 @@ #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) + +int dav_buffer_seek(UcxBuffer *b, curl_off_t offset, int origin) { + return ucx_buffer_seek(b, offset, origin) == 0 ? 0:CURL_SEEKFUNC_CANTSEEK; +} + /* ----------------------------- PROPFIND ----------------------------- */ CURLcode do_propfind_request( @@ -60,6 +65,7 @@ curl_easy_setopt(handle, CURLOPT_UPLOAD, 1); curl_easy_setopt(handle, CURLOPT_READFUNCTION, ucx_buffer_read); + curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, dav_buffer_seek); curl_easy_setopt(handle, CURLOPT_READDATA, request); curl_easy_setopt(handle, CURLOPT_INFILESIZE, request->size); @@ -732,6 +738,7 @@ curl_easy_setopt(handle, CURLOPT_UPLOAD, 1); curl_easy_setopt(handle, CURLOPT_READFUNCTION, ucx_buffer_read); + curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, dav_buffer_seek); curl_easy_setopt(handle, CURLOPT_READDATA, request); curl_easy_setopt(handle, CURLOPT_INFILESIZE, request->size); @@ -920,7 +927,7 @@ return s*n; } -CURLcode do_put_request(DavSession *sn, char *lock, DavBool create, void *data, dav_read_func read_func, size_t length) { +CURLcode do_put_request(DavSession *sn, char *lock, DavBool create, void *data, dav_read_func read_func, dav_seek_func seek_func, size_t length) { CURL *handle = sn->handle; curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, NULL); curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L); @@ -960,6 +967,7 @@ } curl_easy_setopt(handle, CURLOPT_READFUNCTION, read_func); + curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, seek_func); curl_easy_setopt(handle, CURLOPT_READDATA, data); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, dummy_write); @@ -1189,6 +1197,7 @@ curl_easy_setopt(handle, CURLOPT_UPLOAD, 1); curl_easy_setopt(handle, CURLOPT_READFUNCTION, ucx_buffer_read); + curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, dav_buffer_seek); curl_easy_setopt(handle, CURLOPT_READDATA, request); curl_easy_setopt(handle, CURLOPT_INFILESIZE, request->size); diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/methods.h --- a/libidav/methods.h Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/methods.h Thu Oct 11 19:29:45 2018 +0200 @@ -60,6 +60,8 @@ char *locktoken; }; +int dav_buffer_seek(UcxBuffer *b, curl_off_t offset, int origin); + CURLcode do_propfind_request( DavSession *sn, UcxBuffer *request, @@ -77,6 +79,7 @@ DavBool create, void *data, dav_read_func read_func, + dav_seek_func seek_func, size_t length); UcxBuffer* create_allprop_propfind_request(void); diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/resource.c --- a/libidav/resource.c Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/resource.c Thu Oct 11 19:29:45 2018 +0200 @@ -225,6 +225,7 @@ data->remove = NULL; data->content = NULL; data->read = NULL; + data->seek = NULL; data->length = 0; return data; } @@ -600,10 +601,11 @@ } -void dav_set_content(DavResource *res, void *stream, dav_read_func read_func) { +void dav_set_content(DavResource *res, void *stream, dav_read_func read_func, dav_seek_func seek_func) { DavResourceData *data = res->data; data->content = stream; data->read = read_func; + data->seek = seek_func; data->length = 0; } @@ -613,6 +615,7 @@ data->content = dav_session_malloc(sn, length); memcpy(data->content, content, length); data->read = NULL; + data->seek = NULL; data->length = length; } @@ -671,14 +674,19 @@ AESEncrypter *enc = NULL; UcxBuffer *buf = NULL; if(data->read) { - enc = aes_encrypter_new(sn->key, data->content, data->read); + enc = aes_encrypter_new( + sn->key, + data->content, + data->read, + data->seek); } else { buf = ucx_buffer_new(data->content, data->length, 0); buf->size = data->length; enc = aes_encrypter_new( sn->key, buf, - (dav_read_func)ucx_buffer_read); + (dav_read_func)ucx_buffer_read, + (dav_seek_func)dav_buffer_seek); } // put resource @@ -688,6 +696,7 @@ TRUE, enc, (dav_read_func)aes_read, + (dav_seek_func)aes_encrypter_reset, 0); // get sha256 hash @@ -715,6 +724,7 @@ TRUE, data->content, data->read, + data->seek, data->length); } @@ -977,7 +987,7 @@ if(res->iscollection) { code = do_mkcol_request(sn, locktoken); } else { - code = do_put_request(sn, locktoken, TRUE, "", NULL, 0); + code = do_put_request(sn, locktoken, TRUE, "", NULL, NULL, 0); } long s = 0; curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &s); diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/resource.h --- a/libidav/resource.h Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/resource.h Thu Oct 11 19:29:45 2018 +0200 @@ -52,6 +52,10 @@ */ read_func read; /* + * curl seek func + */ + dav_seek_func seek; + /* * content length */ size_t length; diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/webdav.c --- a/libidav/webdav.c Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/webdav.c Thu Oct 11 19:29:45 2018 +0200 @@ -261,6 +261,17 @@ // TODO: add sstr_t version of dav_get_property_ns +void dav_set_effective_href(DavSession *sn, DavResource *resource) { + char *eff_url; + curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &eff_url); + if(eff_url) { + char *href = util_url_path(eff_url); + if(strcmp(href, resource->href)) { + dav_session_free(sn, resource->href); + resource->href = dav_session_strdup(sn, href); + } + } +} DavResource* dav_get(DavSession *sn, char *path, char *properties) { CURL *handle = sn->handle; @@ -281,6 +292,8 @@ long status = 0; curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); if(ret == CURLE_OK && status == 207) { + dav_set_effective_href(sn, resource); + //printf("response\n%s\n", rpbuf->space); // TODO: use PropfindParser resource = parse_propfind_response(sn, resource, rpbuf); @@ -322,6 +335,7 @@ curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status); if(ret == CURLE_OK && status == 207) { //printf("response\n%s\n", rpbuf->space); + dav_set_effective_href(sn, resource); resource = parse_propfind_response(sn, resource, rpbuf); sn->error = DAV_OK; } else { diff -r 7bb47ddc1b5e -r ff477f1f7765 libidav/webdav.h --- a/libidav/webdav.h Sun Oct 07 09:14:03 2018 +0200 +++ b/libidav/webdav.h Thu Oct 11 19:29:45 2018 +0200 @@ -62,6 +62,7 @@ typedef size_t(*dav_read_func)(void*, size_t, size_t, void*); typedef size_t(*dav_write_func)(const void*, size_t, size_t, void*); +typedef int(*dav_seek_func)(const void *, long, int); typedef int(*dav_auth_func)(DavSession *, void *); typedef void(*dav_progress_func)(DavResource *, int64_t, int64_t, void *); @@ -239,7 +240,7 @@ void dav_session_free(DavSession *sn, void *ptr); char* dav_session_strdup(DavSession *sn, const char *str); - +void dav_set_effective_href(DavSession *sn, DavResource *resource); DavResource* dav_get(DavSession *sn, char *path, char *properties); UcxList* parse_properties_string(DavContext *context, sstr_t str); @@ -297,7 +298,7 @@ DavPropName* dav_get_property_names(DavResource *res, size_t *count); -void dav_set_content(DavResource *res, void *stream, dav_read_func read_func); +void dav_set_content(DavResource *res, void *stream, dav_read_func read_func, dav_seek_func seek_func); void dav_set_content_data(DavResource *res, char *content, size_t length); void dav_set_content_length(DavResource *res, size_t length); diff -r 7bb47ddc1b5e -r ff477f1f7765 test/crypto.c --- a/test/crypto.c Sun Oct 07 09:14:03 2018 +0200 +++ b/test/crypto.c Thu Oct 11 19:29:45 2018 +0200 @@ -268,7 +268,7 @@ pbuf->pos = 0; pbuf->size = 0; - AESEncrypter *enc = aes_encrypter_new(key, data, (dav_read_func)ucx_buffer_read); + AESEncrypter *enc = aes_encrypter_new(key, data, (dav_read_func)ucx_buffer_read, NULL); char buf[1024]; size_t r = 0; while((r = aes_read(buf, 1, 1024, enc)) != 0) {