Consistently remove internally handled extra fields.
diff --git a/TODO b/TODO index e689a1d..f23688c 100644 --- a/TODO +++ b/TODO
@@ -51,9 +51,6 @@ Bugs ==== -! D zip64 extra field not removed from local extra fields (extra_count_ignore_zip64.test) - create function to filter internal efs, use in _zip_dirent_read and _zip_read_local_ef - define macro ZIP_EF_IS_INTERNAL, use in zip_file_extra_field_set and filter function ! D check for off_t overflow ! D fix OpenSUSE i686 regression failures ! D readd zip_get_num_files man page @@ -78,6 +75,7 @@ Test Case Issues ================ +! W extra_count_ignore_zip64.test: lc count is 3, not 4 (Info-ZIP UNIX merged?) * test calls against old API * run regression tests also from CMake framework * rename file to dir/ and vice versa (fails)
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index df91a5b..8cdd660 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c
@@ -486,9 +486,9 @@ if (zde->disk_number == ZIP_UINT16_MAX) zde->disk_number = _zip_read4(&ef); } - - zde->extra_fields = _zip_ef_delete_by_id(zde->extra_fields, ZIP_EF_ZIP64, ZIP_EXTRA_FIELD_ALL, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL); } + + zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); if (bufp) *bufp = cur; @@ -523,8 +523,6 @@ } } - de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, id, ZIP_EXTRA_FIELD_ALL, ZIP_EF_BOTH); - return str; }
diff --git a/lib/zip_extra_field.c b/lib/zip_extra_field.c index d4bc77f..9b9e399 100644 --- a/lib/zip_extra_field.c +++ b/lib/zip_extra_field.c
@@ -255,6 +255,35 @@ +struct zip_extra_field * +_zip_ef_remove_internal(struct zip_extra_field *ef) +{ + struct zip_extra_field *ef_head; + struct zip_extra_field *prev, *next; + + ef_head = prev = ef; + + while (ef) { + if (ZIP_EF_IS_INTERNAL(ef->id)) { + next = ef->next; + if (ef_head == ef) + ef_head = next; + ef->next = NULL; + _zip_ef_free(ef); + if (prev) + prev->next = next; + ef = next; + } + else { + prev = ef; + ef = ef->next; + } + } + + return ef_head; +} + + zip_uint16_t _zip_ef_size(struct zip_extra_field *ef, zip_flags_t flags) { @@ -339,7 +368,7 @@ } free(ef_raw); - /* XXX: remove fields handled internally (Zip64, UTF-8) */ + ef = _zip_ef_remove_internal(ef); e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); }
diff --git a/lib/zip_extra_field_api.c b/lib/zip_extra_field_api.c index 0458c70..d232073 100644 --- a/lib/zip_extra_field_api.c +++ b/lib/zip_extra_field_api.c
@@ -220,7 +220,7 @@ return -1; } - if (ef_id == ZIP_EF_ZIP64 || ef_id == ZIP_EF_UTF_8_NAME || ef_id == ZIP_EF_UTF_8_COMMENT) { + if (ZIP_EF_IS_INTERNAL(ef_id)) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; }
diff --git a/lib/zipint.h b/lib/zipint.h index fae8177..2477a59 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -136,6 +136,7 @@ #define ZIP_EF_UTF_8_NAME 0x7075 #define ZIP_EF_ZIP64 0x0001 +#define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_ZIP64) /* This section contains API that won't materialize like this. It's @@ -408,6 +409,7 @@ struct zip_extra_field *_zip_ef_merge(struct zip_extra_field *, struct zip_extra_field *); struct zip_extra_field *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t); struct zip_extra_field *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *); +struct zip_extra_field *_zip_ef_remove_internal(struct zip_extra_field *); zip_uint16_t _zip_ef_size(struct zip_extra_field *, zip_flags_t); void _zip_ef_write(struct zip_extra_field *, zip_flags_t, FILE *);