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;
}