diff options
-rw-r--r-- | ext/zip/config.w32 | 3 | ||||
-rw-r--r-- | ext/zip/lib/zip.h | 3 | ||||
-rw-r--r-- | ext/zip/lib/zip_close.c | 188 | ||||
-rw-r--r-- | ext/zip/lib/zip_dirent.c | 59 | ||||
-rw-r--r-- | ext/zip/lib/zip_err_str.c | 4 | ||||
-rw-r--r-- | ext/zip/lib/zip_filerange_crc.c | 71 | ||||
-rw-r--r-- | ext/zip/lib/zip_get_archive_flag.c | 48 | ||||
-rw-r--r-- | ext/zip/lib/zip_open.c | 23 | ||||
-rw-r--r-- | ext/zip/lib/zip_rename.c | 20 | ||||
-rw-r--r-- | ext/zip/lib/zip_set_archive_flag.c | 49 | ||||
-rw-r--r-- | ext/zip/lib/zip_source_file.c | 17 | ||||
-rw-r--r-- | ext/zip/lib/zip_source_filep.c | 53 | ||||
-rw-r--r-- | ext/zip/lib/zip_source_zip.c | 4 | ||||
-rw-r--r-- | ext/zip/lib/zip_unchange_archive.c | 6 | ||||
-rw-r--r-- | ext/zip/lib/zipint.h | 9 |
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); |