add session flag for content hash creation

Sun, 07 Apr 2019 17:33:05 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 07 Apr 2019 17:33:05 +0200
changeset 555
c9ada14ee90e
parent 554
ebac6e1ac190
child 556
1a58014260e0

add session flag for content hash creation

libidav/resource.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
--- a/libidav/resource.c	Sun Apr 07 14:18:13 2019 +0200
+++ b/libidav/resource.c	Sun Apr 07 17:33:05 2019 +0200
@@ -655,6 +655,51 @@
     return ret;
 }
 
+
+/*
+ * read wrapper with integrated hashing
+ */
+
+typedef struct {
+    DAV_SHA_CTX *sha;
+    void *stream;
+    dav_read_func read;
+    dav_seek_func seek;
+    int error;
+} HashStream;
+
+static void init_hash_stream(HashStream *hstr, void *stream, dav_read_func readfn, dav_seek_func seekfn) {
+    hstr->sha = NULL;
+    hstr->stream = stream;
+    hstr->read = readfn;
+    hstr->seek = seekfn;
+    hstr->error = 0;
+}
+
+static size_t dav_read_h(void *buf, size_t size, size_t nelm, void *stream) {
+    HashStream *s = stream;
+    if(!s->sha) {
+        s->sha = dav_hash_init();
+    }
+     
+    size_t r = s->read(buf, size, nelm, s->stream);
+    dav_hash_update(s->sha, buf, r);
+    return r;
+}
+
+static int dav_seek_h(void *stream, long offset, int whence) {
+    HashStream *s = stream;
+    if(offset == 0 && whence == SEEK_SET) {
+        char buf[DAV_SHA256_DIGEST_LENGTH];
+        dav_hash_final(s->sha, buf);
+        s->sha = NULL;
+    } else {
+        s->error = 1;
+    }
+    return s->seek(s->stream, offset, whence);
+}
+
+
 int dav_store(DavResource *res) {
     DavSession *sn = res->session;
     DavResourceData *data = res->data;
@@ -698,9 +743,8 @@
                     0);
             
             // get sha256 hash
-            unsigned char sha[DAV_SHA256_DIGEST_LENGTH];
-            dav_get_hash(&enc->sha256, sha);
-            char *enc_hash = aes_encrypt((char*)sha, DAV_SHA256_DIGEST_LENGTH, sn->key);
+            dav_get_hash(&enc->sha256, (unsigned char*)data->hash);
+            char *enc_hash = aes_encrypt(data->hash, DAV_SHA256_DIGEST_LENGTH, sn->key);
             
             aes_encrypter_close(enc);
             if(buf) {
@@ -715,6 +759,40 @@
             }
             resource_add_string_property(res, DAV_NS, "crypto-hash", enc_hash);
             free(enc_hash);
+        } else if((sn->flags & DAV_SESSION_STORE_HASH) == DAV_SESSION_STORE_HASH) {
+            HashStream hstr;
+            UcxBuffer *iobuf = NULL;
+            if(!data->read) {
+                iobuf = ucx_buffer_new(data->content, data->length, 0);
+                iobuf->size = data->length;
+                init_hash_stream(
+                        &hstr,
+                        iobuf,
+                        (dav_read_func)ucx_buffer_read,
+                        (dav_seek_func)ucx_buffer_seek);
+            } else {
+                init_hash_stream(
+                        &hstr,
+                        data->content,
+                        data->read,
+                        data->seek);
+            }
+            
+            ret = do_put_request(
+                    sn,
+                    locktoken,
+                    TRUE,
+                    &hstr,
+                    dav_read_h,
+                    (dav_seek_func)dav_seek_h,
+                    data->length);
+            
+            if(hstr.sha) {
+                dav_hash_final(hstr.sha, (unsigned char*)data->hash);
+                char *hash = util_hexstr(data->hash, 32);
+                dav_set_string_property_ns(res, DAV_NS, "content-hash", hash);
+                free(hash);
+            }
         } else {
             ret = do_put_request(
                     sn,
--- a/libidav/webdav.h	Sun Apr 07 14:18:13 2019 +0200
+++ b/libidav/webdav.h	Sun Apr 07 17:33:05 2019 +0200
@@ -106,6 +106,7 @@
 #define DAV_SESSION_ENCRYPT_NAME        0x0002
 #define DAV_SESSION_DECRYPT_CONTENT     0x0004
 #define DAV_SESSION_DECRYPT_NAME        0x0008
+#define DAV_SESSION_STORE_HASH          0x0010
 
 #define DAV_SESSION_CONTENT_ENCRYPTION  0x0005
 #define DAV_SESSION_FULL_ENCRYPTION     0x000f

mercurial