Allow sources to provide more information.
In particular, some general purpose bit flags, the ASCII bit,
the operating system, the external file attributes and the version-needed
can now be provided by a source.
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 8ac6af5..7683aed 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -133,12 +133,12 @@
zip_source_filep.c
zip_source_free.c
zip_source_function.c
- zip_source_get_compression_flags.c
+ zip_source_get_file_attributes.c
zip_source_is_deleted.c
zip_source_layered.c
zip_source_open.c
- zip_source_pkware_encode.c
zip_source_pkware_decode.c
+ zip_source_pkware_encode.c
zip_source_read.c
zip_source_remove.c
zip_source_rollback_write.c
diff --git a/lib/zip.h b/lib/zip.h
index ebedc1f..547387b 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -230,9 +230,10 @@
ZIP_SOURCE_TELL_WRITE, /* get write position */
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
ZIP_SOURCE_REMOVE, /* remove file */
- ZIP_SOURCE_GET_COMPRESSION_FLAGS, /* get compression flags, internal only */
+ ZIP_SOURCE_RESERVED_1, /* previously used internally */
ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
- ZIP_SOURCE_ACCEPT_EMPTY /* whether empty files are valid archives */
+ ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */
+ ZIP_SOURCE_GET_FILE_ATTRIBUTES /* get additional file attributes */
};
typedef enum zip_source_cmd zip_source_cmd_t;
@@ -309,6 +310,23 @@
zip_uint64_t length;
};
+struct zip_file_attributes {
+ zip_uint64_t valid; /* which fields have valid values */
+ zip_uint8_t version; /* version of this struct, currently 1 */
+ zip_uint8_t host_system; /* host system on which file was created */
+ zip_uint8_t ascii; /* flag whether file is ASCII text */
+ zip_uint8_t version_needed; /* minimum version needed to extract file */
+ zip_uint32_t external_file_attributes; /* external file attributes (host-system specific) */
+ zip_uint16_t general_purpose_bit_flags; /* general purpose big flags, only some bits are honored */
+ zip_uint16_t general_purpose_bit_mask; /* which bits in general_purpose_bit_flags are valid */
+};
+
+#define ZIP_FILE_ATTRIBUTES_HOST_SYSTEM 0x0001u
+#define ZIP_FILE_ATTRIBUTES_ASCII 0x0002u
+#define ZIP_FILE_ATTRIBUTES_VERSION_NEEDED 0x0004u
+#define ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES 0x0008u
+#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS 0x0010u
+
struct zip;
struct zip_file;
struct zip_source;
@@ -316,6 +334,7 @@
typedef struct zip zip_t;
typedef struct zip_error zip_error_t;
typedef struct zip_file zip_file_t;
+typedef struct zip_file_attributes zip_file_attributes_t;
typedef struct zip_source zip_source_t;
typedef struct zip_stat zip_stat_t;
typedef struct zip_buffer_fragment zip_buffer_fragment_t;
@@ -363,6 +382,7 @@
ZIP_EXTERN int zip_fclose(zip_file_t * _Nonnull);
ZIP_EXTERN zip_t * _Nullable zip_fdopen(int, int, int * _Nullable);
ZIP_EXTERN zip_int64_t zip_file_add(zip_t * _Nonnull, const char * _Nonnull, zip_source_t * _Nonnull, zip_flags_t);
+ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t * _Nonnull);
ZIP_EXTERN void zip_file_error_clear(zip_file_t * _Nonnull);
ZIP_EXTERN int zip_file_extra_field_delete(zip_t * _Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t * _Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
@@ -419,6 +439,7 @@
ZIP_EXTERN void zip_source_free(zip_source_t * _Nullable);
ZIP_EXTERN zip_source_t * _Nullable zip_source_function(zip_t * _Nonnull, zip_source_callback _Nonnull , void * _Nullable);
ZIP_EXTERN zip_source_t * _Nullable zip_source_function_create(zip_source_callback _Nonnull , void * _Nullable, zip_error_t * _Nullable);
+ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t * _Nonnull, zip_file_attributes_t * _Nonnull);
ZIP_EXTERN int zip_source_is_deleted(zip_source_t * _Nonnull);
ZIP_EXTERN void zip_source_keep(zip_source_t * _Nonnull);
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...);
diff --git a/lib/zip_algorithm_bzip2.c b/lib/zip_algorithm_bzip2.c
index a1d2898..d287fe9 100644
--- a/lib/zip_algorithm_bzip2.c
+++ b/lib/zip_algorithm_bzip2.c
@@ -90,8 +90,8 @@
}
-static int
-compression_flags(void *ud) {
+static zip_uint16_t
+general_purpose_bit_flags(void *ud) {
return 0;
}
@@ -247,7 +247,7 @@
zip_compression_algorithm_t zip_algorithm_bzip2_compress = {
compress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
start,
end,
input,
@@ -259,7 +259,7 @@
zip_compression_algorithm_t zip_algorithm_bzip2_decompress = {
decompress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
start,
end,
input,
diff --git a/lib/zip_algorithm_deflate.c b/lib/zip_algorithm_deflate.c
index daf4a2c..cfae602 100644
--- a/lib/zip_algorithm_deflate.c
+++ b/lib/zip_algorithm_deflate.c
@@ -91,8 +91,8 @@
}
-static int
-compression_flags(void *ud) {
+static zip_uint16_t
+general_purpose_bit_flags(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
if (!ctx->compress) {
@@ -100,10 +100,10 @@
}
if (ctx->compression_flags < 3) {
- return 2;
+ return 2 << 1;
}
else if (ctx->compression_flags > 7) {
- return 1;
+ return 1 << 1;
}
return 0;
}
@@ -225,7 +225,7 @@
zip_compression_algorithm_t zip_algorithm_deflate_compress = {
compress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
start,
end,
input,
@@ -237,7 +237,7 @@
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
decompress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
start,
end,
input,
diff --git a/lib/zip_algorithm_xz.c b/lib/zip_algorithm_xz.c
index 821ac12..bb9342c 100644
--- a/lib/zip_algorithm_xz.c
+++ b/lib/zip_algorithm_xz.c
@@ -51,7 +51,7 @@
static void *
allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method) {
struct ctx *ctx;
-
+
if (compression_flags < 0) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
@@ -92,8 +92,8 @@
}
-static int
-compression_flags(void *ud) {
+static zip_uint16_t
+general_purpose_bit_flags(void *ud) {
/* struct ctx *ctx = (struct ctx *)ud; */
return 0;
}
@@ -222,7 +222,7 @@
zip_compression_algorithm_t zip_algorithm_xz_compress = {
compress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
start,
end,
input,
@@ -234,7 +234,7 @@
zip_compression_algorithm_t zip_algorithm_xz_decompress = {
decompress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
start,
end,
input,
diff --git a/lib/zip_close.c b/lib/zip_close.c
index d7a86ca..7896d1c 100644
--- a/lib/zip_close.c
+++ b/lib/zip_close.c
@@ -51,7 +51,7 @@
#endif
-static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
+static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
static int copy_data(zip_t *, zip_uint64_t);
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
@@ -222,7 +222,7 @@
}
/* add_data writes dirent */
- if (add_data(za, zs ? zs : entry->source, de) < 0) {
+ if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
error = 1;
if (zs)
zip_source_free(zs);
@@ -294,14 +294,14 @@
static int
-add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
+add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
zip_int64_t offstart, offdata, offend, data_length;
- struct zip_stat st;
+ zip_stat_t st;
+ zip_file_attributes_t attributes;
zip_source_t *src_final, *src_tmp;
int ret;
int is_zip64;
zip_flags_t flags;
- zip_int8_t compression_flags;
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
if (zip_source_stat(src, &st) < 0) {
@@ -486,7 +486,7 @@
ret = -1;
}
- if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
+ if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
_zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
@@ -522,8 +522,7 @@
de->crc = st.crc;
de->uncomp_size = st.size;
de->comp_size = (zip_uint64_t)(offend - offdata);
- de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1));
- _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0);
+ _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
return -1;
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c
index 340c70b..2e38c75 100644
--- a/lib/zip_dirent.c
+++ b/lib/zip_dirent.c
@@ -1091,41 +1091,51 @@
void
-_zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) {
+_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed)
+{
zip_uint16_t length;
+ if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
+ zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
+ de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
+ }
+ if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
+ de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
+ }
+ /* manually set attributes are preferred over attributes provided by source */
+ if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
+ de->ext_attrib = attributes->external_file_attributes;
+ }
+
if (de->comp_method == ZIP_CM_LZMA) {
de->version_needed = 63;
- return;
}
-
- if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
+ else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
de->version_needed = 51;
- return;
}
-
- if (de->comp_method == ZIP_CM_BZIP2) {
+ else if (de->comp_method == ZIP_CM_BZIP2) {
de->version_needed = 46;
- return;
}
-
- if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
+ else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
de->version_needed = 45;
- return;
}
-
- if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
+ else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
de->version_needed = 20;
- return;
+ }
+ else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
+ de->version_needed = 20;
+ }
+ else {
+ de->version_needed = 10;
}
- /* directory */
- if ((length = _zip_string_length(de->filename)) > 0) {
- if (de->filename->raw[length - 1] == '/') {
- de->version_needed = 20;
- return;
+ if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
+ if (attributes->version_needed > de->version_needed) {
+ de->version_needed = attributes->version_needed;
}
}
- de->version_needed = 10;
+ if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
+ de->version_madeby = 63 | (attributes->host_system << 8);
+ }
}
diff --git a/lib/zip_source_buffer.c b/lib/zip_source_buffer.c
index 0685fb3..eb1e604 100644
--- a/lib/zip_source_buffer.c
+++ b/lib/zip_source_buffer.c
@@ -61,6 +61,7 @@
struct read_data {
zip_error_t error;
time_t mtime;
+ zip_file_attributes_t attributes;
buffer_t *in;
buffer_t *out;
};
@@ -79,18 +80,27 @@
static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t);
+zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
+zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
+
ZIP_EXTERN zip_source_t *
zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
if (za == NULL)
return NULL;
- return zip_source_buffer_create(data, len, freep, &za->error);
+ return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
}
ZIP_EXTERN zip_source_t *
zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
+ return zip_source_buffer_with_attributes_create(data, len, freep, NULL, error);
+}
+
+
+zip_source_t *
+zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error) {
zip_buffer_fragment_t fragment;
if (data == NULL) {
@@ -105,7 +115,7 @@
fragment.data = (zip_uint8_t *)data;
fragment.length = len;
- return zip_source_buffer_fragment_create(&fragment, 1, freep, error);
+ return zip_source_buffer_fragment_with_attributes_create(&fragment, 1, freep, attributes, error);
}
@@ -115,12 +125,17 @@
return NULL;
}
- return zip_source_buffer_fragment_create(fragments, nfragments, freep, &za->error);
+ return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error);
}
ZIP_EXTERN zip_source_t *
zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error) {
+ return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, error);
+}
+
+zip_source_t *
+zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error) {
struct read_data *ctx;
zip_source_t *zs;
buffer_t *buffer;
@@ -143,6 +158,12 @@
ctx->in = buffer;
ctx->out = NULL;
ctx->mtime = time(NULL);
+ if (attributes) {
+ memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
+ }
+ else {
+ zip_file_attributes_init(&ctx->attributes);
+ }
zip_error_init(&ctx->error);
if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) {
@@ -155,6 +176,11 @@
}
+zip_source_t *
+zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes) {
+ return zip_source_buffer_with_attributes_create(data, len, freep, attributes, &za->error);
+}
+
static zip_int64_t
read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
struct read_data *ctx = (struct read_data *)state;
diff --git a/lib/zip_source_compress.c b/lib/zip_source_compress.c
index 4c318e0..356656c 100644
--- a/lib/zip_source_compress.c
+++ b/lib/zip_source_compress.c
@@ -357,9 +357,6 @@
}
return 0;
- case ZIP_SOURCE_GET_COMPRESSION_FLAGS:
- return ctx->is_stored ? 0 : ctx->algorithm->compression_flags(ctx->ud);
-
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
@@ -367,8 +364,22 @@
context_free(ctx);
return 0;
+ case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
+ zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
+
+ if (len < sizeof(*attributes)) {
+ return -1;
+ }
+
+ attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
+ attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
+ attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud));
+
+ return sizeof(*attributes);
+ }
+
case ZIP_SOURCE_SUPPORTS:
- return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1);
+ return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
default:
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
diff --git a/lib/zip_source_crc.c b/lib/zip_source_crc.c
index 56572c0..0dc5d9d 100644
--- a/lib/zip_source_crc.c
+++ b/lib/zip_source_crc.c
@@ -167,7 +167,7 @@
return -1;
}
- return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1);
+ return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
}
case ZIP_SOURCE_SEEK: {
diff --git a/lib/zip_source_filep.c b/lib/zip_source_filep.c
index 1d89c1d..b00d811 100644
--- a/lib/zip_source_filep.c
+++ b/lib/zip_source_filep.c
@@ -62,7 +62,8 @@
/* reading */
char *fname; /* name of file to read from */
FILE *f; /* file to read from */
- struct zip_stat st; /* stat information passed in */
+ zip_stat_t st; /* stat information passed in */
+ zip_file_attributes_t attributes; /* additional file attributes */
zip_error_t stat_error; /* error returned for stat */
zip_uint64_t start; /* start offset of data to read */
zip_uint64_t end; /* end offset of data to read relative to start, 0 for up to EOF */
@@ -159,6 +160,7 @@
ctx->fout = NULL;
zip_error_init(&ctx->error);
+ zip_file_attributes_init(&ctx->attributes);
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
@@ -202,6 +204,14 @@
}
}
}
+
+ /* We're using UNIX file API, even on Windows; thus, we supply external file attributes with Unix values. */
+ /* TODO: This could be improved on Windows by providing Windows-specific file attributes */
+ ctx->attributes.valid = ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES;
+ ctx->attributes.host_system = ZIP_OPSYS_UNIX;
+ ctx->attributes.external_file_attributes = sb.st_mode << 8;
+
+ ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES);
}
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
@@ -432,6 +442,13 @@
free(ctx);
return 0;
+ case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
+ if (len < sizeof(ctx->attributes))
+ return -1;
+
+ memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
+ return sizeof(ctx->attributes);
+
case ZIP_SOURCE_OPEN:
if (ctx->fname) {
if ((ctx->f = _zip_fopen(ctx->fname, false)) == NULL) {
diff --git a/lib/zip_source_get_compression_flags.c b/lib/zip_source_get_compression_flags.c
deleted file mode 100644
index 7e04bed..0000000
--- a/lib/zip_source_get_compression_flags.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- zip_source_get_compression_flags.c -- get compression flags for entry
- Copyright (C) 2017-2019 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"
-
-#define ZIP_COMPRESSION_BITFLAG_MAX 3
-
-zip_int8_t
-zip_source_get_compression_flags(zip_source_t *src) {
- while (src) {
- if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_COMPRESSION_FLAGS))) {
- zip_int64_t ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_GET_COMPRESSION_FLAGS);
- if (ret < 0) {
- return -1;
- }
- if (ret > ZIP_COMPRESSION_BITFLAG_MAX) {
- zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
- return -1;
- }
- return (zip_int8_t)ret;
- }
- src = src->src;
- }
-
- return 0;
-}
diff --git a/lib/zip_source_get_file_attributes.c b/lib/zip_source_get_file_attributes.c
new file mode 100644
index 0000000..eb0144b
--- /dev/null
+++ b/lib/zip_source_get_file_attributes.c
@@ -0,0 +1,104 @@
+/*
+ zip_source_get_file_attributes.c -- get attributes for file from source
+ Copyright (C) 2020 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 void
+zip_file_attributes_init(zip_file_attributes_t *attributes) {
+ attributes->valid = 0;
+ attributes->version = 1;
+}
+
+int
+zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) {
+ if (src->source_closed) {
+ return -1;
+ }
+ if (attributes == NULL) {
+ zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+ return -1;
+ }
+
+ zip_file_attributes_init(attributes);
+
+ if (src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES)) {
+ if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) {
+ return -1;
+ }
+ }
+
+ if (ZIP_SOURCE_IS_LAYERED(src)) {
+ zip_file_attributes_t lower_attributes;
+
+ if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) {
+ _zip_error_set_from_source(&src->error, src->src);
+ return -1;
+ }
+
+ if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) {
+ attributes->host_system = lower_attributes.host_system;
+ attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM;
+ }
+ if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) {
+ attributes->ascii = lower_attributes.ascii;
+ attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII;
+ }
+ if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) {
+ if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
+ attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed);
+ }
+ else {
+ attributes->version_needed = lower_attributes.version_needed;
+ attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED;
+ }
+ }
+ if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) {
+ attributes->external_file_attributes = lower_attributes.external_file_attributes;
+ attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES;
+ }
+ if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) {
+ if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
+ attributes->general_purpose_bit_flags &= ~ lower_attributes.general_purpose_bit_mask;
+ attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask;
+ attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask;
+ }
+ else {
+ attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
+ attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags;
+ attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/zip_source_window.c b/lib/zip_source_window.c
index 1276485..a601a6b 100644
--- a/lib/zip_source_window.c
+++ b/lib/zip_source_window.c
@@ -48,7 +48,7 @@
zip_uint64_t offset; /* offset in src for next read */
zip_stat_t stat;
- zip_int8_t compression_flags;
+ zip_file_attributes_t attributes;
zip_error_t error;
zip_int64_t supports;
bool needs_seek;
@@ -64,7 +64,7 @@
zip_source_t *
-_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) {
+_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) {
struct window *ctx;
if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) {
@@ -80,11 +80,16 @@
ctx->start = start;
ctx->end = start + length;
zip_stat_init(&ctx->stat);
- ctx->compression_flags = compression_flags;
+ if (attributes != NULL) {
+ memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
+ }
+ else {
+ zip_file_attributes_init(&ctx->attributes);
+ }
ctx->source_archive = source_archive;
ctx->source_index = source_index;
zip_error_init(&ctx->error);
- ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
+ ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false;
if (st) {
@@ -231,8 +236,12 @@
return 0;
}
- case ZIP_SOURCE_GET_COMPRESSION_FLAGS:
- return ctx->compression_flags;
+ case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
+ if (len < sizeof(ctx->attributes))
+ return -1;
+
+ memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
+ return sizeof(ctx->attributes);
case ZIP_SOURCE_SUPPORTS:
return ctx->supports;
diff --git a/lib/zip_source_zip_new.c b/lib/zip_source_zip_new.c
index f36609b..6d547f0 100644
--- a/lib/zip_source_zip_new.c
+++ b/lib/zip_source_zip_new.c
@@ -36,15 +36,19 @@
#include "zipint.h"
+static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de);
zip_source_t *
_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) {
zip_source_t *src, *s2;
- struct zip_stat st;
+ zip_stat_t st;
+ zip_file_attributes_t attributes;
+ zip_dirent_t *de;
bool partial_data, needs_crc, needs_decrypt, needs_decompress;
- if (za == NULL)
+ if (za == NULL) {
return NULL;
+ }
if (srcza == NULL || srcidx >= srcza->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -61,8 +65,9 @@
return NULL;
}
- if (flags & ZIP_FL_ENCRYPTED)
+ if (flags & ZIP_FL_ENCRYPTED) {
flags |= ZIP_FL_COMPRESSED;
+ }
if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -95,8 +100,13 @@
}
}
+ if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
+ return NULL;
+ }
+ _zip_file_attributes_from_dirent(&attributes, de);
+
if (st.comp_size == 0) {
- return zip_source_buffer(za, NULL, 0, 0);
+ return zip_source_buffer_with_attributes(za, NULL, 0, 0, &attributes);
}
if (partial_data && !needs_decrypt && !needs_decompress) {
@@ -108,17 +118,12 @@
st2.mtime = st.mtime;
st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME;
- if ((src = _zip_source_window_new(srcza->src, start, len, &st2, 0, srcza, srcidx, &za->error)) == NULL) {
+ if ((src = _zip_source_window_new(srcza->src, start, len, &st2, &attributes, srcza, srcidx, &za->error)) == NULL) {
return NULL;
}
}
else {
- zip_dirent_t *de;
-
- if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
- return NULL;
- }
- if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, (de->bitflags >> 1) & 3, srcza, srcidx, &za->error)) == NULL) {
+ if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, &attributes, srcza, srcidx, &za->error)) == NULL) {
return NULL;
}
}
@@ -173,3 +178,14 @@
return src;
}
+
+static void
+_zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de) {
+ zip_file_attributes_init(attributes);
+ attributes->valid = ZIP_FILE_ATTRIBUTES_ASCII | ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
+ attributes->ascii = de->int_attrib & 1;
+ attributes->host_system = de->version_madeby >> 8;
+ attributes->external_file_attributes = de->ext_attrib;
+ attributes->general_purpose_bit_flags = de->bitflags;
+ attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
+}
diff --git a/lib/zipint.h b/lib/zipint.h
index 4cb7e73..df2ed9e 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -98,6 +98,7 @@
/* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */
#define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u << 16)
+#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x0836
#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b))
#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -131,7 +132,7 @@
void (*deallocate)(void *ctx);
/* get compression specific general purpose bitflags */
- int (*compression_flags)(void *ctx);
+ zip_uint16_t (*general_purpose_bit_flags)(void *ctx);
/* start processing */
bool (*start)(void *ctx);
@@ -178,7 +179,7 @@
zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t);
zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
-
+zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes);
/* error source for layered sources */
@@ -481,6 +482,7 @@
time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t);
void _zip_deregister_source(zip_t *za, zip_source_t *src);
+void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t);
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
void _zip_dirent_free(zip_dirent_t *);
void _zip_dirent_finalize(zip_dirent_t *);
@@ -561,12 +563,11 @@
zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command);
bool _zip_source_eof(zip_source_t *);
zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error);
-zip_int8_t zip_source_get_compression_flags(zip_source_t *);
bool _zip_source_had_error(zip_source_t *);
void _zip_source_invalidate(zip_source_t *src);
zip_source_t *_zip_source_new(zip_error_t *error);
int _zip_source_set_source_archive(zip_source_t *, zip_t *);
-zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
+zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *);
int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error);
diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt
index 19d57bc..d0a46cb 100644
--- a/man/CMakeLists.txt
+++ b/man/CMakeLists.txt
@@ -25,6 +25,7 @@
zip_fclose.3
zip_fdopen.3
zip_file_add.3
+ zip_file_attributes_init.3
zip_file_extra_field_delete.3
zip_file_extra_field_get.3
zip_file_extra_field_set.3
diff --git a/man/libzip.man b/man/libzip.man
index aac756e..b3a2bb6 100644
--- a/man/libzip.man
+++ b/man/libzip.man
@@ -30,7 +30,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "LIBZIP" "3" "January 7, 2020" "NiH" "Library Functions Manual"
+.TH "LIBZIP" "3" "April 17, 2020" "NiH" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -120,6 +120,12 @@
.PD 0
.TP 4n
\fB\(bu\fR
+zip_compression_method_supported(3)
+.TP 4n
+\fB\(bu\fR
+zip_encryption_method_supported(3)
+.TP 4n
+\fB\(bu\fR
zip_file_get_comment(3)
.TP 4n
\fB\(bu\fR
@@ -249,10 +255,13 @@
.SS "miscellaneous (writing)"
.TP 4n
\fB\(bu\fR
-zip_libzip_version(3)
+zip_file_attributes_init(3)
.PD 0
.TP 4n
\fB\(bu\fR
+zip_libzip_version(3)
+.TP 4n
+\fB\(bu\fR
zip_register_progress_callback_with_state(3)
.TP 4n
\fB\(bu\fR
diff --git a/man/libzip.mdoc b/man/libzip.mdoc
index 70917db..ec2fd6c 100644
--- a/man/libzip.mdoc
+++ b/man/libzip.mdoc
@@ -29,7 +29,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd April 2, 2020
+.Dd April 17, 2020
.Dt LIBZIP 3
.Os
.Sh NAME
@@ -209,6 +209,8 @@
.Ss miscellaneous (writing)
.Bl -bullet -compact
.It
+.Xr zip_file_attributes_init 3
+.It
.Xr zip_libzip_version 3
.It
.Xr zip_register_progress_callback_with_state 3
diff --git a/man/zip_compression_method_supported.man b/man/zip_compression_method_supported.man
new file mode 100644
index 0000000..44811f2
--- /dev/null
+++ b/man/zip_compression_method_supported.man
@@ -0,0 +1,70 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\" zip_compression_method_supported.mdoc -- return if compression method is supported
+.\" Copyright (C) 2020 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP files.
+.\" 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.
+.\"
+.TH "ZIP_COMPRESSION_METHOD_SUPPORTED" "3" "April 2, 2020" "NiH" "Library Functions Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBzip_compression_method_supported\fR
+\- return if a compression method is supported
+.SH "LIBRARY"
+libzip (-lzip)
+.SH "SYNOPSIS"
+\fB#include <zip.h>\fR
+.sp
+\fIint\fR
+.br
+.PD 0
+.HP 4n
+\fBzip_compression_method_supported\fR(\fIzip_int32_t\ method\fR, \fIint\ compress\fR);
+.PD
+.SH "DESCRIPTION"
+The
+\fBzip_compression_method_supported\fR()
+returns if the compression method
+\fImethod\fR
+is supported for compression (if
+\fIcompress\fR
+is zero) or decompression (otherwise).
+.SH "RETURN VALUES"
+Returns 1 if the method is supported, 0 otherwise.
+.SH "SEE ALSO"
+libzip(3),
+zip_encryption_method_supported(3),
+zip_set_file_compression(3)
+.SH "HISTORY"
+\fBzip_compression_method_supported\fR()
+was added in libzip 1.7.0.
+.SH "AUTHORS"
+Dieter Baron <\fIdillo@nih.at\fR>
+and
+Thomas Klausner <\fItk@giga.or.at\fR>
diff --git a/man/zip_encryption_method_supported.man b/man/zip_encryption_method_supported.man
new file mode 100644
index 0000000..4ab4e3b
--- /dev/null
+++ b/man/zip_encryption_method_supported.man
@@ -0,0 +1,70 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\" zip_encryption_method_supported.mdoc -- return if encryption method is supported
+.\" Copyright (C) 2020 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP files.
+.\" 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.
+.\"
+.TH "ZIP_ENCRYPTION_METHOD_SUPPORTED" "3" "April 2, 2020" "NiH" "Library Functions Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBzip_encryption_method_supported\fR
+\- return if an encryption method is supported
+.SH "LIBRARY"
+libzip (-lzip)
+.SH "SYNOPSIS"
+\fB#include <zip.h>\fR
+.sp
+\fIint\fR
+.br
+.PD 0
+.HP 4n
+\fBzip_encryption_method_supported\fR(\fIzip_int16_t\ method\fR, \fIint\ encrypt\fR);
+.PD
+.SH "DESCRIPTION"
+The
+\fBzip_encryption_method_supported\fR()
+returns if the encryption method
+\fImethod\fR
+is supported for encryption (if
+\fIencrypt\fR
+is zero) or decryption (otherwise).
+.SH "RETURN VALUES"
+Returns 1 if the method is supported, 0 otherwise.
+.SH "SEE ALSO"
+libzip(3),
+zip_compression_method_supported(3),
+zip_file_set_encryption(3)
+.SH "HISTORY"
+\fBzip_encryption_method_supported\fR()
+was added in libzip 1.7.0.
+.SH "AUTHORS"
+Dieter Baron <\fIdillo@nih.at\fR>
+and
+Thomas Klausner <\fItk@giga.or.at\fR>
diff --git a/man/zip_error_set.man b/man/zip_error_set.man
index 250b97f..9bc4cb8 100644
--- a/man/zip_error_set.man
+++ b/man/zip_error_set.man
@@ -30,7 +30,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "ZIP_ERROR_SET" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_ERROR_SET" "3" "April 2, 2020" "NiH" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -59,7 +59,7 @@
.PP
\fIze\fR
must be allocated and initialized with
-zip_error_fini(3)
+zip_error_init(3)
before calling
\fBzip_error\fR(\fIset\fR).
.SH "SEE ALSO"
diff --git a/man/zip_file_attributes_init.man b/man/zip_file_attributes_init.man
new file mode 100644
index 0000000..20036c9
--- /dev/null
+++ b/man/zip_file_attributes_init.man
@@ -0,0 +1,66 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\" zip_file_attributes_init.mdoc -- initialize attributes structure
+.\" Copyright (C) 2020 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP files.
+.\" 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.
+.\"
+.TH "ZIP_FILE_ATTRIBUTES_INIT" "" "April 17, 2020" "NiH" "LOCAL"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBzip_file_attributes_init\fR
+\- initialize zip file attributes structure
+.SH "LIBRARY"
+libzip (-lzip)
+.SH "SYNOPSIS"
+\fB#include <zip.h>\fR
+.sp
+\fIvoid\fR
+.br
+.PD 0
+.HP 4n
+\fBzip_file_attributes_init\fR(\fIzip_file_attributes_t\ *attributes\fR);
+.PD
+.SH "DESCRIPTION"
+The
+\fBzip_file_attributes_init\fR()
+initializes a
+\fIzip_file_attributes_t\fR
+structure with default values.
+It must be called before modifying such a structure for the first time.
+.SH "SEE ALSO"
+libzip(3),
+zip_source_function(3)
+.SH "HISTORY"
+\fBzip_file_attributes_init\fR()
+was added in libzip 1.7.0.
+.SH "AUTHORS"
+Dieter Baron <\fIdillo@nih.at\fR>
+and
+Thomas Klausner <\fItk@giga.or.at\fR>
diff --git a/man/zip_file_attributes_init.mdoc b/man/zip_file_attributes_init.mdoc
new file mode 100644
index 0000000..93d2981
--- /dev/null
+++ b/man/zip_file_attributes_init.mdoc
@@ -0,0 +1,61 @@
+.\" zip_file_attributes_init.mdoc -- initialize attributes structure
+.\" Copyright (C) 2020 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP files.
+.\" 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.
+.\"
+.Dd April 17, 2020
+.Dt ZIP_FILE_ATTRIBUTES_INIT
+.Os
+.Sh NAME
+.Nm zip_file_attributes_init
+.Nd initialize zip file attributes structure
+.Sh LIBRARY
+libzip (-lzip)
+.Sh SYNOPSIS
+.In zip.h
+.Ft void
+.Fn zip_file_attributes_init "zip_file_attributes_t *attributes"
+.Sh DESCRIPTION
+The
+.Fn zip_file_attributes_init
+initializes a
+.Vt zip_file_attributes_t
+structure with default values.
+It must be called before modifying such a structure for the first time.
+.Sh SEE ALSO
+.Xr libzip 3 ,
+.Xr zip_source_function 3
+.Sh HISTORY
+.Fn zip_file_attributes_init
+was added in libzip 1.7.0.
+.Sh AUTHORS
+.An -nosplit
+.An Dieter Baron Aq Mt dillo@nih.at
+and
+.An Thomas Klausner Aq Mt tk@giga.or.at
diff --git a/man/zip_file_set_encryption.man b/man/zip_file_set_encryption.man
index d82e28e..da983f9 100644
--- a/man/zip_file_set_encryption.man
+++ b/man/zip_file_set_encryption.man
@@ -30,7 +30,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "ZIP_FILE_SET_ENCRYPTION" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_FILE_SET_ENCRYPTION" "3" "April 2, 2020" "NiH" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -75,6 +75,12 @@
.TP 19n
\fRZIP_EM_AES_256\fR
Winzip AES-256 encryption.
+.TP 19n
+\fRZIP_EM_TRAD_PKWARE\fR
+.br
+Traditional PKWare encryption.
+Do not use this method, it is not secure.
+It is only provided for backwards compatibility.
.PP
If
\fIpassword\fR
@@ -112,6 +118,9 @@
Read-only zip file, no changes allowed.
.SH "SEE ALSO"
libzip(3),
+zip_encryption_method_supported(3),
+zip_fopen_encrypted(3),
+zip_fopen_index_encrypted(3),
zip_set_default_password(3),
zip_stat(3)
.SH "HISTORY"
diff --git a/man/zip_set_file_compression.man b/man/zip_set_file_compression.man
index 759309b..15bacde 100644
--- a/man/zip_set_file_compression.man
+++ b/man/zip_set_file_compression.man
@@ -30,7 +30,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "ZIP_SET_FILE_COMPRESSION" "3" "December 18, 2017" "NiH" "Library Functions Manual"
+.TH "ZIP_SET_FILE_COMPRESSION" "3" "April 2, 2020" "NiH" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -121,6 +121,7 @@
Read-only zip file, no changes allowed.
.SH "SEE ALSO"
libzip(3),
+zip_compression_method_supported(3),
zip_stat(3)
.SH "HISTORY"
\fBzip_set_file_compression\fR()
diff --git a/man/zip_source_function.man b/man/zip_source_function.man
index 4901694..4d43f99 100644
--- a/man/zip_source_function.man
+++ b/man/zip_source_function.man
@@ -30,7 +30,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.TH "ZIP_SOURCE_FUNCTION" "3" "September 17, 2019" "NiH" "Library Functions Manual"
+.TH "ZIP_SOURCE_FUNCTION" "3" "April 17, 2020" "NiH" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -163,6 +163,65 @@
Clean up and free all resources, including
\fIuserdata\fR.
The callback function will not be called again.
+.SS "\fRZIP_SOURCE_GET_FILE_ATTRIBUTES\fR"
+Provide information about various data.
+Then the data should be put in the appropriate entry in the passed
+\fIzip_file_attributes_t\fR
+argument, and the appropriate
+\fRZIP_FILE_ATTRIBUTES_*\fR
+value must be or'ed into the
+\fIvalid\fR
+member to denote that the corresponding data has been provided.
+A
+\fIzip_file_attributes_t\fR
+structure can be initialized using
+zip_file_attributes_init(3).
+.TP 12n
+ASCII mode
+If a file is a plaintext file in ASCII.
+Can be used by extraction tools to automatically convert line endings
+(part of the interal file attributes).
+Member
+\fIascii\fR,
+flag
+\fRZIP_FILE_ATTRIBUTES_ASCII\fR.
+.TP 12n
+General Purpose Bit Flags (limited to Compression Flags)
+The general purpose bit flag in the zip in the local and central
+directory headers contain information about the compression method.
+Member
+\fIgeneral_purpose_bit_flags\fR
+and
+\fIgeneral_purpose_bit_mask\fR
+to denote which members have been set;
+flag
+\fRZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS\fR.
+.TP 12n
+External File Attributes
+The external file attributes (usually operating system-specific).
+Member
+\fIexternal_file_attributes\fR,
+flag
+\fRZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES\fR.
+.TP 12n
+Version Needed
+A minimum version needed required to unpack this entry (in the usual
+"major * 10 + minor" format).
+Member
+\fIversion_needed\fR,
+flag
+\fRZIP_FILE_ATTRIBUTES_VERSION_NEEDED\fR.
+.TP 12n
+Operating System
+One of the operating systems as defined by the
+\fRZIP_OPSYS_*\fR
+variables (see
+\fIzip.h\fR).
+This value affects the interpretation of the external file attributes.
+Member
+\fIhost_system\fR,
+flag
+\fRZIP_FILE_ATTRIBUTES_HOST_SYSTEM\fR.
.SS "\fRZIP_SOURCE_OPEN\fR"
Prepare for reading.
.SS "\fRZIP_SOURCE_READ\fR"
@@ -293,6 +352,9 @@
\fRZIP_SOURCE_ROLLBACK_WRITE\fR
will be called.
.PP
+\fRZIP_SOURCE_ACCEPT_EMPTY\fR,
+\fRZIP_SOURCE_GET_FILE_ATTRIBUTES\fR,
+and
\fRZIP_SOURCE_STAT\fR
can be issued at any time.
.PP
@@ -336,6 +398,7 @@
.SH "SEE ALSO"
libzip(3),
zip_file_add(3),
+zip_file_attributes_init(3),
zip_file_replace(3),
zip_source(3),
zip_stat_init(3)
diff --git a/man/zip_source_function.mdoc b/man/zip_source_function.mdoc
index 9a9cc4b..aeb31f5 100644
--- a/man/zip_source_function.mdoc
+++ b/man/zip_source_function.mdoc
@@ -29,7 +29,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd September 17, 2019
+.Dd April 17, 2020
.Dt ZIP_SOURCE_FUNCTION 3
.Os
.Sh NAME
@@ -153,6 +153,62 @@
Clean up and free all resources, including
.Ar userdata .
The callback function will not be called again.
+.Ss Dv ZIP_SOURCE_GET_FILE_ATTRIBUTES
+Provide information about various data.
+Then the data should be put in the appropriate entry in the passed
+.Vt zip_file_attributes_t
+argument, and the appropriate
+.Dv ZIP_FILE_ATTRIBUTES_*
+value must be or'ed into the
+.Ar valid
+member to denote that the corresponding data has been provided.
+A
+.Vt zip_file_attributes_t
+structure can be initialized using
+.Xr zip_file_attributes_init 3 .
+.Bl -tag -width 10n
+.It ASCII mode
+If a file is a plaintext file in ASCII.
+Can be used by extraction tools to automatically convert line endings
+(part of the interal file attributes).
+Member
+.Ar ascii ,
+flag
+.Dv ZIP_FILE_ATTRIBUTES_ASCII .
+.It General Purpose Bit Flags (limited to Compression Flags)
+The general purpose bit flag in the zip in the local and central
+directory headers contain information about the compression method.
+Member
+.Ar general_purpose_bit_flags
+and
+.Ar general_purpose_bit_mask
+to denote which members have been set;
+flag
+.Dv ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS .
+.It External File Attributes
+The external file attributes (usually operating system-specific).
+Member
+.Ar external_file_attributes ,
+flag
+.Dv ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES .
+.It Version Needed
+A minimum version needed required to unpack this entry (in the usual
+"major * 10 + minor" format).
+Member
+.Ar version_needed ,
+flag
+.Dv ZIP_FILE_ATTRIBUTES_VERSION_NEEDED .
+.It Operating System
+One of the operating systems as defined by the
+.Dv ZIP_OPSYS_*
+variables (see
+.Pa zip.h ) .
+This value affects the interpretation of the external file attributes.
+Member
+.Ar host_system ,
+flag
+.Dv ZIP_FILE_ATTRIBUTES_HOST_SYSTEM .
+.El
.Ss Dv ZIP_SOURCE_OPEN
Prepare for reading.
.Ss Dv ZIP_SOURCE_READ
@@ -280,6 +336,9 @@
.Dv ZIP_SOURCE_ROLLBACK_WRITE
will be called.
.Pp
+.Dv ZIP_SOURCE_ACCEPT_EMPTY ,
+.Dv ZIP_SOURCE_GET_FILE_ATTRIBUTES ,
+and
.Dv ZIP_SOURCE_STAT
can be issued at any time.
.Pp
@@ -324,6 +383,7 @@
.Sh SEE ALSO
.Xr libzip 3 ,
.Xr zip_file_add 3 ,
+.Xr zip_file_attributes_init 3 ,
.Xr zip_file_replace 3 ,
.Xr zip_source 3 ,
.Xr zip_stat_init 3
diff --git a/regress/encrypt-aes128-noentropy.zip b/regress/encrypt-aes128-noentropy.zip
index 333f031..01d5bc6 100644
--- a/regress/encrypt-aes128-noentropy.zip
+++ b/regress/encrypt-aes128-noentropy.zip
Binary files differ
diff --git a/regress/encrypt-aes192-noentropy.zip b/regress/encrypt-aes192-noentropy.zip
index 6ada818..0a9ad4b 100644
--- a/regress/encrypt-aes192-noentropy.zip
+++ b/regress/encrypt-aes192-noentropy.zip
Binary files differ
diff --git a/regress/encrypt-aes256-noentropy.zip b/regress/encrypt-aes256-noentropy.zip
index ff3be84..b3a6cad 100644
--- a/regress/encrypt-aes256-noentropy.zip
+++ b/regress/encrypt-aes256-noentropy.zip
Binary files differ
diff --git a/regress/encrypt-none.zip b/regress/encrypt-none.zip
index 0a2f770..c7ba696 100644
--- a/regress/encrypt-none.zip
+++ b/regress/encrypt-none.zip
Binary files differ
diff --git a/regress/encrypt-pkware-noentropy.zip b/regress/encrypt-pkware-noentropy.zip
index ee0833d..e0c39a7 100644
--- a/regress/encrypt-pkware-noentropy.zip
+++ b/regress/encrypt-pkware-noentropy.zip
Binary files differ