From f0a8792b556444e03b5cd9b91813d7ff72d90e44 Mon Sep 17 00:00:00 2001 From: Dieter Baron Date: Fri, 22 Nov 2024 14:29:15 +0100 Subject: [PATCH] Revert last two commits, they break PKWare encryption. --- lib/zip_close.c | 122 ++++++++++++++++++----------------------------- lib/zip_dirent.c | 57 +++++++--------------- lib/zipint.h | 2 +- 3 files changed, 64 insertions(+), 117 deletions(-) diff --git a/lib/zip_close.c b/lib/zip_close.c index a33b246da..4313592cd 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c @@ -305,8 +305,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { int is_zip64; zip_flags_t flags; bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; - bool have_dos_time, dirent_changed; - time_t mtime_before_copy; if (zip_source_stat(src, &st) < 0) { zip_error_set_from_source(&za->error, src); @@ -318,9 +316,8 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { st.comp_method = ZIP_CM_STORE; } - if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) { + if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) de->comp_method = st.comp_method; - } else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) { st.valid |= ZIP_STAT_COMP_SIZE; st.comp_size = st.size; @@ -375,33 +372,17 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { } } - if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) { - int ret2 = zip_source_get_dos_time(src, &de->last_mod); - if (ret2 < 0) { - zip_error_set_from_source(&za->error, src); - return -1; - } - if (ret2 == 1) { - have_dos_time = true; - } - else { - if (st.valid & ZIP_STAT_MTIME) { - mtime_before_copy = st.mtime; - } - else { - time(&mtime_before_copy); - } - if (_zip_u2d_time(mtime_before_copy, &de->last_mod, &za->error) < 0) { - return -1; - } - } - } - if ((offstart = zip_source_tell_write(za->src)) < 0) { zip_error_set_from_source(&za->error, za->src); return -1; } + /* as long as we don't support non-seekable output, clear data descriptor bit */ + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; + if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) { + return -1; + } + needs_recompress = ZIP_WANT_TORRENTZIP(za) || st.comp_method != ZIP_CM_ACTUAL(de->comp_method); needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE); /* in these cases we can compute the CRC ourselves, so we do */ @@ -504,19 +485,6 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { src_final = src_tmp; } - if (!ZIP_WANT_TORRENTZIP(za)) { - if (zip_source_get_file_attributes(src_final, &attributes) != 0) { - zip_error_set_from_source(&za->error, src_final); - ret = -1; - } - _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed); - } - - /* as long as we don't support non-seekable output, clear data descriptor bit */ - de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; - if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) { - return -1; - } if ((offdata = zip_source_tell_write(za->src)) < 0) { zip_error_set_from_source(&za->error, za->src); @@ -530,11 +498,9 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { ret = -1; } - if (!ZIP_WANT_TORRENTZIP(za)) { - if (zip_source_get_file_attributes(src_final, &attributes) != 0) { - zip_error_set_from_source(&za->error, src_final); - ret = -1; - } + if (zip_source_get_file_attributes(src_final, &attributes) != 0) { + zip_error_set_from_source(&za->error, src_final); + ret = -1; } zip_source_free(src_final); @@ -548,51 +514,57 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { return -1; } + if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) { zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } - dirent_changed = ZIP_CM_ACTUAL(de->comp_method) != st.comp_method || de->crc != st.crc || de->uncomp_size != st.size || de->comp_size != (zip_uint64_t)(offend - offdata); + if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) { + int ret2 = zip_source_get_dos_time(src, &de->last_mod); + if (ret2 < 0) { + zip_error_set_from_source(&za->error, src); + return -1; + } + if (ret2 == 0) { + time_t mtime; + if (st.valid & ZIP_STAT_MTIME) { + mtime = st.mtime; + } + else { + time(&mtime); + } + if (_zip_u2d_time(mtime, &de->last_mod, &za->error) < 0) { + return -1; + } + } + } de->comp_method = st.comp_method; de->crc = st.crc; de->uncomp_size = st.size; de->comp_size = (zip_uint64_t)(offend - offdata); + _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed); - if (!ZIP_WANT_TORRENTZIP(za)) { - dirent_changed |= _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed); - - if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0 && !have_dos_time) { - if (st.valid & ZIP_STAT_MTIME) { - if (st.mtime != mtime_before_copy) { - if (_zip_u2d_time(st.mtime, &de->last_mod, &za->error) < 0) { - return -1; - } - dirent_changed = true; - } - } - } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_dirent_torrentzip_normalize(de); } - if (dirent_changed) { - if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { - zip_error_set_from_source(&za->error, za->src); - return -1; - } - - if ((ret = _zip_dirent_write(za, de, flags)) < 0) - return -1; + if ((ret = _zip_dirent_write(za, de, flags)) < 0) + return -1; - if (is_zip64 != ret) { - /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ - zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); - return -1; - } + if (is_zip64 != ret) { + /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } - if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { - zip_error_set_from_source(&za->error, za->src); - return -1; - } + if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; } if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index d116e4233..24bc6abf9 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c @@ -968,7 +968,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES); } else { - _zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method)); + _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method); } if (ZIP_WANT_TORRENTZIP(za)) { @@ -1190,76 +1190,52 @@ _zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) { } -bool +void _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed) { zip_uint16_t length; - bool has_changed = false; if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; - zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask); - if (de->bitflags != bitflags) { - de->bitflags = bitflags; - has_changed = true; - } + de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask); } if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) { - zip_uint16_t int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0); - if (de->int_attrib != int_attrib) { - de->int_attrib = int_attrib; - has_changed = true; - } + de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0); } /* manually set attributes are preferred over attributes provided by source */ if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) { - if (de->ext_attrib != attributes->external_file_attributes) { - de->ext_attrib = attributes->external_file_attributes; - has_changed = true; - } + de->ext_attrib = attributes->external_file_attributes; } - zip_uint16_t version_needed; if (de->comp_method == ZIP_CM_LZMA) { - version_needed = 63; + de->version_needed = 63; } else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) { - version_needed = 51; + de->version_needed = 51; } else if (de->comp_method == ZIP_CM_BZIP2) { - version_needed = 46; + de->version_needed = 46; } else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) { - version_needed = 45; + de->version_needed = 45; } else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) { - version_needed = 20; + de->version_needed = 20; } else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') { - version_needed = 20; + de->version_needed = 20; } else { - version_needed = 10; + de->version_needed = 10; } if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { - version_needed = ZIP_MAX(version_needed, attributes->version_needed); + de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed); } - if (de->version_needed != version_needed) { - de->version_needed = version_needed; - has_changed = true; - } - - zip_int16_t version_madeby = 63 | (de->version_madeby & 0xff00); + de->version_madeby = 63 | (de->version_madeby & 0xff00); if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) { - version_madeby = (version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8); - } - if (de->version_madeby != version_madeby) { - de->version_madeby = version_madeby; - has_changed = true; + de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8); } - - return has_changed; } @@ -1289,8 +1265,7 @@ zip_dirent_check_consistency(zip_dirent_t *dirent) { return 0; } -time_t -zip_dirent_get_last_mod_mtime(zip_dirent_t *de) { +time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) { if (!de->last_mod_mtime_valid) { de->last_mod_mtime = _zip_d2u_time(&de->last_mod); de->last_mod_mtime_valid = true; diff --git a/lib/zipint.h b/lib/zipint.h index a65dba11b..e22d74c21 100644 --- a/lib/zipint.h +++ b/lib/zipint.h @@ -552,7 +552,7 @@ zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint6 time_t _zip_d2u_time(const zip_dostime_t*); void _zip_deregister_source(zip_t *za, zip_source_t *src); -bool _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t); +void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t); int zip_dirent_check_consistency(zip_dirent_t *dirent); zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *); void _zip_dirent_free(zip_dirent_t *);