API cleanup, be less strict with file name arguments.
diff --git a/NEWS b/NEWS index 6519c3f..ea0ce92 100644 --- a/NEWS +++ b/NEWS
@@ -2,6 +2,7 @@ * Added Zip64 support (large file support) * Added UTF-8 support for file names, file comments, and archive comments +* Changed API for name and comment related functions for UTF-8 support * Added zip_discard() * Added ZIP_TRUNCATE for zip_open() * Added zip_set_file_compression() @@ -16,7 +17,7 @@ 0.10 [2010/03/18] -* Added zip_get_num_files(), deprecated zip_get_num_entries(). +* Added zip_get_num_entries(), deprecated zip_get_num_files(). * Better windows support. * Support for traditional PKWARE encryption added. * Fix opening archives with more than 65535 entries.
diff --git a/TODO b/TODO index 75b4e65..ef82ba5 100644 --- a/TODO +++ b/TODO
@@ -9,14 +9,6 @@ API Issues ========== -! character encoding in file names and comments (allow non-UTF8) - Replacement functions with flags: - * zip_archive_set_comment - * zip_file_add - * zip_file_rename - * zip_file_set_comment -! use this case to go over all function names and make them consistent - (e.g., zip_*_file_extra_* -> zip_file_*) ! clean up first version of extra field support * compression/crypt implementations: how to set error code on failure * compression/crypt error messages a la ZIP_ER_ZLIB (no detailed info passing) @@ -25,14 +17,16 @@ Features ======== -! read InfoZIP extra fields for UTF-8 file name/file comment ! Implement missing extra field functions ! Document extra field functions ! Document API changes . _set_name allows NULL (document) . old extra fields API removed . change in return value of get_comment: NULL if error, else pointer to empty array and len=0 - . add ZIP_DISABLE_DEPRECATED and rename deprecated functions so they are only available when it's not set + . document ZIP_DISABLE_DEPRECATED (libzip man page) + . renames of zip_add, zip_rename, zip_replace, zip_add_dir, zip_{set,get}_file_comment + . NULL is now allowed for file names (zip_add, zip_add_dir, zip_rename) +! add flag for zip_file_add that overwrites any existing entry with same name * do not compress if storing is smaller * I/O methods
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index b8ad48f..2ea8f73 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt
@@ -58,6 +58,7 @@ zip_add_entry.c zip_close.c zip_delete.c + zip_dir_add.c zip_dirent.c zip_discard.c zip_entry.c @@ -72,9 +73,14 @@ zip_extra_field_api.c zip_fclose.c zip_fdopen.c + zip_file_add.c zip_file_error_clear.c zip_file_error_get.c + zip_file_get_comment.c zip_file_get_offset.c + zip_file_rename.c + zip_file_replace.c + zip_file_set_comment.c zip_file_strerror.c zip_filerange_crc.c zip_fopen.c
diff --git a/lib/Makefile.am b/lib/Makefile.am index de5c718..921a328 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am
@@ -15,6 +15,7 @@ zip_add_entry.c \ zip_close.c \ zip_delete.c \ + zip_dir_add.c \ zip_dirent.c \ zip_discard.c \ zip_entry.c \ @@ -29,9 +30,14 @@ zip_extra_field_api.c \ zip_fclose.c \ zip_fdopen.c \ + zip_file_add.c \ zip_file_error_clear.c \ zip_file_error_get.c \ + zip_file_get_comment.c \ zip_file_get_offset.c \ + zip_file_rename.c \ + zip_file_replace.c \ + zip_file_set_comment.c \ zip_file_strerror.c \ zip_filerange_crc.c \ zip_fopen.c \
diff --git a/lib/zip.h b/lib/zip.h index 4f00f68..c04c9ed 100644 --- a/lib/zip.h +++ b/lib/zip.h
@@ -72,12 +72,14 @@ #define ZIP_FL_UNCHANGED 8 /* use original data, ignoring changes */ #define ZIP_FL_RECOMPRESS 16 /* force recompression of data */ #define ZIP_FL_ENCRYPTED 32 /* read encrypted data (implies ZIP_FL_COMPRESSED) */ -#define ZIP_FL_NAME_GUESS 0 /* guess name encoding (is default) */ -#define ZIP_FL_NAME_RAW 64 /* get unmodified name */ -#define ZIP_FL_NAME_STRICT 128 /* follow specification strictly */ +#define ZIP_FL_ENC_GUESS 0 /* guess string encoding (is default) */ +#define ZIP_FL_ENC_RAW 64 /* get unmodified string */ +#define ZIP_FL_ENC_STRICT 128 /* follow specification strictly */ #define ZIP_FL_LOCAL 256 /* in local header */ #define ZIP_FL_CENTRAL 512 /* in central directory */ /* 1024 reserved for internal use */ +#define ZIP_FL_ENC_UTF_8 2048 /* string is UTF-8 encoded */ +#define ZIP_FL_ENC_CP437 4096 /* string is CP437 encoded */ /* archive global flags flags */ @@ -222,13 +224,22 @@ -ZIP_EXTERN zip_int64_t zip_add(struct zip *, const char *, struct zip_source *); -ZIP_EXTERN zip_int64_t zip_add_dir(struct zip *, const char *); +#ifndef ZIP_DISABLE_DEPRECATED +ZIP_EXTERN zip_int64_t zip_add(struct zip *, const char *, struct zip_source *); /* use zip_file_add */ +ZIP_EXTERN zip_int64_t zip_add_dir(struct zip *, const char *); /* use zip_dir_add */ +ZIP_EXTERN const char *zip_get_file_comment(struct zip *, zip_uint64_t, int *, int); /* use zip_file_get_comment */ +ZIP_EXTERN int zip_rename(struct zip *, zip_uint64_t, const char *); /* use zip_file_rename */ +ZIP_EXTERN int zip_replace(struct zip *, zip_uint64_t, struct zip_source *); /* use zip_file_replace */ +ZIP_EXTERN int zip_set_file_comment(struct zip *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */ +#endif + +ZIP_EXTERN zip_int64_t zip_file_add(struct zip *, const char *, struct zip_source *, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_dir_add(struct zip *, const char *, zip_flags_t); ZIP_EXTERN int zip_close(struct zip *); ZIP_EXTERN void zip_discard(struct zip *); ZIP_EXTERN int zip_delete(struct zip *, zip_uint64_t); -ZIP_EXTERN int zip_delete_file_extra_field(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t); -ZIP_EXTERN int zip_delete_file_extra_field_by_id(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t); +ZIP_EXTERN int zip_file_extra_field_delete(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_delete_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); ZIP_EXTERN void zip_error_clear(struct zip *); ZIP_EXTERN void zip_error_get(struct zip *, int *, int *); ZIP_EXTERN int zip_error_get_sys_type(int); @@ -239,51 +250,38 @@ ZIP_EXTERN void zip_file_error_get(struct zip_file *, int *, int *); ZIP_EXTERN const char *zip_file_strerror(struct zip_file *); ZIP_EXTERN struct zip_file *zip_fopen(struct zip *, const char *, int); -ZIP_EXTERN struct zip_file *zip_fopen_encrypted(struct zip *, const char *, - int, const char *); +ZIP_EXTERN struct zip_file *zip_fopen_encrypted(struct zip *, const char *, int, const char *); ZIP_EXTERN struct zip_file *zip_fopen_index(struct zip *, zip_uint64_t, int); -ZIP_EXTERN struct zip_file *zip_fopen_index_encrypted(struct zip *, - zip_uint64_t, int, - const char *); +ZIP_EXTERN struct zip_file *zip_fopen_index_encrypted(struct zip *, zip_uint64_t, int, const char *); ZIP_EXTERN zip_int64_t zip_fread(struct zip_file *, void *, zip_uint64_t); ZIP_EXTERN const char *zip_get_archive_comment(struct zip *, int *, int); ZIP_EXTERN int zip_get_archive_flag(struct zip *, int, int); -ZIP_EXTERN const char *zip_get_file_comment(struct zip *, zip_uint64_t, - int *, int); -ZIP_EXTERN const zip_uint8_t *zip_get_file_extra_field(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *); -ZIP_EXTERN const zip_uint8_t *zip_get_file_extra_field_by_id(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *); -ZIP_EXTERN zip_int16_t zip_get_file_num_extra_fields(struct zip *, zip_uint64_t, zip_flags_t); -ZIP_EXTERN zip_int16_t zip_get_file_num_extra_fields_by_id(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t); +ZIP_EXTERN const char *zip_file_get_comment(struct zip *, zip_uint64_t, zip_uint32_t *, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(struct zip *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); ZIP_EXTERN const char *zip_get_name(struct zip *, zip_uint64_t, int); ZIP_EXTERN zip_uint64_t zip_get_num_entries(struct zip *, int); ZIP_EXTERN int zip_get_num_files(struct zip *); /* deprecated, use zip_get_num_entries instead */ ZIP_EXTERN int zip_name_locate(struct zip *, const char *, int); ZIP_EXTERN struct zip *zip_open(const char *, int, int *); -ZIP_EXTERN int zip_rename(struct zip *, zip_uint64_t, const char *); -ZIP_EXTERN int zip_replace(struct zip *, zip_uint64_t, struct zip_source *); +ZIP_EXTERN int zip_file_rename(struct zip *, zip_uint64_t, const char *, zip_flags_t); +ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, struct zip_source *, zip_flags_t); ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, int); ZIP_EXTERN int zip_set_archive_flag(struct zip *, int, int); ZIP_EXTERN int zip_set_default_password(struct zip *, const char *); -ZIP_EXTERN int zip_set_file_comment(struct zip *, zip_uint64_t, - const char *, int); -ZIP_EXTERN int zip_set_file_compression(struct zip *, zip_uint64_t, - zip_int32_t, zip_uint32_t); -ZIP_EXTERN int zip_set_file_extra_field(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t); -ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *, - zip_uint64_t, int); -ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *, - zip_uint64_t, zip_int64_t); -ZIP_EXTERN struct zip_source *zip_source_filep(struct zip *, FILE *, - zip_uint64_t, zip_int64_t); +ZIP_EXTERN int zip_file_set_comment(struct zip *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_set_file_compression(struct zip *, zip_uint64_t, zip_int32_t, zip_uint32_t); +ZIP_EXTERN int zip_file_extra_field_set(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *, zip_uint64_t, int); +ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN struct zip_source *zip_source_filep(struct zip *, FILE *, zip_uint64_t, zip_int64_t); ZIP_EXTERN void zip_source_free(struct zip_source *); -ZIP_EXTERN struct zip_source *zip_source_function(struct zip *, - zip_source_callback, void *); -ZIP_EXTERN struct zip_source *zip_source_zip(struct zip *, struct zip *, - zip_uint64_t, int, - zip_uint64_t, zip_int64_t); +ZIP_EXTERN struct zip_source *zip_source_function(struct zip *, zip_source_callback, void *); +ZIP_EXTERN struct zip_source *zip_source_zip(struct zip *, struct zip *, zip_uint64_t, int, zip_uint64_t, zip_int64_t); ZIP_EXTERN int zip_stat(struct zip *, const char *, int, struct zip_stat *); -ZIP_EXTERN int zip_stat_index(struct zip *, zip_uint64_t, int, - struct zip_stat *); +ZIP_EXTERN int zip_stat_index(struct zip *, zip_uint64_t, int, struct zip_stat *); ZIP_EXTERN void zip_stat_init(struct zip_stat *); ZIP_EXTERN const char *zip_strerror(struct zip *); ZIP_EXTERN int zip_unchange(struct zip *, zip_uint64_t);
diff --git a/lib/zip_add.c b/lib/zip_add.c index 3c22ddc..b298af1 100644 --- a/lib/zip_add.c +++ b/lib/zip_add.c
@@ -1,6 +1,6 @@ /* zip_add.c -- add file via callback function - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 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> @@ -46,10 +46,5 @@ ZIP_EXTERN zip_int64_t zip_add(struct zip *za, const char *name, struct zip_source *source) { - if (name == NULL || source == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - return _zip_replace(za, ZIP_UINT64_MAX, name, source); + return zip_file_add(za, name, source, 0); }
diff --git a/lib/zip_add_dir.c b/lib/zip_add_dir.c index 28a8ad1..84834b5 100644 --- a/lib/zip_add_dir.c +++ b/lib/zip_add_dir.c
@@ -1,6 +1,6 @@ /* zip_add_dir.c -- add directory - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 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> @@ -45,44 +45,5 @@ ZIP_EXTERN zip_int64_t zip_add_dir(struct zip *za, const char *name) { - int len; - zip_int64_t ret; - char *s; - struct zip_source *source; - - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; - } - - if (name == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - s = NULL; - len = strlen(name); - - if (name[len-1] != '/') { - if ((s=(char *)malloc(len+2)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; - } - strcpy(s, name); - s[len] = '/'; - s[len+1] = '\0'; - } - - if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) { - free(s); - return -1; - } - - ret = _zip_replace(za, -1, s ? s : name, source); - - free(s); - if (ret < 0) - zip_source_free(source); - - return ret; + return zip_dir_add(za, name, 0); }
diff --git a/lib/zip_close.c b/lib/zip_close.c index bd0d9b7..1ac9153 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c
@@ -76,7 +76,6 @@ struct zip_filelist *filelist; int reopen_on_error; int new_torrentzip; - enum zip_encoding_type com_enc, enc; int changed; reopen_on_error = 0; @@ -166,15 +165,6 @@ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) _zip_dirent_torrent_normalize(entry->changes); - /* set general purpose bit flag for file name/comment encoding */ - enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); - com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); - if ((enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || - (enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN ) || - (enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN )) - de->bitflags |= ZIP_GPBF_ENCODING_UTF_8; - else - de->bitflags &= ~ZIP_GPBF_ENCODING_UTF_8; de->offset = ftello(out);
diff --git a/lib/zip_dir_add.c b/lib/zip_dir_add.c new file mode 100644 index 0000000..57389c5 --- /dev/null +++ b/lib/zip_dir_add.c
@@ -0,0 +1,88 @@ +/* + zip_dir_add.c -- add directory + Copyright (C) 1999-2012 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> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +ZIP_EXTERN zip_int64_t +zip_dir_add(struct zip *za, const char *name, zip_flags_t flags) +{ + int len; + zip_int64_t ret; + char *s; + struct zip_source *source; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + s = NULL; + len = strlen(name); + + if (name[len-1] != '/') { + if ((s=(char *)malloc(len+2)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + strcpy(s, name); + s[len] = '/'; + s[len+1] = '\0'; + } + + if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) { + free(s); + return -1; + } + + ret = _zip_file_replace(za, -1, s ? s : name, source, flags); + + free(s); + if (ret < 0) + zip_source_free(source); + + return ret; +}
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index 8b44a78..77cf4a3 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c
@@ -44,6 +44,8 @@ static time_t _zip_d2u_time(int, int); static struct zip_string *_zip_read_string(const unsigned char **, FILE *, int, int, struct zip_error *); +static struct zip_string *_zip_dirent_process_ef_utf_8(struct zip_dirent *, zip_uint16_t, struct zip_string *); +static struct zip_extra_field *_zip_ef_utf8(zip_uint16_t, struct zip_string *, struct zip_error *); @@ -439,6 +441,8 @@ } } + zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename); + zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment); /* Zip64 */ @@ -487,6 +491,38 @@ +static struct zip_string * +_zip_dirent_process_ef_utf_8(struct zip_dirent *de, zip_uint16_t id, struct zip_string *str) +{ + zip_uint16_t ef_len; + zip_uint8_t string; + zip_uint32_t string_len; + zip_uint32_t ef_crc; + + const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL); + + if (ef == NULL || ef_len < 5 || ef[0] != 1) + return str; + + ef++; + ef_crc = _zip_read4(&ef); + + if (_zip_string_crc32(str) == ef_crc) { + struct zip_string *ef_str = _zip_string_new(ef, ef_len-5, ZIP_ENCODING_UTF8_KNOWN, NULL); + + if (ef_str != NULL) { + _zip_string_free(str); + str = ef_str; + } + } + + de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, id, ZIP_EXTRA_FIELD_ALL, ZIP_EF_BOTH); + + return str; +} + + + zip_int32_t _zip_dirent_size(FILE *f, zip_uint16_t flags, struct zip_error *error) { @@ -583,90 +619,126 @@ */ int -_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int flags, - struct zip_error *error) +_zip_dirent_write(struct zip_dirent *de, FILE *fp, int flags, struct zip_error *error) { unsigned short dostime, dosdate; zip_uint16_t zip64_ef_size; + enum zip_encoding_type com_enc, name_enc; + struct zip_extra_field *ef; + zip_uint8_t ef_zip64[24], *ef_zip64_p; + int is_zip64; - zip64_ef_size = 0; + ef = NULL; + + is_zip64 = 0; fwrite((flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp); + name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); + com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); + + if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || + (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || + (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN)) + de->bitflags |= ZIP_GPBF_ENCODING_UTF_8; + else { + de->bitflags &= ~ZIP_GPBF_ENCODING_UTF_8; + if (name_enc == ZIP_ENCODING_UTF8_KNOWN) { + ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, error); + if (ef == NULL) + return -1; + } + if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){ + struct zip_extra_field *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, error); + if (ef2 == NULL) { + _zip_ef_free(ef); + return -1; + } + ef2->next = ef; + ef = ef2; + } + } + + ef_zip64_p = ef_zip64; + if (flags & ZIP_FL_LOCAL) { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { + _zip_poke8(de->comp_size, &ef_zip64_p); + _zip_poke8(de->uncomp_size, &ef_zip64_p); + } + } + else { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) { + if (de->comp_size >= ZIP_UINT32_MAX) + _zip_poke8(de->comp_size, &ef_zip64_p); + if (de->uncomp_size >= ZIP_UINT32_MAX) + _zip_poke8(de->uncomp_size, &ef_zip64_p); + if (de->offset >= ZIP_UINT32_MAX) + _zip_poke8(de->offset, &ef_zip64_p); + } + } + + if (ef_zip64_p != ef_zip64) { + struct zip_extra_field *ef64 = _zip_ef_new(ZIP_EF_ZIP64, ef_zip64_p-ef_zip64, ef_zip64, ZIP_EF_BOTH); + ef64->next = ef; + ef = ef64; + is_zip64 = 1; + } if ((flags & ZIP_FL_LOCAL) == 0) - _zip_write2(zde->version_madeby, fp); - _zip_write2(zde->version_needed, fp); /* XXX: at least 4.5 if zip64 */ - _zip_write2(zde->bitflags, fp); - _zip_write2(zde->comp_method, fp); + _zip_write2(de->version_madeby, fp); + _zip_write2(de->version_needed, fp); /* XXX: at least 4.5 if zip64 */ + _zip_write2(de->bitflags, fp); + _zip_write2(de->comp_method, fp); - _zip_u2d_time(zde->last_mod, &dostime, &dosdate); + _zip_u2d_time(de->last_mod, &dostime, &dosdate); _zip_write2(dostime, fp); _zip_write2(dosdate, fp); - - _zip_write4(zde->crc, fp); - if (zde->comp_size < ZIP_UINT32_MAX) - _zip_write4(zde->comp_size, fp); - else { - _zip_write4(ZIP_UINT32_MAX, fp); - zip64_ef_size += 8; - } - if (zde->uncomp_size < ZIP_UINT32_MAX) - _zip_write4(zde->uncomp_size, fp); - else { - _zip_write4(ZIP_UINT32_MAX, fp); - zip64_ef_size += 8; - } - if (flags & ZIP_FL_LOCAL) { - if (zip64_ef_size > 0 || (flags & ZIP_FL_FORCE_ZIP64)) - zip64_ef_size = 16; - } - else if (zde->offset >= ZIP_UINT32_MAX) - zip64_ef_size += 8; + _zip_write4(de->crc, fp); + if (de->comp_size < ZIP_UINT32_MAX) + _zip_write4(de->comp_size, fp); + else + _zip_write4(ZIP_UINT32_MAX, fp); + if (de->uncomp_size < ZIP_UINT32_MAX) + _zip_write4(de->uncomp_size, fp); + else + _zip_write4(ZIP_UINT32_MAX, fp); - _zip_write2(_zip_string_length(zde->filename), fp); - _zip_write2(_zip_ef_size(zde->extra_fields, flags) + (zip64_ef_size ? (zip64_ef_size+4) : 0), fp); + _zip_write2(_zip_string_length(de->filename), fp); + _zip_write2(_zip_ef_size(de->extra_fields, flags) + _zip_ef_size(ef, ZIP_EF_BOTH), fp); if ((flags & ZIP_FL_LOCAL) == 0) { - _zip_write2(_zip_string_length(zde->comment), fp); - _zip_write2(zde->disk_number, fp); - _zip_write2(zde->int_attrib, fp); - _zip_write4(zde->ext_attrib, fp); - if (zde->offset < ZIP_UINT32_MAX) - _zip_write4(zde->offset, fp); + _zip_write2(_zip_string_length(de->comment), fp); + _zip_write2(de->disk_number, fp); + _zip_write2(de->int_attrib, fp); + _zip_write4(de->ext_attrib, fp); + if (de->offset < ZIP_UINT32_MAX) + _zip_write4(de->offset, fp); else _zip_write4(ZIP_UINT32_MAX, fp); } - if (zde->filename) - _zip_string_write(zde->filename, fp); + if (de->filename) + _zip_string_write(de->filename, fp); - if (zde->extra_fields) - _zip_ef_write(zde->extra_fields, flags, fp); - - if (zip64_ef_size > 0) { - _zip_write2(ZIP_EF_ZIP64, fp); - _zip_write2(zip64_ef_size, fp); - if ((flags & ZIP_EF_LOCAL) || zde->uncomp_size >= ZIP_UINT32_MAX) - _zip_write8(zde->uncomp_size, fp); - if ((flags & ZIP_EF_LOCAL) || zde->comp_size >= ZIP_UINT32_MAX) - _zip_write8(zde->comp_size, fp); - if (((flags & ZIP_EF_LOCAL) == 0) && zde->offset >= ZIP_UINT32_MAX) - _zip_write8(zde->offset, fp); - } + if (ef) + _zip_ef_write(ef, ZIP_EF_BOTH, fp); + if (de->extra_fields) + _zip_ef_write(de->extra_fields, flags, fp); if ((flags & ZIP_FL_LOCAL) == 0) { - if (zde->comment) - _zip_string_write(zde->comment, fp); + if (de->comment) + _zip_string_write(de->comment, fp); } + _zip_ef_free(ef); + if (ferror(fp)) { _zip_error_set(error, ZIP_ER_WRITE, errno); return -1; } - return zip64_ef_size > 0; + return is_zip64; } @@ -694,6 +766,34 @@ +static struct zip_extra_field * +_zip_ef_utf8(zip_uint16_t id, struct zip_string *str, struct zip_error *error) +{ + const zip_uint8_t *raw; + zip_uint8_t *data, *p; + zip_uint32_t len; + struct zip_extra_field *ef; + + raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL); + + if ((data=malloc(len+5)) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + p = data; + *(p++) = 1; + _zip_poke4(_zip_string_crc32(str), &p); + memcpy(p, raw, len); + p += len; + + ef = _zip_ef_new(id, p-data, data, ZIP_EF_BOTH); + free(data); + return ef; +} + + + struct zip_dirent * _zip_get_dirent(struct zip *za, zip_uint64_t idx, int flags, struct zip_error *error) { @@ -810,7 +910,33 @@ if ((raw=_zip_read_data(buf, fp, len, nulp, error)) == NULL) return NULL; - return _zip_string_new(raw, len, error); + return _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error); +} + + + +void +_zip_poke4(zip_uint32_t i, zip_uint8_t **p) +{ + *((*p)++) = i&0xff; + *((*p)++) = (i>>8)&0xff; + *((*p)++) = (i>>16)&0xff; + *((*p)++) = (i>>24)&0xff; +} + + + +void +_zip_poke8(zip_uint64_t i, zip_uint8_t **p) +{ + *((*p)++) = i&0xff; + *((*p)++) = (i>>8)&0xff; + *((*p)++) = (i>>16)&0xff; + *((*p)++) = (i>>24)&0xff; + *((*p)++) = (i>>32)&0xff; + *((*p)++) = (i>>40)&0xff; + *((*p)++) = (i>>48)&0xff; + *((*p)++) = (i>>56)&0xff; }
diff --git a/lib/zip_extra_field_api.c b/lib/zip_extra_field_api.c index 17bbd60..1c45dd9 100644 --- a/lib/zip_extra_field_api.c +++ b/lib/zip_extra_field_api.c
@@ -38,7 +38,7 @@ ZIP_EXTERN int -zip_delete_file_extra_field(struct zip *za, zip_uint64_t idx, zip_uint32_t flags, zip_uint16_t ef_idx) +zip_file_extra_field_delete(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags) { /* XXX */ return -1; @@ -47,7 +47,7 @@ ZIP_EXTERN int -zip_delete_file_extra_field_by_id(struct zip *za, zip_uint64_t idx, zip_uint32_t flags, zip_uint16_t ef_id, zip_uint16_t ef_idx) +zip_file_extra_field_delete_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags) { /* XXX */ return -1; @@ -56,7 +56,7 @@ ZIP_EXTERN const zip_uint8_t * -zip_get_file_extra_field(struct zip *za, zip_uint64_t idx, zip_uint32_t flags, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp) +zip_file_extra_field_get(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags) { static const zip_uint8_t empty[1]; @@ -101,7 +101,7 @@ ZIP_EXTERN const zip_uint8_t * -zip_get_file_extra_field_by_id(struct zip *za, zip_uint64_t idx, zip_uint32_t flags, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp) +zip_file_extra_field_get_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags) { struct zip_dirent *de; @@ -121,7 +121,7 @@ ZIP_EXTERN zip_int16_t -zip_get_file_num_extra_fields(struct zip *za, zip_uint64_t idx, zip_uint32_t flags) +zip_file_extra_fields_count(struct zip *za, zip_uint64_t idx, zip_flags_t flags) { struct zip_dirent *de; struct zip_extra_field *ef; @@ -148,7 +148,7 @@ ZIP_EXTERN zip_int16_t -zip_get_file_num_extra_fields_by_id(struct zip *za, zip_uint64_t idx, zip_uint32_t flags, zip_uint16_t ef_id) +zip_file_extra_fields_count_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags) { struct zip_dirent *de; struct zip_extra_field *ef; @@ -175,7 +175,7 @@ ZIP_EXTERN int -zip_set_file_extra_field(struct zip *za, zip_uint64_t idx, zip_uint32_t flags, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len) +zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags) { /* XXX: ZIP_ER_INVAL if ef_id == ZIP_EF_ZIP64 */ /* XXX: size of ef + new <= ZIP_UINT16_MAX */
diff --git a/lib/zip_file_add.c b/lib/zip_file_add.c new file mode 100644 index 0000000..995cb91 --- /dev/null +++ b/lib/zip_file_add.c
@@ -0,0 +1,55 @@ +/* + zip_file_add.c -- add file via callback function + Copyright (C) 1999-2012 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> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + +/* + NOTE: Return type is signed so we can return -1 on error. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. +*/ + +ZIP_EXTERN zip_int64_t +zip_file_add(struct zip *za, const char *name, struct zip_source *source, zip_flags_t flags) +{ + if (name == NULL || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags); +}
diff --git a/lib/zip_file_get_comment.c b/lib/zip_file_get_comment.c new file mode 100644 index 0000000..e71e058 --- /dev/null +++ b/lib/zip_file_get_comment.c
@@ -0,0 +1,57 @@ +/* + zip_file_get_comment.c -- get file comment + Copyright (C) 2006-2012 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> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN const char * +zip_file_get_comment(struct zip *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags) +{ + struct zip_dirent *de; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL) + return NULL; + + if ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL) + return NULL; + + if (lenp) + *lenp = len; + + return (const char *)str; +}
diff --git a/lib/zip_file_rename.c b/lib/zip_file_rename.c new file mode 100644 index 0000000..383a52a --- /dev/null +++ b/lib/zip_file_rename.c
@@ -0,0 +1,70 @@ +/* + zip_file_rename.c -- rename file in zip archive + Copyright (C) 1999-2012 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> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <string.h> + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_file_rename(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags) +{ + const char *old_name; + int old_is_dir, new_is_dir; + + if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((old_name=zip_get_name(za, idx, 0)) == NULL) + return -1; + + new_is_dir = (name != NULL && name[strlen(name)-1] == '/'); + old_is_dir = (old_name[strlen(old_name)-1] == '/'); + + if (new_is_dir != old_is_dir) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_set_name(za, idx, name, flags); +}
diff --git a/lib/zip_file_replace.c b/lib/zip_file_replace.c new file mode 100644 index 0000000..14da8ad --- /dev/null +++ b/lib/zip_file_replace.c
@@ -0,0 +1,93 @@ +/* + zip_file_replace.c -- replace file via callback function + Copyright (C) 1999-2012 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> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_file_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source, zip_flags_t flags) +{ + if (idx >= za->nentry || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_file_replace(za, idx, NULL, source, flags) == -1) + return -1; + + return 0; +} + + + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_file_replace(struct zip *za, zip_uint64_t idx, const char *name, struct zip_source *source, zip_flags_t flags) +{ + zip_uint64_t za_nentry_prev; + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + za_nentry_prev = za->nentry; + if (idx == ZIP_UINT64_MAX) { + zip_int64_t i; + + /* create and use new entry, used by zip_add */ + if ((i=_zip_add_entry(za)) < 0) + return -1; + idx = i; + } + + if (name && _zip_set_name(za, idx, name, flags) != 0) { + if (za->nentry != za_nentry_prev) { + _zip_entry_finalize(za->entry+idx); + za->nentry = za_nentry_prev; + } + return -1; + } + + /* does not change any name related data, so we can do it here; + * needed for a double add of the same file name */ + _zip_unchange_data(za->entry+idx); + + za->entry[idx].source = source; + + return idx; +}
diff --git a/lib/zip_file_set_comment.c b/lib/zip_file_set_comment.c new file mode 100644 index 0000000..16955ac --- /dev/null +++ b/lib/zip_file_set_comment.c
@@ -0,0 +1,102 @@ +/* + zip_file_set_comment.c -- set comment for file in archive + Copyright (C) 2006-2012 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> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_file_set_comment(struct zip *za, zip_uint64_t idx, + const char *comment, zip_uint16_t len, zip_flags_t flags) +{ + struct zip_entry *e; + struct zip_string *cstr; + struct zip_dirent *de; + int changed; + + if ((de=_zip_get_dirent(za, idx, 0, NULL)) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (len > 0 && comment == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + cstr->encoding = ZIP_ENCODING_UTF8_KNOWN; + } + else + cstr = NULL; + + e = za->entry+idx; + + if (e->changes) { + _zip_string_free(e->changes->comment); + e->changes->comment = NULL; + e->changes->changed &= ~ZIP_DIRENT_COMMENT; + } + + if (e->orig && e->orig->comment) + changed = !_zip_string_equal(e->orig->comment, cstr); + else + changed = (cstr != NULL); + + if (changed) { + if (e->changes == NULL) + e->changes = _zip_dirent_clone(e->orig); + e->changes->comment = cstr; + e->changes->changed |= ZIP_DIRENT_COMMENT; + } + else { + _zip_string_free(cstr); + if (e->changes && e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + + return 0; +}
diff --git a/lib/zip_get_file_comment.c b/lib/zip_get_file_comment.c index a7a586a..8fb8460 100644 --- a/lib/zip_get_file_comment.c +++ b/lib/zip_get_file_comment.c
@@ -40,18 +40,13 @@ ZIP_EXTERN const char * zip_get_file_comment(struct zip *za, zip_uint64_t idx, int *lenp, int flags) { - struct zip_dirent *de; zip_uint32_t len; - const zip_uint8_t *str; + const char *s; - if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL) - return NULL; + if ((s=zip_file_get_comment(za, idx, &len, flags)) != NULL) { + if (lenp) + *lenp = len; + } - if ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL) - return NULL; - - if (lenp) - *lenp = len; - - return (const char *)str; + return s; }
diff --git a/lib/zip_open.c b/lib/zip_open.c index c2ab512..c000381 100644 --- a/lib/zip_open.c +++ b/lib/zip_open.c
@@ -228,7 +228,7 @@ } if (comment_len) { - if ((cd->comment=_zip_string_new(eocd+EOCDLEN, comment_len, error)) == NULL) { + if ((cd->comment=_zip_string_new(eocd+EOCDLEN, comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) { _zip_cdir_free(cd); return NULL; }
diff --git a/lib/zip_rename.c b/lib/zip_rename.c index ea2e676..41f63b9 100644 --- a/lib/zip_rename.c +++ b/lib/zip_rename.c
@@ -1,6 +1,6 @@ /* zip_rename.c -- rename file in zip archive - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 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> @@ -42,29 +42,5 @@ ZIP_EXTERN int zip_rename(struct zip *za, zip_uint64_t idx, const char *name) { - const char *old_name; - int old_is_dir, new_is_dir; - - if (idx >= za->nentry || name == NULL || strlen(name) > ZIP_UINT16_MAX) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; - } - - if ((old_name=zip_get_name(za, idx, 0)) == NULL) - return -1; - - new_is_dir = (name[strlen(name)-1] == '/'); - old_is_dir = (old_name[strlen(old_name)-1] == '/'); - - if (new_is_dir != old_is_dir) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - return _zip_set_name(za, idx, name); + return zip_file_rename(za, idx, name, 0); }
diff --git a/lib/zip_replace.c b/lib/zip_replace.c index 0d39306..d74952b 100644 --- a/lib/zip_replace.c +++ b/lib/zip_replace.c
@@ -1,6 +1,6 @@ /* zip_replace.c -- replace file via callback function - Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 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> @@ -40,55 +40,5 @@ ZIP_EXTERN int zip_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source) { - if (idx >= za->nentry || source == NULL) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (_zip_replace(za, idx, NULL, source) == -1) - return -1; - - return 0; -} - - - - -/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ - -zip_int64_t -_zip_replace(struct zip *za, zip_uint64_t idx, const char *name, - struct zip_source *source) -{ - zip_uint64_t za_nentry_prev; - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; - } - - za_nentry_prev = za->nentry; - if (idx == ZIP_UINT64_MAX) { - zip_int64_t i; - - /* create and use new entry, used by zip_add */ - if ((i=_zip_add_entry(za)) < 0) - return -1; - idx = i; - } - - if (name && _zip_set_name(za, idx, name) != 0) { - if (za->nentry != za_nentry_prev) { - _zip_entry_finalize(za->entry+idx); - za->nentry = za_nentry_prev; - } - return -1; - } - - /* does not change any name related data, so we can do it here; - * needed for a double add of the same file name */ - _zip_unchange_data(za->entry+idx); - - za->entry[idx].source = source; - - return idx; + return zip_file_replace(za, idx, source, 0); }
diff --git a/lib/zip_set_archive_comment.c b/lib/zip_set_archive_comment.c index f71bea7..bf72983 100644 --- a/lib/zip_set_archive_comment.c +++ b/lib/zip_set_archive_comment.c
@@ -56,7 +56,7 @@ } if (len > 0) { - if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, &za->error)) == NULL) + if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL) return -1; if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
diff --git a/lib/zip_set_file_comment.c b/lib/zip_set_file_comment.c index 0621ad2..654c64f 100644 --- a/lib/zip_set_file_comment.c +++ b/lib/zip_set_file_comment.c
@@ -41,77 +41,7 @@ ZIP_EXTERN int -zip_set_file_comment(struct zip *za, zip_uint64_t idx, - const char *comment, int len) +zip_set_file_comment(struct zip *za, zip_uint64_t idx, const char *comment, int len) { - struct zip_entry *e; - struct zip_string *cstr; - struct zip_dirent *de; - enum zip_encoding_type com_enc, name_enc; - int changed; - - if ((de=_zip_get_dirent(za, idx, 0, NULL)) == NULL) - return -1; - - if (ZIP_IS_RDONLY(za)) { - _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); - return -1; - } - - if (len < 0 || len > MAXCOMLEN - || (len > 0 && comment == NULL)) { - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (len > 0) { - if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, &za->error)) == NULL) - return -1; - - if ((com_enc=_zip_guess_encoding(cstr, ZIP_ENCODING_UTF8_KNOWN)) == ZIP_ENCODING_ERROR) { - _zip_string_free(cstr); - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } - } - else { - cstr = NULL; - com_enc = ZIP_ENCODING_ASCII; - } - - name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); - - if (name_enc == ZIP_ENCODING_CP437 && com_enc == ZIP_ENCODING_UTF8_KNOWN) { - _zip_error_set(&za->error, ZIP_ER_ENCMISMATCH, 0); - return -1; - } - - e = za->entry+idx; - - if (e->changes) { - _zip_string_free(e->changes->comment); - e->changes->comment = NULL; - e->changes->changed &= ~ZIP_DIRENT_COMMENT; - } - - if (e->orig && e->orig->comment) - changed = !_zip_string_equal(e->orig->comment, cstr); - else - changed = (cstr != NULL); - - if (changed) { - if (e->changes == NULL) - e->changes = _zip_dirent_clone(e->orig); - e->changes->comment = cstr; - e->changes->changed |= ZIP_DIRENT_COMMENT; - } - else { - _zip_string_free(cstr); - if (e->changes && e->changes->changed == 0) { - _zip_dirent_free(e->changes); - e->changes = NULL; - } - } - - return 0; + return zip_file_set_comment(za, idx, comment, len, 0); }
diff --git a/lib/zip_set_name.c b/lib/zip_set_name.c index 70a01d9..8acbec8 100644 --- a/lib/zip_set_name.c +++ b/lib/zip_set_name.c
@@ -41,12 +41,10 @@ int -_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name) +_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { struct zip_entry *e; struct zip_string *str; - struct zip_dirent *de; - enum zip_encoding_type com_enc, name_enc; int changed; int i; @@ -61,20 +59,15 @@ } if (name && strlen(name) > 0) { - if ((str=_zip_string_new((const zip_uint8_t *)name, strlen(name), &za->error)) == NULL) + if ((str=_zip_string_new((const zip_uint8_t *)name, strlen(name), flags, &za->error)) == NULL) return -1; - - if ((name_enc=_zip_guess_encoding(str, ZIP_ENCODING_UTF8_KNOWN)) == ZIP_ENCODING_ERROR) { - _zip_string_free(str); - _zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return -1; - } + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = ZIP_ENCODING_UTF8_KNOWN; } - else { + else str = NULL; - name_enc = ZIP_ENCODING_ASCII; - } + /* XXX: encoding flags needed for CP437? */ if ((i=_zip_name_locate(za, name, 0, NULL)) != -1 && i != idx) { _zip_string_free(str); _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); @@ -87,20 +80,6 @@ return 0; } - de = _zip_get_dirent(za, idx, 0, NULL); - - if (de) - com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); - else - com_enc = ZIP_ENCODING_ASCII; - - if (com_enc == ZIP_ENCODING_CP437 && name_enc == ZIP_ENCODING_UTF8_KNOWN) { - _zip_string_free(str); - _zip_error_set(&za->error, ZIP_ER_ENCMISMATCH, 0); - return -1; - } - - e = za->entry+idx; if (e->changes) {
diff --git a/lib/zip_string.c b/lib/zip_string.c index b837ea8..d49e521 100644 --- a/lib/zip_string.c +++ b/lib/zip_string.c
@@ -40,6 +40,21 @@ +zip_uint32_t +_zip_string_crc32(const struct zip_string *s) +{ + zip_uint32_t crc; + + crc = crc32(0L, Z_NULL, 0); + + if (s != NULL) + crc = crc32(crc, s->raw, s->length); + + return crc; +} + + + int _zip_string_equal(const struct zip_string *a, const struct zip_string *b) { @@ -70,7 +85,7 @@ const zip_uint8_t * -_zip_string_get(struct zip_string *string, zip_uint32_t *lenp, int flags, struct zip_error *error) +_zip_string_get(struct zip_string *string, zip_uint32_t *lenp, zip_flags_t flags, struct zip_error *error) { static const zip_uint8_t empty[1] = ""; @@ -80,12 +95,12 @@ return empty; } - if ((flags & ZIP_FL_NAME_RAW) == 0) { + if ((flags & ZIP_FL_ENC_RAW) == 0) { /* start guessing */ if (string->encoding == ZIP_ENCODING_UNKNOWN) _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN); - if (((flags & ZIP_FL_NAME_STRICT) + if (((flags & ZIP_FL_ENC_STRICT) && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) || (string->encoding == ZIP_ENCODING_CP437)) { if (string->converted == NULL) { @@ -118,13 +133,29 @@ struct zip_string * -_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, struct zip_error *error) +_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, struct zip_error *error) { struct zip_string *s; + enum zip_encoding_type expected_encoding; if (length == 0) return NULL; + switch (flags & ZIP_FL_ENCODING_ALL) { + case ZIP_FL_ENC_GUESS: + expected_encoding = ZIP_ENCODING_UNKNOWN; + break; + case ZIP_FL_ENC_UTF_8: + expected_encoding = ZIP_ENCODING_UTF8_KNOWN; + break; + case ZIP_FL_ENC_CP437: + expected_encoding = ZIP_ENCODING_CP437; + break; + default: + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if ((s=malloc(sizeof(*s))) == NULL) { _zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; @@ -142,6 +173,14 @@ s->converted = NULL; s->converted_length = 0; + if (expected_encoding != ZIP_ENCODING_UNKNOWN) { + if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { + _zip_string_free(s); + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + } + return s; }
diff --git a/lib/zipint.h b/lib/zipint.h index b9f26a7..44c5baf 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -42,6 +42,8 @@ #include <io.h> #endif +#define ZIP_DISABLE_DEPRECATED + #include "zip.h" #include "config.h" @@ -116,7 +118,9 @@ #define CDBUFSIZE (MAXCOMLEN+EOCDLEN+EOCD64LOCLEN) #define BUFSIZE 8192 -#define ZIP_EF_ZIP64 0x0001 +#define ZIP_EF_UTF_8_COMMENT 0x6375 +#define ZIP_EF_UTF_8_NAME 0x7075 +#define ZIP_EF_ZIP64 0x0001 @@ -199,6 +203,8 @@ #define ZIP_FL_FORCE_ZIP64 1024 /* force zip64 extra field (_zip_dirent_write) */ +#define ZIP_FL_ENCODING_ALL (ZIP_FL_ENC_GUESS|ZIP_FL_ENC_CP437|ZIP_FL_ENC_UTF_8) + /* encoding type */ enum zip_encoding_type { @@ -331,7 +337,7 @@ struct zip_string { zip_uint8_t *raw; /* raw string */ zip_uint16_t length; /* length of raw string */ - unsigned short encoding; /* autorecognized encoding */ + enum zip_encoding_type encoding; /* autorecognized encoding */ zip_uint8_t *converted; /* autoconverted string */ zip_uint32_t converted_length; /* length of converted */ }; @@ -428,9 +434,10 @@ int _zip_string_equal(const struct zip_string *, const struct zip_string *); void _zip_string_free(struct zip_string *); -const zip_uint8_t *_zip_string_get(struct zip_string *, zip_uint32_t *, int, struct zip_error *); +zip_uint32_t _zip_string_crc32(const struct zip_string *); +const zip_uint8_t *_zip_string_get(struct zip_string *, zip_uint32_t *, zip_flags_t, struct zip_error *); zip_uint16_t _zip_string_length(const struct zip_string *); -struct zip_string *_zip_string_new(const zip_uint8_t *, zip_uint16_t, struct zip_error *); +struct zip_string *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *); void _zip_string_write(const struct zip_string *, FILE *); int _zip_changed(struct zip *, int *); @@ -443,13 +450,14 @@ zip_uint32_t _zip_read4(const unsigned char **); zip_uint64_t _zip_read8(const unsigned char **); zip_uint8_t *_zip_read_data(const unsigned char **, FILE *, int, int, struct zip_error *); -zip_int64_t _zip_replace(struct zip *, zip_uint64_t, const char *, - struct zip_source *); -int _zip_set_name(struct zip *, zip_uint64_t, const char *); +zip_int64_t _zip_file_replace(struct zip *, zip_uint64_t, const char *, struct zip_source *, zip_flags_t); +int _zip_set_name(struct zip *, zip_uint64_t, const char *, zip_flags_t); void _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *); int _zip_unchange(struct zip *, zip_uint64_t, int); void _zip_unchange_data(struct zip_entry *); +void _zip_poke4(zip_uint32_t, zip_uint8_t **); +void _zip_poke8(zip_uint64_t, zip_uint8_t **); void _zip_write2(zip_uint16_t, FILE *); void _zip_write4(zip_uint32_t, FILE *); void _zip_write8(zip_uint64_t, FILE *);
diff --git a/regress/Makefile.am b/regress/Makefile.am index 457b6e3..4391354 100644 --- a/regress/Makefile.am +++ b/regress/Makefile.am
@@ -31,7 +31,9 @@ test.zip \ test2.zip \ test-cp437.zip \ + test-cp437-comment-utf-8.zip \ test-cp437-fc.zip \ + test-cp437-fc-utf-8-filename.zip \ test-utf8.zip \ test-utf8-unmarked.zip \ testbuffer.zip \ @@ -46,6 +48,7 @@ testextrabytes.zip \ testfile.txt \ testfile.zip \ + testfile-cp437.zip \ testfile-UTF8.zip \ testnottorrent.zip \ teststdin.zip \
diff --git a/regress/file_comment_encmismatch.test b/regress/file_comment_encmismatch.test index 8685cdb..8d6dc98 100644 --- a/regress/file_comment_encmismatch.test +++ b/regress/file_comment_encmismatch.test
@@ -1,6 +1,5 @@ -# set file comment to UTF-8 for CP437 encoded filename (fails) +# set file comment to UTF-8 for CP437 encoded filename (adds InfoZIP extra field) program modify -return 1 -args testfile set_file_comment 0 ÄÖÜßäöü -file testfile test-cp437.zip test-cp437.zip -stderr can't set file comment at index `0' to `ÄÖÜßäöü': Encoding of name and comment do not match +return 0 +args testfile.zip set_file_comment 0 ÄÖÜßäöü +file testfile.zip test-cp437.zip test-cp437-comment-utf-8.zip
diff --git a/regress/rename_cp437.test b/regress/rename_cp437.test index 6865b7e..5445608 100644 --- a/regress/rename_cp437.test +++ b/regress/rename_cp437.test
@@ -1,6 +1,5 @@ # rename file to CP437 name in zip archive (fails) program modify -return 1 +return 0 args testfile.zip rename 0 -file testfile.zip testfile.zip testfile.zip -stderr can't rename file at index `0' to ` ': Invalid argument +file testfile.zip testfile.zip testfile-cp437.zip
diff --git a/regress/rename_utf8_encmismatch.test b/regress/rename_utf8_encmismatch.test index 60c44f4..12cc537 100644 --- a/regress/rename_utf8_encmismatch.test +++ b/regress/rename_utf8_encmismatch.test
@@ -1,6 +1,5 @@ -# rename file to UTF-8 name in zip archive with CP437 comment (fails) +# rename file to UTF-8 name in zip archive with CP437 comment (sets InfoZIP UTF-8 Name Extension) program modify -return 1 +return 0 args testfile rename 0 ÄÖÜßäöü -file testfile test-cp437-fc.zip test-cp437-fc.zip -stderr can't rename file at index `0' to `ÄÖÜßäöü': Encoding of name and comment do not match +file testfile test-cp437-fc.zip test-cp437-fc-utf-8-filename.zip
diff --git a/regress/stat_index.c b/regress/stat_index.c index 4f323c1..14c8116 100644 --- a/regress/stat_index.c +++ b/regress/stat_index.c
@@ -66,13 +66,13 @@ while ((c=getopt(argc, argv, "grs")) != -1) { switch (c) { case 'g': - flags = ZIP_FL_NAME_GUESS; + flags = ZIP_FL_ENC_GUESS; break; case 'r': - flags = ZIP_FL_NAME_RAW; + flags = ZIP_FL_ENC_RAW; break; case 's': - flags = ZIP_FL_NAME_STRICT; + flags = ZIP_FL_ENC_STRICT; break; default:
diff --git a/regress/test-cp437-comment-utf-8.zip b/regress/test-cp437-comment-utf-8.zip new file mode 100644 index 0000000..04fbaac --- /dev/null +++ b/regress/test-cp437-comment-utf-8.zip Binary files differ
diff --git a/regress/test-cp437-fc-utf-8-filename.zip b/regress/test-cp437-fc-utf-8-filename.zip new file mode 100644 index 0000000..7aeb809 --- /dev/null +++ b/regress/test-cp437-fc-utf-8-filename.zip Binary files differ
diff --git a/regress/testfile-cp437.zip b/regress/testfile-cp437.zip new file mode 100644 index 0000000..169a903 --- /dev/null +++ b/regress/testfile-cp437.zip Binary files differ
diff --git a/src/zipcmp.c b/src/zipcmp.c index 18eabd5..30f44d7 100644 --- a/src/zipcmp.c +++ b/src/zipcmp.c
@@ -343,8 +343,8 @@ int i; zip_uint16_t len; - n_local = zip_get_file_num_extra_fields(za, idx, ZIP_FL_LOCAL); - n_central = zip_get_file_num_extra_fields(za, idx, ZIP_FL_CENTRAL); + n_local = zip_file_extra_fields_count(za, idx, ZIP_FL_LOCAL); + n_central = zip_file_extra_fields_count(za, idx, ZIP_FL_CENTRAL); e->n_extra_fields = n_local + n_central; if ((e->extra_fields=malloc(sizeof(e->extra_fields[0])*e->n_extra_fields)) == NULL) @@ -352,13 +352,13 @@ for (i=0; i<n_local; i++) { e->extra_fields[i].name = e->name; - if ((e->extra_fields[i].data=zip_get_file_extra_field(za, idx, ZIP_FL_LOCAL, i, &e->extra_fields[i].id, &e->extra_fields[i].size)) == NULL) + if ((e->extra_fields[i].data=zip_file_extra_field_get(za, idx, i, &e->extra_fields[i].id, &e->extra_fields[i].size, ZIP_FL_LOCAL)) == NULL) return -1; e->extra_fields[i].flags = ZIP_FL_LOCAL; } for (; i<e->n_extra_fields; i++) { e->extra_fields[i].name = e->name; - if ((e->extra_fields[i].data=zip_get_file_extra_field(za, idx, ZIP_FL_CENTRAL, i-n_local, &e->extra_fields[i].id, &e->extra_fields[i].size)) == NULL) + if ((e->extra_fields[i].data=zip_file_extra_field_get(za, idx, i-n_local, &e->extra_fields[i].id, &e->extra_fields[i].size, ZIP_FL_CENTRAL)) == NULL) return -1; e->extra_fields[i].flags = ZIP_FL_CENTRAL; }