fixes redirects v1.2

Thu, 11 Oct 2018 19:29:45 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 11 Oct 2018 19:29:45 +0200
branch
v1.2
changeset 481
ff477f1f7765
parent 480
7bb47ddc1b5e
child 482
d96464f42b84

fixes redirects

dav/main.c file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
dav/tar.c file | annotate | diff | comparison | revisions
dav/tar.h file | annotate | diff | comparison | revisions
libidav/crypto.c file | annotate | diff | comparison | revisions
libidav/crypto.h file | annotate | diff | comparison | revisions
libidav/davqlexec.c 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/resource.h file | annotate | diff | comparison | revisions
libidav/webdav.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
test/crypto.c file | annotate | diff | comparison | revisions
--- 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);
     }
--- 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");
--- 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);
--- 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);
 
 
--- 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);
--- 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);
--- 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);
--- 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);
     
--- 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);
--- 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);
--- 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;
--- 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  {
--- 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);
 
--- 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) {

mercurial