Skip to content

Commit

Permalink
Revert last two commits, they break PKWare encryption.
Browse files Browse the repository at this point in the history
  • Loading branch information
dillof committed Nov 22, 2024
1 parent a2014d6 commit f0a8792
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 117 deletions.
122 changes: 47 additions & 75 deletions lib/zip_close.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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) {
Expand Down
57 changes: 16 additions & 41 deletions lib/zip_dirent.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;
}


Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/zipint.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down

0 comments on commit f0a8792

Please sign in to comment.