VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/libzip/zip_close.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/libzip/zip_close.c')
-rw-r--r--src/Common/libzip/zip_close.c151
1 files changed, 110 insertions, 41 deletions
diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c
index b5eca67a..88fa4449 100644
--- a/src/Common/libzip/zip_close.c
+++ b/src/Common/libzip/zip_close.c
@@ -1,6 +1,6 @@
/*
zip_close.c -- close zip archive and update changes
- Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -131,10 +131,14 @@ zip_close(zip_t *za)
zip_entry_t *entry;
zip_dirent_t *de;
+ if (za->progress_callback) {
+ za->progress_callback((double)j/survivors);
+ }
+
i = filelist[j].idx;
entry = za->entry+i;
- new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD));
+ new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
/* create new local directory entry */
if (entry->changes == NULL) {
@@ -222,6 +226,10 @@ zip_close(zip_t *za)
return -1;
}
+ if (za->progress_callback) {
+ za->progress_callback(1);
+ }
+
zip_discard(za);
return 0;
@@ -233,10 +241,11 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
{
zip_int64_t offstart, offdata, offend;
struct zip_stat st;
- zip_source_t *s2;
+ zip_source_t *src_final, *src_tmp;
int ret;
int is_zip64;
zip_flags_t flags;
+ bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
if (zip_source_stat(src, &st) < 0) {
_zip_error_set_from_source(&za->error, src);
@@ -259,6 +268,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
st.valid &= ~ZIP_STAT_COMP_SIZE;
}
+ if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
+ st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
+ st.encryption_method = ZIP_EM_NONE;
+ }
flags = ZIP_EF_LOCAL;
@@ -285,67 +298,123 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0)
return -1;
+ needs_recompress = !((st.comp_method == de->comp_method) || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method == ZIP_CM_DEFLATE));
+ needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
+ needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
+ needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
+
+ needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method);
+ needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE);
+ needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE);
+
+ src_final = src;
+ zip_source_keep(src_final);
+
+ if (needs_decrypt) {
+ zip_encryption_implementation impl;
+
+ if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+ zip_source_free(src_final);
+ return -1;
+ }
+ if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
+ /* error set by impl */
+ zip_source_free(src_final);
+ return -1;
+ }
- if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) {
- zip_source_t *s_store, *s_crc;
+ zip_source_free(src_final);
+ src_final = src_tmp;
+ }
+
+ if (needs_decompress) {
zip_compression_implementation comp_impl;
- if (st.comp_method != ZIP_CM_STORE) {
- if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
- return -1;
- }
- if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
- /* error set by comp_impl */
- return -1;
- }
+ if ((comp_impl = _zip_get_compression_implementation(st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+ zip_source_free(src_final);
+ return -1;
}
- else {
- /* to have the same reference count to src as in the case where it's not stored */
- zip_source_keep(src);
- s_store = src;
+ if ((src_tmp = comp_impl(za, src_final, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
+ /* error set by comp_impl */
+ zip_source_free(src_final);
+ return -1;
}
- s_crc = zip_source_crc(za, s_store, 0);
- zip_source_free(s_store);
- if (s_crc == NULL) {
+ zip_source_free(src_final);
+ src_final = src_tmp;
+ }
+
+ if (needs_crc) {
+ if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
+ zip_source_free(src_final);
return -1;
}
- if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
- if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
- zip_source_free(s_crc);
- return -1;
- }
- s2 = comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE);
- zip_source_free(s_crc);
- if (s2 == NULL) {
- return -1;
- }
+ zip_source_free(src_final);
+ src_final = src_tmp;
+ }
+
+ if (needs_compress) {
+ zip_compression_implementation comp_impl;
+
+ if ((comp_impl = _zip_get_compression_implementation(de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+ zip_source_free(src_final);
+ return -1;
}
- else {
- s2 = s_crc;
+ if ((src_tmp = comp_impl(za, src_final, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
+ zip_source_free(src_final);
+ return -1;
}
+
+ zip_source_free(src_final);
+ src_final = src_tmp;
}
- else {
- zip_source_keep(src);
- s2 = src;
+
+
+ if (needs_encrypt) {
+ zip_encryption_implementation impl;
+ const char *password = NULL;
+
+ if (de->password) {
+ password = de->password;
+ } else if (za->default_password) {
+ password = za->default_password;
+ }
+
+ if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+ zip_source_free(src_final);
+ return -1;
+ }
+ if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
+ /* error set by impl */
+ zip_source_free(src_final);
+ return -1;
+ }
+
+ zip_source_free(src_final);
+ src_final = src_tmp;
}
+
if ((offdata = zip_source_tell_write(za->src)) < 0) {
return -1;
}
- ret = copy_source(za, s2);
+ ret = copy_source(za, src_final);
- if (zip_source_stat(s2, &st) < 0)
+ if (zip_source_stat(src_final, &st) < 0) {
ret = -1;
+ }
- zip_source_free(s2);
+ zip_source_free(src_final);
- if (ret < 0)
+ if (ret < 0) {
return -1;
+ }
if ((offend = zip_source_tell_write(za->src)) < 0) {
return -1;