Add API for getting/setting extra field data. Doesn't parse the fields yet, just provides them to the library user. Open points: * cdir extra field entries are not changed * heuristics for finding cdir should be adapted Based on patch provided by Jono Spiro <jono.spiro@gmail.com> (with minimal changes). --HG-- branch : HEAD
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 29ba802..4d80b1e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt
@@ -85,6 +85,7 @@ zip_get_compression_implementation.c zip_get_encryption_implementation.c zip_get_file_comment.c + zip_get_file_extra.c zip_get_name.c zip_get_num_files.c zip_memdup.c @@ -97,6 +98,7 @@ zip_set_archive_flag.c zip_set_default_password.c zip_set_file_comment.c + zip_set_file_extra.c zip_set_name.c zip_source_buffer.c zip_source_close.c
diff --git a/lib/Makefile.am b/lib/Makefile.am index 6faf4a1..b12e83c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am
@@ -42,6 +42,7 @@ zip_get_compression_implementation.c \ zip_get_encryption_implementation.c \ zip_get_file_comment.c \ + zip_get_file_extra.c \ zip_get_num_files.c \ zip_get_name.c \ zip_memdup.c \ @@ -54,6 +55,7 @@ zip_set_archive_flag.c \ zip_set_default_password.c \ zip_set_file_comment.c \ + zip_set_file_extra.c \ zip_source_buffer.c \ zip_source_close.c \ zip_source_crc.c \
diff --git a/lib/zip.h b/lib/zip.h index 94ee69b..261e550 100644 --- a/lib/zip.h +++ b/lib/zip.h
@@ -230,6 +230,8 @@ 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 char *zip_get_file_extra(struct zip *, zip_uint64_t, + int *, int); ZIP_EXTERN const char *zip_get_name(struct zip *, zip_uint64_t, int); ZIP_EXTERN int zip_get_num_files(struct zip *); ZIP_EXTERN int zip_name_locate(struct zip *, const char *, int); @@ -241,6 +243,8 @@ 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_extra(struct zip *, zip_uint64_t, + const char *, int); 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 *,
diff --git a/lib/zip_close.c b/lib/zip_close.c index ded5345..6b7f8d2 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c
@@ -217,6 +217,22 @@ cd->entry[j].filename_len = de.filename_len; } + if (za->entry[i].ch_extra_len != -1) { + free(de.extrafield); + if ((de.extrafield=malloc(za->entry[i].ch_extra_len)) == NULL) { + error = 1; + break; + } + memcpy(de.extrafield, za->entry[i].ch_extra, za->entry[i].ch_extra_len); + de.extrafield_len = za->entry[i].ch_extra_len; + /* as the rest of cd entries, its malloc/free is done by za */ + /* TODO unsure if this should also be set in the CD -- + * not done for now + cd->entry[j].extrafield = za->entry[i].ch_extra; + cd->entry[j].extrafield_len = za->entry[i].ch_extra_len; + */ + } + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0 && za->entry[i].ch_comment_len != -1) { /* as the rest of cd entries, its malloc/free is done by za */ @@ -557,6 +573,7 @@ for (i=0; i<za->nentry; i++) { if ((za->entry[i].state != ZIP_ST_UNCHANGED) + || (za->entry[i].ch_extra_len != -1) || (za->entry[i].ch_comment_len != -1)) changed = 1; if (za->entry[i].state != ZIP_ST_DELETED)
diff --git a/lib/zip_entry_free.c b/lib/zip_entry_free.c index c50c943..e8a7770 100644 --- a/lib/zip_entry_free.c +++ b/lib/zip_entry_free.c
@@ -44,6 +44,9 @@ { free(ze->ch_filename); ze->ch_filename = NULL; + free(ze->ch_extra); + ze->ch_extra = NULL; + ze->ch_extra_len = -1; free(ze->ch_comment); ze->ch_comment = NULL; ze->ch_comment_len = -1;
diff --git a/lib/zip_entry_new.c b/lib/zip_entry_new.c index a22dd40..26d5c6a 100644 --- a/lib/zip_entry_new.c +++ b/lib/zip_entry_new.c
@@ -67,6 +67,8 @@ ze->state = ZIP_ST_UNCHANGED; ze->ch_filename = NULL; + ze->ch_extra = NULL; + ze->ch_extra_len = -1; ze->ch_comment = NULL; ze->ch_comment_len = -1; ze->source = NULL;
diff --git a/lib/zip_get_file_extra.c b/lib/zip_get_file_extra.c new file mode 100644 index 0000000..afa507b --- /dev/null +++ b/lib/zip_get_file_extra.c
@@ -0,0 +1,58 @@ +/* + zip_get_file_extra.c -- get file extra field + Copyright (C) 2006-2010 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_get_file_extra(struct zip *za, zip_uint64_t idx, int *lenp, int flags) +{ + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) + || (za->entry[idx].ch_extra_len == -1)) { + if (lenp != NULL) + *lenp = za->cdir->entry[idx].extrafield_len; + return za->cdir->entry[idx].extrafield; + } + + if (lenp != NULL) + *lenp = za->entry[idx].ch_extra_len; + return za->entry[idx].ch_extra; +}
diff --git a/lib/zip_set_file_extra.c b/lib/zip_set_file_extra.c new file mode 100644 index 0000000..9b80bde --- /dev/null +++ b/lib/zip_set_file_extra.c
@@ -0,0 +1,72 @@ +/* + zip_set_file_extra.c -- set extra field for file in archive + Copyright (C) 2006-2010 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 "zipint.h" + + + +ZIP_EXTERN int +zip_set_file_extra(struct zip *za, zip_uint64_t idx, + const char *extra, int len) +{ + char *tmpext; + + if (idx >= za->nentry + || len < 0 || len > MAXEXTLEN + || (len > 0 && extra == NULL)) { + _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 (len > 0) { + if ((tmpext=(char *)_zip_memdup(extra, len, &za->error)) == NULL) + return -1; + } + else + tmpext = NULL; + + free(za->entry[idx].ch_extra); + za->entry[idx].ch_extra = tmpext; + za->entry[idx].ch_extra_len = len; + + return 0; +}
diff --git a/lib/zip_unchange.c b/lib/zip_unchange.c index 58ec54b..e64186e 100644 --- a/lib/zip_unchange.c +++ b/lib/zip_unchange.c
@@ -72,6 +72,9 @@ za->entry[idx].ch_filename = NULL; } + free(za->entry[idx].ch_extra); + za->entry[idx].ch_extra = NULL; + za->entry[idx].ch_extra_len = -1; free(za->entry[idx].ch_comment); za->entry[idx].ch_comment = NULL; za->entry[idx].ch_comment_len = -1;
diff --git a/lib/zipint.h b/lib/zipint.h index 57304d2..e105461 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -103,6 +103,7 @@ #define CDENTRYSIZE 46u #define LENTRYSIZE 30 #define MAXCOMLEN 65536 +#define MAXEXTLEN 65536 #define EOCDLEN 22 #define CDBUFSIZE (MAXCOMLEN+EOCDLEN) #define BUFSIZE 8192 @@ -275,6 +276,8 @@ enum zip_state state; struct zip_source *source; char *ch_filename; + char *ch_extra; + int ch_extra_len; char *ch_comment; int ch_comment_len; };