# HG changeset patch # User Olaf Wintermann # Date 1554651185 -7200 # Node ID c9ada14ee90efd35111215633947554350c3dc8d # Parent ebac6e1ac190f1f315c5dcb8ba64c548ca4a3049 add session flag for content hash creation diff -r ebac6e1ac190 -r c9ada14ee90e libidav/resource.c --- 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, diff -r ebac6e1ac190 -r c9ada14ee90e libidav/webdav.h --- 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