summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Joye <pajoye@php.net>2008-08-07 23:24:11 +0000
committerPierre Joye <pajoye@php.net>2008-08-07 23:24:11 +0000
commit490a34220583be5eee4ad2e8be56e9e285ec0e74 (patch)
tree8b67a365ee193b545a0c067c23c478e8d5fcbe06
parentc94f8b4a1cb303bebc22ca83d09a05064877bf4b (diff)
downloadphp-git-490a34220583be5eee4ad2e8be56e9e285ec0e74.tar.gz
- MFH: update to 0.9 (torrentzip support, files open only when necessary), windows fixes
-rw-r--r--ext/zip/config.w323
-rw-r--r--ext/zip/lib/zip.h3
-rw-r--r--ext/zip/lib/zip_close.c188
-rw-r--r--ext/zip/lib/zip_dirent.c59
-rw-r--r--ext/zip/lib/zip_err_str.c4
-rw-r--r--ext/zip/lib/zip_filerange_crc.c71
-rw-r--r--ext/zip/lib/zip_get_archive_flag.c48
-rw-r--r--ext/zip/lib/zip_open.c23
-rw-r--r--ext/zip/lib/zip_rename.c20
-rw-r--r--ext/zip/lib/zip_set_archive_flag.c49
-rw-r--r--ext/zip/lib/zip_source_file.c17
-rw-r--r--ext/zip/lib/zip_source_filep.c53
-rw-r--r--ext/zip/lib/zip_source_zip.c4
-rw-r--r--ext/zip/lib/zip_unchange_archive.c6
-rw-r--r--ext/zip/lib/zipint.h9
15 files changed, 475 insertions, 82 deletions
diff --git a/ext/zip/config.w32 b/ext/zip/config.w32
index c207cd301b..e60a983b3a 100644
--- a/ext/zip/config.w32
+++ b/ext/zip/config.w32
@@ -17,7 +17,8 @@ if (PHP_ZIP != "no") {
zip_error_get_sys_type.c zip_file_get_offset.c \
zip_get_name.c zip_replace.c zip_source_function.c \
zip_unchange.c zip_dirent.c zip_error_strerror.c \
- zip_file_strerror.c zip_get_num_files.c \
+ zip_filerange_crc.c zip_file_strerror.c zip_get_num_files.c \
+ zip_get_archive_flag.c zip_set_archive_flag.c \
zip_set_name.c zip_source_zip.c zip_unchange_data.c \
zip_entry_free.c zip_error_to_str.c zip_fopen.c \
zip_name_locate.c zip_source_buffer.c zip_stat.c \
diff --git a/ext/zip/lib/zip.h b/ext/zip/lib/zip.h
index 5c8460bf27..ecdb0f2d8e 100644
--- a/ext/zip/lib/zip.h
+++ b/ext/zip/lib/zip.h
@@ -70,6 +70,7 @@ BEGIN_EXTERN_C()
#define ZIP_FL_NODIR 2 /* ignore directory component */
#define ZIP_FL_COMPRESSED 4 /* read compressed data */
#define ZIP_FL_UNCHANGED 8 /* use original data, ignoring changes */
+#define ZIP_FL_RECOMPRESS 16 /* force recompression of data */
/* archive global flags flags */
@@ -161,8 +162,6 @@ enum zip_source_cmd {
ZIP_SOURCE_FREE /* cleanup and free resources */
};
-
-
typedef ssize_t (*zip_source_callback)(void *state, void *data,
size_t len, enum zip_source_cmd cmd);
diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c
index 49ab4c840b..7c2f875012 100644
--- a/ext/zip/lib/zip_close.c
+++ b/ext/zip/lib/zip_close.c
@@ -42,16 +42,26 @@
#include "zipint.h"
-static int add_data(struct zip *, int, struct zip_dirent *, FILE *);
+static int add_data(struct zip *, struct zip_source *, struct zip_dirent *,
+ FILE *);
static int add_data_comp(zip_source_callback, void *, struct zip_stat *,
FILE *, struct zip_error *);
-static int add_data_uncomp(zip_source_callback, void *, struct zip_stat *,
- FILE *, struct zip_error *);
+static int add_data_uncomp(struct zip *, zip_source_callback, void *,
+ struct zip_stat *, FILE *);
static void ch_set_error(struct zip_error *, zip_source_callback, void *);
static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
+static int write_cdir(struct zip *, struct zip_cdir *, FILE *);
static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
static int _zip_changed(struct zip *, int *);
static char *_zip_create_temp_output(struct zip *, FILE **);
+static int _zip_torrentzip_cmp(const void *, const void *);
+
+
+
+struct filelist {
+ int idx;
+ const char *name;
+};
@@ -65,7 +75,9 @@ zip_close(struct zip *za)
mode_t mask;
struct zip_cdir *cd;
struct zip_dirent de;
+ struct filelist *filelist;
int reopen_on_error;
+ int new_torrentzip;
reopen_on_error = 0;
@@ -79,7 +91,7 @@ zip_close(struct zip *za)
/* don't create zip files with no entries */
if (survivors == 0) {
- if (za->zn) {
+ if (za->zn && za->zp) {
if (remove(za->zn) != 0) {
_zip_error_set(&za->error, ZIP_ER_REMOVE, errno);
return -1;
@@ -89,45 +101,85 @@ zip_close(struct zip *za)
return 0;
}
- if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL)
+ if ((filelist=(struct filelist *)malloc(sizeof(filelist[0])*survivors))
+ == NULL)
return -1;
+ if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL) {
+ free(filelist);
+ return -1;
+ }
+
for (i=0; i<survivors; i++)
_zip_dirent_init(&cd->entry[i]);
+ /* archive comment is special for torrentzip */
+ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) {
+ cd->comment = _zip_memdup(TORRENT_SIG "XXXXXXXX",
+ TORRENT_SIG_LEN + TORRENT_CRC_LEN,
+ &za->error);
+ if (cd->comment == NULL) {
+ _zip_cdir_free(cd);
+ free(filelist);
+ return -1;
+ }
+ cd->comment_len = TORRENT_SIG_LEN + TORRENT_CRC_LEN;
+ }
+ else if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, ZIP_FL_UNCHANGED) == 0) {
if (_zip_cdir_set_comment(cd, za) == -1) {
_zip_cdir_free(cd);
+ free(filelist);
return -1;
}
+ }
if ((temp=_zip_create_temp_output(za, &out)) == NULL) {
_zip_cdir_free(cd);
return -1;
}
- error = 0;
+
+ /* create list of files with index into original archive */
for (i=j=0; i<za->nentry; i++) {
if (za->entry[i].state == ZIP_ST_DELETED)
continue;
+ filelist[j].idx = i;
+ filelist[j].name = zip_get_name(za, i, 0);
+ j++;
+ }
+ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
+ qsort(filelist, survivors, sizeof(filelist[0]),
+ _zip_torrentzip_cmp);
+
+ new_torrentzip = (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 1
+ && zip_get_archive_flag(za, ZIP_AFL_TORRENT,
+ ZIP_FL_UNCHANGED) == 0);
+ error = 0;
+ for (j=0; j<survivors; j++) {
+ i = filelist[j].idx;
+
/* create new local directory entry */
- if (ZIP_ENTRY_DATA_CHANGED(za->entry+i)) {
+ if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {
_zip_dirent_init(&de);
+
+ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
+ _zip_dirent_torrent_normalize(&de);
+
/* use it as central directory entry */
memcpy(cd->entry+j, &de, sizeof(cd->entry[j]));
/* set/update file name */
if (za->entry[i].ch_filename == NULL) {
- if (za->entry[i].state == ZIP_ST_REPLACED) {
- de.filename = strdup(za->cdir->entry[i].filename);
- de.filename_len = strlen(de.filename);
- cd->entry[j].filename = za->cdir->entry[i].filename;
- cd->entry[j].filename_len = de.filename_len;
- }
- else {
+ if (za->entry[i].state == ZIP_ST_ADDED) {
de.filename = strdup("-");
de.filename_len = 1;
cd->entry[j].filename = "-";
+ }
+ else {
+ de.filename = strdup(za->cdir->entry[i].filename);
+ de.filename_len = strlen(de.filename);
+ cd->entry[j].filename = za->cdir->entry[i].filename;
cd->entry[j].filename_len = de.filename_len;
}
}
@@ -147,7 +199,7 @@ zip_close(struct zip *za)
de.crc = za->cdir->entry[i].crc;
de.comp_size = za->cdir->entry[i].comp_size;
de.uncomp_size = za->cdir->entry[i].uncomp_size;
- /* de.bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; */
+ de.bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
}
memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j]));
}
@@ -163,7 +215,8 @@ zip_close(struct zip *za)
cd->entry[j].filename_len = de.filename_len;
}
- if (za->entry[i].ch_comment_len != -1) {
+ 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 */
cd->entry[j].comment = za->entry[i].ch_comment;
cd->entry[j].comment_len = za->entry[i].ch_comment_len;
@@ -171,8 +224,19 @@ zip_close(struct zip *za)
cd->entry[j].offset = ftello(out);
- if (ZIP_ENTRY_DATA_CHANGED(za->entry+i)) {
- if (add_data(za, i, &de, out) < 0) {
+ if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {
+ struct zip_source *zs;
+
+ zs = NULL;
+ if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) {
+ if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1))
+ == NULL) {
+ error = 1;
+ break;
+ }
+ }
+
+ if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) {
error = 1;
break;
}
@@ -195,13 +259,11 @@ zip_close(struct zip *za)
}
}
- j++;
-
_zip_dirent_finalize(&de);
}
if (!error) {
- if (_zip_cdir_write(cd, out, &za->error) < 0)
+ if (write_cdir(za, cd, out) < 0)
error = 1;
}
@@ -252,15 +314,15 @@ zip_close(struct zip *za)
static int
-add_data(struct zip *za, int idx, struct zip_dirent *de, FILE *ft)
+add_data(struct zip *za, struct zip_source *zs, struct zip_dirent *de, FILE *ft)
{
off_t offstart, offend;
zip_source_callback cb;
void *ud;
struct zip_stat st;
- cb = za->entry[idx].source->f;
- ud = za->entry[idx].source->ud;
+ cb = zs->f;
+ ud = zs->ud;
if (cb(ud, &st, sizeof(st), ZIP_SOURCE_STAT) < (ssize_t)sizeof(st)) {
ch_set_error(&za->error, cb, ud);
@@ -282,7 +344,7 @@ add_data(struct zip *za, int idx, struct zip_dirent *de, FILE *ft)
return -1;
}
else {
- if (add_data_uncomp(cb, ud, &st, ft, &za->error) < 0)
+ if (add_data_uncomp(za, cb, ud, &st, ft) < 0)
return -1;
}
@@ -298,12 +360,16 @@ add_data(struct zip *za, int idx, struct zip_dirent *de, FILE *ft)
return -1;
}
- de->comp_method = st.comp_method;
+
de->last_mod = st.mtime;
+ de->comp_method = st.comp_method;
de->crc = st.crc;
de->uncomp_size = st.size;
de->comp_size = st.comp_size;
+ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
+ _zip_dirent_torrent_normalize(de);
+
if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
return -1;
@@ -344,14 +410,15 @@ add_data_comp(zip_source_callback cb, void *ud, struct zip_stat *st,FILE *ft,
static int
-add_data_uncomp(zip_source_callback cb, void *ud, struct zip_stat *st,
- FILE *ft, struct zip_error *error)
+add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud,
+ struct zip_stat *st, FILE *ft)
{
char b1[BUFSIZE], b2[BUFSIZE];
int end, flush, ret;
ssize_t n;
size_t n2;
z_stream zstr;
+ int mem_level;
st->comp_method = ZIP_CM_DEFLATE;
st->comp_size = st->size = 0;
@@ -363,8 +430,13 @@ add_data_uncomp(zip_source_callback cb, void *ud, struct zip_stat *st,
zstr.avail_in = 0;
zstr.avail_out = 0;
- /* -15: undocumented feature of zlib to _not_ write a zlib header */
- deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 9,
+ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
+ mem_level = TORRENT_MEM_LEVEL;
+ else
+ mem_level = MAX_MEM_LEVEL;
+
+ /* -MAX_WBITS: undocumented feature of zlib to _not_ write a zlib header */
+ deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, mem_level,
Z_DEFAULT_STRATEGY);
zstr.next_out = (Bytef *)b2;
@@ -376,7 +448,7 @@ add_data_uncomp(zip_source_callback cb, void *ud, struct zip_stat *st,
while (!end) {
if (zstr.avail_in == 0 && !flush) {
if ((n=cb(ud, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) {
- ch_set_error(error, cb, ud);
+ ch_set_error(&za->error, cb, ud);
deflateEnd(&zstr);
return -1;
}
@@ -392,7 +464,7 @@ add_data_uncomp(zip_source_callback cb, void *ud, struct zip_stat *st,
ret = deflate(&zstr, flush);
if (ret != Z_OK && ret != Z_STREAM_END) {
- _zip_error_set(error, ZIP_ER_ZLIB, ret);
+ _zip_error_set(&za->error, ZIP_ER_ZLIB, ret);
return -1;
}
@@ -400,7 +472,7 @@ add_data_uncomp(zip_source_callback cb, void *ud, struct zip_stat *st,
n2 = sizeof(b2) - zstr.avail_out;
if (fwrite(b2, 1, n2, ft) != n2) {
- _zip_error_set(error, ZIP_ER_WRITE, errno);
+ _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
return -1;
}
@@ -471,6 +543,44 @@ copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error)
static int
+write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out)
+{
+ off_t offset;
+ uLong crc;
+ char buf[TORRENT_CRC_LEN+1];
+
+ if (_zip_cdir_write(cd, out, &za->error) < 0)
+ return -1;
+
+ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0)
+ return 0;
+
+
+ /* fix up torrentzip comment */
+
+ offset = ftello(out);
+
+ if (_zip_filerange_crc(out, cd->offset, cd->size, &crc, &za->error) < 0)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "%08lX", (long)crc);
+
+ if (fseeko(out, offset-TORRENT_CRC_LEN, SEEK_SET) < 0) {
+ _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
+ return -1;
+ }
+
+ if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) {
+ _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static int
_zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src)
{
if (src->ch_comment_len != -1) {
@@ -501,7 +611,8 @@ _zip_changed(struct zip *za, int *survivorsp)
changed = survivors = 0;
- if (za->ch_comment_len != -1)
+ if (za->ch_comment_len != -1
+ || za->ch_flags != za->flags)
changed = 1;
for (i=0; i<za->nentry; i++) {
@@ -550,3 +661,12 @@ _zip_create_temp_output(struct zip *za, FILE **outp)
*outp = tfp;
return temp;
}
+
+
+
+static int
+_zip_torrentzip_cmp(const void *a, const void *b)
+{
+ return strcasecmp(((const struct filelist *)a)->name,
+ ((const struct filelist *)b)->name);
+}
diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c
index 7b953596ad..1b2db34dec 100644
--- a/ext/zip/lib/zip_dirent.c
+++ b/ext/zip/lib/zip_dirent.c
@@ -1,6 +1,6 @@
/*
zip_dirent.c -- read directory entry (local or central), clean dirent
- Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2008 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>
@@ -318,6 +318,63 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
+/* _zip_dirent_torrent_normalize(de);
+ Set values suitable for torrentzip.
+*/
+
+void
+_zip_dirent_torrent_normalize(struct zip_dirent *de)
+{
+ static struct tm torrenttime;
+ static time_t last_mod = 0;
+
+ if (last_mod == 0) {
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ time_t now;
+ struct tm *l;
+#endif
+
+ torrenttime.tm_sec = 0;
+ torrenttime.tm_min = 32;
+ torrenttime.tm_hour = 23;
+ torrenttime.tm_mday = 24;
+ torrenttime.tm_mon = 11;
+ torrenttime.tm_year = 96;
+ torrenttime.tm_wday = 0;
+ torrenttime.tm_yday = 0;
+ torrenttime.tm_isdst = 0;
+
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ time(&now);
+ l = localtime(&now);
+ torrenttime.tm_gmtoff = l->tm_gmtoff;
+ torrenttime.tm_zone = l->tm_zone;
+#endif
+
+ last_mod = mktime(&torrenttime);
+ }
+
+ de->version_madeby = 0;
+ de->version_needed = 20; /* 2.0 */
+ de->bitflags = 2; /* maximum compression */
+ de->comp_method = ZIP_CM_DEFLATE;
+ de->last_mod = last_mod;
+
+ de->disk_number = 0;
+ de->int_attrib = 0;
+ de->ext_attrib = 0;
+ de->offset = 0;
+
+ free(de->extrafield);
+ de->extrafield = NULL;
+ de->extrafield_len = 0;
+ free(de->comment);
+ de->comment = NULL;
+ de->comment_len = 0;
+}
+
+
+
/* _zip_dirent_write(zde, fp, localp, error):
Writes zip directory entry zde to file fp.
diff --git a/ext/zip/lib/zip_err_str.c b/ext/zip/lib/zip_err_str.c
index ce1652a701..3fcdf1738a 100644
--- a/ext/zip/lib/zip_err_str.c
+++ b/ext/zip/lib/zip_err_str.c
@@ -1,6 +1,6 @@
/*
- This file was generated automatically by make_zip_err_str.sh
- from zip.h; make changes there.
+ This file was generated automatically by ./make_zip_err_str.sh
+ from ./zip.h; make changes there.
*/
#include "zipint.h"
diff --git a/ext/zip/lib/zip_filerange_crc.c b/ext/zip/lib/zip_filerange_crc.c
new file mode 100644
index 0000000000..4d1ad56692
--- /dev/null
+++ b/ext/zip/lib/zip_filerange_crc.c
@@ -0,0 +1,71 @@
+/*
+ zip_filerange_crc.c -- compute CRC32 for a range of a file
+ Copyright (C) 2008 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 <stdio.h>
+#include <errno.h>
+
+#include "zipint.h"
+
+
+
+
+int
+_zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp,
+ struct zip_error *errp)
+{
+ Bytef buf[BUFSIZE];
+ size_t n;
+
+ *crcp = crc32(0L, Z_NULL, 0);
+
+ if (fseeko(fp, start, SEEK_SET) != 0) {
+ _zip_error_set(errp, ZIP_ER_SEEK, errno);
+ return -1;
+ }
+
+ while (len > 0) {
+ n = len > BUFSIZE ? BUFSIZE : len;
+ if ((n=fread(buf, 1, n, fp)) <= 0) {
+ _zip_error_set(errp, ZIP_ER_READ, errno);
+ return -1;
+ }
+
+ *crcp = crc32(*crcp, buf, n);
+
+ len-= n;
+ }
+
+ return 0;
+}
diff --git a/ext/zip/lib/zip_get_archive_flag.c b/ext/zip/lib/zip_get_archive_flag.c
new file mode 100644
index 0000000000..2d46aa39ff
--- /dev/null
+++ b/ext/zip/lib/zip_get_archive_flag.c
@@ -0,0 +1,48 @@
+/*
+ zip_get_archive_flag.c -- get archive global flag
+ Copyright (C) 2008 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_get_archive_flag(struct zip *za, int flag, int flags)
+{
+ int fl;
+
+ fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags;
+
+ return (fl & flag) ? 1 : 0;
+}
diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c
index 7247b7b8d6..cb3e66d2ca 100644
--- a/ext/zip/lib/zip_open.c
+++ b/ext/zip/lib/zip_open.c
@@ -310,9 +310,8 @@ static void
_zip_check_torrentzip(struct zip *za)
{
uLong crc_got, crc_should;
+ char buf[8+1];
char *end;
- Bytef buf[BUFSIZE];
- unsigned int n, remain;
if (za->zp == NULL || za->cdir == NULL)
return;
@@ -321,27 +320,17 @@ _zip_check_torrentzip(struct zip *za)
|| strncmp(za->cdir->comment, TORRENT_SIG, TORRENT_SIG_LEN) != 0)
return;
+ memcpy(buf, za->cdir->comment+TORRENT_SIG_LEN, 8);
+ buf[8] = '\0';
errno = 0;
- crc_should = strtoul(za->cdir->comment+TORRENT_SIG_LEN, &end, 16);
+ crc_should = strtoul(buf, &end, 16);
if ((crc_should == UINT_MAX && errno != 0) || (end && *end))
return;
- crc_got = crc32(0L, Z_NULL, 0);
-
- if (fseek(za->zp, za->cdir->offset, SEEK_SET) != 0)
- return;
- remain = za->cdir->size;
-
- while (remain > 0) {
- n = remain > BUFSIZE ? BUFSIZE : remain;
- if ((n=fread(buf, 1, n, za->zp)) <= 0)
+ if (_zip_filerange_crc(za->zp, za->cdir->offset, za->cdir->size,
+ &crc_got, NULL) < 0)
return;
- crc_got = crc32(crc_got, buf, n);
-
- remain -= n;
- }
-
if (crc_got == crc_should)
za->flags |= ZIP_AFL_TORRENT;
}
diff --git a/ext/zip/lib/zip_rename.c b/ext/zip/lib/zip_rename.c
index a0055fdc47..e57e50c390 100644
--- a/ext/zip/lib/zip_rename.c
+++ b/ext/zip/lib/zip_rename.c
@@ -1,6 +1,6 @@
/*
zip_rename.c -- rename file in zip archive
- Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2008 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>
@@ -33,6 +33,8 @@
+#include <string.h>
+
#include "zipint.h"
@@ -40,7 +42,21 @@
ZIP_EXTERN(int)
zip_rename(struct zip *za, int idx, const char *name)
{
- if (idx >= za->nentry || idx < 0) {
+ const char *old_name;
+ int old_is_dir, new_is_dir;
+
+ if (idx >= za->nentry || idx < 0 || name[0] == '\0') {
+ _zip_error_set(&za->error, ZIP_ER_INVAL, 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;
}
diff --git a/ext/zip/lib/zip_set_archive_flag.c b/ext/zip/lib/zip_set_archive_flag.c
new file mode 100644
index 0000000000..a6fdd8d2d0
--- /dev/null
+++ b/ext/zip/lib/zip_set_archive_flag.c
@@ -0,0 +1,49 @@
+/*
+ zip_get_archive_flag.c -- set archive global flag
+ Copyright (C) 2008 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_set_archive_flag(struct zip *za, int flag, int value)
+{
+ if (value)
+ za->ch_flags |= flag;
+ else
+ za->ch_flags &= ~flag;
+
+ return 0;
+}
diff --git a/ext/zip/lib/zip_source_file.c b/ext/zip/lib/zip_source_file.c
index 204fa1d5a3..a42be670e9 100644
--- a/ext/zip/lib/zip_source_file.c
+++ b/ext/zip/lib/zip_source_file.c
@@ -1,6 +1,6 @@
/*
zip_source_file.c -- create data source from file
- Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2008 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>
@@ -43,9 +43,6 @@
ZIP_EXTERN(struct zip_source *)
zip_source_file(struct zip *za, const char *fname, off_t start, off_t len)
{
- struct zip_source *zs;
- FILE *fp;
-
if (za == NULL)
return NULL;
@@ -54,15 +51,5 @@ zip_source_file(struct zip *za, const char *fname, off_t start, off_t len)
return NULL;
}
- if ((fp=fopen(fname, "rb")) == NULL) {
- _zip_error_set(&za->error, ZIP_ER_OPEN, errno);
- return NULL;
- }
-
- if ((zs=zip_source_filep(za, fp, start, len)) == NULL) {
- fclose(fp);
- return NULL;
- }
-
- return zs;
+ return _zip_source_file_or_p(za, fname, NULL, start, len);
}
diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c
index 48a122d4bd..10f9602e1e 100644
--- a/ext/zip/lib/zip_source_filep.c
+++ b/ext/zip/lib/zip_source_filep.c
@@ -1,6 +1,6 @@
/*
zip_source_filep.c -- create data source from FILE *
- Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2008 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,6 +42,7 @@
#include "zipint.h"
struct read_file {
+ char *fname; /* name of file to copy from */
FILE *f; /* file to copy from */
off_t off; /* start offset of */
off_t len; /* lengt of data to copy */
@@ -57,9 +58,6 @@ static ssize_t read_file(void *state, void *data, size_t len,
ZIP_EXTERN(struct zip_source *)
zip_source_filep(struct zip *za, FILE *file, off_t start, off_t len)
{
- struct read_file *f;
- struct zip_source *zs;
-
if (za == NULL)
return NULL;
@@ -68,11 +66,36 @@ zip_source_filep(struct zip *za, FILE *file, off_t start, off_t len)
return NULL;
}
+ return _zip_source_file_or_p(za, NULL, file, start, len);
+}
+
+
+
+struct zip_source *
+_zip_source_file_or_p(struct zip *za, const char *fname, FILE *file,
+ off_t start, off_t len)
+{
+ struct read_file *f;
+ struct zip_source *zs;
+
+ if (file == NULL && fname == NULL) {
+ _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return NULL;
+ }
+
if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
_zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
}
+ f->fname = NULL;
+ if (fname) {
+ if ((f->fname=strdup(fname)) == NULL) {
+ _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ free(f);
+ return NULL;
+ }
+ }
f->f = file;
f->off = start;
f->len = (len ? len : -1);
@@ -99,6 +122,14 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd)
switch (cmd) {
case ZIP_SOURCE_OPEN:
+ if (z->fname) {
+ if ((z->f=fopen(z->fname, "rb")) == NULL) {
+ z->e[0] = ZIP_ER_OPEN;
+ z->e[1] = errno;
+ return -1;
+ }
+ }
+
if (fseeko(z->f, z->off, SEEK_SET) < 0) {
z->e[0] = ZIP_ER_SEEK;
z->e[1] = errno;
@@ -125,17 +156,27 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd)
return i;
case ZIP_SOURCE_CLOSE:
+ if (z->fname) {
+ fclose(z->f);
+ z->f = NULL;
+ }
return 0;
case ZIP_SOURCE_STAT:
{
struct zip_stat *st;
struct stat fst;
+ int err;
if (len < sizeof(*st))
return -1;
- if (fstat(fileno(z->f), &fst) != 0) {
+ if (z->f)
+ err = fstat(fileno(z->f), &fst);
+ else
+ err = stat(z->fname, &fst);
+
+ if (err != 0) {
z->e[0] = ZIP_ER_READ; /* best match */
z->e[1] = errno;
return -1;
@@ -161,6 +202,8 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd)
return sizeof(int)*2;
case ZIP_SOURCE_FREE:
+ free(z->fname);
+ if (z->f)
fclose(z->f);
free(z);
return 0;
diff --git a/ext/zip/lib/zip_source_zip.c b/ext/zip/lib/zip_source_zip.c
index bf166b3519..58119dd39f 100644
--- a/ext/zip/lib/zip_source_zip.c
+++ b/ext/zip/lib/zip_source_zip.c
@@ -57,6 +57,8 @@ zip_source_zip(struct zip *za, struct zip *srcza, int srcidx, int flags,
struct zip_source *zs;
struct read_zip *p;
+ /* XXX: ZIP_FL_RECOMPRESS */
+
if (za == NULL)
return NULL;
@@ -74,7 +76,7 @@ zip_source_zip(struct zip *za, struct zip *srcza, int srcidx, int flags,
if (len == 0)
len = -1;
- if (start == 0 && len == -1)
+ if (start == 0 && len == -1 && (flags & ZIP_FL_RECOMPRESS) == 0)
flags |= ZIP_FL_COMPRESSED;
else
flags &= ~ZIP_FL_COMPRESSED;
diff --git a/ext/zip/lib/zip_unchange_archive.c b/ext/zip/lib/zip_unchange_archive.c
index b8a85fc9ac..ca2b678544 100644
--- a/ext/zip/lib/zip_unchange_archive.c
+++ b/ext/zip/lib/zip_unchange_archive.c
@@ -1,6 +1,6 @@
/*
zip_unchange_archive.c -- undo global changes to ZIP archive
- Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2008 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>
@@ -34,7 +34,7 @@
#include <stdlib.h>
-#include "zip.h"
+
#include "zipint.h"
@@ -46,5 +46,7 @@ zip_unchange_archive(struct zip *za)
za->ch_comment = NULL;
za->ch_comment_len = -1;
+ za->ch_flags = za->flags;
+
return 0;
}
diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h
index 165f68dc65..25d6bec98f 100644
--- a/ext/zip/lib/zipint.h
+++ b/ext/zip/lib/zipint.h
@@ -67,6 +67,8 @@
#define DATADES_MAGIC "PK\7\8"
#define TORRENT_SIG "TORRENTZIPPED-"
#define TORRENT_SIG_LEN 14
+#define TORRENT_CRC_LEN 8
+#define TORRENT_MEM_LEVEL 8
#define CDENTRYSIZE 46u
#define LENTRYSIZE 30
#define MAXCOMLEN 65536
@@ -208,6 +210,7 @@ extern const int _zip_err_type[];
+int _zip_cdir_compute_crc(struct zip *, uLong *);
void _zip_cdir_free(struct zip_cdir *);
struct zip_cdir *_zip_cdir_new(int, struct zip_error *);
int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *);
@@ -216,6 +219,7 @@ void _zip_dirent_finalize(struct zip_dirent *);
void _zip_dirent_init(struct zip_dirent *);
int _zip_dirent_read(struct zip_dirent *, FILE *,
unsigned char **, unsigned int, int, struct zip_error *);
+void _zip_dirent_torrent_normalize(struct zip_dirent *);
int _zip_dirent_write(struct zip_dirent *, FILE *, int, struct zip_error *);
void _zip_entry_free(struct zip_entry *);
@@ -233,6 +237,11 @@ const char *_zip_error_strerror(struct zip_error *);
int _zip_file_fillbuf(void *, size_t, struct zip_file *);
unsigned int _zip_file_get_offset(struct zip *, int);
+int _zip_filerange_crc(FILE *, off_t, off_t, uLong *, struct zip_error *);
+
+struct zip_source *_zip_source_file_or_p(struct zip *, const char *, FILE *,
+ off_t, off_t);
+
void _zip_free(struct zip *);
const char *_zip_get_name(struct zip *, int, int, struct zip_error *);
int _zip_local_header_read(struct zip *, int);