]> granicus.if.org Git - php/commitdiff
Sync ext/zip with pecl/zip version 1.3.2
authorRemi Collet <remi@php.net>
Mon, 4 Nov 2013 12:23:36 +0000 (13:23 +0100)
committerRemi Collet <remi@php.net>
Mon, 4 Nov 2013 12:23:36 +0000 (13:23 +0100)
- update libzip to version 1.11.1. We don't use any private symbol anymore
- new method ZipArchive::setPassword($password)
- add --with-libzip option to build with system libzip

99 files changed:
ext/zip/CREDITS
ext/zip/config.m4
ext/zip/config.w32
ext/zip/examples/addglob.php [new file with mode: 0644]
ext/zip/examples/addpattern.php [new file with mode: 0644]
ext/zip/lib/mkstemp.c [new file with mode: 0644]
ext/zip/lib/php_zip_config.w32.h [new file with mode: 0644]
ext/zip/lib/zip.h
ext/zip/lib/zip_add.c
ext/zip/lib/zip_add_dir.c
ext/zip/lib/zip_add_entry.c [new file with mode: 0644]
ext/zip/lib/zip_close.c
ext/zip/lib/zip_delete.c
ext/zip/lib/zip_dir_add.c [moved from ext/zip/lib/zip_entry_new.c with 61% similarity]
ext/zip/lib/zip_dirent.c
ext/zip/lib/zip_discard.c [moved from ext/zip/lib/zip_free.c with 86% similarity]
ext/zip/lib/zip_entry.c [moved from ext/zip/lib/zip_entry_free.c with 79% similarity]
ext/zip/lib/zip_error.c
ext/zip/lib/zip_error_clear.c
ext/zip/lib/zip_error_get.c
ext/zip/lib/zip_error_get_sys_type.c
ext/zip/lib/zip_error_to_str.c
ext/zip/lib/zip_extra_field.c [new file with mode: 0644]
ext/zip/lib/zip_extra_field_api.c [new file with mode: 0644]
ext/zip/lib/zip_fclose.c
ext/zip/lib/zip_fdopen.c
ext/zip/lib/zip_file_add.c [new file with mode: 0644]
ext/zip/lib/zip_file_error_clear.c
ext/zip/lib/zip_file_error_get.c
ext/zip/lib/zip_file_get_comment.c [moved from ext/zip/lib/zip_get_file_extra.c with 72% similarity]
ext/zip/lib/zip_file_get_offset.c
ext/zip/lib/zip_file_rename.c [moved from ext/zip/lib/zip_set_file_extra.c with 70% similarity]
ext/zip/lib/zip_file_replace.c [new file with mode: 0644]
ext/zip/lib/zip_file_set_comment.c [new file with mode: 0644]
ext/zip/lib/zip_file_strerror.c
ext/zip/lib/zip_filerange_crc.c
ext/zip/lib/zip_fopen.c
ext/zip/lib/zip_fopen_encrypted.c
ext/zip/lib/zip_fopen_index.c
ext/zip/lib/zip_fopen_index_encrypted.c
ext/zip/lib/zip_fread.c
ext/zip/lib/zip_get_archive_comment.c
ext/zip/lib/zip_get_archive_flag.c
ext/zip/lib/zip_get_compression_implementation.c
ext/zip/lib/zip_get_encryption_implementation.c
ext/zip/lib/zip_get_file_comment.c
ext/zip/lib/zip_get_name.c
ext/zip/lib/zip_get_num_entries.c
ext/zip/lib/zip_get_num_files.c
ext/zip/lib/zip_memdup.c
ext/zip/lib/zip_name_locate.c
ext/zip/lib/zip_new.c
ext/zip/lib/zip_open.c
ext/zip/lib/zip_rename.c
ext/zip/lib/zip_replace.c
ext/zip/lib/zip_set_archive_comment.c
ext/zip/lib/zip_set_archive_flag.c
ext/zip/lib/zip_set_default_password.c
ext/zip/lib/zip_set_file_comment.c
ext/zip/lib/zip_set_file_compression.c [new file with mode: 0644]
ext/zip/lib/zip_set_name.c
ext/zip/lib/zip_source_buffer.c
ext/zip/lib/zip_source_close.c
ext/zip/lib/zip_source_crc.c
ext/zip/lib/zip_source_deflate.c
ext/zip/lib/zip_source_error.c
ext/zip/lib/zip_source_file.c
ext/zip/lib/zip_source_filep.c
ext/zip/lib/zip_source_free.c
ext/zip/lib/zip_source_function.c
ext/zip/lib/zip_source_layered.c
ext/zip/lib/zip_source_open.c
ext/zip/lib/zip_source_pkware.c
ext/zip/lib/zip_source_pop.c
ext/zip/lib/zip_source_read.c
ext/zip/lib/zip_source_stat.c
ext/zip/lib/zip_source_window.c [new file with mode: 0644]
ext/zip/lib/zip_source_zip.c
ext/zip/lib/zip_source_zip_new.c [new file with mode: 0644]
ext/zip/lib/zip_stat.c
ext/zip/lib/zip_stat_index.c
ext/zip/lib/zip_stat_init.c
ext/zip/lib/zip_strerror.c
ext/zip/lib/zip_string.c [new file with mode: 0644]
ext/zip/lib/zip_unchange.c
ext/zip/lib/zip_unchange_all.c
ext/zip/lib/zip_unchange_archive.c
ext/zip/lib/zip_unchange_data.c
ext/zip/lib/zip_utf-8.c [new file with mode: 0644]
ext/zip/lib/zip_win32.h [deleted file]
ext/zip/lib/zipconf.h
ext/zip/lib/zipint.h
ext/zip/php_zip.c
ext/zip/php_zip.h
ext/zip/tests/bug38943.inc [new file with mode: 0644]
ext/zip/tests/bug38943_2.phpt [new file with mode: 0644]
ext/zip/tests/doubleclose.phpt [new file with mode: 0644]
ext/zip/tests/zip_entry_close.phpt [new file with mode: 0644]
ext/zip/zip_stream.c

index 6c7e42d41716065a7548a6935f71eda22adbf222..59b7ef097e531945ce10dbe72da4df38f37a52f0 100644 (file)
@@ -1,2 +1,2 @@
 Zip
-Pierre-Alain Joye
+Pierre-Alain Joye, Remi Collet
index 805d92442e0178c30c0c5902bee1e8ccb7bd2e4d..83e32feca76ee5249b62b1703bf16cb9113df8ad 100644 (file)
@@ -11,10 +11,14 @@ if test -z "$PHP_ZLIB_DIR"; then
 fi
 
 PHP_ARG_WITH(pcre-dir, pcre install prefix,
-[  --with-pcre-dir         ZIP: pcre install prefix], no, no)
+[  --with-pcre-dir           ZIP: pcre install prefix], no, no)
+
+PHP_ARG_WITH(libzip, libzip,
+[ --with-libzip[=DIR]        ZIP: use libzip], no, no)
 
 if test "$PHP_ZIP" != "no"; then
 
+  dnl libzip, depends on zlib
   if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then
     if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then
       PHP_ZLIB_DIR="$PHP_ZLIB_DIR"
@@ -47,61 +51,124 @@ if test "$PHP_ZIP" != "no"; then
     PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR)
   fi
 
-  dnl This is PECL build, check if bundled PCRE library is used
-  old_CPPFLAGS=$CPPFLAGS
-  CPPFLAGS=$INCLUDES
-  AC_EGREP_CPP(yes,[
-#include <main/php_config.h>
-#if defined(HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
-yes
-#endif
-  ],[
-    PHP_PCRE_REGEX=yes
-  ],[
-    AC_EGREP_CPP(yes,[
-#include <main/php_config.h>
-#if defined(HAVE_PCRE) && !defined(COMPILE_DL_PCRE)
-yes
-#endif
-    ],[
-      PHP_PCRE_REGEX=pecl
-    ],[
-      PHP_PCRE_REGEX=no
+  if test "$PHP_LIBZIP" != "no"; then
+
+    AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+
+    dnl system libzip, depends on libzip
+    AC_MSG_CHECKING(for libzip)
+    if test -r $PHP_LIBZIP/include/zip.h; then
+      LIBZIP_CFLAGS="-I$PHP_LIBZIP/include"
+      LIBZIP_LIBDIR="$PHP_LIBZIP/$PHP_LIBDIR"
+      AC_MSG_RESULT(from option: found in $PHP_LIBZIP)
+
+    elif test -x "$PKG_CONFIG" && $PKG_CONFIG --exists libzip; then
+      LIBZIP_CFLAGS=`$PKG_CONFIG libzip --cflags`
+      LIBZIP_LIBDIR=`$PKG_CONFIG libzip --variable=libdir`
+      AC_MSG_RESULT(from pkgconfig: found in $LIBZIP_LIBDIR)
+
+    else
+      for i in /usr/local /usr; do
+        if test -r $i/include/zip.h; then
+          LIBZIP_CFLAGS="-I$i/include"
+          LIBZIP_LIBDIR="$i/$PHP_LIBDIR"
+          AC_MSG_RESULT(in default path: found in $i)
+          break
+        fi
+      done
+    fi
+
+    if test -z "$LIBZIP_LIBDIR"; then
+      AC_MSG_RESULT(not found)
+      AC_MSG_ERROR(Please reinstall the libzip distribution)
+    fi
+
+    dnl Could not think of a simple way to check libzip for overwrite support
+    PHP_CHECK_LIBRARY(zip, zip_open,
+    [
+      PHP_ADD_LIBRARY_WITH_PATH(zip, $LIBZIP_LIBDIR, ZIP_SHARED_LIBADD)
+      AC_DEFINE(HAVE_LIBZIP,1,[ ])
+    ], [
+      AC_MSG_ERROR(could not find usable libzip)
+    ], [
+      -L$LIBZIP_LIBDIR
     ])
-  ])
-  CPPFLAGS=$old_CPPFLAGS
-
-  PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_error.c lib/zip_fclose.c \
-                         lib/zip_fread.c lib/zip_open.c lib/zip_source_filep.c  \
-                         lib/zip_strerror.c lib/zip_close.c lib/zip_error_get.c \
-                         lib/zip_file_error_get.c lib/zip_free.c lib/zip_rename.c \
-                         lib/zip_source_free.c lib/zip_unchange_all.c lib/zip_delete.c \
-                         lib/zip_error_get_sys_type.c lib/zip_file_get_offset.c \
-                         lib/zip_get_name.c lib/zip_replace.c lib/zip_source_function.c \
-                         lib/zip_unchange.c lib/zip_dirent.c lib/zip_error_strerror.c \
-                         lib/zip_filerange_crc.c lib/zip_file_strerror.c lib/zip_get_num_files.c \
-                         lib/zip_get_archive_flag.c lib/zip_set_archive_flag.c \
-                         lib/zip_set_name.c lib/zip_source_zip.c lib/zip_unchange_data.c \
-                         lib/zip_entry_free.c lib/zip_error_to_str.c lib/zip_fopen.c \
-                         lib/zip_name_locate.c lib/zip_source_buffer.c lib/zip_stat.c \
-                         lib/zip_entry_new.c lib/zip_err_str.c lib/zip_fopen_index.c \
-                         lib/zip_get_archive_comment.c lib/zip_get_file_comment.c \
-                         lib/zip_new.c lib/zip_source_file.c lib/zip_stat_index.c \
-                         lib/zip_set_archive_comment.c lib/zip_set_file_comment.c \
-                         lib/zip_unchange_archive.c lib/zip_memdup.c lib/zip_stat_init.c lib/zip_add_dir.c \
-                         lib/zip_error_clear.c lib/zip_file_error_clear.c \
-                                                lib/zip_fdopen.c lib/zip_fopen_encrypted.c lib/zip_fopen_index_encrypted.c \
-                                                lib/zip_get_compression_implementation.c lib/zip_get_encryption_implementation.c \
-                                                lib/zip_get_file_extra.c lib/zip_get_num_entries.c lib/zip_set_default_password.c \
-                                                lib/zip_set_file_extra.c lib/zip_source_close.c lib/zip_source_crc.c \
-                                                lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_layered.c \
-                                                lib/zip_source_open.c lib/zip_source_pkware.c lib/zip_source_pop.c \
-                                                lib/zip_source_read.c lib/zip_source_stat.c"
+
+    AC_DEFINE(HAVE_ZIP,1,[ ])
+    PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c, $ext_shared,, $LIBZIP_CFLAGS)
+    PHP_SUBST(ZIP_SHARED_LIBADD)
+  else
+
+
+  PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_add_dir.c lib/zip_add_entry.c\
+                       lib/zip_close.c lib/zip_delete.c lib/zip_dir_add.c lib/zip_dirent.c lib/zip_discard.c lib/zip_entry.c\
+                       lib/zip_err_str.c lib/zip_error.c lib/zip_error_clear.c lib/zip_error_get.c lib/zip_error_get_sys_type.c\
+                       lib/zip_error_strerror.c lib/zip_error_to_str.c lib/zip_extra_field.c lib/zip_extra_field_api.c\
+                       lib/zip_fclose.c lib/zip_fdopen.c lib/zip_file_add.c lib/zip_file_error_clear.c lib/zip_file_error_get.c\
+                       lib/zip_file_get_comment.c lib/zip_file_get_offset.c lib/zip_file_rename.c lib/zip_file_replace.c\
+                       lib/zip_file_set_comment.c lib/zip_file_strerror.c lib/zip_filerange_crc.c lib/zip_fopen.c\
+                       lib/zip_fopen_encrypted.c lib/zip_fopen_index.c lib/zip_fopen_index_encrypted.c lib/zip_fread.c\
+                       lib/zip_get_archive_comment.c lib/zip_get_archive_flag.c lib/zip_get_compression_implementation.c\
+                       lib/zip_get_encryption_implementation.c lib/zip_get_file_comment.c lib/zip_get_name.c lib/zip_get_num_entries.c \
+                       lib/zip_get_num_files.c lib/zip_memdup.c lib/zip_name_locate.c lib/zip_new.c lib/zip_open.c lib/zip_rename.c lib/zip_replace.c\
+                       lib/zip_set_archive_comment.c lib/zip_set_archive_flag.c lib/zip_set_default_password.c lib/zip_set_file_comment.c\
+                       lib/zip_set_file_compression.c lib/zip_set_name.c lib/zip_source_buffer.c lib/zip_source_close.c lib/zip_source_crc.c\
+                       lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_file.c lib/zip_source_filep.c lib/zip_source_free.c\
+                       lib/zip_source_function.c lib/zip_source_layered.c lib/zip_source_open.c lib/zip_source_pkware.c lib/zip_source_pop.c\
+                       lib/zip_source_read.c lib/zip_source_stat.c lib/zip_source_window.c lib/zip_source_zip.c lib/zip_source_zip_new.c\
+                       lib/zip_stat.c lib/zip_stat_index.c lib/zip_stat_init.c lib/zip_strerror.c lib/zip_string.c lib/zip_unchange.c lib/zip_unchange_all.c\
+                       lib/zip_unchange_archive.c lib/zip_unchange_data.c lib/zip_utf-8.c lib/mkstemp.c"
 
   AC_DEFINE(HAVE_ZIP,1,[ ])
   PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c $PHP_ZIP_SOURCES, $ext_shared)
   PHP_ADD_BUILD_DIR($ext_builddir/lib, 1)
   PHP_SUBST(ZIP_SHARED_LIBADD)
+fi
+
+
+AC_CHECK_TYPES([int8_t])
+AC_CHECK_TYPES([int16_t])
+AC_CHECK_TYPES([int32_t])
+AC_CHECK_TYPES([int64_t])
+AC_CHECK_TYPES([uint8_t])
+AC_CHECK_TYPES([uint16_t])
+AC_CHECK_TYPES([uint32_t])
+AC_CHECK_TYPES([uint64_t])
+AC_CHECK_TYPES([ssize_t])
+
+AC_CHECK_SIZEOF([short])
+AC_CHECK_SIZEOF([int])
+AC_CHECK_SIZEOF([long])
+AC_CHECK_SIZEOF([long long])
+AC_CHECK_SIZEOF([off_t])
+AC_CHECK_SIZEOF([size_t])
+
+AC_PATH_PROG([TOUCH], [touch])
+AC_PATH_PROG([UNZIP], [unzip])
+
+AC_STRUCT_TIMEZONE
+
+case $host_os
+in
+    *bsd*) MANFMT=mdoc;;
+    *) MANFMT=man;;
+esac
+AC_SUBST([MANFMT])
+
+AH_BOTTOM([
+#ifndef HAVE_SSIZE_T
+#  if SIZEOF_SIZE_T == SIZEOF_INT
+typedef int ssize_t;
+#  elif SIZEOF_SIZE_T == SIZEOF_LONG
+typedef long ssize_t;
+#  elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+typedef long long ssize_t;
+#  else
+#error no suitable type for ssize_t found
+#  endif
+#endif
+])
+
 
   dnl so we always include the known-good working hack.
   PHP_ADD_MAKEFILE_FRAGMENT
index fa0a5180df5ce280ef874138c61b078a79e2728f..5b9f09575a769ec4b4eecaa3fc08c2256ca549d1 100644 (file)
@@ -9,36 +9,28 @@ if (PHP_ZIP != "no") {
                        (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "zip", PHP_ZIP)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED)))
                ) {
                EXTENSION('zip', 'php_zip.c zip_stream.c');
-               ADD_SOURCES(configure_module_dirname + "/lib", "zip_add.c zip_error.c zip_fclose.c \
-                     zip_fread.c zip_open.c zip_source_filep.c  \
-                     zip_strerror.c zip_close.c zip_error_get.c \
-                     zip_file_error_get.c zip_free.c zip_rename.c \
-                     zip_source_free.c zip_unchange_all.c zip_delete.c \
-                     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_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 \
-                     zip_entry_new.c zip_err_str.c zip_fopen_index.c \
-                     zip_new.c zip_source_file.c zip_stat_index.c \
-                     zip_get_archive_comment.c zip_get_file_comment.c \
-                     zip_set_archive_comment.c zip_set_file_comment.c \
-                     zip_unchange_archive.c zip_memdup.c zip_stat_init.c \
-                     zip_add_dir.c zip_file_error_clear.c zip_error_clear.c \
-                     zip_fdopen.c zip_fopen_encrypted.c zip_fopen_index_encrypted.c \
-                     zip_get_compression_implementation.c zip_get_encryption_implementation.c \
-                     zip_get_file_extra.c zip_get_num_entries.c zip_set_default_password.c \
-                     zip_set_file_extra.c zip_source_close.c zip_source_crc.c \
-                     zip_source_deflate.c zip_source_error.c zip_source_layered.c \
-                     zip_source_open.c zip_source_pkware.c zip_source_pop.c \
-                     zip_source_read.c zip_source_stat.c", "zip");
+               ADD_SOURCES(configure_module_dirname + "/lib", "zip_add.c zip_add_dir.c zip_add_entry.c\
+                       zip_close.c zip_delete.c zip_dir_add.c zip_dirent.c zip_discard.c zip_entry.c\
+                       zip_err_str.c zip_error.c zip_error_clear.c zip_error_get.c zip_error_get_sys_type.c\
+                       zip_error_strerror.c zip_error_to_str.c zip_extra_field.c zip_extra_field_api.c\
+                       zip_fclose.c zip_fdopen.c zip_file_add.c zip_file_error_clear.c zip_file_error_get.c\
+                       zip_file_get_comment.c zip_file_get_offset.c zip_file_rename.c zip_file_replace.c\
+                       zip_file_set_comment.c zip_file_strerror.c zip_filerange_crc.c zip_fopen.c\
+                       zip_fopen_encrypted.c zip_fopen_index.c zip_fopen_index_encrypted.c zip_fread.c\
+                       zip_get_archive_comment.c zip_get_archive_flag.c zip_get_compression_implementation.c\
+                       zip_get_encryption_implementation.c zip_get_file_comment.c zip_get_name.c zip_get_num_entries.c \
+                       zip_get_num_files.c zip_memdup.c zip_name_locate.c zip_new.c zip_open.c zip_rename.c zip_replace.c\
+                       zip_set_archive_comment.c zip_set_archive_flag.c zip_set_default_password.c zip_set_file_comment.c\
+                       zip_set_file_compression.c zip_set_name.c zip_source_buffer.c zip_source_close.c zip_source_crc.c\
+                       zip_source_deflate.c zip_source_error.c zip_source_file.c zip_source_filep.c zip_source_free.c\
+                       zip_source_function.c zip_source_layered.c zip_source_open.c zip_source_pkware.c zip_source_pop.c\
+                       zip_source_read.c zip_source_stat.c zip_source_window.c zip_source_zip.c zip_source_zip_new.c\
+                       zip_stat.c zip_stat_index.c zip_stat_init.c zip_strerror.c zip_string.c zip_unchange.c zip_unchange_all.c\
+                       zip_unchange_archive.c zip_unchange_data.c zip_utf-8.c mkstemp.c", "zip");
 
                AC_DEFINE('HAVE_ZIP', 1);
+               ADD_FLAG("CFLAGS_ZIP", "/D _WIN32");
        } else {
                WARNING("zip not enabled; libraries and headers not found");
        }
 }
-
diff --git a/ext/zip/examples/addglob.php b/ext/zip/examples/addglob.php
new file mode 100644 (file)
index 0000000..790312b
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+$z = new ZipArchive;
+$z->open('a.zip', ZIPARCHIVE::CREATE);
+
+/* or 'remove_all_path' => 0*/
+$options = array(
+       'remove_path' => '/home/francis/myimages',
+       'add_path' => 'images/',
+);
+$found = $z->addGlob("/home/pierre/cvs/gd/libgd/tests/*.png", 0, $options);
+var_dump($found);
+$z->close();
+
diff --git a/ext/zip/examples/addpattern.php b/ext/zip/examples/addpattern.php
new file mode 100644 (file)
index 0000000..a1a9b12
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+$z = new ZipArchive;
+$z->open('a.zip', ZIPARCHIVE::CREATE);
+
+/* or 'remove_all_path' => 0*/
+$options = array('remove_path' => '/home/pierre/cvs/gd/libgd/tests',
+'add_path' => 'images/',
+);
+
+$found = $z->addPattern("/(\.png)$/i", "/home/pierre/cvs/gd/libgd/tests", $options);
+var_dump($found);
+$z->close();
+
diff --git a/ext/zip/lib/mkstemp.c b/ext/zip/lib/mkstemp.c
new file mode 100644 (file)
index 0000000..843d5e3
--- /dev/null
@@ -0,0 +1,151 @@
+/* Adapted from NetBSB libc by Dieter Baron */
+
+/*     NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp       */
+
+/*
+ * Copyright (c) 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * 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. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+\f
+
+int
+_zip_mkstemp(char *path)
+{
+#ifdef _WIN32
+       int ret;
+       ret = _creat(_mktemp(path), _S_IREAD|_S_IWRITE);
+       if (ret == -1) {
+               return 0;
+       } else {
+               return ret;
+       }
+#else
+       int fd;   
+       char *start, *trv;
+       struct stat sbuf;
+       pid_t pid;
+
+       /* To guarantee multiple calls generate unique names even if
+          the file is not created. 676 different possibilities with 7
+          or more X's, 26 with 6 or less. */
+       static char xtra[2] = "aa";
+       int xcnt = 0;
+
+       pid = getpid();
+
+       /* Move to end of path and count trailing X's. */
+       for (trv = path; *trv; ++trv)
+               if (*trv == 'X')
+                       xcnt++;
+               else
+                       xcnt = 0;       
+
+       /* Use at least one from xtra.  Use 2 if more than 6 X's. */
+       if (*(trv - 1) == 'X')
+               *--trv = xtra[0];
+       if (xcnt > 6 && *(trv - 1) == 'X')
+               *--trv = xtra[1];
+
+       /* Set remaining X's to pid digits with 0's to the left. */
+       while (*--trv == 'X') {
+               *trv = (pid % 10) + '0';
+               pid /= 10;
+       }
+
+       /* update xtra for next call. */
+       if (xtra[0] != 'z')
+               xtra[0]++;
+       else {
+               xtra[0] = 'a';
+               if (xtra[1] != 'z')
+                       xtra[1]++;
+               else
+                       xtra[1] = 'a';
+       }
+
+       /*
+        * check the target directory; if you have six X's and it
+        * doesn't exist this runs for a *very* long time.
+        */
+       for (start = trv + 1;; --trv) {
+               if (trv <= path)
+                       break;
+               if (*trv == '/') {
+                       *trv = '\0';
+                       if (stat(path, &sbuf))
+                               return (0);
+                       if (!S_ISDIR(sbuf.st_mode)) {
+                               errno = ENOTDIR;
+                               return (0);
+                       }
+                       *trv = '/';
+                       break;
+               }
+       }
+
+       for (;;) {
+               if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0)
+                       return (fd);
+               if (errno != EEXIST)
+                       return (0);
+
+               /* tricky little algorithm for backward compatibility */
+               for (trv = start;;) {
+                       if (!*trv)
+                               return (0);
+                       if (*trv == 'z')
+                               *trv++ = 'a';
+                       else {
+                               if (isdigit((unsigned char)*trv))
+                                       *trv = 'a';
+                               else
+                                       ++*trv;
+                               break;
+                       }
+               }
+       }
+       /*NOTREACHED*/
+#endif
+}
diff --git a/ext/zip/lib/php_zip_config.w32.h b/ext/zip/lib/php_zip_config.w32.h
new file mode 100644 (file)
index 0000000..8956839
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef HAD_CONFIG_H\r
+#define HAD_CONFIG_H\r
+#define HAVE__CLOSE\r
+#define HAVE__DUP\r
+#define HAVE__FDOPEN\r
+#define HAVE__FILENO\r
+#define HAVE__OPEN\r
+#define HAVE__SNPRINTF\r
+/* #undef HAVE__STRCMPI */\r
+#define HAVE__STRDUP\r
+#define HAVE__STRICMP\r
+/* #undef HAVE_FSEEKO */\r
+/* #undef HAVE_FTELLO */\r
+/* #undef HAVE_MKSTEMP */\r
+#define HAVE_MOVEFILEEXA\r
+/* #undef HAVE_SNPRINTF */\r
+/* #undef HAVE_STRCASECMP */\r
+/* #undef HAVE_STRINGS_H */\r
+/* #undef HAVE_STRUCT_TM_TM_ZONE */\r
+/* #undef HAVE_UNISTD_H */\r
+#define PACKAGE "libzip"\r
+#define VERSION "0.10.b"\r
+\r
+/* #undef HAVE_SSIZE_T */\r
+\r
+#ifndef HAVE_SSIZE_T\r
+\r
+#ifndef SIZE_T_LIBZIP\r
+#define SIZE_T_LIBZIP 4\r
+#endif\r
+#ifndef INT_LIBZIP\r
+#define INT_LIBZIP 4\r
+#endif\r
+#ifndef LONG_LIBZIP\r
+#define LONG_LIBZIP 4\r
+#endif\r
+#ifndef LONG_LONG_LIBZIP\r
+#define LONG_LONG_LIBZIP 8\r
+#endif\r
+#ifndef SIZEOF_OFF_T\r
+#define SIZEOF_OFF_T 4\r
+#endif\r
+\r
+#  if SIZE_T_LIBZIP == INT_LIBZIP\r
+# ifndef ssize_t\r
+typedef int ssize_t;\r
+# endif\r
+#  elif SIZE_T_LIBZIP == LONG_LIBZIP\r
+typedef long ssize_t;\r
+#  elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP\r
+typedef long long ssize_t;\r
+#  else\r
+#error no suitable type for ssize_t found\r
+#  endif\r
+#endif\r
+\r
+#endif /* HAD_CONFIG_H */\r
index f11c9aba7f99c494905943dae044ec705467201c..1fb1dbf5e0f5b1cbf312dec4d6cc3181d1a638e5 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
   zip.h -- exported declarations.
-  Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 #include "main/php.h"
 
 #ifdef PHP_WIN32
-#      include "zip_win32.h"
-#      ifdef PHP_ZIP_EXPORTS
-#              define ZIP_EXTERN(rt) __declspec(dllexport)rt _stdcall
-#      else
-#              define ZIP_EXTERN(rt) rt
-#      endif
+#ifdef PHP_ZIP_EXPORTS
+#  define ZIP_EXTERN __declspec(dllexport) _stdcall
+# else
+#  define ZIP_EXTERN
+# endif
 #elif defined(__GNUC__) && __GNUC__ >= 4
-#      define ZIP_EXTERN(rt) __attribute__ ((visibility("default"))) rt
+# define ZIP_EXTERN __attribute__ ((visibility("default")))
 #else
-#      define ZIP_EXTERN(rt) rt
+# define ZIP_EXTERN
 #endif
 
+
+#ifndef ZIP_EXTERN
+#ifdef _WIN32
+#define ZIP_EXTERN __declspec(dllimport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ZIP_EXTERN __attribute__ ((visibility ("default")))
+#else
+#define ZIP_EXTERN
+#endif
+#endif
+
+
+
 BEGIN_EXTERN_C()
 
 #include "zipconf.h"
@@ -63,27 +75,40 @@ BEGIN_EXTERN_C()
 #define ZIP_CREATE           1
 #define ZIP_EXCL             2
 #define ZIP_CHECKCONS        4
-#define ZIP_OVERWRITE        8
-
+#define ZIP_TRUNCATE         8
 
 /* flags for zip_name_locate, zip_fopen, zip_stat, ... */
 
-#define ZIP_FL_NOCASE          1 /* ignore case on name lookup */
-#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 */
-#define ZIP_FL_ENCRYPTED       32 /* read encrypted data
-                                    (implies ZIP_FL_COMPRESSED) */
+#define ZIP_FL_NOCASE          1u /* ignore case on name lookup */
+#define ZIP_FL_NODIR           2u /* ignore directory component */
+#define ZIP_FL_COMPRESSED      4u /* read compressed data */
+#define ZIP_FL_UNCHANGED       8u /* use original data, ignoring changes */
+#define ZIP_FL_RECOMPRESS      16u /* force recompression of data */
+#define ZIP_FL_ENCRYPTED       32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */
+#define ZIP_FL_ENC_GUESS        0u /* guess string encoding (is default) */
+#define ZIP_FL_ENC_RAW         64u /* get unmodified string */
+#define ZIP_FL_ENC_STRICT     128u /* follow specification strictly */
+#define ZIP_FL_LOCAL         256u /* in local header */
+#define ZIP_FL_CENTRAL       512u /* in central directory */
+/*                           1024u    reserved for internal use */
+#define ZIP_FL_ENC_UTF_8     2048u /* string is UTF-8 encoded */
+#define ZIP_FL_ENC_CP437     4096u /* string is CP437 encoded */
+#define ZIP_FL_OVERWRITE     8192u /* zip_file_add: if file with name exists, overwrite (replace) it */
 
 /* archive global flags flags */
 
-#define ZIP_AFL_TORRENT                1 /* torrent zipped */
-#define ZIP_AFL_RDONLY         2 /* read only -- cannot be cleared */
+#define ZIP_AFL_TORRENT                1u /* torrent zipped */
+#define ZIP_AFL_RDONLY         2u /* read only -- cannot be cleared */
+
 
+/* create a new extra field */
+
+#define ZIP_EXTRA_FIELD_ALL    ZIP_UINT16_MAX
+#define ZIP_EXTRA_FIELD_NEW    ZIP_UINT16_MAX
 
 /* flags for compression and encryption sources */
 
+#define ZIP_CODEC_DECODE       0 /* decompress/decrypt (encode flag not set) */
 #define ZIP_CODEC_ENCODE       1 /* compress/encrypt */
 
 
@@ -178,15 +203,15 @@ enum zip_source_cmd {
 
 #define ZIP_SOURCE_ERR_LOWER   -2
 
-#define ZIP_STAT_NAME                  0x0001
-#define ZIP_STAT_INDEX                 0x0002
-#define ZIP_STAT_SIZE                  0x0004
-#define ZIP_STAT_COMP_SIZE             0x0008
-#define ZIP_STAT_MTIME                 0x0010
-#define ZIP_STAT_CRC                   0x0020
-#define ZIP_STAT_COMP_METHOD           0x0040
-#define ZIP_STAT_ENCRYPTION_METHOD     0x0080
-#define ZIP_STAT_FLAGS                 0x0100
+#define ZIP_STAT_NAME                  0x0001u
+#define ZIP_STAT_INDEX                 0x0002u
+#define ZIP_STAT_SIZE                  0x0004u
+#define ZIP_STAT_COMP_SIZE             0x0008u
+#define ZIP_STAT_MTIME                 0x0010u
+#define ZIP_STAT_CRC                   0x0020u
+#define ZIP_STAT_COMP_METHOD           0x0040u
+#define ZIP_STAT_ENCRYPTION_METHOD     0x0080u
+#define ZIP_STAT_FLAGS                 0x0100u
 
 struct zip_stat {
     zip_uint64_t valid;                        /* which fields have valid values */
@@ -205,72 +230,78 @@ struct zip;
 struct zip_file;
 struct zip_source;
 
+typedef zip_uint32_t zip_flags_t;    
+
 typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t,
                                           enum zip_source_cmd);
 
 \f
 
-ZIP_EXTERN(zip_int64_t) zip_add(struct zip *, const char *, struct zip_source *);
-ZIP_EXTERN(zip_int64_t) zip_add_dir(struct zip *, const char *);
-ZIP_EXTERN(int) zip_close(struct zip *);
-ZIP_EXTERN(int) zip_delete(struct zip *, zip_uint64_t);
-ZIP_EXTERN(void) zip_error_clear(struct zip *);
-ZIP_EXTERN(void) zip_error_get(struct zip *, int *, int *);
-ZIP_EXTERN(int) zip_error_get_sys_type(int);
-ZIP_EXTERN(int) zip_error_to_str(char *, zip_uint64_t, int, int);
-ZIP_EXTERN(int) zip_fclose(struct zip_file *);
-ZIP_EXTERN(struct zip *)zip_fdopen(int, int, int *);
-ZIP_EXTERN(void) zip_file_error_clear(struct zip_file *);
-ZIP_EXTERN(void) zip_file_error_get(struct zip_file *, int *, int *);
-ZIP_EXTERN(const char *)zip_file_strerror(struct zip_file *);
-ZIP_EXTERN(struct) zip_file *zip_fopen(struct zip *, const char *, int);
-ZIP_EXTERN(struct) zip_file *zip_fopen_encrypted(struct zip *, const char *,
-                                               int, const char *);
-ZIP_EXTERN(struct zip_file *)zip_fopen_index(struct zip *, zip_uint64_t, int);
-ZIP_EXTERN(struct zip_file *)zip_fopen_index_encrypted(struct zip *,
-                                                     zip_uint64_t, int,
-                                                     const char *);
-ZIP_EXTERN(zip_int64_t) zip_fread(struct zip_file *, void *, zip_uint64_t);
-ZIP_EXTERN(const char *)zip_get_archive_comment(struct zip *, int *, int);
-ZIP_EXTERN(int) zip_get_archive_flag(struct zip *, int, int);
-ZIP_EXTERN(const char *)zip_get_file_comment(struct zip *, zip_uint64_t,
-                                           int *, int);
-ZIP_EXTERN(const 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(zip_uint64_t) zip_get_num_entries(struct zip *, int);
-ZIP_EXTERN(int) zip_get_num_files(struct zip *);  /* deprecated, use zip_get_num_entries instead */
-ZIP_EXTERN(int) zip_name_locate(struct zip *, const char *, int);
-ZIP_EXTERN(struct zip *)zip_open(const char *, int, int *);
-ZIP_EXTERN(int) zip_rename(struct zip *, zip_uint64_t, const char *);
-ZIP_EXTERN(int) zip_replace(struct zip *, zip_uint64_t, struct zip_source *);
-ZIP_EXTERN(int) zip_set_archive_comment(struct zip *, const char *, int);
-ZIP_EXTERN(int) zip_set_archive_flag(struct zip *, int, int);
-ZIP_EXTERN(int) zip_set_default_password(struct zip *, const char *);
-ZIP_EXTERN(int) zip_set_file_comment(struct zip *, zip_uint64_t,
-                                   const char *, int);
-ZIP_EXTERN(int) zip_set_file_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 *,
-                                             zip_uint64_t, zip_int64_t);
-ZIP_EXTERN(struct) zip_source *zip_source_filep(struct zip *, FILE *,
-                                              zip_uint64_t, zip_int64_t);
-ZIP_EXTERN(void) zip_source_free(struct zip_source *);
-ZIP_EXTERN(struct zip_source *)zip_source_function(struct zip *,
-                                                 zip_source_callback, void *);
-ZIP_EXTERN(struct zip_source *)zip_source_zip(struct zip *, struct zip *,
-                                            zip_uint64_t, int,
-                                            zip_uint64_t, zip_int64_t);
-ZIP_EXTERN(int) zip_stat(struct zip *, const char *, int, struct zip_stat *);
-ZIP_EXTERN(int) zip_stat_index(struct zip *, zip_uint64_t, int,
-                             struct zip_stat *);
-ZIP_EXTERN(void) zip_stat_init(struct zip_stat *);
-ZIP_EXTERN(const char *)zip_strerror(struct zip *);
-ZIP_EXTERN(int) zip_unchange(struct zip *, zip_uint64_t);
-ZIP_EXTERN(int) zip_unchange_all(struct zip *);
-ZIP_EXTERN(int) zip_unchange_archive(struct zip *);
+#ifndef ZIP_DISABLE_DEPRECATED
+ZIP_EXTERN zip_int64_t zip_add(struct zip *, const char *, struct zip_source *); /* use zip_file_add */
+ZIP_EXTERN zip_int64_t zip_add_dir(struct zip *, const char *); /* use zip_dir_add */
+ZIP_EXTERN const char *zip_get_file_comment(struct zip *, zip_uint64_t, int *, int); /* use zip_file_get_comment */
+ZIP_EXTERN int zip_get_num_files(struct zip *);  /* use zip_get_num_entries instead */
+ZIP_EXTERN int zip_rename(struct zip *, zip_uint64_t, const char *); /* use zip_file_rename */
+ZIP_EXTERN int zip_replace(struct zip *, zip_uint64_t, struct zip_source *); /* use zip_file_replace */
+ZIP_EXTERN int zip_set_file_comment(struct zip *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */
+#endif
+
+ZIP_EXTERN int zip_archive_set_tempdir(struct zip *, const char *);
+ZIP_EXTERN zip_int64_t zip_file_add(struct zip *, const char *, struct zip_source *, zip_flags_t);
+ZIP_EXTERN zip_int64_t zip_dir_add(struct zip *, const char *, zip_flags_t);
+ZIP_EXTERN int zip_close(struct zip *);
+ZIP_EXTERN void zip_discard(struct zip *);
+ZIP_EXTERN int zip_delete(struct zip *, zip_uint64_t);
+ZIP_EXTERN int zip_file_extra_field_delete(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN int zip_file_extra_field_delete_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN void zip_error_clear(struct zip *);
+ZIP_EXTERN void zip_error_get(struct zip *, int *, int *);
+ZIP_EXTERN int zip_error_get_sys_type(int);
+ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int);
+ZIP_EXTERN int zip_fclose(struct zip_file *);
+ZIP_EXTERN struct zip *zip_fdopen(int, int, int *);
+ZIP_EXTERN void zip_file_error_clear(struct zip_file *);
+ZIP_EXTERN void zip_file_error_get(struct zip_file *, int *, int *);
+ZIP_EXTERN const char *zip_file_strerror(struct zip_file *);
+ZIP_EXTERN struct zip_file *zip_fopen(struct zip *, const char *, zip_flags_t);
+ZIP_EXTERN struct zip_file *zip_fopen_encrypted(struct zip *, const char *, zip_flags_t, const char *);
+ZIP_EXTERN struct zip_file *zip_fopen_index(struct zip *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN struct zip_file *zip_fopen_index_encrypted(struct zip *, zip_uint64_t, zip_flags_t, const char *);
+ZIP_EXTERN zip_int64_t zip_fread(struct zip_file *, void *, zip_uint64_t);
+ZIP_EXTERN const char *zip_get_archive_comment(struct zip *, int *, zip_flags_t);
+ZIP_EXTERN int zip_get_archive_flag(struct zip *, zip_flags_t, zip_flags_t);
+ZIP_EXTERN const char *zip_file_get_comment(struct zip *, zip_uint64_t, zip_uint32_t *, zip_flags_t);
+ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t);
+ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t);
+ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(struct zip *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN const char *zip_get_name(struct zip *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN zip_int64_t zip_get_num_entries(struct zip *, zip_flags_t);
+ZIP_EXTERN zip_int64_t zip_name_locate(struct zip *, const char *, zip_flags_t);
+ZIP_EXTERN struct zip *zip_open(const char *, int, int *);
+ZIP_EXTERN int zip_file_rename(struct zip *, zip_uint64_t, const char *, zip_flags_t);
+ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, struct zip_source *, zip_flags_t);
+ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, zip_uint16_t);
+ZIP_EXTERN int zip_set_archive_flag(struct zip *, zip_flags_t, int);
+ZIP_EXTERN int zip_set_default_password(struct zip *, const char *);
+ZIP_EXTERN int zip_file_set_comment(struct zip *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN int zip_set_file_compression(struct zip *, zip_uint64_t, zip_int32_t, zip_uint32_t);
+ZIP_EXTERN int zip_file_extra_field_set(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *, zip_uint64_t, int);
+ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN struct zip_source *zip_source_filep(struct zip *, FILE *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN void zip_source_free(struct zip_source *);
+ZIP_EXTERN struct zip_source *zip_source_function(struct zip *, zip_source_callback, void *);
+ZIP_EXTERN struct zip_source *zip_source_zip(struct zip *, struct zip *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN int zip_stat(struct zip *, const char *, zip_flags_t, struct zip_stat *);
+ZIP_EXTERN int zip_stat_index(struct zip *, zip_uint64_t, zip_flags_t, struct zip_stat *);
+ZIP_EXTERN void zip_stat_init(struct zip_stat *);
+ZIP_EXTERN const char *zip_strerror(struct zip *);
+ZIP_EXTERN int zip_unchange(struct zip *, zip_uint64_t);
+ZIP_EXTERN int zip_unchange_all(struct zip *);
+ZIP_EXTERN int zip_unchange_archive(struct zip *);
+
 
 END_EXTERN_C();
 #endif /* _HAD_ZIP_H */
index 6067abbac491fb64532b2d195af7ce08de3fee26..4bce3fd4af2743330110162e0738d020034c25e6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_add.c -- add file via callback function
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -33,6 +33,7 @@
 
 \f
 
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 \f
         ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
 */
 
-ZIP_EXTERN(zip_int64_t)
+ZIP_EXTERN zip_int64_t
 zip_add(struct zip *za, const char *name, struct zip_source *source)
 {
-    if (name == NULL || source == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
-    }
-       
-    return _zip_replace(za, ZIP_UINT64_MAX, name, source);
+    return zip_file_add(za, name, source, 0);
 }
index 0a9d7f4863011edb8ff89fd4c624a3d0e31a6cb3..22a28bd8562531a28d4232039df7f364db5ec662 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_add_dir.c -- add directory
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2013 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>
 
 \f
 
-#include <stdlib.h>
-#include <string.h>
-
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 \f
 
 /* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
 
-ZIP_EXTERN(zip_int64_t)
+ZIP_EXTERN zip_int64_t
 zip_add_dir(struct zip *za, const char *name)
 {
-    int len;
-    zip_int64_t ret;
-    char *s;
-    struct zip_source *source;
-
-    if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
-    }
-
-    if (name == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
-    }
-
-    s = NULL;
-    len = strlen(name);
-
-    if (name[len-1] != '/') {
-       if ((s=(char *)malloc(len+2)) == NULL) {
-           _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-           return -1;
-       }
-       strcpy(s, name);
-       s[len] = '/';
-       s[len+1] = '\0';
-    }
-
-    if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) {
-       free(s);
-       return -1;
-    }
-       
-    ret = _zip_replace(za, -1, s ? s : name, source);
-
-    free(s);
-    if (ret < 0)
-       zip_source_free(source);
-
-    return ret;
+    return zip_dir_add(za, name, 0);
 }
diff --git a/ext/zip/lib/zip_add_entry.c b/ext/zip/lib/zip_add_entry.c
new file mode 100644 (file)
index 0000000..3a7e2cc
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+  zip_add_entry.c -- create and init struct zip_entry
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include <stdlib.h>
+
+#include "zipint.h"
+
+\f
+
+/* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
+
+zip_int64_t
+_zip_add_entry(struct zip *za)
+{
+    zip_uint64_t idx;
+
+    if (za->nentry+1 >= za->nentry_alloc) {
+       struct zip_entry *rentries;
+       zip_uint64_t nalloc = za->nentry_alloc + 16;
+       rentries = (struct zip_entry *)realloc(za->entry, sizeof(struct zip_entry) * nalloc);
+       if (!rentries) {
+           _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+           return -1;
+       }
+       za->entry = rentries;
+       za->nentry_alloc = nalloc;
+    }
+
+    idx = za->nentry++;
+
+    _zip_entry_init(za->entry+idx);
+
+    return (zip_int64_t)idx;
+}
index 576be3b3536fb68e4d48d742ec7098c7878edd6c..c9c7e58088644d51beaea984bf1b3829afd04206 100644 (file)
@@ -38,6 +38,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
 #include <errno.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #include <fcntl.h>
 #endif
 
-static int add_data(struct zip *, struct zip_source *, struct zip_dirent *,
-                   FILE *);
-static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
+\f
+
+/* max deflate size increase: size + ceil(size/16k)*5+6 */
+#define MAX_DEFLATE_SIZE_32    4293656963u
+
+static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, FILE *);
+static int copy_data(FILE *, zip_uint64_t, FILE *, struct zip_error *);
 static int copy_source(struct zip *, struct zip_source *, FILE *);
-static int write_cdir(struct zip *, struct zip_cdir *, FILE *);
-static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *);
+static int write_cdir(struct zip *, const struct zip_filelist *, zip_uint64_t, FILE *);
 static char *_zip_create_temp_output(struct zip *, FILE **);
 static int _zip_torrentzip_cmp(const void *, const void *);
 
 \f
 
-struct filelist {
-    int idx;
-    const char *name;
-};
-
-\f
-
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_close(struct zip *za)
 {
-    int survivors;
-    int i, j, error;
+    zip_uint64_t i, j, survivors;
+    int error;
     char *temp;
     FILE *out;
 #ifndef PHP_WIN32
     mode_t mask;
 #endif
-    struct zip_cdir *cd;
-    struct zip_dirent de;
-    struct filelist *filelist;
+    struct zip_filelist *filelist;
     int reopen_on_error;
     int new_torrentzip;
+    int changed;
 
     reopen_on_error = 0;
 
     if (za == NULL)
        return -1;
 
-    if (!_zip_changed(za, &survivors)) {
-       _zip_free(za);
-       return 0;
-    }
+    changed = _zip_changed(za, &survivors);
 
     /* don't create zip files with no entries */
     if (survivors == 0) {
-       if (za->zn && za->zp) {
+       if (za->zn && ((za->open_flags & ZIP_TRUNCATE) || (changed && za->zp))) {
            if (remove(za->zn) != 0) {
                _zip_error_set(&za->error, ZIP_ER_REMOVE, errno);
                return -1;
            }
        }
-       _zip_free(za);
+       zip_discard(za);
        return 0;
     }         
 
-    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;
+    if (!changed) {
+       zip_discard(za);
+       return 0;
     }
 
-    for (i=0; i<survivors; i++)
-       _zip_dirent_init(&cd->entry[i]);
+    if (survivors > za->nentry) {
+        _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
+    }
+    
+    if ((filelist=(struct zip_filelist *)malloc(sizeof(filelist[0])*survivors)) == NULL)
+       return -1;
 
     /* 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);
+       /* XXX: use internal function when zip_set_archive_comment clears TORRENT flag */
+       if (zip_set_archive_comment(za, TORRENT_SIG "XXXXXXXX", TORRENT_SIG_LEN + TORRENT_CRC_LEN) < 0) {
            free(filelist);
            return -1;
        }
     }
-
-    if ((temp=_zip_create_temp_output(za, &out)) == NULL) {
-       _zip_cdir_free(cd);
-       free(filelist);
-       return -1;
-    }
+    /* XXX: if no longer torrentzip and archive comment not changed by user, delete it */
 
 
     /* 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)
+       if (za->entry[i].deleted)
            continue;
 
+        if (j >= survivors) {
+            free(filelist);
+            _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+            return -1;
+        }
+        
        filelist[j].idx = i;
        filelist[j].name = zip_get_name(za, i, 0);
        j++;
     }
+    if (j < survivors) {
+        free(filelist);
+        _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        return -1;
+    }
+
+
+    if ((temp=_zip_create_temp_output(za, &out)) == NULL) {
+       free(filelist);
+       return -1;
+    }
+    
+    
     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
        qsort(filelist, survivors, sizeof(filelist[0]),
              _zip_torrentzip_cmp);
@@ -162,106 +161,49 @@ zip_close(struct zip *za)
                                              ZIP_FL_UNCHANGED) == 0);
     error = 0;
     for (j=0; j<survivors; j++) {
+       int new_data;
+       struct zip_entry *entry;
+       struct zip_dirent *de;
+
        i = filelist[j].idx;
+       entry = za->entry+i;
 
-       _zip_dirent_init(&de);
+       new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || new_torrentzip || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD));
 
        /* create new local directory entry */
-       if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {
-
-           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_ADDED) {
-                   de.filename = strdup("-");
-                   de.filename_len = 1;
-                   cd->entry[j].filename = "-";
-                   cd->entry[j].filename_len = 1;
-               }
-               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;
-               }
+       if (entry->changes == NULL) {
+           if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) {
+                _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                error = 1;
+                break;
            }
        }
-       else {
-           /* copy existing directory entries */
-           if ((NULL == za->zp) || (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0)) {
-               _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
-               error = 1;
-               break;
-           }
-           if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1,
-                                &za->error) != 0) {
-               error = 1;
-               break;
-           }
-           memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j]));
-           if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
-               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;
-           cd->entry[j].bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
-               }
-       }
+       de = entry->changes;
 
-       if (za->entry[i].ch_filename) {
-           free(de.filename);
-           if ((de.filename=strdup(za->entry[i].ch_filename)) == NULL) {
-               error = 1;
-               break;
-           }
-           de.filename_len = strlen(de.filename);
-           cd->entry[j].filename = za->entry[i].ch_filename;
-           cd->entry[j].filename_len = de.filename_len;
+       if (_zip_read_local_ef(za, i) < 0) {
+           error = 1;
+           break;
        }
 
-       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))
+           _zip_dirent_torrent_normalize(entry->changes);
 
-       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;
-       }
 
-       cd->entry[j].offset = ftello(out);
+       de->offset = (zip_uint64_t)ftello(out); /* XXX: check for errors */
 
-       if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) {
+       if (new_data) {
            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) {
+           if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
+               if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
                    error = 1;
                    break;
                }
            }
 
-           if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) {
+           /* add_data writes dirent */
+           if (add_data(za, zs ? zs : entry->source, de, out) < 0) {
                error = 1;
                if (zs)
                    zip_source_free(zs);
@@ -269,51 +211,49 @@ zip_close(struct zip *za)
            }
            if (zs)
                zip_source_free(zs);
-           
-           cd->entry[j].last_mod = de.last_mod;
-           cd->entry[j].comp_method = de.comp_method;
-           cd->entry[j].comp_size = de.comp_size;
-           cd->entry[j].uncomp_size = de.uncomp_size;
-           cd->entry[j].crc = de.crc;
        }
        else {
-           if (_zip_dirent_write(&de, out, 1, &za->error) < 0) {
+           zip_uint64_t offset;
+
+           /* when copying data, all sizes are known -> no data descriptor needed */
+           de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
+           if (_zip_dirent_write(de, out, ZIP_FL_LOCAL, &za->error) < 0) {
                error = 1;
                break;
            }
-           /* we just read the local dirent, file is at correct position */
-           if (copy_data(za->zp, cd->entry[j].comp_size, out,
-                         &za->error) < 0) {
+           if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) {
+               error = 1;
+               break;
+           }
+           if ((fseek(za->zp, (off_t)offset, SEEK_SET) < 0)) {
+               _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
+               error = 1;
+               break;
+           }
+           if (copy_data(za->zp, de->comp_size, out, &za->error) < 0) {
                error = 1;
                break;
            }
        }
-
-       _zip_dirent_finalize(&de);
     }
 
-    free(filelist);
-
     if (!error) {
-       if (write_cdir(za, cd, out) < 0)
+       if (write_cdir(za, filelist, survivors, out) < 0)
            error = 1;
     }
 
-    /* pointers in cd entries are owned by za */
-    cd->nentry = 0;
-    _zip_cdir_free(cd);
+    free(filelist);
 
     if (error) {
-       _zip_dirent_finalize(&de);
        fclose(out);
-       remove(temp);
+       (void)remove(temp);
        free(temp);
        return -1;
     }
 
     if (fclose(out) != 0) {
        _zip_error_set(&za->error, ZIP_ER_CLOSE, errno);
-       remove(temp);
+       (void)remove(temp);
        free(temp);
        return -1;
     }
@@ -325,7 +265,7 @@ zip_close(struct zip *za)
     }
     if (_zip_rename(temp, za->zn) != 0) {
        _zip_error_set(&za->error, ZIP_ER_RENAME, errno);
-       remove(temp);
+       (void)remove(temp);
        free(temp);
        if (reopen_on_error) {
            /* ignore errors, since we're already in an error case */
@@ -339,56 +279,112 @@ zip_close(struct zip *za)
     chmod(za->zn, 0666&~mask);
 #endif
 
-    _zip_free(za);
-       free(temp);
-
+    zip_discard(za);
+    free(temp);
+    
     return 0;
 }
 
 \f
 
 static int
-add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de,
-        FILE *ft)
+add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, FILE *ft)
 {
     off_t offstart, offdata, offend;
     struct zip_stat st;
     struct zip_source *s2;
-    zip_compression_implementation comp_impl;
     int ret;
+    int is_zip64;
+    zip_flags_t flags;
     
     if (zip_source_stat(src, &st) < 0) {
        _zip_error_set_from_source(&za->error, src);
        return -1;
     }
 
+    if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
+       st.valid |= ZIP_STAT_COMP_METHOD;
+       st.comp_method = ZIP_CM_STORE;
+    }
+
+    if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
+       de->comp_method = st.comp_method;
+    else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
+       st.valid |= ZIP_STAT_COMP_SIZE;
+       st.comp_size = st.size;
+    }
+    else {
+       /* we'll recompress */
+       st.valid &= ~ZIP_STAT_COMP_SIZE;
+    }
+
+
+    flags = ZIP_EF_LOCAL;
+
+    if ((st.valid & ZIP_STAT_SIZE) == 0)
+       flags |= ZIP_FL_FORCE_ZIP64;
+    else {
+       de->uncomp_size = st.size;
+       
+       if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
+           if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
+                || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
+               flags |= ZIP_FL_FORCE_ZIP64;
+       }
+       else
+           de->comp_size = st.comp_size;
+    }
+
+
     offstart = ftello(ft);
 
-    if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
+    /* as long as we don't support non-seekable output, clear data descriptor bit */
+    de->bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR;
+    if ((is_zip64=_zip_dirent_write(de, ft, flags, &za->error)) < 0)
        return -1;
 
-    if ((s2=zip_source_crc(za, src, 0)) == NULL) {
-       zip_source_pop(s2);
-       return -1;
-    }
-    
-    /* XXX: deflate 0-byte files for torrentzip? */
-    if (((st.valid & ZIP_STAT_COMP_METHOD) == 0
-        || st.comp_method == ZIP_CM_STORE)
-       && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
-       comp_impl = NULL;
-       if ((comp_impl=zip_get_compression_implementation(ZIP_CM_DEFLATE))
-           == NULL) {
-           _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
-           zip_source_pop(s2);
-           return -1;
+
+    if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) {
+       struct zip_source *s_store, *s_crc;
+       zip_compression_implementation comp_impl;
+       
+       if (st.comp_method != ZIP_CM_STORE) {
+           if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) {
+               _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+               return -1;
+           }
+           if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
+               /* error set by comp_impl */
+               return -1;
+           }
        }
-       if ((s2=comp_impl(za, s2, ZIP_CM_DEFLATE, ZIP_CODEC_ENCODE))
-           == NULL) {
-           /* XXX: set error? */
-           zip_source_pop(s2);
+       else
+           s_store = src;
+
+       if ((s_crc=zip_source_crc(za, s_store, 0)) == NULL) {
+           if (s_store != src)
+               zip_source_pop(s_store);
            return -1;
        }
+
+       /* XXX: deflate 0-byte files for torrentzip? */
+       if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
+           if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) {
+               _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+               zip_source_pop(s_crc);
+               if (s_store != src)
+                   zip_source_pop(s_store);
+               return -1;
+           }
+           if ((s2=comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) {
+               zip_source_pop(s_crc);
+               if (s_store != src)
+                   zip_source_pop(s_store);
+               return -1;
+           }
+       }
+       else
+           s2 = s_crc;
     }
     else
        s2 = src;
@@ -418,18 +414,33 @@ add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de,
        return -1;
     }
 
-    de->last_mod = st.mtime;
+    if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
+       _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+       return -1;
+    }
+
+    if (st.valid & ZIP_STAT_MTIME)
+       de->last_mod = st.mtime;
+    else
+       time(&de->last_mod);
     de->comp_method = st.comp_method;
     de->crc = st.crc;
     de->uncomp_size = st.size;
-    de->comp_size = offend - offdata;
+    de->comp_size = (zip_uint64_t)(offend - offdata);
 
     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)
+    if ((ret=_zip_dirent_write(de, ft, flags, &za->error)) < 0)
        return -1;
-    
+    if (is_zip64 != ret) {
+       /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
+       _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+       return -1;
+    }
+
+   
     if (fseeko(ft, offend, SEEK_SET) < 0) {
        _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
        return -1;
@@ -441,24 +452,26 @@ add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de,
 \f
 
 static int
-copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error)
+copy_data(FILE *fs, zip_uint64_t len, FILE *ft, struct zip_error *error)
 {
     char buf[BUFSIZE];
-    int n, nn;
+    size_t n, nn;
 
     if (len == 0)
        return 0;
 
     while (len > 0) {
        nn = len > sizeof(buf) ? sizeof(buf) : len;
-       if ((n=fread(buf, 1, nn, fs)) < 0) {
-           _zip_error_set(error, ZIP_ER_READ, errno);
-           return -1;
-       }
-       else if (n == 0) {
-           _zip_error_set(error, ZIP_ER_EOF, 0);
-           return -1;
-       }
+       if ((n=fread(buf, 1, nn, fs)) == 0) {
+            if (ferror(fs)) {
+                _zip_error_set(error, ZIP_ER_READ, errno);
+                return -1;
+            }
+            else {
+                _zip_error_set(error, ZIP_ER_EOF, 0);
+                return -1;
+            }
+        }
 
        if (fwrite(buf, 1, n, ft) != (size_t)n) {
            _zip_error_set(error, ZIP_ER_WRITE, errno);
@@ -487,7 +500,7 @@ copy_source(struct zip *za, struct zip_source *src, FILE *ft)
 
     ret = 0;
     while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
-       if (fwrite(buf, 1, n, ft) != (size_t)n) {
+       if (fwrite(buf, 1, (size_t)n, ft) != (size_t)n) {
            _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
            ret = -1;
            break;
@@ -508,29 +521,32 @@ copy_source(struct zip *za, struct zip_source *src, FILE *ft)
 \f
 
 static int
-write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out)
+write_cdir(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *out)
 {
-    off_t offset;
+    off_t cd_start, end;
+    zip_int64_t size;
     uLong crc;
     char buf[TORRENT_CRC_LEN+1];
     
-    if (_zip_cdir_write(cd, out, &za->error) < 0)
+    cd_start = ftello(out);
+
+    if ((size=_zip_cdir_write(za, filelist, survivors, out)) < 0)
        return -1;
     
+    end = ftello(out);
+
     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)
+    if (_zip_filerange_crc(out, cd_start, size, &crc, &za->error) < 0)
        return -1;
 
     snprintf(buf, sizeof(buf), "%08lX", (long)crc);
 
-    if (fseeko(out, offset-TORRENT_CRC_LEN, SEEK_SET) < 0) {
+    if (fseeko(out, end-TORRENT_CRC_LEN, SEEK_SET) < 0) {
        _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
        return -1;
     }
@@ -545,47 +561,22 @@ write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out)
 
 \f
 
-static int
-_zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src)
-{
-    if (src->ch_comment_len != -1) {
-       dest->comment = _zip_memdup(src->ch_comment,
-                                   src->ch_comment_len, &src->error);
-       if (dest->comment == NULL)
-           return -1;
-       dest->comment_len = src->ch_comment_len;
-    } else {
-       if (src->cdir && src->cdir->comment) {
-           dest->comment = _zip_memdup(src->cdir->comment,
-                                       src->cdir->comment_len, &src->error);
-           if (dest->comment == NULL)
-               return -1;
-           dest->comment_len = src->cdir->comment_len;
-       }
-    }
-
-    return 0;
-}
-
-\f
-
 int
-_zip_changed(struct zip *za, int *survivorsp)
+_zip_changed(const struct zip *za, zip_uint64_t *survivorsp)
 {
-    int changed, i, survivors;
+    int changed;
+    zip_uint64_t i, survivors;
 
-    changed = survivors = 0;
+    changed = 0;
+    survivors = 0;
 
-    if (za->ch_comment_len != -1
-       || za->ch_flags != za->flags)
+    if (za->comment_changed || za->ch_flags != za->flags)
        changed = 1;
 
     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))
+       if (za->entry[i].deleted || za->entry[i].source || (za->entry[i].changes && za->entry[i].changes->changed != 0))
            changed = 1;
-       if (za->entry[i].state != ZIP_ST_DELETED)
+       if (!za->entry[i].deleted)
            survivors++;
     }
 
@@ -603,14 +594,21 @@ _zip_create_temp_output(struct zip *za, FILE **outp)
     char *temp;
     int tfd;
     FILE *tfp;
-       int len = strlen(za->zn) + 8;
-
-    if ((temp=(char *)malloc(len)) == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return NULL;
+    
+    if (za->tempdir) {
+        if ((temp=(char *)malloc(strlen(za->tempdir)+13)) == NULL) {
+            _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return NULL;
+        }
+        sprintf(temp, "%s/.zip.XXXXXX", za->tempdir);
+    }
+    else {
+        if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) {
+            _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return NULL;
+        }
+        sprintf(temp, "%s.XXXXXX", za->zn);
     }
-
-               snprintf(temp, len, "%s.XXXXXX", za->zn);
 
     if ((tfd=mkstemp(temp)) == -1) {
        _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno);
@@ -621,7 +619,7 @@ _zip_create_temp_output(struct zip *za, FILE **outp)
     if ((tfp=fdopen(tfd, "r+b")) == NULL) {
        _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno);
        close(tfd);
-       remove(temp);
+       (void)remove(temp);
        free(temp);
        return NULL;
     }
@@ -630,7 +628,7 @@ _zip_create_temp_output(struct zip *za, FILE **outp)
       According to Pierre Joye, Windows in some environments per
       default creates text files, so force binary mode.
     */
-       _setmode(_fileno(tfp), _O_BINARY );
+    _setmode(_fileno(tfp), _O_BINARY );
 #endif
 
     *outp = tfp;
@@ -642,6 +640,13 @@ _zip_create_temp_output(struct zip *za, FILE **outp)
 static int
 _zip_torrentzip_cmp(const void *a, const void *b)
 {
-    return strcasecmp(((const struct filelist *)a)->name,
-                     ((const struct filelist *)b)->name);
+    const char *aname = ((const struct zip_filelist *)a)->name;
+    const char *bname = ((const struct zip_filelist *)b)->name;
+
+    if (aname == NULL)
+       return (bname != NULL) * -1;
+    else if (bname == NULL)
+       return 1;
+
+    return strcasecmp(aname, bname);
 }
index 131d444124c4b56cda3625adc4aaf63c63d83935..cb769367cc6f643edc19032cdd29d6cc03501959 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_delete(struct zip *za, zip_uint64_t idx)
 {
     if (idx >= za->nentry) {
@@ -55,7 +55,7 @@ zip_delete(struct zip *za, zip_uint64_t idx)
     if (_zip_unchange(za, idx, 1) != 0)
        return -1;
 
-    za->entry[idx].state = ZIP_ST_DELETED;
+    za->entry[idx].deleted = 1;
 
     return 0;
 }
similarity index 61%
rename from ext/zip/lib/zip_entry_new.c
rename to ext/zip/lib/zip_dir_add.c
index ad5d59975a927444fef49e5d1e48e4badc0a681c..0a74bd608764ec9814dad1c1c2a42284e0785329 100644 (file)
@@ -1,6 +1,6 @@
 /*
-  zip_entry_new.c -- create and init struct zip_entry
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  zip_dir_add.c -- add directory
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 \f
 
 #include <stdlib.h>
+#include <string.h>
 
 #include "zipint.h"
 
 \f
 
-struct zip_entry *
-_zip_entry_new(struct zip *za)
+/* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
+
+ZIP_EXTERN zip_int64_t
+zip_dir_add(struct zip *za, const char *name, zip_flags_t flags)
 {
-    struct zip_entry *ze;
-    if (!za) {
-       ze = (struct zip_entry *)malloc(sizeof(struct zip_entry));
-       if (!ze) {
-           return NULL;
-       }
+    size_t len;
+    zip_int64_t ret;
+    char *s;
+    struct zip_source *source;
+
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       return -1;
     }
-    else {
-       if (za->nentry+1 >= za->nentry_alloc) {
-           struct zip_entry *rentries;
-           za->nentry_alloc += 16;
-           rentries = (struct zip_entry *)realloc(za->entry,
-                                                  sizeof(struct zip_entry)
-                                                  * za->nentry_alloc);
-           if (!rentries) {
-               _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               return NULL;
-           }
-           za->entry = rentries;
-       }
-       ze = za->entry+za->nentry;
+
+    if (name == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
     }
 
-    ze->state = ZIP_ST_UNCHANGED;
+    s = NULL;
+    len = strlen(name);
 
-    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;
+    if (name[len-1] != '/') {
+       if ((s=(char *)malloc(len+2)) == NULL) {
+           _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+           return -1;
+       }
+       strcpy(s, name);
+       s[len] = '/';
+       s[len+1] = '\0';
+    }
+
+    if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) {
+       free(s);
+       return -1;
+    }
+       
+    ret = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
 
-    if (za)
-       za->nentry++;
+    free(s);
+    if (ret < 0)
+       zip_source_free(source);
 
-    return ze;
+    return ret;
 }
index b9dac5c989e3276d6a2b94fe1628af5cc9ae20dc..f4f2deb6fc5b9e2b1d572a6c04b3734056ae0333 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_dirent.c -- read directory entry (local or central), clean dirent
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2013 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>
 
 #include "zipint.h"
 
-static time_t _zip_d2u_time(int, int);
-static char *_zip_readfpstr(FILE *, unsigned int, int, struct zip_error *);
-static char *_zip_readstr(unsigned char **, int, int, struct zip_error *);
-static void _zip_write2(unsigned short, FILE *);
-static void _zip_write4(unsigned int, FILE *);
+static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t);
+static struct zip_string *_zip_read_string(const unsigned char **, FILE *, zip_uint16_t, int, struct zip_error *);
+static struct zip_string *_zip_dirent_process_ef_utf_8(const struct zip_dirent *, zip_uint16_t, struct zip_string *);
+static struct zip_extra_field *_zip_ef_utf8(zip_uint16_t, struct zip_string *, struct zip_error *);
 
 \f
 
 void
 _zip_cdir_free(struct zip_cdir *cd)
 {
-    int i;
+    zip_uint64_t i;
 
     if (!cd)
        return;
 
     for (i=0; i<cd->nentry; i++)
-       _zip_dirent_finalize(cd->entry+i);
-    free(cd->comment);
+       _zip_entry_finalize(cd->entry+i);
     free(cd->entry);
+    _zip_string_free(cd->comment);
     free(cd);
 }
 
 \f
 
 int
-_zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error)
+_zip_cdir_grow(struct zip_cdir *cd, zip_uint64_t nentry, struct zip_error *error)
 {
-    struct zip_dirent *entry;
+    struct zip_entry *entry;
+    zip_uint64_t i;
 
-    if (nentry < cd->nentry) {
+    if (nentry < cd->nentry_alloc) {
        _zip_error_set(error, ZIP_ER_INTERNAL, 0);
        return -1;
     }
 
-    if ((entry=((struct zip_dirent *)
+    if (nentry == cd->nentry_alloc)
+       return 0;
+
+    if ((entry=((struct zip_entry *)
                realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) {
        _zip_error_set(error, ZIP_ER_MEMORY, 0);
        return -1;
     }
+    
+    for (i=cd->nentry_alloc; i<nentry; i++)
+       _zip_entry_init(entry+i);
 
-    cd->nentry = nentry;
+    cd->nentry_alloc = nentry;
     cd->entry = entry;
 
     return 0;
@@ -92,64 +98,132 @@ _zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error)
 \f
 
 struct zip_cdir *
-_zip_cdir_new(int nentry, struct zip_error *error)
+_zip_cdir_new(zip_uint64_t nentry, struct zip_error *error)
 {
     struct zip_cdir *cd;
+    zip_uint64_t i;
     
     if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) {
        _zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
-    if ((cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*nentry))
-       == NULL) {
+    if (nentry == 0)
+       cd->entry = NULL;
+    else if ((cd->entry=(struct zip_entry *)malloc(sizeof(*(cd->entry))*nentry)) == NULL) {
        _zip_error_set(error, ZIP_ER_MEMORY, 0);
        free(cd);
        return NULL;
     }
 
-    /* entries must be initialized by caller */
+    for (i=0; i<nentry; i++)
+       _zip_entry_init(cd->entry+i);
 
-    cd->nentry = nentry;
+    cd->nentry = cd->nentry_alloc = nentry;
     cd->size = cd->offset = 0;
     cd->comment = NULL;
-    cd->comment_len = 0;
 
     return cd;
 }
 
 \f
 
-int
-_zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error)
+zip_int64_t
+_zip_cdir_write(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *fp)
 {
-    int i;
+    off_t off;
+    zip_uint64_t offset, size;
+    struct zip_string *comment;
+    zip_uint64_t i;
+    int is_zip64;
+    int ret;
+
+    if ((off=ftello(fp)) < 0) {
+        _zip_error_set(&za->error, ZIP_ER_READ, errno);
+        return -1;
+    }
+    offset = (zip_uint64_t)off;
 
-    cd->offset = ftello(fp);
+    is_zip64 = 0;
 
-    for (i=0; i<cd->nentry; i++) {
-       if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0)
+    for (i=0; i<survivors; i++) {
+       struct zip_entry *entry = za->entry+filelist[i].idx;
+
+       if ((ret=_zip_dirent_write(entry->changes ? entry->changes : entry->orig, fp, ZIP_FL_CENTRAL, &za->error)) < 0)
            return -1;
+       if (ret)
+           is_zip64 = 1;
+    }
+
+    if ((off=ftello(fp)) < 0) {
+        _zip_error_set(&za->error, ZIP_ER_READ, errno);
+        return -1;
+    }
+    size = (zip_uint64_t)off - offset;
+
+    if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX)
+       is_zip64 = 1;
+
+    if (is_zip64) {
+       fwrite(EOCD64_MAGIC, 1, 4, fp);
+       _zip_write8(EOCD64LEN-12, fp);
+       _zip_write2(45, fp);
+       _zip_write2(45, fp);
+       _zip_write4(0, fp);
+       _zip_write4(0, fp);
+       _zip_write8(survivors, fp);
+       _zip_write8(survivors, fp);
+       _zip_write8(size, fp);
+       _zip_write8(offset, fp);
+
+       fwrite(EOCD64LOC_MAGIC, 1, 4, fp);
+       _zip_write4(0, fp);
+       _zip_write8(offset+size, fp);
+       _zip_write4(1, fp);
+                   
     }
 
-    cd->size = ftello(fp) - cd->offset;
-    
     /* clearerr(fp); */
     fwrite(EOCD_MAGIC, 1, 4, fp);
     _zip_write4(0, fp);
-    _zip_write2((unsigned short)cd->nentry, fp);
-    _zip_write2((unsigned short)cd->nentry, fp);
-    _zip_write4(cd->size, fp);
-    _zip_write4(cd->offset, fp);
-    _zip_write2(cd->comment_len, fp);
-    fwrite(cd->comment, 1, cd->comment_len, fp);
+    _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors, fp);
+    _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : (zip_uint16_t)survivors, fp);
+    _zip_write4(size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size, fp);
+    _zip_write4(offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset, fp);
+
+    comment = za->comment_changed ? za->comment_changes : za->comment_orig;
+
+    _zip_write2(comment ? comment->length : 0, fp);
+    if (comment)
+       fwrite(comment->raw, 1, comment->length, fp);
 
     if (ferror(fp)) {
-       _zip_error_set(error, ZIP_ER_WRITE, errno);
+       _zip_error_set(&za->error, ZIP_ER_WRITE, errno);
        return -1;
     }
 
-    return 0;
+    return (zip_int64_t)size;
+}
+
+\f
+
+struct zip_dirent *
+_zip_dirent_clone(const struct zip_dirent *sde)
+{
+    struct zip_dirent *tde;
+
+    if ((tde=(struct zip_dirent *)malloc(sizeof(*tde))) == NULL)
+       return NULL;
+
+    if (sde)
+       memcpy(tde, sde, sizeof(*sde));
+    else
+       _zip_dirent_init(tde);
+    
+    tde->changed = 0;
+    tde->cloned = 1;
+
+    return tde;
 }
 
 \f
@@ -157,18 +231,24 @@ _zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error)
 void
 _zip_dirent_finalize(struct zip_dirent *zde)
 {
-    if (zde->filename_len > 0) {
-        free(zde->filename);
-    }
-    zde->filename = NULL;
-    if (zde->extrafield_len > 0) {
-        free(zde->extrafield);
-    }
-    zde->extrafield = NULL;
-    if (zde->comment_len > 0) {
-        free(zde->comment);
-    }
-    zde->comment = NULL;
+    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME)
+       _zip_string_free(zde->filename);
+    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD)
+       _zip_ef_free(zde->extra_fields);
+    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT)
+       _zip_string_free(zde->comment);
+}
+
+\f
+
+void
+_zip_dirent_free(struct zip_dirent *zde)
+{
+    if (zde == NULL)
+       return;
+
+    _zip_dirent_finalize(zde);
+    free(zde);
 }
 
 \f
@@ -176,20 +256,21 @@ _zip_dirent_finalize(struct zip_dirent *zde)
 void
 _zip_dirent_init(struct zip_dirent *de)
 {
-    de->version_madeby = 0;
+    de->changed = 0;
+    de->local_extra_fields_read = 0;
+    de->cloned = 0;
+
+    de->version_madeby = 20;
     de->version_needed = 20; /* 2.0 */
     de->bitflags = 0;
-    de->comp_method = 0;
+    de->comp_method = ZIP_CM_DEFAULT;
     de->last_mod = 0;
     de->crc = 0;
     de->comp_size = 0;
     de->uncomp_size = 0;
     de->filename = NULL;
-    de->filename_len = 0;
-    de->extrafield = NULL;
-    de->extrafield_len = 0;
+    de->extra_fields = NULL;
     de->comment = NULL;
-    de->comment_len = 0;
     de->disk_number = 0;
     de->int_attrib = 0;
     de->ext_attrib = 0;
@@ -198,6 +279,32 @@ _zip_dirent_init(struct zip_dirent *de)
 
 \f
 
+int
+_zip_dirent_needs_zip64(const struct zip_dirent *de, zip_flags_t flags)
+{
+    if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX
+       || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX))
+       return 1;
+
+    return 0;
+}
+
+\f
+
+struct zip_dirent *
+_zip_dirent_new(void)
+{
+    struct zip_dirent *de;
+
+    if ((de=(struct zip_dirent *)malloc(sizeof(*de))) == NULL)
+       return NULL;
+
+    _zip_dirent_init(de);
+    return de;
+}
+
+\f
+
 /* _zip_dirent_read(zde, fp, bufp, left, localp, error):
    Fills the zip directory entry zde.
 
@@ -218,13 +325,14 @@ _zip_dirent_init(struct zip_dirent *de)
 
 int
 _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
-                unsigned char **bufp, zip_uint32_t *leftp, int local,
+                const unsigned char **bufp, zip_uint64_t *leftp, int local,
                 struct zip_error *error)
 {
     unsigned char buf[CDENTRYSIZE];
-    unsigned char *cur;
-    unsigned short dostime, dosdate;
+    const unsigned char *cur;
+    zip_uint16_t dostime, dosdate;
     zip_uint32_t size;
+    zip_uint16_t filename_len, comment_len, ef_len;
 
     if (local)
        size = LENTRYSIZE;
@@ -255,9 +363,10 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
     }
     cur += 4;
 
-    
+
     /* convert buffercontents to zip_dirent */
-    
+
+    _zip_dirent_init(zde);
     if (!local)
        zde->version_madeby = _zip_read2(&cur);
     else
@@ -275,17 +384,17 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
     zde->comp_size = _zip_read4(&cur);
     zde->uncomp_size = _zip_read4(&cur);
     
-    zde->filename_len = _zip_read2(&cur);
-    zde->extrafield_len = _zip_read2(&cur);
+    filename_len = _zip_read2(&cur);
+    ef_len = _zip_read2(&cur);
     
     if (local) {
-       zde->comment_len = 0;
+       comment_len = 0;
        zde->disk_number = 0;
        zde->int_attrib = 0;
        zde->ext_attrib = 0;
        zde->offset = 0;
     } else {
-       zde->comment_len = _zip_read2(&cur);
+       comment_len = _zip_read2(&cur);
        zde->disk_number = _zip_read2(&cur);
        zde->int_attrib = _zip_read2(&cur);
        zde->ext_attrib = _zip_read4(&cur);
@@ -293,56 +402,102 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
     }
 
     zde->filename = NULL;
-    zde->extrafield = NULL;
+    zde->extra_fields = NULL;
     zde->comment = NULL;
 
-    size += zde->filename_len+zde->extrafield_len+zde->comment_len;
+    size += filename_len+ef_len+comment_len;
 
     if (leftp && (*leftp < size)) {
-       _zip_error_set(error, ZIP_ER_NOZIP, 0);
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
        return -1;
     }
 
-    if (bufp) {
-       if (zde->filename_len) {
-           zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error);
-           if (!zde->filename)
-                   return -1;
-       }
+    if (filename_len) {
+       zde->filename = _zip_read_string(bufp ? &cur : NULL, fp, filename_len, 1, error);
+       if (!zde->filename)
+           return -1;
 
-       if (zde->extrafield_len) {
-           zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0,
-                                          error);
-           if (!zde->extrafield)
+       if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
+           if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
+               _zip_error_set(error, ZIP_ER_INCONS, 0);
                return -1;
+           }
        }
+    }
 
-       if (zde->comment_len) {
-           zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error);
-           if (!zde->comment)
-               return -1;
+    if (ef_len) {
+       zip_uint8_t *ef = _zip_read_data(bufp ? &cur : NULL, fp, ef_len, 0, error);
+
+       if (ef == NULL)
+           return -1;
+       if ((zde->extra_fields=_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error)) == NULL) {
+           free(ef);
+           return -1;
        }
+       free(ef);
+       if (local)
+           zde->local_extra_fields_read = 1;
     }
-    else {
-       if (zde->filename_len) {
-           zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error);
-           if (!zde->filename)
-                   return -1;
-       }
 
-       if (zde->extrafield_len) {
-           zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0,
-                                            error);
-           if (!zde->extrafield)
+    if (comment_len) {
+       zde->comment = _zip_read_string(bufp ? &cur : NULL, fp, comment_len, 0, error);
+       if (!zde->comment)
+           return -1;
+
+       if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
+           if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
+               _zip_error_set(error, ZIP_ER_INCONS, 0);
                return -1;
+           }
        }
+    }
 
-       if (zde->comment_len) {
-           zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error);
-           if (!zde->comment)
-               return -1;
+    zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename);
+    zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment);
+
+    /* Zip64 */
+
+    if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
+       zip_uint16_t got_len, needed_len;
+       const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error);
+       /* XXX: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
+       if (ef == NULL)
+           return -1;
+
+
+       if (local)
+           needed_len = 16;
+       else
+           needed_len = ((zde->uncomp_size == ZIP_UINT32_MAX) + (zde->comp_size == ZIP_UINT32_MAX) + (zde->offset == ZIP_UINT32_MAX)) * 8
+               + (zde->disk_number == ZIP_UINT16_MAX) * 4;
+
+       if (got_len != needed_len) {
+           _zip_error_set(error, ZIP_ER_INCONS, 0);
+           return -1;
        }
+       
+       if (zde->uncomp_size == ZIP_UINT32_MAX)
+           zde->uncomp_size = _zip_read8(&ef);
+       else if (local)
+           ef += 8;
+       if (zde->comp_size == ZIP_UINT32_MAX)
+           zde->comp_size = _zip_read8(&ef);
+       if (!local) {
+           if (zde->offset == ZIP_UINT32_MAX)
+               zde->offset = _zip_read8(&ef);
+           if (zde->disk_number == ZIP_UINT16_MAX)
+               zde->disk_number = _zip_read4(&ef);
+       }
+    }
+    
+    if (!local) {
+        if (zde->offset > ZIP_OFF_MAX) {
+            _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+            return -1;
+        }
     }
+    
+    zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
 
     if (bufp)
       *bufp = cur;
@@ -354,6 +509,65 @@ _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
 
 \f
 
+static struct zip_string *
+_zip_dirent_process_ef_utf_8(const struct zip_dirent *de, zip_uint16_t id, struct zip_string *str)
+{
+    zip_uint16_t ef_len;
+    zip_uint32_t ef_crc;
+
+    const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
+
+    if (ef == NULL || ef_len < 5 || ef[0] != 1)
+       return str;
+
+    ef++;
+    ef_crc = _zip_read4(&ef);
+
+    if (_zip_string_crc32(str) == ef_crc) {
+       struct zip_string *ef_str = _zip_string_new(ef, ef_len-5, ZIP_ENCODING_UTF8_KNOWN, NULL);
+
+       if (ef_str != NULL) {
+           _zip_string_free(str);
+           str = ef_str;
+       }
+    }
+    
+    return str;
+}
+
+\f
+
+zip_int32_t
+_zip_dirent_size(FILE *f, zip_uint16_t flags, struct zip_error *error)
+{
+    zip_int32_t size;
+    int local = (flags & ZIP_EF_LOCAL);
+    int i;
+    unsigned char b[6];
+    const unsigned char *p;
+
+    size = local ? LENTRYSIZE : CDENTRYSIZE;
+
+    if (fseek(f, local ? 26 : 28, SEEK_CUR) < 0) {
+       _zip_error_set(error, ZIP_ER_SEEK, errno);
+       return -1;
+    }
+
+    if (fread(b, (local ? 4 : 6), 1, f) != 1) {
+       _zip_error_set(error, ZIP_ER_READ, errno);
+       return -1;
+    }
+
+    p = b;
+    for (i=0; i<(local ? 2 : 3); i++) {
+       size += _zip_read2(&p);
+    }
+
+    return size;
+}
+
+\f
+
 /* _zip_dirent_torrent_normalize(de);
    Set values suitable for torrentzip.
 */
@@ -399,84 +613,157 @@ _zip_dirent_torrent_normalize(struct zip_dirent *de)
     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);
+    _zip_ef_free(de->extra_fields);
+    de->extra_fields = NULL;
+    _zip_string_free(de->comment);
     de->comment = NULL;
-    de->comment_len = 0;
 }
 
 \f
 
-/* _zip_dirent_write(zde, fp, localp, error):
+/* _zip_dirent_write(zde, fp, flags, error):
    Writes zip directory entry zde to file fp.
 
-   If localp != 0, it writes a local header instead of a central
-   directory entry.
+   If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
+   directory entry.  If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
 
-   Returns 0 if successful. On error, error is filled in and -1 is
+   Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
    returned.
 */
 
 int
-_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp,
-                 struct zip_error *error)
+_zip_dirent_write(struct zip_dirent *de, FILE *fp, zip_flags_t flags, struct zip_error *error)
 {
     unsigned short dostime, dosdate;
+    enum zip_encoding_type com_enc, name_enc;
+    struct zip_extra_field *ef;
+    zip_uint8_t ef_zip64[24], *ef_zip64_p;
+    int is_zip64;
+    int is_really_zip64;
+
+    ef = NULL;
 
-    fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
+    is_zip64 = 0;
 
-    if (!localp)
-       _zip_write2(zde->version_madeby, fp);
-    _zip_write2(zde->version_needed, fp);
-    _zip_write2(zde->bitflags, fp);
-    _zip_write2(zde->comp_method, fp);
+    fwrite((flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
 
-    _zip_u2d_time(zde->last_mod, &dostime, &dosdate);
+    name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
+    com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
+
+    if ((name_enc == ZIP_ENCODING_UTF8_KNOWN  && com_enc == ZIP_ENCODING_ASCII) ||
+       (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) ||
+       (name_enc == ZIP_ENCODING_UTF8_KNOWN  && com_enc == ZIP_ENCODING_UTF8_KNOWN))
+       de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
+    else {
+       de->bitflags &= ~ZIP_GPBF_ENCODING_UTF_8;
+       if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
+           ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, error);
+           if (ef == NULL)
+               return -1;
+       }
+       if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){
+           struct zip_extra_field *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, error);
+           if (ef2 == NULL) {
+               _zip_ef_free(ef);
+               return -1;
+           }
+           ef2->next = ef;
+           ef = ef2;
+       }
+    }
+
+    ef_zip64_p = ef_zip64;
+    if (flags & ZIP_FL_LOCAL) {
+       if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
+           _zip_poke8(de->comp_size, &ef_zip64_p);
+           _zip_poke8(de->uncomp_size, &ef_zip64_p);
+       }
+    }
+    else {
+       if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
+           if (de->comp_size >= ZIP_UINT32_MAX)
+               _zip_poke8(de->comp_size, &ef_zip64_p);
+           if (de->uncomp_size >= ZIP_UINT32_MAX)
+               _zip_poke8(de->uncomp_size, &ef_zip64_p);
+           if (de->offset >= ZIP_UINT32_MAX)
+               _zip_poke8(de->offset, &ef_zip64_p);
+       }
+    }
+
+    if (ef_zip64_p != ef_zip64) {
+       struct zip_extra_field *ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(ef_zip64_p-ef_zip64), ef_zip64, ZIP_EF_BOTH);
+       ef64->next = ef;
+       ef = ef64;
+       is_zip64 = 1;
+    }
+
+    if ((flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64))
+       is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
+    else
+       is_really_zip64 = is_zip64;
+    
+    if ((flags & ZIP_FL_LOCAL) == 0)
+       _zip_write2(is_really_zip64 ? 45 : de->version_madeby, fp);
+    _zip_write2(is_really_zip64 ? 45 : de->version_needed, fp);
+    _zip_write2(de->bitflags&0xfff9, fp); /* clear compression method specific flags */
+    _zip_write2((zip_uint16_t)de->comp_method, fp); /* XXX: can it be ZIP_CM_DEFAULT? */
+
+    _zip_u2d_time(de->last_mod, &dostime, &dosdate);
     _zip_write2(dostime, fp);
     _zip_write2(dosdate, fp);
+
+    _zip_write4(de->crc, fp);
+    if (de->comp_size < ZIP_UINT32_MAX)
+       _zip_write4((zip_uint32_t)de->comp_size, fp);
+    else
+       _zip_write4(ZIP_UINT32_MAX, fp);
+    if (de->uncomp_size < ZIP_UINT32_MAX)
+       _zip_write4((zip_uint32_t)de->uncomp_size, fp);
+    else
+       _zip_write4(ZIP_UINT32_MAX, fp);
+
+    _zip_write2(_zip_string_length(de->filename), fp);
+    _zip_write2(_zip_ef_size(de->extra_fields, flags) + _zip_ef_size(ef, ZIP_EF_BOTH), fp);
     
-    _zip_write4(zde->crc, fp);
-    _zip_write4(zde->comp_size, fp);
-    _zip_write4(zde->uncomp_size, fp);
-    
-    _zip_write2(zde->filename_len, fp);
-    _zip_write2(zde->extrafield_len, fp);
-    
-    if (!localp) {
-       _zip_write2(zde->comment_len, fp);
-       _zip_write2(zde->disk_number, fp);
-       _zip_write2(zde->int_attrib, fp);
-       _zip_write4(zde->ext_attrib, fp);
-       _zip_write4(zde->offset, fp);
+    if ((flags & ZIP_FL_LOCAL) == 0) {
+       _zip_write2(_zip_string_length(de->comment), fp);
+       _zip_write2((zip_uint16_t)de->disk_number, fp);
+       _zip_write2(de->int_attrib, fp);
+       _zip_write4(de->ext_attrib, fp);
+       if (de->offset < ZIP_UINT32_MAX)
+           _zip_write4((zip_uint32_t)de->offset, fp);
+       else
+           _zip_write4(ZIP_UINT32_MAX, fp);
     }
 
-    if (zde->filename_len)
-       fwrite(zde->filename, 1, zde->filename_len, fp);
+    if (de->filename)
+       _zip_string_write(de->filename, fp);
 
-    if (zde->extrafield_len)
-       fwrite(zde->extrafield, 1, zde->extrafield_len, fp);
+    if (ef)
+       _zip_ef_write(ef, ZIP_EF_BOTH, fp);
+    if (de->extra_fields)
+       _zip_ef_write(de->extra_fields, flags, fp);
 
-    if (!localp) {
-       if (zde->comment_len)
-           fwrite(zde->comment, 1, zde->comment_len, fp);
+    if ((flags & ZIP_FL_LOCAL) == 0) {
+       if (de->comment)
+           _zip_string_write(de->comment, fp);
     }
 
+    _zip_ef_free(ef);
+
     if (ferror(fp)) {
        _zip_error_set(error, ZIP_ER_WRITE, errno);
        return -1;
     }
 
-    return 0;
+    return is_zip64;
 }
 
 \f
 
 static time_t
-_zip_d2u_time(int dtime, int ddate)
+_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
 {
     struct tm tm;
 
@@ -498,12 +785,72 @@ _zip_d2u_time(int dtime, int ddate)
 
 \f
 
-unsigned short
-_zip_read2(unsigned char **a)
+static struct zip_extra_field *
+_zip_ef_utf8(zip_uint16_t id, struct zip_string *str, struct zip_error *error)
 {
-    unsigned short ret;
+    const zip_uint8_t *raw;
+    zip_uint8_t *data, *p;
+    zip_uint32_t len;
+    struct zip_extra_field *ef;
+
+    raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL);
+
+    if (len+5 > ZIP_UINT16_MAX) {
+        /* XXX: error */
+    }
+    
+    if ((data=(zip_uint8_t *)malloc(len+5)) == NULL) {
+       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+
+    p = data;
+    *(p++) = 1;
+    _zip_poke4(_zip_string_crc32(str), &p);
+    memcpy(p, raw, len);
+    p += len;
+
+    ef = _zip_ef_new(id, (zip_uint16_t)(p-data), data, ZIP_EF_BOTH);
+    free(data);
+    return ef;
+}
+
+\f
+
+struct zip_dirent *
+_zip_get_dirent(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_error *error)
+{
+    if (error == NULL)
+       error = &za->error;
+
+    if (idx >= za->nentry) {
+       _zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
+       if (za->entry[idx].orig == NULL) {
+           _zip_error_set(error, ZIP_ER_INVAL, 0);
+           return NULL;
+       }
+       if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
+           _zip_error_set(error, ZIP_ER_DELETED, 0);
+           return NULL;
+       }
+       return za->entry[idx].orig;
+    }
+    else
+       return za->entry[idx].changes;
+}
+
+\f
 
-    ret = (*a)[0]+((*a)[1]<<8);
+zip_uint16_t
+_zip_read2(const zip_uint8_t **a)
+{
+    zip_uint16_t ret;
+
+    ret = (zip_uint16_t)((*a)[0]+((*a)[1]<<8));
     *a += 2;
 
     return ret;
@@ -511,12 +858,12 @@ _zip_read2(unsigned char **a)
 
 \f
 
-unsigned int
-_zip_read4(unsigned char **a)
+zip_uint32_t
+_zip_read4(const zip_uint8_t **a)
 {
-    unsigned int ret;
+    zip_uint32_t ret;
 
-    ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
+    ret = ((((((zip_uint32_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
     *a += 4;
 
     return ret;
@@ -524,65 +871,108 @@ _zip_read4(unsigned char **a)
 
 \f
 
-static char *
-_zip_readfpstr(FILE *fp, unsigned int len, int nulp, struct zip_error *error)
+zip_uint64_t
+_zip_read8(const zip_uint8_t **a)
 {
-    char *r, *o;
+    zip_uint64_t x, y;
+
+    x = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
+    *a += 4;
+    y = ((((((zip_uint64_t)(*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
+    *a += 4;
+
+    return x+(y<<32);
+}
 
-    r = (char *)malloc(nulp ? len+1 : len);
+\f
+
+zip_uint8_t *
+_zip_read_data(const zip_uint8_t **buf, FILE *fp, size_t len, int nulp, struct zip_error *error)
+{
+    zip_uint8_t *r;
+
+    if (len == 0 && nulp == 0)
+       return NULL;
+
+    r = (zip_uint8_t *)malloc(nulp ? len+1 : len);
     if (!r) {
        _zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
-    if (fread(r, 1, len, fp)<len) {
-       free(r);
-       _zip_error_set(error, ZIP_ER_READ, errno);
-       return NULL;
+    if (buf) {
+       memcpy(r, *buf, len);
+       *buf += len;
+    }
+    else {
+       if (fread(r, 1, len, fp)<len) {
+           free(r);
+            if (ferror(fp))
+                _zip_error_set(error, ZIP_ER_READ, errno);
+            else
+                _zip_error_set(error, ZIP_ER_INCONS, 0);
+           return NULL;
+       }
     }
 
     if (nulp) {
+       zip_uint8_t *o;
        /* replace any in-string NUL characters with spaces */
        r[len] = 0;
        for (o=r; o<r+len; o++)
            if (*o == '\0')
                *o = ' ';
     }
-    
+
     return r;
 }
 
 \f
 
-static char *
-_zip_readstr(unsigned char **buf, int len, int nulp, struct zip_error *error)
+static struct zip_string *
+_zip_read_string(const zip_uint8_t **buf, FILE *fp, zip_uint16_t len, int nulp, struct zip_error *error)
 {
-    char *r, *o;
+    zip_uint8_t *raw;
+    struct zip_string *s;
 
-    r = (char *)malloc(nulp ? len+1 : len);
-    if (!r) {
-       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+    if ((raw=_zip_read_data(buf, fp, len, nulp, error)) == NULL)
        return NULL;
-    }
-    
-    memcpy(r, *buf, len);
-    *buf += len;
 
-    if (nulp) {
-       /* replace any in-string NUL characters with spaces */
-       r[len] = 0;
-       for (o=r; o<r+len; o++)
-           if (*o == '\0')
-               *o = ' ';
-    }
+    s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
+    free(raw);
+    return s;
+}
 
-    return r;
+\f
+
+void
+_zip_poke4(zip_uint32_t i, zip_uint8_t **p)
+{
+    *((*p)++) = i&0xff;
+    *((*p)++) = (i>>8)&0xff;
+    *((*p)++) = (i>>16)&0xff;
+    *((*p)++) = (i>>24)&0xff;
+}
+
+\f
+
+void
+_zip_poke8(zip_uint64_t i, zip_uint8_t **p)
+{
+    *((*p)++) = i&0xff;
+    *((*p)++) = (i>>8)&0xff;
+    *((*p)++) = (i>>16)&0xff;
+    *((*p)++) = (i>>24)&0xff;
+    *((*p)++) = (i>>32)&0xff;
+    *((*p)++) = (i>>40)&0xff;
+    *((*p)++) = (i>>48)&0xff;
+    *((*p)++) = (i>>56)&0xff;
 }
 
 \f
 
-static void
-_zip_write2(unsigned short i, FILE *fp)
+void
+_zip_write2(zip_uint16_t i, FILE *fp)
 {
     putc(i&0xff, fp);
     putc((i>>8)&0xff, fp);
@@ -592,13 +982,30 @@ _zip_write2(unsigned short i, FILE *fp)
 
 \f
 
-static void
-_zip_write4(unsigned int i, FILE *fp)
+void
+_zip_write4(zip_uint32_t i, FILE *fp)
+{
+    putc(i&0xff, fp);
+    putc((i>>8)&0xff, fp);
+    putc((i>>16)&0xff, fp);
+    putc((i>>24)&0xff, fp);
+    
+    return;
+}
+
+\f
+
+void
+_zip_write8(zip_uint64_t i, FILE *fp)
 {
     putc(i&0xff, fp);
     putc((i>>8)&0xff, fp);
     putc((i>>16)&0xff, fp);
     putc((i>>24)&0xff, fp);
+    putc((i>>32)&0xff, fp);
+    putc((i>>40)&0xff, fp);
+    putc((i>>48)&0xff, fp);
+    putc((i>>56)&0xff, fp);
     
     return;
 }
@@ -606,15 +1013,13 @@ _zip_write4(unsigned int i, FILE *fp)
 \f
 
 void
-_zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate)
+_zip_u2d_time(time_t time, zip_uint16_t *dtime, zip_uint16_t *ddate)
 {
     struct tm *tm;
 
     tm = localtime(&time);
-    *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5)
-       + tm->tm_mday;
-    *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5)
-       + ((tm->tm_sec)>>1);
+    *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday);
+    *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1));
 
     return;
 }
similarity index 86%
rename from ext/zip/lib/zip_free.c
rename to ext/zip/lib/zip_discard.c
index 9932c14fec9a2067cf36f52cb16fd051c77e159c..37ba8c2ea64dec32c76acc8844872f6c6d7fcb2f 100644 (file)
@@ -1,6 +1,6 @@
 /*
-  zip_free.c -- free struct zip
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  zip_discard.c -- discard and free struct zip
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 \f
 
-/* _zip_free:
+/* zip_discard:
    frees the space allocated to a zipfile struct, and closes the
    corresponding file. */
 
 void
-_zip_free(struct zip *za)
+zip_discard(struct zip *za)
 {
-    int i;
+    zip_uint64_t i;
 
     if (za == NULL)
        return;
@@ -58,13 +58,12 @@ _zip_free(struct zip *za)
        fclose(za->zp);
 
     free(za->default_password);
-    _zip_cdir_free(za->cdir);
-    free(za->ch_comment);
+    _zip_string_free(za->comment_orig);
+    _zip_string_free(za->comment_changes);
 
     if (za->entry) {
-       for (i=0; i<za->nentry; i++) {
-           _zip_entry_free(za->entry+i);
-       }
+       for (i=0; i<za->nentry; i++)
+           _zip_entry_finalize(za->entry+i);
        free(za->entry);
     }
 
similarity index 79%
rename from ext/zip/lib/zip_entry_free.c
rename to ext/zip/lib/zip_entry.c
index e8a77707f0bfa991954dde1256c307babdd9515a..58663e8d0c88e2e09ad441059add1024c2d35299 100644 (file)
@@ -1,6 +1,6 @@
 /*
-  zip_entry_free.c -- free struct zip_entry
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  zip_entry.c -- struct zip_entry helper functions
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 \f
 
-#include <stdlib.h>
-
 #include "zipint.h"
 
+void
+_zip_entry_finalize(struct zip_entry *e)
+{
+    _zip_unchange_data(e);
+    _zip_dirent_free(e->orig);
+    _zip_dirent_free(e->changes);
+}
+
 \f
 
 void
-_zip_entry_free(struct zip_entry *ze)
+_zip_entry_init(struct zip_entry *e)
 {
-    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;
-
-    _zip_unchange_data(ze);
+    e->orig = NULL;
+    e->changes = NULL;
+    e->source = NULL;
+    e->deleted = 0;
 }
index b8d907abf4d9a56531363c446533f187a6b4ce0c..4b1f27921a25650d3ad334090a87f4bc75df9d86 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error.c -- struct zip_error helper functions
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2013 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,9 @@
 void
 _zip_error_clear(struct zip_error *err)
 {
+    if (err == NULL)
+       return;
+
     err->zip_err = ZIP_ER_OK;
     err->sys_err = 0;
 }
@@ -49,7 +52,7 @@ _zip_error_clear(struct zip_error *err)
 \f
 
 void
-_zip_error_copy(struct zip_error *dst, struct zip_error *src)
+_zip_error_copy(struct zip_error *dst, const struct zip_error *src)
 {
     dst->zip_err = src->zip_err;
     dst->sys_err = src->sys_err;
@@ -67,7 +70,7 @@ _zip_error_fini(struct zip_error *err)
 \f
 
 void
-_zip_error_get(struct zip_error *err, int *zep, int *sep)
+_zip_error_get(const struct zip_error *err, int *zep, int *sep)
 {
     if (zep)
        *zep = err->zip_err;
index 34e7dea48ebbaaa0719c8d7e6a07ad19f9bf09e3..b4ff10391290a1b21c7093a7c586f5b7294f400e 100644 (file)
 
 \f
 
-ZIP_EXTERN(void)
+ZIP_EXTERN void
 zip_error_clear(struct zip *za)
 {
+    if (za == NULL)
+       return;
+
     _zip_error_clear(&za->error);
 }
index c15705e32fccdd75ec6e7fa1a4894c87f0505f6c..6d1c958c177660608e6bc451d6f5d355600b79e4 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(void)
+ZIP_EXTERN void
 zip_error_get(struct zip *za, int *zep, int *sep)
 {
     _zip_error_get(&za->error, zep, sep);
index 47aa93e69b927c44f416c2a6d8fb918914c4fe8c..6c6f38074040e7f68d1dd94023a0962152933505 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_error_get_sys_type(int ze)
 {
     if (ze < 0 || ze >= _zip_nerr_str)
index bafe74335a04942a74c4e5d75ef9741900d68e7e..11a0cd2bb0e6ddf684ad1d5048f664add716bff2 100644 (file)
@@ -42,7 +42,7 @@
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se)
 {
     const char *zs, *ss;
diff --git a/ext/zip/lib/zip_extra_field.c b/ext/zip/lib/zip_extra_field.c
new file mode 100644 (file)
index 0000000..41fd2b1
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+  zip_extra_field.c -- manipulate extra fields
+  Copyright (C) 2012-2013 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.
+*/
+
+\f
+
+#include "zipint.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+\f
+
+struct zip_extra_field *
+_zip_ef_clone(const struct zip_extra_field *ef, struct zip_error *error)
+{
+    struct zip_extra_field *head, *prev, *def;
+    
+    head = prev = NULL;
+    
+    while (ef) {
+        if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
+            _zip_error_set(error, ZIP_ER_MEMORY, 0);
+            _zip_ef_free(head);
+            return NULL;
+        }
+        
+        if (head == NULL)
+            head = def;
+        if (prev)
+            prev->next = def;
+        prev = def;
+
+       ef = ef->next;
+    }
+    
+    return head;
+}
+
+
+struct zip_extra_field *
+_zip_ef_delete_by_id(struct zip_extra_field *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags)
+{
+    struct zip_extra_field *head, *prev;
+    int i;
+
+    i = 0;
+    head = ef;
+    prev = NULL;
+    for (; ef; ef=(prev ? prev->next : head)) {
+       if ((ef->flags & flags & ZIP_EF_BOTH) && ef->id == id) {
+           if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
+               ef->flags &= ~(flags & ZIP_EF_BOTH);
+               if ((ef->flags & ZIP_EF_BOTH) == 0) {
+                   if (prev)
+                       prev->next = ef->next;
+                   else
+                       head = ef->next;
+                   ef->next = NULL;
+                   _zip_ef_free(ef);
+
+                   if (id_idx == ZIP_EXTRA_FIELD_ALL)
+                       continue;
+               }
+           }
+           
+           i++;
+           if (i > id_idx)
+               break;
+       }
+       prev = ef;
+    }
+
+    return head;
+}
+
+
+\f
+
+void
+_zip_ef_free(struct zip_extra_field *ef)
+{
+    struct zip_extra_field *ef2;
+
+    while (ef) {
+       ef2 = ef->next;
+       free(ef->data);
+       free(ef);
+       ef = ef2;
+    }
+}
+
+\f
+
+const zip_uint8_t *
+_zip_ef_get_by_id(const struct zip_extra_field *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, struct zip_error *error)
+{
+    static const zip_uint8_t empty[1] = { '\0' };
+    
+    int i;
+
+    i = 0;
+    for (; ef; ef=ef->next) {
+       if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
+           if (i < id_idx) {
+               i++;
+               continue;
+           }
+
+           if (lenp)
+               *lenp = ef->size;
+           if (ef->size > 0)
+               return ef->data;
+           else
+               return empty;
+       }
+    }
+
+    _zip_error_set(error, ZIP_ER_NOENT, 0);
+    return NULL;
+}
+
+\f
+
+struct zip_extra_field *
+_zip_ef_merge(struct zip_extra_field *to, struct zip_extra_field *from)
+{
+    struct zip_extra_field *ef2, *tt, *tail;
+    int duplicate;
+
+    if (to == NULL)
+       return from;
+
+    for (tail=to; tail->next; tail=tail->next)
+       ;
+
+    for (; from; from=ef2) {
+       ef2 = from->next;
+
+       duplicate = 0;
+       for (tt=to; tt; tt=tt->next) {
+           if (tt->id == from->id && tt->size == from->size && memcmp(tt->data, from->data, tt->size) == 0) {
+               tt->flags |= (from->flags & ZIP_EF_BOTH);
+               duplicate = 1;
+               break;
+           }
+       }
+
+       from->next = NULL;
+       if (duplicate)
+           _zip_ef_free(from);
+       else
+           tail = tail->next = from;
+    }
+
+    return to;
+}
+
+\f
+
+struct zip_extra_field *
+_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags)
+{
+    struct zip_extra_field *ef;
+
+    if ((ef=(struct zip_extra_field *)malloc(sizeof(*ef))) == NULL)
+       return NULL;
+
+    ef->next = NULL;
+    ef->flags = flags;
+    ef->id = id;
+    ef->size = size;
+    if (size > 0) {
+       if ((ef->data=(zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
+           free(ef);
+           return NULL;
+       }
+    }
+    else
+       ef->data = NULL;
+
+    return ef;
+}
+
+\f
+
+struct zip_extra_field *
+_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, struct zip_error *error)
+{
+    struct zip_extra_field *ef, *ef2, *ef_head;
+    const zip_uint8_t *p;
+    zip_uint16_t fid, flen;
+
+    ef_head = NULL;
+    for (p=data; p<data+len; p+=flen) {
+       if (p+4 > data+len) {
+           _zip_error_set(error, ZIP_ER_INCONS, 0);
+           _zip_ef_free(ef_head);
+           return NULL;
+       }
+
+       fid = _zip_read2(&p);
+       flen = _zip_read2(&p);
+
+       if (p+flen > data+len) {
+           _zip_error_set(error, ZIP_ER_INCONS, 0);
+           _zip_ef_free(ef_head);
+           return NULL;
+       }
+
+       if ((ef2=_zip_ef_new(fid, flen, p, flags)) == NULL) {
+           _zip_error_set(error, ZIP_ER_MEMORY, 0);
+           _zip_ef_free(ef_head);
+           return NULL;
+       }
+
+       if (ef_head) {
+           ef->next = ef2;
+           ef = ef2;
+       }
+       else
+           ef_head = ef = ef2;
+    }
+
+    return ef_head;
+}
+
+\f
+
+struct zip_extra_field *
+_zip_ef_remove_internal(struct zip_extra_field *ef)
+{
+    struct zip_extra_field *ef_head;
+    struct zip_extra_field *prev, *next;
+    
+    ef_head = ef;
+    prev = NULL;
+    
+    while (ef) {
+        if (ZIP_EF_IS_INTERNAL(ef->id)) {
+            next = ef->next;
+            if (ef_head == ef)
+                ef_head = next;
+            ef->next = NULL;
+            _zip_ef_free(ef);
+            if (prev)
+                prev->next = next;
+            ef = next;
+        }
+        else {
+            prev = ef;
+            ef = ef->next;
+        }
+    }
+    
+    return ef_head;
+}
+
+
+zip_uint16_t
+_zip_ef_size(const struct zip_extra_field *ef, zip_flags_t flags)
+{
+    zip_uint16_t size;
+
+    size = 0;
+    for (; ef; ef=ef->next) {
+       if (ef->flags & flags & ZIP_EF_BOTH)
+           size += 4+ef->size;
+    }
+
+    return size;
+}
+
+\f
+
+void
+_zip_ef_write(const struct zip_extra_field *ef, zip_flags_t flags, FILE *f)
+{
+    for (; ef; ef=ef->next) {
+       if (ef->flags & flags & ZIP_EF_BOTH) {
+           _zip_write2(ef->id, f);
+           _zip_write2(ef->size, f);
+           if (ef->size > 0)
+               fwrite(ef->data, ef->size, 1, f);
+       }
+    }
+}
+
+\f
+
+int
+_zip_read_local_ef(struct zip *za, zip_uint64_t idx)
+{
+    struct zip_entry *e;
+    unsigned char b[4];
+    const unsigned char *p;
+    zip_uint16_t fname_len, ef_len;
+
+    if (idx >= za->nentry) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    e = za->entry+idx;
+
+    if (e->orig == NULL || e->orig->local_extra_fields_read)
+       return 0;
+
+
+    if (fseeko(za->zp, (off_t)(e->orig->offset + 26), SEEK_SET) < 0) {
+       _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
+       return -1;
+    }
+
+    if (fread(b, sizeof(b), 1, za->zp) != 1) {
+       _zip_error_set(&za->error, ZIP_ER_READ, errno);
+       return -1;
+    }
+
+    p = b;
+    fname_len = _zip_read2(&p);
+    ef_len = _zip_read2(&p);
+
+    if (ef_len > 0) {
+       struct zip_extra_field *ef;
+       zip_uint8_t *ef_raw;
+
+       if (fseek(za->zp, fname_len, SEEK_CUR) < 0) {
+           _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
+           return -1;
+       }
+
+       ef_raw = _zip_read_data(NULL, za->zp, ef_len, 0, &za->error);
+
+       if (ef_raw == NULL)
+           return -1;
+
+       if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) {
+           free(ef_raw);
+           return -1;
+       }
+       free(ef_raw);
+       
+        ef = _zip_ef_remove_internal(ef);
+       e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
+    }
+
+    e->orig->local_extra_fields_read = 1;
+    
+    if (e->changes && e->changes->local_extra_fields_read == 0) {
+       e->changes->extra_fields = e->orig->extra_fields;
+       e->changes->local_extra_fields_read = 1;
+    }
+
+    return 0;
+}
diff --git a/ext/zip/lib/zip_extra_field_api.c b/ext/zip/lib/zip_extra_field_api.c
new file mode 100644 (file)
index 0000000..02ed455
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+  zip_extra_field_api.c -- public extra fields API functions
+  Copyright (C) 2012-2013 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.
+*/
+
+\f
+
+#include "zipint.h"
+
+\f
+
+ZIP_EXTERN int
+zip_file_extra_field_delete(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags)
+{
+    struct zip_dirent *de;
+
+    if ((flags & ZIP_EF_BOTH) == 0) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+    
+    if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
+       return -1;
+    
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       return -1;
+    }
+
+    if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
+        return -1;
+    
+    de = za->entry[idx].changes;
+    
+    de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags);
+    return 0;
+}
+
+\f
+
+ZIP_EXTERN int
+zip_file_extra_field_delete_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags)
+{
+    struct zip_dirent *de;
+
+    if ((flags & ZIP_EF_BOTH) == 0) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+    
+    if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
+       return -1;
+
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       return -1;
+    }
+    
+    if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
+        return -1;
+    
+    de = za->entry[idx].changes;
+
+    de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags);
+    return 0;
+}
+
+\f
+
+ZIP_EXTERN const zip_uint8_t *
+zip_file_extra_field_get(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags)
+{
+    static const zip_uint8_t empty[1] = { '\0' };
+
+    struct zip_dirent *de;
+    struct zip_extra_field *ef;
+    int i;
+
+    if ((flags & ZIP_EF_BOTH) == 0) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
+       return NULL;
+
+    if (flags & ZIP_FL_LOCAL)
+       if (_zip_read_local_ef(za, idx) < 0)
+           return NULL;
+
+    i = 0;
+    for (ef=de->extra_fields; ef; ef=ef->next) {
+       if (ef->flags & flags & ZIP_EF_BOTH) {
+           if (i < ef_idx) {
+               i++;
+               continue;
+           }
+
+           if (idp)
+               *idp = ef->id;
+           if (lenp)
+               *lenp = ef->size;
+           if (ef->size > 0)
+               return ef->data;
+           else
+               return empty;
+       }
+    }
+
+    _zip_error_set(&za->error, ZIP_ER_NOENT, 0);
+    return NULL;
+
+}
+
+\f
+
+ZIP_EXTERN const zip_uint8_t *
+zip_file_extra_field_get_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags)
+{
+    struct zip_dirent *de;
+
+    if ((flags & ZIP_EF_BOTH) == 0) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
+       return NULL;
+
+    if (flags & ZIP_FL_LOCAL)
+       if (_zip_read_local_ef(za, idx) < 0)
+           return NULL;
+
+    return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error);
+}
+
+\f
+
+ZIP_EXTERN zip_int16_t
+zip_file_extra_fields_count(struct zip *za, zip_uint64_t idx, zip_flags_t flags)
+{
+    struct zip_dirent *de;
+    struct zip_extra_field *ef;
+    zip_uint16_t n;
+
+    if ((flags & ZIP_EF_BOTH) == 0) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
+       return -1;
+
+    if (flags & ZIP_FL_LOCAL)
+       if (_zip_read_local_ef(za, idx) < 0)
+           return -1;
+
+    n = 0;
+    for (ef=de->extra_fields; ef; ef=ef->next)
+       if (ef->flags & flags & ZIP_EF_BOTH)
+           n++;
+
+    return (zip_int16_t)n;
+}
+
+\f
+
+ZIP_EXTERN zip_int16_t
+zip_file_extra_fields_count_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags)
+{
+    struct zip_dirent *de;
+    struct zip_extra_field *ef;
+    zip_uint16_t n;
+
+    if ((flags & ZIP_EF_BOTH) == 0) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
+       return -1;
+
+    if (flags & ZIP_FL_LOCAL)
+       if (_zip_read_local_ef(za, idx) < 0)
+           return -1;
+
+    n = 0;
+    for (ef=de->extra_fields; ef; ef=ef->next)
+       if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
+           n++;
+
+    return (zip_int16_t)n;
+}
+
+\f
+
+ZIP_EXTERN int
+zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags)
+{
+    struct zip_dirent *de;
+    zip_uint16_t ls, cs;
+    struct zip_extra_field *ef, *ef_prev, *ef_new;
+    int i, found, new_len;
+
+    if ((flags & ZIP_EF_BOTH) == 0) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
+       return -1;
+    
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       return -1;
+    }
+    
+    if (ZIP_EF_IS_INTERNAL(ef_id)) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
+        return -1;
+    
+    de = za->entry[idx].changes;
+
+    ef = de->extra_fields;
+    ef_prev = NULL;
+    i = 0;
+    found = 0;
+
+    for (; ef; ef=ef->next) {
+       if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
+           if (i == ef_idx) {
+               found = 1;
+               break;
+           }
+           i++;
+       }
+       ef_prev = ef;
+    }
+
+    if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    if (flags & ZIP_EF_LOCAL)
+       ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
+    else
+       ls = 0;
+    if (flags & ZIP_EF_CENTRAL)
+       cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
+    else
+       cs = 0;
+
+    new_len = ls > cs ? ls : cs;
+    if (found)
+       new_len -= ef->size + 4;
+    new_len += len + 4;
+
+    if (new_len > ZIP_UINT16_MAX) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+    
+    if ((ef_new=_zip_ef_new(ef_id, len, data, flags)) == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+       return -1;
+    }
+
+    if (found) {
+       if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
+           ef_new->next = ef->next;
+           ef->next = NULL;
+           _zip_ef_free(ef);
+           if (ef_prev)
+               ef_prev->next = ef_new;
+           else
+               de->extra_fields = ef_new;
+       }
+       else {
+           ef->flags &= ~(flags & ZIP_EF_BOTH);
+           ef_new->next = ef->next;
+           ef->next = ef_new;
+       }           
+    }
+    else if (ef_prev) {
+       ef_new->next = ef_prev->next;
+       ef_prev->next = ef_new;
+    }
+    else
+       de->extra_fields = ef_new;
+    
+    return 0;
+}
+
+
+
+int
+_zip_file_extra_field_prepare_for_change(struct zip *za, zip_uint64_t idx)
+{
+    struct zip_entry *e;
+    
+    if (idx >= za->nentry) {
+        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
+    }
+    
+    e = za->entry+idx;
+    
+    if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
+        return 0;
+
+    if (e->orig) {
+       if (_zip_read_local_ef(za, idx) < 0)
+           return -1;
+    }
+    
+    if (e->changes == NULL) {
+        if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+            _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+            return -1;
+        }
+    }
+    
+    if (e->orig && e->orig->extra_fields) {
+       if ((e->changes->extra_fields=_zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
+           return -1;
+    }
+    e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
+    
+    return 0;
+}
+
index eb55ddbcea4559827ec27b0b0fdb0b33c73d08ae..093c30eada9f155a06f2ad447162a81e834e1b57 100644 (file)
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_fclose(struct zip_file *zf)
 {
-    int i, ret;
+    int ret;
+    unsigned int i;
     
     if (zf->src)
        zip_source_free(zf->src);
 
-    for (i=0; i<zf->za->nfile; i++) {
-       if (zf->za->file[i] == zf) {
-           zf->za->file[i] = zf->za->file[zf->za->nfile-1];
-           zf->za->nfile--;
-           break;
-       }
+    if (zf->za) {
+        for (i=0; i<zf->za->nfile; i++) {
+            if (zf->za->file[i] == zf) {
+                zf->za->file[i] = zf->za->file[zf->za->nfile-1];
+                zf->za->nfile--;
+                break;
+            }
+        }
     }
 
     ret = 0;
index df70f27561ace9c5416c71aab6fbc16ed3e6a45c..bda9aabac4915af573631bda33e23709212301d4 100644 (file)
 
 \f
 
-ZIP_EXTERN(struct zip *)
-zip_fdopen(int fd_orig, int flags, int *zep)
+ZIP_EXTERN struct zip *
+zip_fdopen(int fd_orig, int _flags, int *zep)
 {
     int fd;
     FILE *fp;
+    unsigned int flags;
+
+    if (_flags < 0) {
+        if (zep)
+            *zep = ZIP_ER_INVAL;
+        return  NULL;
+    }
+    flags = (unsigned int)_flags;
+        
+    if (flags & ZIP_TRUNCATE) {
+       *zep = ZIP_ER_INVAL;
+       return NULL;
+    }
 
     /* We dup() here to avoid messing with the passed in fd.
        We could not restore it to the original state in case of error. */
@@ -58,5 +71,5 @@ zip_fdopen(int fd_orig, int flags, int *zep)
     }
 
     close(fd_orig);
-    return _zip_open(NULL, fp, flags, ZIP_AFL_RDONLY, zep);
+    return _zip_open(NULL, fp, flags, zep);
 }
diff --git a/ext/zip/lib/zip_file_add.c b/ext/zip/lib/zip_file_add.c
new file mode 100644 (file)
index 0000000..995cb91
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+  zip_file_add.c -- add file via callback function
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include "zipint.h"
+\f
+
+/*
+  NOTE: Return type is signed so we can return -1 on error.
+        The index can not be larger than ZIP_INT64_MAX since the size
+        of the central directory cannot be larger than
+        ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
+*/
+
+ZIP_EXTERN zip_int64_t
+zip_file_add(struct zip *za, const char *name, struct zip_source *source, zip_flags_t flags)
+{
+    if (name == NULL || source == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+       
+    return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);
+}
index 6c9c2a02b3f0f54528efe829624c654cf0f7b7fd..ce8b6cbd9403ac3247c292f4cec8e398e62c029d 100644 (file)
 
 \f
 
-ZIP_EXTERN(void)
+ZIP_EXTERN void
 zip_file_error_clear(struct zip_file *zf)
 {
+    if (zf == NULL)
+       return;
+
     _zip_error_clear(&zf->error);
 }
index a53fa7e0033243c236fea130160980d8e28739ad..f20e011fc747e1dc4e659a4e07a6e0f4f58320a4 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(void)
+ZIP_EXTERN void
 zip_file_error_get(struct zip_file *zf, int *zep, int *sep)
 {
     _zip_error_get(&zf->error, zep, sep);
similarity index 72%
rename from ext/zip/lib/zip_get_file_extra.c
rename to ext/zip/lib/zip_file_get_comment.c
index a27edd8ee9452cdb452c21cefb8d5fb1d877ad05..766731ea268efbc056248f64382def10070b5d0d 100644 (file)
@@ -1,6 +1,6 @@
 /*
-  zip_get_file_extra.c -- get file extra field
-  Copyright (C) 2006-2010 Dieter Baron and Thomas Klausner
+  zip_file_get_comment.c -- get file comment
+  Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
+\f
 
 #include "zipint.h"
 
+\f
+/* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */
 
-
-ZIP_EXTERN(const char *)
-zip_get_file_extra(struct zip *za, zip_uint64_t idx, int *lenp, int flags)
+ZIP_EXTERN const char *
+zip_file_get_comment(struct zip *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags)
 {
-    if (idx >= za->nentry) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+    struct zip_dirent *de;
+    zip_uint32_t len;
+    const zip_uint8_t *str;
+
+    if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL)
        return NULL;
-    }
-
-    if ((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;
+
+    if ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
+       return NULL;
+
+    if (lenp)
+       *lenp = len;
+
+    return (const char *)str;
 }
index b96fd5e48090766cb920ef7ff9e599690c928694..65a011fc077c334ca00ccf3b467e760b38e7fb57 100644 (file)
    On error, fills in za->error and returns 0.
 */
 
-unsigned int
-_zip_file_get_offset(struct zip *za, int idx)
+zip_uint64_t
+_zip_file_get_offset(const struct zip *za, zip_uint64_t idx, struct zip_error *error)
 {
-    struct zip_dirent de;
-    unsigned int offset;
+    zip_uint64_t offset;
+    zip_int32_t size;
 
-    offset = za->cdir->entry[idx].offset;
+    offset = za->entry[idx].orig->offset;
 
-    if (fseeko(za->zp, offset, SEEK_SET) != 0) {
-       _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
+    if (fseeko(za->zp, (off_t)offset, SEEK_SET) != 0) {
+       _zip_error_set(error, ZIP_ER_SEEK, errno);
        return 0;
     }
 
-    if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, &za->error) != 0)
+    /* XXX: cache? */
+    if ((size=_zip_dirent_size(za->zp, ZIP_EF_LOCAL, error)) < 0)
        return 0;
 
-    offset += LENTRYSIZE + de.filename_len + de.extrafield_len;
-
-    _zip_dirent_finalize(&de);
-
-    return offset;
+    if (offset+(zip_uint32_t)size > ZIP_OFF_MAX) {
+        _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return 0;
+    }
+    
+    return offset + (zip_uint32_t)size;
 }
similarity index 70%
rename from ext/zip/lib/zip_set_file_extra.c
rename to ext/zip/lib/zip_file_rename.c
index db829e2e0a84249c153579dcc077e1378aa7e7bb..383a52adae71446ea94b2bd2e6a9595e1423c709 100644 (file)
@@ -1,6 +1,6 @@
 /*
-  zip_set_file_extra.c -- set extra field for file in archive
-  Copyright (C) 2006-2010 Dieter Baron and Thomas Klausner
+  zip_file_rename.c -- rename file in zip archive
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+\f
 
-
-#include <stdlib.h>
+#include <string.h>
 
 #include "zipint.h"
 
+\f
 
-
-ZIP_EXTERN(int)
-zip_set_file_extra(struct zip *za, zip_uint64_t idx,
-                  const char *extra, int len)
+ZIP_EXTERN int
+zip_file_rename(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
 {
-    char *tmpext;
-
-    if (idx >= za->nentry
-       || len < 0 || len > MAXEXTLEN
-       || (len > 0 && extra == NULL)) {
+    const char *old_name;
+    int old_is_dir, new_is_dir;
+    
+    if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) {
        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
@@ -57,16 +55,16 @@ zip_set_file_extra(struct zip *za, zip_uint64_t idx,
        return -1;
     }
 
-    if (len > 0) {
-       if ((tmpext=(char *)_zip_memdup(extra, len, &za->error)) == NULL)
-           return -1;
-    }
-    else
-       tmpext = NULL;
+    if ((old_name=zip_get_name(za, idx, 0)) == NULL)
+       return -1;
+                                                                   
+    new_is_dir = (name != NULL && name[strlen(name)-1] == '/');
+    old_is_dir = (old_name[strlen(old_name)-1] == '/');
 
-    free(za->entry[idx].ch_extra);
-    za->entry[idx].ch_extra = tmpext;
-    za->entry[idx].ch_extra_len = len;
+    if (new_is_dir != old_is_dir) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
 
-    return 0;
+    return _zip_set_name(za, idx, name, flags);
 }
diff --git a/ext/zip/lib/zip_file_replace.c b/ext/zip/lib/zip_file_replace.c
new file mode 100644 (file)
index 0000000..7e7e942
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+  zip_file_replace.c -- replace file via callback function
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include "zipint.h"
+
+\f
+
+ZIP_EXTERN int
+zip_file_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source, zip_flags_t flags)
+{
+    if (idx >= za->nentry || source == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    if (_zip_file_replace(za, idx, NULL, source, flags) == -1)
+       return -1;
+
+    return 0;
+}
+
+
+\f
+
+/* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
+
+zip_int64_t
+_zip_file_replace(struct zip *za, zip_uint64_t idx, const char *name, struct zip_source *source, zip_flags_t flags)
+{
+    zip_uint64_t za_nentry_prev;
+    
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       return -1;
+    }
+
+    za_nentry_prev = za->nentry;
+    if (idx == ZIP_UINT64_MAX) {
+       zip_int64_t i = -1;
+       
+       if (flags & ZIP_FL_OVERWRITE)
+           i = _zip_name_locate(za, name, flags, NULL);
+
+       if (i == -1) {
+           /* create and use new entry, used by zip_add */
+           if ((i=_zip_add_entry(za)) < 0)
+               return -1;
+       }
+       idx = (zip_uint64_t)i;
+    }
+    
+    if (name && _zip_set_name(za, idx, name, flags) != 0) {
+       if (za->nentry != za_nentry_prev) {
+           _zip_entry_finalize(za->entry+idx);
+           za->nentry = za_nentry_prev;
+       }
+       return -1;
+    }
+
+    /* does not change any name related data, so we can do it here;
+     * needed for a double add of the same file name */
+    _zip_unchange_data(za->entry+idx);
+
+    if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) {
+        if (za->entry[idx].changes == NULL) {
+            if ((za->entry[idx].changes=_zip_dirent_clone(za->entry[idx].orig)) == NULL) {
+                _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+
+        za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
+        za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
+    }
+       
+    za->entry[idx].source = source;
+
+    return (zip_int64_t)idx;
+}
diff --git a/ext/zip/lib/zip_file_set_comment.c b/ext/zip/lib/zip_file_set_comment.c
new file mode 100644 (file)
index 0000000..722f3d4
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+  zip_file_set_comment.c -- set comment for file in archive
+  Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include <stdlib.h>
+
+#include "zipint.h"
+
+\f
+
+ZIP_EXTERN int
+zip_file_set_comment(struct zip *za, zip_uint64_t idx,
+                    const char *comment, zip_uint16_t len, zip_flags_t flags)
+{
+    struct zip_entry *e;
+    struct zip_string *cstr;
+    int changed;
+
+    if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
+       return -1;
+
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       return -1;
+    }
+
+    if (len > 0 && comment == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    if (len > 0) {
+       if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
+           return -1;
+       if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
+           cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
+    }
+    else
+       cstr = NULL;
+
+    e = za->entry+idx;
+
+    if (e->changes) {
+       _zip_string_free(e->changes->comment);
+       e->changes->comment = NULL;
+       e->changes->changed &= ~ZIP_DIRENT_COMMENT;
+    }
+
+    if (e->orig && e->orig->comment)
+       changed = !_zip_string_equal(e->orig->comment, cstr);
+    else
+       changed = (cstr != NULL);
+       
+    if (changed) {
+        if (e->changes == NULL) {
+            if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+                _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+               _zip_string_free(cstr);
+                return -1;
+            }
+        }
+        e->changes->comment = cstr;
+        e->changes->changed |= ZIP_DIRENT_COMMENT;
+    }
+    else {
+       _zip_string_free(cstr);
+       if (e->changes && e->changes->changed == 0) {
+           _zip_dirent_free(e->changes);
+           e->changes = NULL;
+       }
+    }
+
+    return 0;
+}
index c2864f2ba1aafeb42bb2816e2e3ae17ae016dfeb..9ba70f14ff52bf8fecd28b0a2b71091d30f56e11 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(const char *)
+ZIP_EXTERN const char *
 zip_file_strerror(struct zip_file *zf)
 {
     return _zip_error_strerror(&zf->error);
index 4d1ad566929f8d5d0c0d15833340f3584d039289..3b1c868407ef914c5f48f2585f396105e9412184 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_filerange_crc.c -- compute CRC32 for a range of a file
-  Copyright (C) 2008 Dieter Baron and Thomas Klausner
+  Copyright (C) 2008-2013 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>
@@ -56,13 +56,13 @@ _zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp,
     }
     
     while (len > 0) {
-       n = len > BUFSIZE ? BUFSIZE : len;
-       if ((n=fread(buf, 1, n, fp)) <= 0) {
+       n = len > BUFSIZE ? BUFSIZE : (size_t)len;
+       if ((n=fread(buf, 1, n, fp)) == 0) {
            _zip_error_set(errp, ZIP_ER_READ, errno);
            return -1;
        }
 
-       *crcp = crc32(*crcp, buf, n);
+       *crcp = crc32(*crcp, buf, (uInt)n);
 
        len-= n;
     }
index f62adbbf926925c9edec4e2b6592f704203ea9d2..331f79ea361495633290339c8ae4d29abf050002 100644 (file)
 
 \f
 
-ZIP_EXTERN(struct zip_file *)
-zip_fopen(struct zip *za, const char *fname, int flags)
+ZIP_EXTERN struct zip_file *
+zip_fopen(struct zip *za, const char *fname, zip_flags_t flags)
 {
-    int idx;
+    zip_int64_t idx;
 
     if ((idx=zip_name_locate(za, fname, flags)) < 0)
        return NULL;
 
-    return zip_fopen_index_encrypted(za, idx, flags, za->default_password);
+    return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
 }
index 8aba0625672bc6eaf7ae74bd998230275d45ff5f..34230f00d7c0ac03848d894efdaeb6898d70b428 100644 (file)
 
 \f
 
-ZIP_EXTERN(struct zip_file *)
-zip_fopen_encrypted(struct zip *za, const char *fname, int flags,
-                   const char *password)
+ZIP_EXTERN struct zip_file *
+zip_fopen_encrypted(struct zip *za, const char *fname, zip_flags_t flags, const char *password)
 {
-    int idx;
+    zip_int64_t idx;
 
     if ((idx=zip_name_locate(za, fname, flags)) < 0)
        return NULL;
 
-    return zip_fopen_index_encrypted(za, idx, flags, password);
+    return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
 }
index b60fd33e8f53e75b2450a93d8161e930e26358c6..30466ffa19a59e48c5e7f80c6d838a472f59660b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index.c -- open file in zip archive for reading by index
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2013 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>
@@ -41,8 +41,8 @@
 
 \f
 
-ZIP_EXTERN(struct zip_file *)
-zip_fopen_index(struct zip *za, zip_uint64_t fileno, int flags)
+ZIP_EXTERN struct zip_file *
+zip_fopen_index(struct zip *za, zip_uint64_t index, zip_flags_t flags)
 {
-    return zip_fopen_index_encrypted(za, fileno, flags, za->default_password);
+    return zip_fopen_index_encrypted(za, index, flags, za->default_password);
 }
index 988a78fe03f9a187287fce0b77c2651c6ac4f331..cc81ca7f53b677381ac5226db7b834666907c09a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index_encrypted.c -- open file for reading by index w/ password
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2013 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,103 +43,15 @@ static struct zip_file *_zip_file_new(struct zip *za);
 
 \f
 
-ZIP_EXTERN(struct zip_file *)
-zip_fopen_index_encrypted(struct zip *za, zip_uint64_t fileno, int flags,
+ZIP_EXTERN struct zip_file *
+zip_fopen_index_encrypted(struct zip *za, zip_uint64_t index, zip_flags_t flags,
                          const char *password)
 {
     struct zip_file *zf;
-    zip_compression_implementation comp_impl;
-    zip_encryption_implementation enc_impl;
-    struct zip_source *src, *s2;
-    zip_uint64_t start;
-    struct zip_stat st;
-
-    if (fileno >= za->nentry) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
-    }
+    struct zip_source *src;
 
-    if ((flags & ZIP_FL_UNCHANGED) == 0
-       && ZIP_ENTRY_DATA_CHANGED(za->entry+fileno)) {
-       _zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
+    if ((src=_zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
        return NULL;
-    }
-
-    if (fileno >= za->cdir->nentry) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
-    }
-
-    if (flags & ZIP_FL_ENCRYPTED)
-       flags |= ZIP_FL_COMPRESSED;
-
-    zip_stat_index(za, fileno, flags, &st);
-
-    enc_impl = NULL;
-    if ((flags & ZIP_FL_ENCRYPTED) == 0) {
-       if (st.encryption_method != ZIP_EM_NONE) {
-           if (password == NULL) {
-               _zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0);
-               return NULL;
-           }
-           if ((enc_impl=zip_get_encryption_implementation(
-                    st.encryption_method)) == NULL) {
-               _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
-               return NULL;
-           }
-       }
-    }
-
-    comp_impl = NULL;
-    if ((flags & ZIP_FL_COMPRESSED) == 0) {
-       if (st.comp_method != ZIP_CM_STORE) {
-           if ((comp_impl=zip_get_compression_implementation(
-                    st.comp_method)) == NULL) {
-               _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
-               return NULL;
-           }
-       }
-    }
-
-    if ((start=_zip_file_get_offset(za, fileno)) == 0)
-       return NULL;
-
-    if (st.comp_size == 0) {
-       if ((src=zip_source_buffer(za, NULL, 0, 0)) == NULL)
-           return NULL;
-    }
-    else {
-       if ((src=_zip_source_file_or_p(za, NULL, za->zp, start, st.comp_size,
-                                      0, &st)) == NULL)
-           return NULL;
-       if (enc_impl) {
-           if ((s2=enc_impl(za, src, ZIP_EM_TRAD_PKWARE, 0,
-                            password)) == NULL) {
-               zip_source_free(src);
-               /* XXX: set error (how?) */
-               return NULL;
-           }
-           src = s2;
-       }
-       if (comp_impl) {
-           if ((s2=comp_impl(za, src, za->cdir->entry[fileno].comp_method,
-                             0)) == NULL) {
-               zip_source_free(src);
-               /* XXX: set error (how?) */
-               return NULL;
-           }
-           src = s2;
-       }
-       if ((flags & ZIP_FL_COMPRESSED) == 0
-           || st.comp_method == ZIP_CM_STORE ) {
-           if ((s2=zip_source_crc(za, src, 1)) == NULL) {
-               zip_source_free(src);
-               /* XXX: set error (how?) */
-               return NULL;
-           }
-           src = s2;
-       }
-    }
 
     if (zip_source_open(src) < 0) {
        _zip_error_set_from_source(&za->error, src);
@@ -147,7 +59,10 @@ zip_fopen_index_encrypted(struct zip *za, zip_uint64_t fileno, int flags,
        return NULL;
     }
 
-    zf = _zip_file_new(za);
+    if ((zf=_zip_file_new(za)) == NULL) {
+       zip_source_free(src);
+       return NULL;
+    }
 
     zf->src = src;
 
@@ -160,14 +75,14 @@ static struct zip_file *
 _zip_file_new(struct zip *za)
 {
     struct zip_file *zf, **file;
-    int n;
 
     if ((zf=(struct zip_file *)malloc(sizeof(struct zip_file))) == NULL) {
        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
     
-    if (za->nfile >= za->nfile_alloc-1) {
+    if (za->nfile+1 >= za->nfile_alloc) {
+       unsigned int n;
        n = za->nfile_alloc + 10;
        file = (struct zip_file **)realloc(za->file,
                                           n*sizeof(struct zip_file *));
index a6c0851b0aaac5a614b3504dd89d178f23c10f4e..8235c6dfacf80fd292f73cc1095bf8fb52990e6f 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(zip_int64_t)
+ZIP_EXTERN zip_int64_t
 zip_fread(struct zip_file *zf, void *outbuf, zip_uint64_t toread)
 {
     zip_int64_t n;
index fe97e6e8c18a1fd8dc6945ee3b58e91c4ed33be9..202f761f4e852d73bfbbdde71ee188e5dab72ca3 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_archive_comment.c -- get archive comment
-  Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 \f
 
+#include <string.h>
+
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(const char *)
-zip_get_archive_comment(struct zip *za, int *lenp, int flags)
+ZIP_EXTERN const char *
+zip_get_archive_comment(struct zip *za, int *lenp, zip_flags_t flags)
 {
-    if ((flags & ZIP_FL_UNCHANGED)
-       || (za->ch_comment_len == -1)) {
-       if (za->cdir) {
-           if (lenp != NULL)
-               *lenp = za->cdir->comment_len;
-           return za->cdir->comment;
-       }
-       else {
-           if (lenp != NULL)
-               *lenp = -1;
-           return NULL;
-       }
-    }
-    
-    if (lenp != NULL)
-       *lenp = za->ch_comment_len;
-    return za->ch_comment;
+    struct zip_string *comment;
+    zip_uint32_t len;
+    const zip_uint8_t *str;
+
+    if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL))
+       comment = za->comment_orig;
+    else
+       comment = za->comment_changes;
+
+    if ((str=_zip_string_get(comment, &len, flags, &za->error)) == NULL)
+       return NULL;
+
+    if (lenp)
+       *lenp = (int)len;
+
+    return (const char *)str;
 }
index 2d46aa39ffbb4d4323e85129a9dcedb4ad5bb50c..c3be5c14fec3851fab617b5292567cb4592de11b 100644 (file)
 
 \f
 
-ZIP_EXTERN(int)
-zip_get_archive_flag(struct zip *za, int flag, int flags)
+ZIP_EXTERN int
+zip_get_archive_flag(struct zip *za, unsigned int flag, zip_flags_t flags)
 {
-    int fl;
+    unsigned int fl;
 
     fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags;
 
index 197cd49635d41f5b1ce145b04027a4e195bd1fd2..aa4a1605c0f36ad74d661a4eff77775be5ea8d75 100644 (file)
 
 \f
 
-ZIP_EXTERN(zip_compression_implementation)
-zip_get_compression_implementation(zip_uint16_t cm)
+zip_compression_implementation
+_zip_get_compression_implementation(zip_int32_t cm)
 {
-    if (cm == ZIP_CM_DEFLATE)
+    if (cm == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(cm))
        return zip_source_deflate;
     return NULL;
 }
index 783d538d3f6ff2f330bfe3602930cca786d72eba..7dcb99210d49815d4d93f5b9d29cd55d65b14cab 100644 (file)
@@ -37,8 +37,8 @@
 
 \f
 
-ZIP_EXTERN(zip_encryption_implementation)
-zip_get_encryption_implementation(zip_uint16_t em)
+zip_encryption_implementation
+_zip_get_encryption_implementation(zip_uint16_t em)
 {
     if (em == ZIP_EM_TRAD_PKWARE)
        return zip_source_pkware;
index 43c1520e1d438f4df758d2be88c290421bc29f0e..3be459d4da6b00dfd711c88c9674b24b9643a5cc 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_file_comment.c -- get file comment
-  Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 \f
 
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(const char *)
+ZIP_EXTERN const char *
 zip_get_file_comment(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;
-    }
+    zip_uint32_t len;
+    const char *s;
 
-    if ((flags & ZIP_FL_UNCHANGED)
-       || (za->entry[idx].ch_comment_len == -1)) {
-       if (lenp != NULL)
-           *lenp = za->cdir->entry[idx].comment_len;
-       return za->cdir->entry[idx].comment;
+    if ((s=zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
+       if (lenp)
+           *lenp = (int)len;
     }
-    
-    if (lenp != NULL)
-       *lenp = za->entry[idx].ch_comment_len;
-    return za->entry[idx].ch_comment;
+
+    return s;
 }
index 945e24e1501d58f96aa4093d7f4078c676b3c330..f67c7caf4305f13a033bf376b1b1a679be0d5868 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_get_name.c -- get filename for a file in zip file
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 \f
 
+#include <string.h>
+
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(const char *)
-zip_get_name(struct zip *za, zip_uint64_t idx, int flags)
+ZIP_EXTERN const char *
+zip_get_name(struct zip *za, zip_uint64_t idx, zip_flags_t flags)
 {
     return _zip_get_name(za, idx, flags, &za->error);
 }
@@ -46,27 +48,16 @@ zip_get_name(struct zip *za, zip_uint64_t idx, int flags)
 \f
 
 const char *
-_zip_get_name(struct zip *za, zip_uint64_t idx, int flags,
-             struct zip_error *error)
+_zip_get_name(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_error *error)
 {
-    if (idx >= za->nentry) {
-       _zip_error_set(error, ZIP_ER_INVAL, 0);
-       return NULL;
-    }
+    struct zip_dirent *de;
+    const zip_uint8_t *str;
 
-    if ((flags & ZIP_FL_UNCHANGED) == 0) {
-       if (za->entry[idx].state == ZIP_ST_DELETED) {
-           _zip_error_set(error, ZIP_ER_DELETED, 0);
-           return NULL;
-       }
-       if (za->entry[idx].ch_filename)
-           return za->entry[idx].ch_filename;
-    }
+    if ((de=_zip_get_dirent(za, idx, flags, error)) == NULL)
+       return NULL;
 
-    if (za->cdir == NULL || idx >= za->cdir->nentry) {
-       _zip_error_set(error, ZIP_ER_INVAL, 0);
+    if ((str=_zip_string_get(de->filename, NULL, flags, error)) == NULL)
        return NULL;
-    }
-    
-    return za->cdir->entry[idx].filename;
+
+    return (const char *)str;
 }
index dd392e909592e94c79db5e21d2cd237a99a570ef..26484baff22a6a289a3ab7d8d7d26a13d22a7c79 100644 (file)
 
 \f
 
-ZIP_EXTERN(zip_uint64_t)
-zip_get_num_entries(struct zip *za, int flags)
+ZIP_EXTERN zip_int64_t
+zip_get_num_entries(struct zip *za, zip_flags_t flags)
 {
+    zip_uint64_t n;
+
     if (za == NULL)
        return -1;
 
     if (flags & ZIP_FL_UNCHANGED) {
-      if (za->cdir == NULL)
-       return 0;
-      return za->cdir->nentry;
+       n = za->nentry;
+       while (n>0 && za->entry[n-1].orig == NULL)
+           --n;
+       return (zip_int64_t)n;
     }
-    return za->nentry;
+    return (zip_int64_t)za->nentry;
 }
index a442f293ec350a18a512c75d62c4815bd92f6799..29b06dc8193ff1981250311de4668fd5fc3f6704 100644 (file)
 
 \f
 
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_get_num_files(struct zip *za)
 {
     if (za == NULL)
        return -1;
 
-    return za->nentry;
+    /* XXX: check for overflow */
+    return (int)za->nentry;
 }
index 641125ed2d1b21488e825e22743d25d2c8101294..06af2dabd36c7e1f83e11971fcd55ebfda5088ba 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_memdup.c -- internal zip function, "strdup" with len
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -43,6 +43,9 @@ _zip_memdup(const void *mem, size_t len, struct zip_error *error)
 {
     void *ret;
 
+    if (len == 0)
+       return NULL;
+
     ret = malloc(len);
     if (!ret) {
        _zip_error_set(error, ZIP_ER_MEMORY, 0);
index 8cdd2c4d7ea0bcef2f0eca7c38edf70ea97f38b7..3cac11054367295bc3acbf9eb3bed1bbdf94bef1 100644 (file)
 \f
 
 #include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
 
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(int)
-zip_name_locate(struct zip *za, const char *fname, int flags)
+ZIP_EXTERN zip_int64_t
+zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags)
 {
     return _zip_name_locate(za, fname, flags, &za->error);
 }
 
 \f
 
-int
-_zip_name_locate(struct zip *za, const char *fname, int flags,
-                struct zip_error *error)
+zip_int64_t
+_zip_name_locate(struct zip *za, const char *fname, zip_flags_t flags, struct zip_error *error)
 {
     int (*cmp)(const char *, const char *);
     const char *fn, *p;
-    int i, n;
+    zip_uint64_t i;
 
     if (za == NULL)
        return -1;
@@ -63,21 +65,12 @@ _zip_name_locate(struct zip *za, const char *fname, int flags,
        return -1;
     }
 
-    if ((flags & ZIP_FL_UNCHANGED)  && za->cdir == NULL) {
-        _zip_error_set(error, ZIP_ER_NOENT, 0);
-        return -1;
-    }
-
-    cmp = (flags & ZIP_FL_NOCASE) ? strcmpi : strcmp;
+    cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
 
-    n = (flags & ZIP_FL_UNCHANGED) ? za->cdir->nentry : za->nentry;
-    for (i=0; i<n; i++) {
-       if (flags & ZIP_FL_UNCHANGED)
-           fn = za->cdir->entry[i].filename;
-       else
-           fn = _zip_get_name(za, i, flags, error);
+    for (i=0; i<za->nentry; i++) {
+       fn = _zip_get_name(za, i, flags, error);
 
-       /* newly added (partially filled) entry */
+       /* newly added (partially filled) entry or error */
        if (fn == NULL)
            continue;
        
@@ -87,11 +80,12 @@ _zip_name_locate(struct zip *za, const char *fname, int flags,
                fn = p+1;
        }
 
-       if (cmp(fname, fn) == 0)
-           return i;
+       if (cmp(fname, fn) == 0) {
+           _zip_error_clear(error);
+           return (zip_int64_t)i;
+       }
     }
 
-/* Look for an entry should not raise an error  */
-/*    _zip_error_set(error, ZIP_ER_NOENT, 0);*/
+    _zip_error_set(error, ZIP_ER_NOENT, 0);
     return -1;
 }
index 7ce1237cdbabdb7d7f269a15ca00e67254f8985b..f77634a389f365e4d58fe9bd302762583de8dd61 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_new.c -- create and init struct zip
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -56,16 +56,17 @@ _zip_new(struct zip_error *error)
 
     za->zn = NULL;
     za->zp = NULL;
+    za->open_flags = 0;
     _zip_error_init(&za->error);
-    za->cdir = NULL;
-    za->ch_comment = NULL;
-    za->ch_comment_len = -1;
+    za->flags = za->ch_flags = 0;
+    za->default_password = NULL;
+    za->comment_orig = za->comment_changes = NULL;
+    za->comment_changed = 0;
     za->nentry = za->nentry_alloc = 0;
     za->entry = NULL;
     za->nfile = za->nfile_alloc = 0;
     za->file = NULL;
-    za->flags = za->ch_flags = 0;
-    za->default_password = NULL;
+    za->tempdir = NULL;
     
     return za;
 }
index 5ce1c1070ae03d4082035e930668116250c766b9..e6a30d5ae706658edff79471d174c9272c1a8ffd 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_open.c -- open zip archive by name
-  Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 #include "zipint.h"
 
-static void set_error(int *, struct zip_error *, int);
-static struct zip *_zip_allocate_new(const char *, int *);
-static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *);
-static void _zip_check_torrentzip(struct zip *);
-static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t);
-static int _zip_file_exists(const char *, int, int *);
-static int _zip_headercomp(struct zip_dirent *, int,
-                          struct zip_dirent *, int);
-static unsigned char *_zip_memmem(const unsigned char *, int,
-                                 const unsigned char *, int);
-static struct zip_cdir *_zip_readcdir(FILE *, off_t, unsigned char *, unsigned char *,
-                                int, int, struct zip_error *);
+static void set_error(int *, const struct zip_error *, int);
+static struct zip *_zip_allocate_new(const char *, unsigned int, int *);
+static zip_int64_t _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *);
+static void _zip_check_torrentzip(struct zip *, const struct zip_cdir *);
+static struct zip_cdir *_zip_find_central_dir(FILE *, unsigned int, int *, off_t);
+static int _zip_file_exists(const char *, unsigned int, int *);
+static int _zip_headercomp(const struct zip_dirent *, const struct zip_dirent *);
+static unsigned char *_zip_memmem(const unsigned char *, size_t,
+                                 const unsigned char *, size_t);
+static struct zip_cdir *_zip_readcdir(FILE *, off_t, unsigned char *, const unsigned char *,
+                                size_t, unsigned int, struct zip_error *);
+static struct zip_cdir *_zip_read_eocd(const unsigned char *, const unsigned char *, off_t,
+                                      size_t, unsigned int, struct zip_error *);
+static struct zip_cdir *_zip_read_eocd64(FILE *, const unsigned char *, const unsigned char *,
+                                        off_t, size_t, unsigned int, struct zip_error *);
 
 \f
 
-ZIP_EXTERN(struct zip *)
-zip_open(const char *fn, int flags, int *zep)
+ZIP_EXTERN struct zip *
+zip_open(const char *fn, int _flags, int *zep)
 {
     FILE *fp;
-
-    if (flags & ZIP_OVERWRITE) {
-       return _zip_allocate_new(fn, zep);
+    unsigned int flags;
+    
+    if (_flags < 0) {
+        if (zep)
+            *zep = ZIP_ER_INVAL;
+        return NULL;
     }
-
+    flags = (unsigned int)_flags;
+        
     switch (_zip_file_exists(fn, flags, zep)) {
     case -1:
-                       if (!(flags & ZIP_OVERWRITE)) {
-                               return NULL;
-                       }
+       return NULL;
     case 0:
-       return _zip_allocate_new(fn, zep);
+       return _zip_allocate_new(fn, flags, zep);
     default:
+       if (flags & ZIP_TRUNCATE) {
+           FILE *f;
+           
+           if ((f = fopen(fn, "rb")) == NULL) {
+               set_error(zep, NULL, ZIP_ER_OPEN);
+               return NULL;
+           }
+           fclose(f);
+           return _zip_allocate_new(fn, flags, zep);
+       }
        break;
     }
 
@@ -82,17 +97,36 @@ zip_open(const char *fn, int flags, int *zep)
        return NULL;
     }
 
-    return _zip_open(fn, fp, flags, 0, zep);
+    return _zip_open(fn, fp, flags, zep);
 }
 
+
+ZIP_EXTERN int
+zip_archive_set_tempdir(struct zip *za, const char *tempdir)
+{
+    char *new_tempdir;
+    
+    if (tempdir) {
+        if ((new_tempdir = strdup(tempdir)) == NULL) {
+            _zip_error_set(&za->error, ZIP_ER_MEMORY, errno);
+            return -1;
+        }
+    }
+    else
+        new_tempdir = NULL;
+    
+    free(za->tempdir);
+    za->tempdir = new_tempdir;
+    
+    return 0;
+}
 \f
 
 struct zip *
-_zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep)
+_zip_open(const char *fn, FILE *fp, unsigned int flags, int *zep)
 {
     struct zip *za;
     struct zip_cdir *cdir;
-    int i;
     off_t len;
 
     if (fseeko(fp, 0, SEEK_END) < 0) {
@@ -103,7 +137,7 @@ _zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep)
 
     /* treat empty files as empty archives */
     if (len == 0) {
-       if ((za=_zip_allocate_new(fn, zep)) == NULL)
+       if ((za=_zip_allocate_new(fn, flags, zep)) == NULL)
            fclose(fp);
        else
            za->zp = fp;
@@ -116,34 +150,32 @@ _zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep)
        return NULL;
     }
 
-    if ((za=_zip_allocate_new(fn, zep)) == NULL) {
+    if ((za=_zip_allocate_new(fn, flags, zep)) == NULL) {
        _zip_cdir_free(cdir);
        fclose(fp);
        return NULL;
     }
 
-    za->cdir = cdir;
+    za->entry = cdir->entry;
+    za->nentry = cdir->nentry;
+    za->nentry_alloc = cdir->nentry_alloc;
+    za->comment_orig = cdir->comment;
+    
     za->zp = fp;
 
-    if ((za->entry=(struct zip_entry *)malloc(sizeof(*(za->entry))
-                                             * cdir->nentry)) == NULL) {
-       set_error(zep, NULL, ZIP_ER_MEMORY);
-       _zip_free(za);
-       return NULL;
-    }
-    for (i=0; i<cdir->nentry; i++)
-       _zip_entry_new(za);
+    _zip_check_torrentzip(za, cdir);
 
-    _zip_check_torrentzip(za);
     za->ch_flags = za->flags;
 
+    free(cdir);
+
     return za;
 }
 
 \f
 
 static void
-set_error(int *zep, struct zip_error *err, int ze)
+set_error(int *zep, const struct zip_error *err, int ze)
 {
     int se;
 
@@ -166,16 +198,17 @@ set_error(int *zep, struct zip_error *err, int ze)
    entries, or NULL if unsuccessful. */
 
 static struct zip_cdir *
-_zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eocd, int buflen,
-             int flags, struct zip_error *error)
+_zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, const unsigned char *eocd, size_t buflen,
+             unsigned int flags, struct zip_error *error)
 {
     struct zip_cdir *cd;
-    unsigned char *cdp, **bufp;
-    int i, comlen, nentry;
-    zip_uint32_t left;
+    const unsigned char *cdp;
+    const unsigned char **bufp;
+    zip_int64_t tail_len, comment_len;
+    zip_uint64_t i, left;
 
-    comlen = buf + buflen - eocd - EOCDLEN;
-    if (comlen < 0) {
+    tail_len = buf + buflen - eocd - EOCDLEN;
+    if (tail_len < 0) {
        /* not enough bytes left for comment */
        _zip_error_set(error, ZIP_ER_NOZIP, 0);
        return NULL;
@@ -192,46 +225,32 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eoc
        return NULL;
     }
 
-    cdp = eocd + 8;
-    /* number of cdir-entries on this disk */
-    i = _zip_read2(&cdp);
-    /* number of cdir-entries */
-    nentry = _zip_read2(&cdp);
+    if (eocd-EOCD64LOCLEN >= buf && memcmp(eocd-EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0)
+       cd = _zip_read_eocd64(fp, eocd-EOCD64LOCLEN, buf, buf_offset, buflen, flags, error);
+    else
+       cd = _zip_read_eocd(eocd, buf, buf_offset, buflen, flags, error);
 
-    if ((cd=_zip_cdir_new(nentry, error)) == NULL)
+    if (cd == NULL)
        return NULL;
 
-    cd->size = _zip_read4(&cdp);
-    cd->offset = _zip_read4(&cdp);
-    cd->comment = NULL;
-    cd->comment_len = _zip_read2(&cdp);
+    cdp = eocd + 20;
+    comment_len = _zip_read2(&cdp);
 
-    if (((zip_uint64_t)cd->offset)+cd->size > buf_offset + (eocd-buf)) {
+    if ((zip_uint64_t)cd->offset+(zip_uint64_t)cd->size > (zip_uint64_t)buf_offset + (zip_uint64_t)(eocd-buf)) {
        /* cdir spans past EOCD record */
        _zip_error_set(error, ZIP_ER_INCONS, 0);
-       cd->nentry = 0;
        _zip_cdir_free(cd);
        return NULL;
     }
 
-    if ((comlen < cd->comment_len) || (cd->nentry != i)) {
-       _zip_error_set(error, ZIP_ER_NOZIP, 0);
-       cd->nentry = 0;
-       _zip_cdir_free(cd);
-       return NULL;
-    }
-    if ((flags & ZIP_CHECKCONS) && comlen != cd->comment_len) {
+    if (tail_len < comment_len || ((flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
        _zip_error_set(error, ZIP_ER_INCONS, 0);
-       cd->nentry = 0;
        _zip_cdir_free(cd);
        return NULL;
     }
 
-    if (cd->comment_len) {
-       if ((cd->comment=(char *)_zip_memdup(eocd+EOCDLEN,
-                                            cd->comment_len, error))
-           == NULL) {
-           cd->nentry = 0;
+    if (comment_len) {
+       if ((cd->comment=_zip_string_new(eocd+EOCDLEN, (zip_uint16_t)comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
            _zip_cdir_free(cd);
            return NULL;
        }
@@ -249,40 +268,32 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eoc
        fseeko(fp, cd->offset, SEEK_SET);
        /* possible consistency check: cd->offset =
           len-(cd->size+cd->comment_len+EOCDLEN) ? */
-       if (ferror(fp) || ((unsigned long)ftello(fp) != cd->offset)) {
+       if (ferror(fp) || (ftello(fp) != cd->offset)) {
            /* seek error or offset of cdir wrong */
            if (ferror(fp))
                _zip_error_set(error, ZIP_ER_SEEK, errno);
            else
                _zip_error_set(error, ZIP_ER_NOZIP, 0);
-           cd->nentry = 0;
            _zip_cdir_free(cd);
            return NULL;
        }
     }
 
-    left = cd->size;
+    left = (zip_uint64_t)cd->size;
     i=0;
     while (i<cd->nentry && left > 0) {
-       if ((_zip_dirent_read(cd->entry+i, fp, bufp, &left, 0, error)) < 0) {
-           cd->nentry = i;
+       if ((cd->entry[i].orig=_zip_dirent_new()) == NULL
+           || (_zip_dirent_read(cd->entry[i].orig, fp, bufp, &left, 0, error)) < 0) {
            _zip_cdir_free(cd);
            return NULL;
        }
        i++;
-       
-       if (i == cd->nentry && left > 0) {
-           /* Infozip extension for more than 64k entries:
-              nentries wraps around, size indicates correct EOCD */
-           if (_zip_cdir_grow(cd, cd->nentry+ZIP_UINT16_MAX, error) < 0) {
-               cd->nentry = i;
-               _zip_cdir_free(cd);
-               return NULL;
-           }
-       }
     }
-
-    cd->nentry = i;
+    if (i != cd->nentry || ((flags & ZIP_CHECKCONS) && left != 0)) {
+        _zip_error_set(error, ZIP_ER_INCONS, 0);
+        _zip_cdir_free(cd);
+        return NULL;
+    }
     
     return cd;
 }
@@ -295,84 +306,88 @@ _zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eoc
    file and header offsets. Returns -1 if not plausible, else the
    difference between the lowest and the highest fileposition reached */
 
-static int
+static zip_int64_t
 _zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error)
 {
-    int i;
-    unsigned int min, max, j;
+    zip_uint64_t i;
+    zip_uint64_t min, max, j;
     struct zip_dirent temp;
 
     if (cd->nentry) {
-       max = cd->entry[0].offset;
-       min = cd->entry[0].offset;
+       max = cd->entry[0].orig->offset;
+       min = cd->entry[0].orig->offset;
     }
     else
        min = max = 0;
 
     for (i=0; i<cd->nentry; i++) {
-       if (cd->entry[i].offset < min)
-           min = cd->entry[i].offset;
-       if (min > cd->offset) {
+       if (cd->entry[i].orig->offset < min)
+           min = cd->entry[i].orig->offset;
+       if (min > (zip_uint64_t)cd->offset) {
            _zip_error_set(error, ZIP_ER_NOZIP, 0);
            return -1;
        }
        
-       j = cd->entry[i].offset + cd->entry[i].comp_size
-           + cd->entry[i].filename_len + LENTRYSIZE;
+       j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size
+           + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
        if (j > max)
            max = j;
-       if (max > cd->offset) {
+       if (max > (zip_uint64_t)cd->offset) {
            _zip_error_set(error, ZIP_ER_NOZIP, 0);
            return -1;
        }
        
-       if (fseeko(fp, cd->entry[i].offset, SEEK_SET) != 0) {
-           _zip_error_set(error, ZIP_ER_SEEK, 0);
+       if (fseeko(fp, (off_t)cd->entry[i].orig->offset, SEEK_SET) != 0) {
+           _zip_error_set(error, ZIP_ER_SEEK, errno);
            return -1;
        }
        
        if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1)
            return -1;
        
-       if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) {
+       if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
            _zip_error_set(error, ZIP_ER_INCONS, 0);
            _zip_dirent_finalize(&temp);
            return -1;
        }
+       
+       cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
+       cd->entry[i].orig->local_extra_fields_read = 1;
+       temp.extra_fields = NULL;
+       
        _zip_dirent_finalize(&temp);
     }
 
-    return max - min;
+    return (max-min) < ZIP_INT64_MAX ? (zip_int64_t)(max-min) : ZIP_INT64_MAX;
 }
 
 \f
 
 /* _zip_check_torrentzip:
-   check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
+   check wether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
 
 static void
-_zip_check_torrentzip(struct zip *za)
+_zip_check_torrentzip(struct zip *za, const struct zip_cdir *cdir)
 {
     uLong crc_got, crc_should;
     char buf[8+1];
     char *end;
 
-    if (za->zp == NULL || za->cdir == NULL)
+    if (za->zp == NULL || cdir == NULL)
        return;
 
-    if (za->cdir->comment_len != TORRENT_SIG_LEN+8
-       || strncmp(za->cdir->comment, TORRENT_SIG, TORRENT_SIG_LEN) != 0)
+    if (_zip_string_length(cdir->comment) != TORRENT_SIG_LEN+8
+       || strncmp((const char *)cdir->comment->raw, TORRENT_SIG, TORRENT_SIG_LEN) != 0)
        return;
 
-    memcpy(buf, za->cdir->comment+TORRENT_SIG_LEN, 8);
+    memcpy(buf, cdir->comment->raw+TORRENT_SIG_LEN, 8);
     buf[8] = '\0';
     errno = 0;
     crc_should = strtoul(buf, &end, 16);
     if ((crc_should == UINT_MAX && errno != 0) || (end && *end))
        return;
 
-    if (_zip_filerange_crc(za->zp, za->cdir->offset, za->cdir->size,
-                          &crc_got, NULL) < 0)
+    if (_zip_filerange_crc(za->zp, cdir->offset, cdir->size, &crc_got, NULL) < 0)
        return;
 
     if (crc_got == crc_should)
@@ -383,68 +398,32 @@ _zip_check_torrentzip(struct zip *za)
 \f
 
 /* _zip_headercomp:
-   compares two headers h1 and h2; if they are local headers, set
-   local1p or local2p respectively to 1, else 0. Return 0 if they
-   are identical, -1 if not. */
+   compares a central directory entry and a local file header
+   Return 0 if they are consistent, -1 if not. */
 
 static int
-_zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2,
-          int local2p)
+_zip_headercomp(const struct zip_dirent *central, const struct zip_dirent *local)
 {
-    if ((h1->version_needed != h2->version_needed)
+    if ((central->version_needed != local->version_needed)
 #if 0
        /* some zip-files have different values in local
           and global headers for the bitflags */
-       || (h1->bitflags != h2->bitflags)
+       || (central->bitflags != local->bitflags)
 #endif
-       || (h1->comp_method != h2->comp_method)
-       || (h1->last_mod != h2->last_mod)
-       || (h1->filename_len != h2->filename_len)
-       || !h1->filename || !h2->filename
-       || strcmp(h1->filename, h2->filename))
+       || (central->comp_method != local->comp_method)
+       || (central->last_mod != local->last_mod)
+       || !_zip_string_equal(central->filename, local->filename))
        return -1;
 
-    /* check that CRC and sizes are zero if data descriptor is used */
-    if ((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local1p
-       && (h1->crc != 0
-           || h1->comp_size != 0
-           || h1->uncomp_size != 0))
-       return -1;
-    if ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local2p
-       && (h2->crc != 0
-           || h2->comp_size != 0
-           || h2->uncomp_size != 0))
-       return -1;
-    
-    /* check that CRC and sizes are equal if no data descriptor is used */
-    if (((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local1p == 0)
-       && ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local2p == 0)) {
-       if ((h1->crc != h2->crc)
-           || (h1->comp_size != h2->comp_size)
-           || (h1->uncomp_size != h2->uncomp_size))
+
+    if ((central->crc != local->crc) || (central->comp_size != local->comp_size)
+       || (central->uncomp_size != local->uncomp_size)) {
+       /* InfoZip stores valid values in local header even when data descriptor is used.
+          This is in violation of the appnote. */
+       if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0
+            || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
            return -1;
     }
-    
-    if ((local1p == local2p)
-       && ((h1->extrafield_len != h2->extrafield_len)
-           || (h1->extrafield_len && h2->extrafield
-               && memcmp(h1->extrafield, h2->extrafield,
-                         h1->extrafield_len))))
-       return -1;
-
-    /* if either is local, nothing more to check */
-    if (local1p || local2p)
-       return 0;
-
-    if ((h1->version_madeby != h2->version_madeby)
-       || (h1->disk_number != h2->disk_number)
-       || (h1->int_attrib != h2->int_attrib)
-       || (h1->ext_attrib != h2->ext_attrib)
-       || (h1->offset != h2->offset)
-       || (h1->comment_len != h2->comment_len)
-       || (h1->comment_len && h2->comment
-           && memcmp(h1->comment, h2->comment, h1->comment_len)))
-       return -1;
 
     return 0;
 }
@@ -452,7 +431,7 @@ _zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2,
 \f
 
 static struct zip *
-_zip_allocate_new(const char *fn, int *zep)
+_zip_allocate_new(const char *fn, unsigned int flags, int *zep)
 {
     struct zip *za;
     struct zip_error error;
@@ -467,18 +446,19 @@ _zip_allocate_new(const char *fn, int *zep)
     else {
        za->zn = strdup(fn);
        if (!za->zn) {
-           _zip_free(za);
+           zip_discard(za);
            set_error(zep, NULL, ZIP_ER_MEMORY);
            return NULL;
        }
     }
+    za->open_flags = flags;
     return za;
 }
 
 \f
 
 static int
-_zip_file_exists(const char *fn, int flags, int *zep)
+_zip_file_exists(const char *fn, unsigned int flags, int *zep)
 {
     struct stat st;
 
@@ -488,7 +468,7 @@ _zip_file_exists(const char *fn, int flags, int *zep)
     }
     
     if (stat(fn, &st) != 0) {
-       if (flags & ZIP_CREATE || flags & ZIP_OVERWRITE)
+       if (flags & ZIP_CREATE)
            return 0;
        else {
            set_error(zep, NULL, ZIP_ER_OPEN);
@@ -508,12 +488,14 @@ _zip_file_exists(const char *fn, int flags, int *zep)
 \f
 
 static struct zip_cdir *
-_zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len)
+_zip_find_central_dir(FILE *fp, unsigned int flags, int *zep, off_t len)
 {
     struct zip_cdir *cdir, *cdirnew;
     unsigned char *buf, *match;
     off_t buf_offset;
-    int a, best, buflen, i;
+    size_t buflen;
+    zip_int64_t a, i;
+    zip_int64_t best;
     struct zip_error zerr;
 
     i = fseeko(fp, -(len < CDBUFSIZE ? len : CDBUFSIZE), SEEK_END);
@@ -541,10 +523,10 @@ _zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len)
     
     best = -1;
     cdir = NULL;
-    match = buf;
+    match = buf+ (buflen < CDBUFSIZE ? 0 : EOCD64LOCLEN);
     _zip_error_set(&zerr, ZIP_ER_NOZIP, 0);
 
-    while ((match=_zip_memmem(match, buflen-(match-buf)-18,
+    while ((match=_zip_memmem(match, buflen-(size_t)(match-buf)-(EOCDLEN-4),
                              (const unsigned char *)EOCD_MAGIC, 4))!=NULL) {
        /* found match -- check, if good */
        /* to avoid finding the same match all over again */
@@ -589,8 +571,7 @@ _zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len)
 \f
 
 static unsigned char *
-_zip_memmem(const unsigned char *big, int biglen, const unsigned char *little, 
-       int littlelen)
+_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen)
 {
     const unsigned char *p;
     
@@ -598,11 +579,159 @@ _zip_memmem(const unsigned char *big, int biglen, const unsigned char *little,
        return NULL;
     p = big-1;
     while ((p=(const unsigned char *)
-               memchr(p+1, little[0], (size_t)(big-(p+1)+biglen-littlelen+1)))
-          != NULL) {
+               memchr(p+1, little[0], (size_t)(big-(p+1))+(size_t)(biglen-littlelen)+1)) != NULL) {
        if (memcmp(p+1, little+1, littlelen-1)==0)
            return (unsigned char *)p;
     }
 
     return NULL;
 }
+
+\f
+
+static struct zip_cdir *
+_zip_read_eocd(const unsigned char *eocd, const unsigned char *buf, off_t buf_offset, size_t buflen,
+              unsigned int flags, struct zip_error *error)
+{
+    struct zip_cdir *cd;
+    const unsigned char *cdp;
+    zip_uint64_t i, nentry, size, offset;
+
+    if (eocd+EOCDLEN > buf+buflen) {
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+
+    cdp = eocd + 8;
+
+    /* number of cdir-entries on this disk */
+    i = _zip_read2(&cdp);
+    /* number of cdir-entries */
+    nentry = _zip_read2(&cdp);
+
+    if (nentry != i) {
+       _zip_error_set(error, ZIP_ER_NOZIP, 0);
+       return NULL;
+    }
+
+    size = _zip_read4(&cdp);
+    offset = _zip_read4(&cdp);
+
+    if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) {
+        _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return NULL;
+    }
+    
+    if (offset+size > (zip_uint64_t)(buf_offset + (eocd-buf))) {
+       /* cdir spans past EOCD record */
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+
+    if ((flags & ZIP_CHECKCONS) && offset+size != (zip_uint64_t)(buf_offset + (eocd-buf))) {
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+
+    if ((cd=_zip_cdir_new(nentry, error)) == NULL)
+       return NULL;
+
+    cd->size = (off_t)size;
+    cd->offset = (off_t)offset;
+    
+    return cd;
+}
+
+\f
+
+static struct zip_cdir *
+_zip_read_eocd64(FILE *f, const zip_uint8_t *eocd64loc, const zip_uint8_t *buf,
+                off_t buf_offset, size_t buflen, unsigned int flags, struct zip_error *error)
+{
+    struct zip_cdir *cd;
+    zip_uint64_t offset;
+    const zip_uint8_t *cdp;
+    zip_uint8_t eocd[EOCD64LEN];
+    zip_uint64_t eocd_offset;
+    zip_uint64_t size, nentry, i;
+
+    cdp = eocd64loc+8;
+    eocd_offset = _zip_read8(&cdp);
+    
+    if (eocd_offset > ZIP_OFF_MAX || eocd_offset + EOCD64LEN > ZIP_OFF_MAX) {
+        _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return NULL;
+    }
+
+    if (eocd64loc < buf || (off_t)eocd_offset+EOCD64LEN > (buf_offset+(eocd64loc-buf))) {
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+
+    if ((off_t)eocd_offset >= buf_offset && (off_t)eocd_offset+EOCD64LEN <= buf_offset+(ssize_t)buflen)
+       cdp = buf+((off_t)eocd_offset-buf_offset);
+    else {
+       if (fseeko(f, (off_t)eocd_offset, SEEK_SET) != 0) {
+           _zip_error_set(error, ZIP_ER_SEEK, errno);
+           return NULL;
+       }
+
+       clearerr(f);
+       if (fread(eocd, 1, EOCD64LEN, f) < EOCD64LEN) {
+            _zip_error_set(error, ZIP_ER_READ, errno);
+            return NULL;
+        }
+
+       if (ferror(f)) {
+           _zip_error_set(error, ZIP_ER_READ, errno);
+           return NULL;
+       }
+
+       cdp = eocd;
+    }
+
+    if (memcmp(cdp, EOCD64_MAGIC, 4) != 0) {
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+    cdp += 4;
+    
+    size = _zip_read8(&cdp);
+
+    if ((flags & ZIP_CHECKCONS) && size+eocd_offset+12 != (zip_uint64_t)(buf_offset+(eocd64loc-buf))) {
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+
+    cdp += 4; /* skip version made by/needed */
+    cdp += 8; /* skip num disks */
+    
+    nentry = _zip_read8(&cdp);
+    i = _zip_read8(&cdp);
+
+    if (nentry != i) {
+       _zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+       return NULL;
+    }
+
+    size = _zip_read8(&cdp);
+    offset = _zip_read8(&cdp);
+
+    if (size > ZIP_OFF_MAX || offset > ZIP_OFF_MAX || offset+size > ZIP_OFF_MAX) {
+        _zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+        return NULL;
+    }
+    if ((flags & ZIP_CHECKCONS) && offset+size != eocd_offset) {
+       _zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+
+    if ((cd=_zip_cdir_new(nentry, error)) == NULL)
+       return NULL;
+
+    
+    cd->size = (off_t)size;
+    cd->offset = (off_t)offset;
+
+    return cd;
+}
index 6b5a0359172da7a0a86a078a372a735f07c87737..8841caeca9a9ec77fb356c59849b761a353a7615 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_rename.c -- rename file in zip archive
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 #include <string.h>
 
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_rename(struct zip *za, zip_uint64_t idx, const char *name)
 {
-    const char *old_name;
-    int old_is_dir, new_is_dir;
-    
-    if (idx >= za->nentry || name[0] == '\0') {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
-    }
-
-    if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
-    }
-
-    if ((old_name=zip_get_name(za, idx, 0)) == NULL)
-       return -1;
-                                                                   
-    new_is_dir = (name[strlen(name)-1] == '/');
-    old_is_dir = (old_name[strlen(old_name)-1] == '/');
-
-    if (new_is_dir != old_is_dir) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
-    }
-
-    return _zip_set_name(za, idx, name);
+    return zip_file_rename(za, idx, name, 0);
 }
index 6dc3dd5ab508f18bafbe44c07f207ee12eb21345..de717afec7dd17cc79a2607c50d0d44e3b7311d7 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_replace.c -- replace file via callback function
-  Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 \f
 
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source)
 {
-    if (idx >= za->nentry || source == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return -1;
-    }
-
-    if (_zip_replace(za, idx, NULL, source) == -1)
-       return -1;
-
-    return 0;
-}
-
-
-\f
-
-/* NOTE: Signed due to -1 on error.  See zip_add.c for more details. */
-
-zip_int64_t
-_zip_replace(struct zip *za, zip_uint64_t idx, const char *name,
-            struct zip_source *source)
-{
-    if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
-       return -1;
-    }
-
-    if (idx == ZIP_UINT64_MAX) {
-       if (_zip_entry_new(za) == NULL)
-           return -1;
-
-       idx = za->nentry - 1;
-    }
-    
-    _zip_unchange_data(za->entry+idx);
-
-    if (name && _zip_set_name(za, idx, name) != 0)
-       return -1;
-    
-    za->entry[idx].state = ((za->cdir == NULL || idx >= za->cdir->nentry)
-                           ? ZIP_ST_ADDED : ZIP_ST_REPLACED);
-    za->entry[idx].source = source;
-
-    return idx;
+    return zip_file_replace(za, idx, source, 0);
 }
index 3cd069c7577c9421d9caa048162354a41fe74f18..df1caee06b11657eb67332df355d1d0e8ba866ef 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_archive_comment.c -- set archive comment
-  Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2013 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>
 
 \f
 
-ZIP_EXTERN(int)
-zip_set_archive_comment(struct zip *za, const char *comment, int len)
+ZIP_EXTERN int
+zip_set_archive_comment(struct zip *za, const char *comment, zip_uint16_t len)
 {
-    char *tmpcom;
+    struct zip_string *cstr;
 
-    if (len < 0 || len > MAXCOMLEN
-       || (len > 0 && comment == NULL)) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
        return -1;
     }
 
-    if (ZIP_IS_RDONLY(za)) {
-       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+    if (len > 0 && comment == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
     if (len > 0) {
-       if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL)
+       if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
            return -1;
+
+       if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
+           _zip_string_free(cstr);
+           _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+           return -1;
+       }
     }
     else
-       tmpcom = NULL;
+       cstr = NULL;
+
+    _zip_string_free(za->comment_changes);
+    za->comment_changes = NULL;
 
-    free(za->ch_comment);
-    za->ch_comment = tmpcom;
-    za->ch_comment_len = len;
+    if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr))
+        || (za->comment_orig == NULL && cstr == NULL))) {
+       _zip_string_free(cstr);
+       za->comment_changed = 0;
+    }
+    else {
+       za->comment_changes = cstr;
+       za->comment_changed = 1;
+    }
     
     return 0;
 }
index 07bcfbe304d8591e8007f86034234222f9216d86..b6cdab120ddb2a14d083087b5109e7dcda3f4bd6 100644 (file)
@@ -37,8 +37,8 @@
 
 \f
 
-ZIP_EXTERN(int)
-zip_set_archive_flag(struct zip *za, int flag, int value)
+ZIP_EXTERN int
+zip_set_archive_flag(struct zip *za, unsigned int flag, int value)
 {
     unsigned int new_flags;
     
index c274d1100bb3a4ef774f0670f886f4951d32d640..b9aa80acffc2570bd9e2a507f61a74449198b966 100644 (file)
@@ -40,7 +40,7 @@
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_set_default_password(struct zip *za, const char *passwd)
 {
     if (za == NULL)
index 5e63dc2730ad402461f10a7de3dfa15343e7dcb0..7acd0eb36de298cee20c0675227bfadcb733cd45 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_file_comment.c -- set comment for file in archive
-  Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 2006-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 
 #include <stdlib.h>
 
+#define _ZIP_COMPILING_DEPRECATED
 #include "zipint.h"
 
 \f
 
-ZIP_EXTERN(int)
-zip_set_file_comment(struct zip *za, zip_uint64_t idx,
-                    const char *comment, int len)
+ZIP_EXTERN int
+zip_set_file_comment(struct zip *za, zip_uint64_t idx, const char *comment, int len)
 {
-    char *tmpcom;
-
-    if (idx >= za->nentry
-       || len < 0 || len > MAXCOMLEN
-       || (len > 0 && comment == 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 || len > ZIP_UINT16_MAX) {
+        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return -1;
     }
-
-    if (len > 0) {
-       if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL)
-           return -1;
-    }
-    else
-       tmpcom = NULL;
-
-    free(za->entry[idx].ch_comment);
-    za->entry[idx].ch_comment = tmpcom;
-    za->entry[idx].ch_comment_len = len;
-    
-    return 0;
+    return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
 }
diff --git a/ext/zip/lib/zip_set_file_compression.c b/ext/zip/lib/zip_set_file_compression.c
new file mode 100644 (file)
index 0000000..ea8517d
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+  zip_set_file_compression.c -- set compression for file in archive
+  Copyright (C) 2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include "zipint.h"
+
+\f
+
+ZIP_EXTERN int
+zip_set_file_compression(struct zip *za, zip_uint64_t idx,
+                        zip_int32_t method, zip_uint32_t flags)
+{
+    struct zip_entry *e;
+    zip_int32_t old_method;
+
+    if (idx >= za->nentry) {
+       _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 (method != ZIP_CM_DEFAULT && method != ZIP_CM_STORE && method != ZIP_CM_DEFLATE) {
+       _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+       return -1;
+    }
+
+    e = za->entry+idx;
+    
+    old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method);
+    
+    /* XXX: revisit this when flags are supported, since they may require a recompression */
+    
+    if (method == old_method) {
+       if (e->changes) {
+           e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
+           if (e->changes->changed == 0) {
+               _zip_dirent_free(e->changes);
+               e->changes = NULL;
+           }
+       }
+    }
+    else {
+        if (e->changes == NULL) {
+            if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+                _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+                return -1;
+            }
+        }
+
+        e->changes->comp_method = method;
+        e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
+    }
+    
+    return 0;
+}
index 2a90601bfec3537008dc31244a7dcf0179d3ab3d..60c9e7d5bf59a69a3e491ff3327424b71aa6844d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_name.c -- rename helper function
-  Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 \f
 
 int
-_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name)
+_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
 {
-    char *s;
+    struct zip_entry *e;
+    struct zip_string *str;
+    int changed;
     zip_int64_t i;
-    
-    if (idx >= za->nentry || name == NULL) {
+
+    if (idx >= za->nentry) {
        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
-    if ((i=_zip_name_locate(za, name, 0, NULL)) != -1 && i != idx) {
+    if (ZIP_IS_RDONLY(za)) {
+       _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+       return -1;
+    }
+
+    if (name && strlen(name) > 0) {
+        /* XXX: check for string too long */
+       if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
+           return -1;
+       if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
+           str->encoding = ZIP_ENCODING_UTF8_KNOWN;
+    }
+    else
+       str = NULL;
+
+    /* XXX: encoding flags needed for CP437? */
+    if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) {
+       _zip_string_free(str);
        _zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
        return -1;
     }
 
     /* no effective name change */
-    if (i == idx)
+    if (i>=0 && (zip_uint64_t)i == idx) {
+       _zip_string_free(str);
        return 0;
-    
-    if ((s=strdup(name)) == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return -1;
     }
-    
-    if (za->entry[idx].state == ZIP_ST_UNCHANGED) 
-       za->entry[idx].state = ZIP_ST_RENAMED;
 
-    free(za->entry[idx].ch_filename);
-    za->entry[idx].ch_filename = s;
+    e = za->entry+idx;
+
+    if (e->changes) {
+       _zip_string_free(e->changes->filename);
+       e->changes->filename = NULL;
+       e->changes->changed &= ~ZIP_DIRENT_FILENAME;
+    }
+
+    if (e->orig)
+       changed = !_zip_string_equal(e->orig->filename, str);
+    else
+       changed = 1;
+       
+    if (changed) {
+        if (e->changes == NULL) {
+            if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+                _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+               _zip_string_free(str);
+                return -1;
+            }
+        }
+        e->changes->filename = str;
+        e->changes->changed |= ZIP_DIRENT_FILENAME;
+    }
+    else {
+       _zip_string_free(str);
+       if (e->changes && e->changes->changed == 0) {
+           _zip_dirent_free(e->changes);
+           e->changes = NULL;
+       }
+    }
 
     return 0;
 }
index 8c9154ce3c5ba8c59f25d1b25be961c7d8251915..8a13e7602d195ee31c87418c39ba7d1cd67f859a 100644 (file)
@@ -48,7 +48,7 @@ static zip_int64_t read_data(void *, void *, zip_uint64_t, enum zip_source_cmd);
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+ZIP_EXTERN struct zip_source *
 zip_source_buffer(struct zip *za, const void *data, zip_uint64_t len, int freep)
 {
     struct read_data *f;
@@ -98,9 +98,7 @@ read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
        return 0;
        
     case ZIP_SOURCE_READ:
-       /* XXX: return error if (len > ZIP_INT64_MAX) */
-
-       n = z->end - z->buf;
+       n = (zip_uint64_t)(z->end - z->buf);
        if (n > len)
            n = len;
 
@@ -109,7 +107,7 @@ read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
            z->buf += n;
        }
 
-       return n;
+       return (zip_int64_t)n;
        
     case ZIP_SOURCE_CLOSE:
        return 0;
@@ -125,7 +123,7 @@ read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
 
            zip_stat_init(st);
            st->mtime = z->mtime;
-           st->size = z->end - z->data;
+           st->size = (zip_uint64_t)(z->end - z->data);
            st->comp_size = st->size;
            st->comp_method = ZIP_CM_STORE;
            st->encryption_method = ZIP_EM_NONE;
index a3bf7e5e1d9bd8e0459c6955292be2675855b890..7b89d5fc15f682fa94ee4dd8092f13bc75034fb9 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(void)
+void
 zip_source_close(struct zip_source *src)
 {
     if (!src->is_open)
index 7fd78f56970cf8d5d017947e0618a8147fdbbcc8..99bc96522889816e60cb75c8a547a0883b4939f2 100644 (file)
@@ -38,7 +38,7 @@
 
 #include "zipint.h"
 
-struct crc {
+struct crc_context {
     int eof;
     int validate;
     int e[2];
@@ -51,23 +51,27 @@ static zip_int64_t crc_read(struct zip_source *, void *, void *
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+struct zip_source *
 zip_source_crc(struct zip *za, struct zip_source *src, int validate)
 {
-    struct crc *ctx;
+    struct crc_context *ctx;
 
     if (src == NULL) {
        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return NULL;
     }
 
-    if ((ctx=(struct crc *)malloc(sizeof(*ctx))) == NULL) {
+    if ((ctx=(struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
        return NULL;
     }
 
+    ctx->eof = 0;
     ctx->validate = validate;
-
+    ctx->e[0] = ctx->e[1] = 0;
+    ctx->size = 0;
+    ctx->crc = 0;
+    
     return zip_source_layered(za, src, crc_read, ctx);
 }
 
@@ -77,15 +81,15 @@ static zip_int64_t
 crc_read(struct zip_source *src, void *_ctx, void *data,
         zip_uint64_t len, enum zip_source_cmd cmd)
 {
-    struct crc *ctx;
+    struct crc_context *ctx;
     zip_int64_t n;
 
-    ctx = (struct crc *)_ctx;
+    ctx = (struct crc_context *)_ctx;
 
     switch (cmd) {
     case ZIP_SOURCE_OPEN:
        ctx->eof = 0;
-       ctx->crc = crc32(0, NULL, 0);
+       ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
        ctx->size = 0;
 
        return 0;
@@ -120,8 +124,8 @@ crc_read(struct zip_source *src, void *_ctx, void *data,
            }
        }
        else {
-           ctx->size += n;
-           ctx->crc = crc32(ctx->crc, data, n);
+           ctx->size += (zip_uint64_t)n;
+           ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data, (uInt)n); /* XXX: check for overflow, use multiple crc calls if needed */
        }
        return n;
 
@@ -139,7 +143,10 @@ crc_read(struct zip_source *src, void *_ctx, void *data,
                        After all, this only works for uncompressed data. */
                st->size = ctx->size;
                st->crc = ctx->crc;
-               st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC;
+               st->comp_size = ctx->size;
+               st->comp_method = ZIP_CM_STORE;
+               st->encryption_method = ZIP_EM_NONE;
+               st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;;
            }
        }
        return 0;
index 5d9c5e67bb605625b6605cdc32487a9ad297de65..879953144ce5699b4a312be0041c5640056be4df 100644 (file)
@@ -60,14 +60,14 @@ static void deflate_free(struct deflate *);
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+struct zip_source *
 zip_source_deflate(struct zip *za, struct zip_source *src,
-                  zip_uint16_t cm, int flags)
+                  zip_int32_t cm, int flags)
 {
     struct deflate *ctx;
     struct zip_source *s2;
 
-    if (src == NULL || cm != ZIP_CM_DEFLATE) {
+    if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return NULL;
     }
@@ -113,7 +113,7 @@ compress_read(struct zip_source *src, struct deflate *ctx,
        return 0;
        
     ctx->zstr.next_out = (Bytef *)data;
-    ctx->zstr.avail_out = len;
+    ctx->zstr.avail_out = (uInt)len; /* XXX: check for overflow */
 
     end = 0;
     while (!end) {
@@ -136,8 +136,7 @@ compress_read(struct zip_source *src, struct deflate *ctx,
                    break;
                }
 
-               if ((n=zip_source_read(src, ctx->buffer,
-                                      sizeof(ctx->buffer))) < 0) {
+               if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
                    zip_source_error(src, ctx->e, ctx->e+1);
                    end = 1;
                    break;
@@ -149,7 +148,7 @@ compress_read(struct zip_source *src, struct deflate *ctx,
                }
                else {
                    ctx->zstr.next_in = (Bytef *)ctx->buffer;
-                   ctx->zstr.avail_in = n;
+                   ctx->zstr.avail_in = (uInt)n;
                }
                continue;
            }
@@ -167,7 +166,7 @@ compress_read(struct zip_source *src, struct deflate *ctx,
     }
 
     if (ctx->zstr.avail_out < len)
-       return len - ctx->zstr.avail_out;
+       return (zip_int64_t)(len - ctx->zstr.avail_out);
 
     return (ctx->e[0] == 0) ? 0 : -1;
 }
@@ -188,7 +187,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx,
        return 0;
        
     ctx->zstr.next_out = (Bytef *)data;
-    ctx->zstr.avail_out = len;
+    ctx->zstr.avail_out = (uInt)len; /* XXX: check for overflow */
 
     end = 0;
     while (!end && ctx->zstr.avail_out) {
@@ -210,8 +209,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx,
                    break;
                }
 
-               if ((n=zip_source_read(src, ctx->buffer,
-                           sizeof(ctx->buffer))) < 0) {
+               if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
                    zip_source_error(src, ctx->e, ctx->e+1);
                    end = 1;
                    break;
@@ -220,7 +218,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx,
                    ctx->eof = 1;
                else {
                    ctx->zstr.next_in = (Bytef *)ctx->buffer;
-                   ctx->zstr.avail_in = n;
+                   ctx->zstr.avail_in = (uInt)n;
                }
                continue;
            }
@@ -237,7 +235,7 @@ decompress_read(struct zip_source *src, struct deflate *ctx,
     }
 
     if (ctx->zstr.avail_out < len)
-       return len - ctx->zstr.avail_out;
+       return (zip_int64_t)(len - ctx->zstr.avail_out);
 
     return (ctx->e[0] == 0) ? 0 : -1;
 }
@@ -334,7 +332,7 @@ deflate_decompress(struct zip_source *src, void *ud, void *data,
        ctx->zstr.zfree = Z_NULL;
        ctx->zstr.opaque = NULL;
        ctx->zstr.next_in = (Bytef *)ctx->buffer;
-       ctx->zstr.avail_in = n;
+       ctx->zstr.avail_in = (uInt)n /* XXX: check for overflow */;
 
        /* negative value to tell zlib that there is no header */
        if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
index 70ec8bc5d452f36273ba2d2d4aa123f8a3473b2a..a1efd551ea3ddaa127059f725182ada05f26c81d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_error.c -- get last error from zip_source
-  Copyright (C) 2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2013 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>
 
 \f
 
-ZIP_EXTERN(void)
+void
 zip_source_error(struct zip_source *src, int *ze, int *se)
 {
-    int e[2] = { 0, 0 };
+    int e[2];
 
     if (src->src == NULL) {
+        if (src->cb.f(src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
+            e[0] = ZIP_ER_INTERNAL;
+            e[1] = 0;
+        }
     }
     else {
        switch (src->error_source) {
        case ZIP_LES_NONE:
-           if (src->src == NULL) {
-               if (src->cb.f(src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
-                   e[0] = ZIP_ER_INTERNAL;
-                   e[1] = 0;
-               }
-           }
-           else
-               e[0] = e[1] = 0;
+           e[0] = e[1] = 0;
            break;
 
        case ZIP_LES_INVAL:
@@ -67,8 +64,7 @@ zip_source_error(struct zip_source *src, int *ze, int *se)
            return;
 
        case ZIP_LES_UPPER:
-           if (src->cb.l(src->src, src->ud, e, sizeof(e),
-                         ZIP_SOURCE_ERROR) < 0) {
+           if (src->cb.l(src->src, src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
                e[0] = ZIP_ER_INTERNAL;
                e[1] = 0;
            }
@@ -77,6 +73,7 @@ zip_source_error(struct zip_source *src, int *ze, int *se)
        default:
            e[0] = ZIP_ER_INTERNAL;
            e[1] = 0;
+           break;
        }
     }
 
index 681cc2f3ea64397f9c644f26139d78502e5cd6aa..79c8ee5aca22b64146728b522ba061df71816573 100644 (file)
@@ -40,7 +40,7 @@
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+ZIP_EXTERN struct zip_source *
 zip_source_file(struct zip *za, const char *fname, zip_uint64_t start,
                zip_int64_t len)
 {
index 4d896a4c01bfc081e778ae5e398d4f613deeb58c..0bd2d6846e5a3b3e17729539761db701f69f566b 100644 (file)
@@ -58,14 +58,14 @@ static zip_int64_t read_file(void *state, void *data, zip_uint64_t len,
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+ZIP_EXTERN struct zip_source *
 zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start,
                 zip_int64_t len)
 {
     if (za == NULL)
        return NULL;
 
-    if (file == NULL || start < 0 || len < -1) {
+    if (file == NULL || len < -1) {
        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return NULL;
     }
@@ -125,7 +125,7 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
 {
     struct read_file *z;
     char *buf;
-    int i, n;
+    size_t i, n;
 
     z = (struct read_file *)state;
     buf = (char *)data;
@@ -140,7 +140,7 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
            }
        }
 
-       if (z->closep) {
+       if (z->closep && z->off > 0) {
            if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) {
                z->e[0] = ZIP_ER_SEEK;
                z->e[1] = errno;
@@ -153,30 +153,31 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
     case ZIP_SOURCE_READ:
        /* XXX: return INVAL if len > size_t max */
        if (z->remain != -1)
-           n = len > z->remain ? z->remain : len;
+           n = len > (zip_uint64_t)z->remain ? (zip_uint64_t)z->remain : len;
        else
            n = len;
 
        if (!z->closep) {
            /* we might share this file with others, so let's be safe */
-           if (fseeko(z->f, (off_t)(z->off + z->len-z->remain),
-                      SEEK_SET) < 0) {
+           if (fseeko(z->f, (off_t)(z->off + (zip_uint64_t)(z->len-z->remain)), SEEK_SET) < 0) {
                z->e[0] = ZIP_ER_SEEK;
                z->e[1] = errno;
                return -1;
            }
        }
 
-       if ((i=fread(buf, 1, n, z->f)) < 0) {
-           z->e[0] = ZIP_ER_READ;
-           z->e[1] = errno;
-           return -1;
+       if ((i=fread(buf, 1, n, z->f)) == 0) {
+            if (ferror(z->f)) {
+                z->e[0] = ZIP_ER_READ;
+                z->e[1] = errno;
+                return -1;
+            }
        }
 
        if (z->remain != -1)
            z->remain -= i;
 
-       return i;
+       return (zip_int64_t)i;
        
     case ZIP_SOURCE_CLOSE:
        if (z->fname) {
@@ -214,11 +215,11 @@ read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
                st->mtime = fst.st_mtime;
                st->valid |= ZIP_STAT_MTIME;
                if (z->len != -1) {
-                   st->size = z->len;
+                   st->size = (zip_uint64_t)z->len;
                    st->valid |= ZIP_STAT_SIZE;
                }
                else if ((fst.st_mode&S_IFMT) == S_IFREG) {
-                   st->size = fst.st_size;
+                   st->size = (zip_uint64_t)fst.st_size;
                    st->valid |= ZIP_STAT_SIZE;
                }
            }
index f71c71ed6c5779e166ae43bdc7b9f3632ee71ac8..b1e78404965c28df0c21a29ff7890b8bce824884 100644 (file)
@@ -39,7 +39,7 @@
 
 \f
 
-ZIP_EXTERN(void)
+ZIP_EXTERN void
 zip_source_free(struct zip_source *src)
 {
     if (src == NULL)
index 984b107f7baa6fecd85d8ef29f021c6eea76531f..cb92e339b4bb27ef94eb7d6f4141affcf56ea7d8 100644 (file)
@@ -39,7 +39,7 @@
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+ZIP_EXTERN struct zip_source *
 zip_source_function(struct zip *za, zip_source_callback zcb, void *ud)
 {
     struct zip_source *zs;
index 86ed4204070716c42de801df35f8fc0b847b0fe2..ad2870333cdeec5b6756a2f370f503d12c429629 100644 (file)
@@ -39,7 +39,7 @@
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+struct zip_source *
 zip_source_layered(struct zip *za, struct zip_source *src,
                   zip_source_layered_callback cb, void *ud)
 {
index 2c768f7f3a4e5e4f55b871ac59039918926113a0..a5010393e7b9ccfd8bb0598a364c6cf4346bd8a6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_open.c -- open zip_source (prepare for reading)
-  Copyright (C) 2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2013 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>
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(int)
+int
 zip_source_open(struct zip_source *src)
 {
     zip_int64_t ret;
@@ -60,7 +60,7 @@ zip_source_open(struct zip_source *src)
        ret = src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_OPEN);
        
        if (ret < 0) {
-           (void)zip_source_close(src->src);
+           zip_source_close(src->src);
            
            if (ret == ZIP_SOURCE_ERR_LOWER)
                src->error_source = ZIP_LES_LOWER;
index 83b5cc5ad5b225bf552d5138389f9bed1f32b19a..ec53dfeef046871f050335774145164759d731c7 100644 (file)
@@ -49,10 +49,6 @@ struct trad_pkware {
 #define KEY1           591751049
 #define KEY2           878082192
 
-static const uLongf *crc = NULL;
-
-#define CRC32(c, b) (crc[((c) ^ (b)) & 0xff] ^ ((c) >> 8))
-
 \f
 
 static void decrypt(struct trad_pkware *, zip_uint8_t *,
@@ -64,7 +60,7 @@ static void pkware_free(struct trad_pkware *);
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+struct zip_source *
 zip_source_pkware(struct zip *za, struct zip_source *src,
                  zip_uint16_t em, int flags, const char *password)
 {
@@ -80,9 +76,6 @@ zip_source_pkware(struct zip *za, struct zip_source *src,
        return NULL;
     }
 
-    if (crc == NULL)
-       crc = get_crc_table();
-
     if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
        return NULL;
@@ -118,7 +111,7 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
 
        if (!update_only) {
            /* decrypt next byte */
-           tmp = ctx->key[2] | 2;
+           tmp = (zip_uint16_t)(ctx->key[2] | 2);
            tmp = (tmp * (tmp ^ 1)) >> 8;
            b ^= tmp;
        }
@@ -128,10 +121,10 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
            out[i] = b;
 
        /* update keys */
-       ctx->key[0] = CRC32(ctx->key[0], b);
+       ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
        ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1;
        b = ctx->key[1] >> 24;
-       ctx->key[2] = CRC32(ctx->key[2], b);
+       ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
     }
 }
 
@@ -196,7 +189,7 @@ pkware_decrypt(struct zip_source *src, void *ud, void *data,
        if ((n=zip_source_read(src, data, len)) < 0)
            return ZIP_SOURCE_ERR_LOWER;
 
-       decrypt(ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n,
+       decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n,
                0);
        return n;
 
index 406093869b96275817bdaddd52f95ebcd9f314ba..cd9cb529b5cc771697a6f41c73d268381f80ea81 100644 (file)
@@ -39,7 +39,7 @@
 
 \f
 
-ZIP_EXTERN(struct zip_source *)
+struct zip_source *
 zip_source_pop(struct zip_source *src)
 {
     struct zip_source *lower;
index 7246f9ccb5367e4343c6a1e8e66c078bd0059c76..81b90ba42de35437a6db8d1789a854caae3fe7b1 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(zip_int64_t)
+zip_int64_t
 zip_source_read(struct zip_source *src, void *data, zip_uint64_t len)
 {
     zip_int64_t ret;
index 662779eb6cfba59a20084c39bca72e80c23cfc5f..85ae6a2fd6a2611f4df59b9e1933a18a32e1ecc3 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(int)
+int
 zip_source_stat(struct zip_source *src, struct zip_stat *st)
 {
     zip_int64_t ret;
diff --git a/ext/zip/lib/zip_source_window.c b/ext/zip/lib/zip_source_window.c
new file mode 100644 (file)
index 0000000..fd20209
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+  zip_source_window.c -- return part of lower source
+  Copyright (C) 2012-2013 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.
+*/
+
+\f
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "zipint.h"
+
+struct window {
+    zip_uint64_t skip;
+    zip_uint64_t len;
+    zip_uint64_t left;
+    int e[2];
+};
+
+static zip_int64_t window_read(struct zip_source *, void *, void *,
+                              zip_uint64_t, enum zip_source_cmd);
+
+\f
+
+struct zip_source *
+zip_source_window(struct zip *za, struct zip_source *src, zip_uint64_t start, zip_uint64_t len)
+{
+    struct window *ctx;
+
+    if (src == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    if ((ctx=(struct window *)malloc(sizeof(*ctx))) == NULL) {
+       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+
+    ctx->skip = start;
+    ctx->len = len;
+    ctx->left = len;
+
+    return zip_source_layered(za, src, window_read, ctx);
+}
+
+\f
+
+static zip_int64_t
+window_read(struct zip_source *src, void *_ctx, void *data,
+           zip_uint64_t len, enum zip_source_cmd cmd)
+{
+    struct window *ctx;
+    zip_int64_t ret;
+    zip_uint64_t n, i;
+    char b[8192];
+
+    ctx = (struct window *)_ctx;
+
+    switch (cmd) {
+    case ZIP_SOURCE_OPEN:
+       for (n=0; n<ctx->skip; n+=(zip_uint64_t)ret) {
+           i = (ctx->skip-n > sizeof(b) ? sizeof(b) : ctx->skip-n);
+           if ((ret=zip_source_read(src, b, i)) < 0)
+               return ZIP_SOURCE_ERR_LOWER;
+           if (ret==0) {
+               ctx->e[0] = ZIP_ER_EOF;
+               ctx->e[1] = 0;
+               return -1;
+           }
+       }
+       return 0;
+
+    case ZIP_SOURCE_READ:
+       if (len > ctx->left)
+           len = ctx->left;
+       
+       if (len == 0)
+           return 0;
+
+       if ((ret=zip_source_read(src, data, len)) < 0)
+           return ZIP_SOURCE_ERR_LOWER;
+
+       ctx->left -= (zip_uint64_t)ret;
+
+        if (ret == 0) {
+           if (ctx->left > 0) {
+               ctx->e[0] = ZIP_ER_EOF;
+               ctx->e[1] = 0;
+               return -1;
+           }
+       }
+       return ret;
+
+    case ZIP_SOURCE_CLOSE:
+       return 0;
+
+    case ZIP_SOURCE_STAT:
+       {
+           struct zip_stat *st;
+
+           st = (struct zip_stat *)data;
+
+           st->size = ctx->len;
+           st->valid |= ZIP_STAT_SIZE;
+           st->valid &= ~(ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE);
+       }
+       return 0;
+       
+    case ZIP_SOURCE_ERROR:
+       memcpy(data, ctx->e, sizeof(ctx->e));
+       return 0;
+
+    case ZIP_SOURCE_FREE:
+       free(ctx);
+       return 0;
+
+    default:
+       return -1;
+    }
+    
+}
index 228803c717f6aeb86538f0c3625827e4d5496d1f..e4fc2229f782c14b1bd1700bde8dcfd73d05735d 100644 (file)
 
 #include "zipint.h"
 
-struct read_zip {
-    struct zip_file *zf;
-    struct zip_stat st;
-    zip_uint64_t off;
-    zip_int64_t len;
-};
-
-static zip_int64_t read_zip(void *st, void *data, zip_uint64_t len,
-                       enum zip_source_cmd cmd);
-
 \f
 
-ZIP_EXTERN(struct zip_source *)
+ZIP_EXTERN struct zip_source *
 zip_source_zip(struct zip *za, struct zip *srcza, zip_uint64_t srcidx,
-              int flags, zip_uint64_t start, zip_int64_t len)
+              zip_flags_t flags, zip_uint64_t start, zip_int64_t len)
 {
-    struct zip_error error;
-    struct zip_source *zs;
-    struct read_zip *p;
-
-    /* XXX: ZIP_FL_RECOMPRESS */
-
-    if (za == NULL)
-       return NULL;
-
-    if (srcza == NULL || len < -1 || srcidx < 0 || srcidx >= srcza->nentry) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-       return NULL;
+    if (len < -1) {
+        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        return NULL;
     }
-
-    if ((flags & ZIP_FL_UNCHANGED) == 0
-       && ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx)) {
-       _zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
-       return NULL;
-    }
-
-    if (len == 0)
-       len = -1;
-
-    if (start == 0 && len == -1 && (flags & ZIP_FL_RECOMPRESS) == 0)
+        
+    if (len == -1)
+       len = 0;
+    
+    if (start == 0 && len == 0)
        flags |= ZIP_FL_COMPRESSED;
     else
        flags &= ~ZIP_FL_COMPRESSED;
 
-    if ((p=(struct read_zip *)malloc(sizeof(*p))) == NULL) {
-       _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-       return NULL;
-    }
-       
-    _zip_error_copy(&error, &srcza->error);
-       
-    if (zip_stat_index(srcza, srcidx, flags, &p->st) < 0
-       || (p->zf=zip_fopen_index(srcza, srcidx, flags)) == NULL) {
-       free(p);
-       _zip_error_copy(&za->error, &srcza->error);
-       _zip_error_copy(&srcza->error, &error);
-       
-       return NULL;
-    }
-    p->off = start;
-    p->len = len;
-
-    if ((flags & ZIP_FL_COMPRESSED) == 0) {
-       p->st.size = p->st.comp_size = len;
-       p->st.comp_method = ZIP_CM_STORE;
-       p->st.crc = 0;
-    }
-    
-    if ((zs=zip_source_function(za, read_zip, p)) == NULL) {
-       free(p);
-       return NULL;
-    }
-
-    return zs;
-}
-
-\f
-
-static zip_int64_t
-read_zip(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
-{
-    struct read_zip *z;
-    char b[8192], *buf;
-    int i;
-    zip_uint64_t n;
-
-    z = (struct read_zip *)state;
-    buf = (char *)data;
-
-    switch (cmd) {
-    case ZIP_SOURCE_OPEN:
-       for (n=0; n<z->off; n+= i) {
-           i = (z->off-n > sizeof(b) ? sizeof(b) : z->off-n);
-           if ((i=zip_fread(z->zf, b, i)) < 0) {
-               zip_fclose(z->zf);
-               z->zf = NULL;
-               return -1;
-           }
-       }
-       return 0;
-       
-    case ZIP_SOURCE_READ:
-       if (z->len != -1)
-           n = len > z->len ? z->len : len;
-       else
-           n = len;
-       
-
-       if ((i=zip_fread(z->zf, buf, n)) < 0)
-           return -1;
-
-       if (z->len != -1)
-           z->len -= i;
-
-       return i;
-       
-    case ZIP_SOURCE_CLOSE:
-       return 0;
-
-    case ZIP_SOURCE_STAT:
-       if (len < sizeof(z->st))
-           return -1;
-       len = sizeof(z->st);
-
-       memcpy(data, &z->st, len);
-       return len;
-
-    case ZIP_SOURCE_ERROR:
-       {
-           int *e;
-
-           if (len < sizeof(int)*2)
-               return -1;
-
-           e = (int *)data;
-           zip_file_error_get(z->zf, e, e+1);
-       }
-       return sizeof(int)*2;
-
-    case ZIP_SOURCE_FREE:
-       zip_fclose(z->zf);
-       free(z);
-       return 0;
-
-    default:
-       ;
-    }
-
-    return -1;
+    return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL);
 }
diff --git a/ext/zip/lib/zip_source_zip_new.c b/ext/zip/lib/zip_source_zip_new.c
new file mode 100644 (file)
index 0000000..8e48f6f
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+  zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip
+  Copyright (C) 2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include <stdlib.h>
+
+#include "zipint.h"
+
+\f
+
+struct zip_source *
+_zip_source_zip_new(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, zip_flags_t flags,
+                   zip_uint64_t start, zip_uint64_t len, const char *password)
+{
+    zip_compression_implementation comp_impl;
+    zip_encryption_implementation enc_impl;
+    struct zip_source *src, *s2;
+    zip_uint64_t offset;
+    struct zip_stat st;
+
+    if (za == NULL)
+       return NULL;
+
+    if (srcza == NULL ||  srcidx >= srcza->nentry) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    if ((flags & ZIP_FL_UNCHANGED) == 0
+       && (ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx) || srcza->entry[srcidx].deleted)) {
+       _zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
+       return NULL;
+    }
+
+    if (zip_stat_index(srcza, srcidx, flags|ZIP_FL_UNCHANGED, &st) < 0) {
+       _zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+       return NULL;
+    }
+
+    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);
+       return NULL;
+    }
+
+    /* overflow or past end of file */
+    if ((start > 0 || len > 0) && (start+len < start || start+len > st.size)) {
+       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+
+    enc_impl = NULL;
+    if (((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE)) {
+       if (password == NULL) {
+           _zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0);
+           return NULL;
+       }
+       if ((enc_impl=_zip_get_encryption_implementation(st.encryption_method)) == NULL) {
+           _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+           return NULL;
+       }
+    }
+
+    comp_impl = NULL;
+    if ((flags & ZIP_FL_COMPRESSED) == 0) {
+       if (st.comp_method != ZIP_CM_STORE) {
+           if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) {
+               _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+               return NULL;
+           }
+       }
+    }
+
+    if ((offset=_zip_file_get_offset(srcza, srcidx, &za->error)) == 0)
+       return NULL;
+
+    if (st.comp_size == 0) {
+       if ((src=zip_source_buffer(za, NULL, 0, 0)) == NULL)
+           return NULL;
+    }
+    else {
+       if (start+len > 0 && enc_impl == NULL && comp_impl == NULL) {
+           struct zip_stat st2;
+
+           st2.size = len ? len : st.size-start;
+           st2.comp_size = st2.size;
+           st2.comp_method = ZIP_CM_STORE;
+           st2.mtime = st.mtime;
+           st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME;
+
+            /* XXX: check for overflow of st2.size */
+           if ((src=_zip_source_file_or_p(za, NULL, srcza->zp, offset+start, (zip_int64_t)st2.size, 0, &st2)) == NULL)
+               return NULL;
+       }
+       else {
+            /* XXX: check for overflow of st.comp_size */
+           if ((src=_zip_source_file_or_p(za, NULL, srcza->zp, offset, (zip_int64_t)st.comp_size, 0, &st)) == NULL)
+               return NULL;
+       }
+       
+       if (enc_impl) {
+           if ((s2=enc_impl(za, src, st.encryption_method, 0, password)) == NULL) {
+               zip_source_free(src);
+               /* XXX: set error (how?) */
+               return NULL;
+           }
+           src = s2;
+       }
+       if (comp_impl) {
+           if ((s2=comp_impl(za, src, st.comp_method, 0)) == NULL) {
+               zip_source_free(src);
+               /* XXX: set error (how?) */
+               return NULL;
+           }
+           src = s2;
+       }
+       if (((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE)
+           && (len == 0 || len == st.comp_size)) {
+           /* when reading the whole file, check for crc errors */
+           if ((s2=zip_source_crc(za, src, 1)) == NULL) {
+               zip_source_free(src);
+               /* XXX: set error (how?) */
+               return NULL;
+           }
+           src = s2;
+       }
+
+       if (start+len > 0 && (comp_impl || enc_impl)) {
+           if ((s2=zip_source_window(za, src, start, len ? len : st.size-start)) == NULL) {
+               zip_source_free(src);
+               /* XXX: set error (how?) (why?) */
+               return NULL;
+           }
+           src = s2;
+       }
+    }
+
+    return src;
+}
index c8a25e1d84ac377cc130d02ae0109d456c0418af..8254627d929f4ecf007f99479c3a738903c0d78c 100644 (file)
 
 \f
 
-ZIP_EXTERN(int)
-zip_stat(struct zip *za, const char *fname, int flags, struct zip_stat *st)
+ZIP_EXTERN int
+zip_stat(struct zip *za, const char *fname, zip_flags_t flags, struct zip_stat *st)
 {
-    int idx;
+    zip_int64_t idx;
 
     if ((idx=zip_name_locate(za, fname, flags)) < 0)
        return -1;
 
-    return zip_stat_index(za, idx, flags, st);
+    return zip_stat_index(za, (zip_uint64_t)idx, flags, st);
 }
index 8faa8cc39497284e4f0ce421f3055610b545953b..f4ce72aaa82d8bf87af1b73b81cfb5aa7ef5fad4 100644 (file)
 
 \f
 
-ZIP_EXTERN(int)
-zip_stat_index(struct zip *za, zip_uint64_t index, int flags,
+ZIP_EXTERN int
+zip_stat_index(struct zip *za, zip_uint64_t index, zip_flags_t flags,
               struct zip_stat *st)
 {
     const char *name;
-    
-    if (index >= za->nentry) {
-       _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+    struct zip_dirent *de;
+
+    if ((de=_zip_get_dirent(za, index, flags, NULL)) == NULL)
        return -1;
-    }
 
     if ((name=zip_get_name(za, index, flags)) == NULL)
        return -1;
@@ -60,20 +59,15 @@ zip_stat_index(struct zip *za, zip_uint64_t index, int flags,
        }
     }
     else {
-       if (za->cdir == NULL || index >= za->cdir->nentry) {
-           _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
-           return -1;
-       }
-
        zip_stat_init(st);
 
-       st->crc = za->cdir->entry[index].crc;
-       st->size = za->cdir->entry[index].uncomp_size;
-       st->mtime = za->cdir->entry[index].last_mod;
-       st->comp_size = za->cdir->entry[index].comp_size;
-       st->comp_method = za->cdir->entry[index].comp_method;
-       if (za->cdir->entry[index].bitflags & ZIP_GPBF_ENCRYPTED) {
-           if (za->cdir->entry[index].bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
+       st->crc = de->crc;
+       st->size = de->uncomp_size;
+       st->mtime = de->last_mod;
+       st->comp_size = de->comp_size;
+       st->comp_method = (zip_uint16_t)de->comp_method;
+       if (de->bitflags & ZIP_GPBF_ENCRYPTED) {
+           if (de->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
                /* XXX */
                st->encryption_method = ZIP_EM_UNKNOWN;
            }
index 74e1ffd0b0dceabf543e1c09368c72e4f71dbc36..d17613bf5e7e80fe74afdcaff0f1cfeebde78678 100644 (file)
@@ -37,7 +37,7 @@
 
 \f
 
-ZIP_EXTERN(void)
+ZIP_EXTERN void
 zip_stat_init(struct zip_stat *st)
 {
     st->valid = 0;
index ad23bafed6c629dca6427e39d9f00b76280321e0..9ebee144f908ad6608e0391647f877c3ce220318 100644 (file)
@@ -36,7 +36,8 @@
 #include "zipint.h"
 
 \f
-ZIP_EXTERN(const char *)
+
+ZIP_EXTERN const char *
 zip_strerror(struct zip *za)
 {
     return _zip_error_strerror(&za->error);
diff --git a/ext/zip/lib/zip_string.c b/ext/zip/lib/zip_string.c
new file mode 100644 (file)
index 0000000..a2d5eb5
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+  zip_string.c -- string handling (with encoding)
+  Copyright (C) 2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "zipint.h"
+
+\f
+
+zip_uint32_t
+_zip_string_crc32(const struct zip_string *s)
+{
+    zip_uint32_t crc;
+    
+    crc = (zip_uint32_t)crc32(0L, Z_NULL, 0);
+
+    if (s != NULL)    
+       crc = (zip_uint32_t)crc32(crc, s->raw, s->length);
+
+    return crc;
+}
+
+\f
+
+int
+_zip_string_equal(const struct zip_string *a, const struct zip_string *b)
+{
+    if (a == NULL || b == NULL)
+       return a == b;
+
+    if (a->length != b->length)
+       return 0;
+
+    /* XXX: encoding */
+
+    return (memcmp(a->raw, b->raw, a->length) == 0);
+}
+
+\f
+
+void
+_zip_string_free(struct zip_string *s)
+{
+    if (s == NULL)
+       return;
+
+    free(s->raw);
+    free(s->converted);
+    free(s);
+}
+
+\f
+
+const zip_uint8_t *
+_zip_string_get(struct zip_string *string, zip_uint32_t *lenp, zip_flags_t flags, struct zip_error *error)
+{
+    static const zip_uint8_t empty[1] = "";
+
+    if (string == NULL) {
+       if (lenp)
+           *lenp = 0;
+       return empty;
+    }
+
+    if ((flags & ZIP_FL_ENC_RAW) == 0) {
+       /* start guessing */
+       if (string->encoding == ZIP_ENCODING_UNKNOWN)
+           _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN);
+
+       if (((flags & ZIP_FL_ENC_STRICT)
+            && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN)
+           || (string->encoding == ZIP_ENCODING_CP437)) {
+           if (string->converted == NULL) {
+               if ((string->converted=_zip_cp437_to_utf8(string->raw, string->length,
+                                                         &string->converted_length, error)) == NULL)
+                   return NULL;
+           }
+           if (lenp)
+               *lenp = string->converted_length;
+           return string->converted;
+       }
+    }
+    
+    if (lenp)
+       *lenp = string->length;
+    return string->raw;
+}
+
+\f
+
+zip_uint16_t
+_zip_string_length(const struct zip_string *s)
+{
+    if (s == NULL)
+       return 0;
+
+    return s->length;
+}
+
+\f
+
+struct zip_string *
+_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, struct zip_error *error)
+{
+    struct zip_string *s;
+    enum zip_encoding_type expected_encoding;
+    
+    if (length == 0)
+       return NULL;
+
+    switch (flags & ZIP_FL_ENCODING_ALL) {
+    case ZIP_FL_ENC_GUESS:
+       expected_encoding = ZIP_ENCODING_UNKNOWN;
+       break;
+    case ZIP_FL_ENC_UTF_8:
+       expected_encoding = ZIP_ENCODING_UTF8_KNOWN;
+       break;
+    case ZIP_FL_ENC_CP437:
+       expected_encoding = ZIP_ENCODING_CP437;
+       break;
+    default:
+       _zip_error_set(error, ZIP_ER_INVAL, 0);
+       return NULL;
+    }
+       
+    if ((s=(struct zip_string *)malloc(sizeof(*s))) == NULL) {
+       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+
+    if ((s->raw=(zip_uint8_t *)malloc(length+1)) == NULL) {
+       free(s);
+       return NULL;
+    }
+
+    memcpy(s->raw, raw, length);
+    s->raw[length] = '\0';
+    s->length = length;
+    s->encoding = ZIP_ENCODING_UNKNOWN;
+    s->converted = NULL;
+    s->converted_length = 0;
+
+    if (expected_encoding != ZIP_ENCODING_UNKNOWN) {
+       if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) {
+           _zip_string_free(s);
+           _zip_error_set(error, ZIP_ER_INVAL, 0);
+           return NULL;
+       }
+    }
+    
+    return s;
+}
+
+\f
+
+void
+_zip_string_write(const struct zip_string *s, FILE *f)
+{
+    if (s == NULL)
+       return;
+    
+    fwrite(s->raw, s->length, 1, f);
+}
index 550e8b99031f22153f769d35013f8e0d7c0470ec..5f0e753b78634304e2ea86f7175314511ad7b2bd 100644 (file)
@@ -39,7 +39,7 @@
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_unchange(struct zip *za, zip_uint64_t idx)
 {
     return _zip_unchange(za, idx, 0);
@@ -50,34 +50,23 @@ zip_unchange(struct zip *za, zip_uint64_t idx)
 int
 _zip_unchange(struct zip *za, zip_uint64_t idx, int allow_duplicates)
 {
-    int i;
+    zip_int64_t i;
     
     if (idx >= za->nentry) {
        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
     }
 
-    if (za->entry[idx].ch_filename) {
-       if (!allow_duplicates) {
-           i = _zip_name_locate(za,
-                        _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL),
-                                0, NULL);
-           if (i != -1 && i != idx) {
-               _zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
-               return -1;
-           }
+    if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) {
+       i = _zip_name_locate(za, _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), 0, NULL);
+       if (i >= 0 && (zip_uint64_t)i != idx) {
+           _zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+           return -1;
        }
-
-       free(za->entry[idx].ch_filename);
-       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;
+    _zip_dirent_free(za->entry[idx].changes);
+    za->entry[idx].changes = NULL;
 
     _zip_unchange_data(za->entry+idx);
 
index 01282f89dbbafa05fe67aba83eb4c762ba014e98..bbc2825eb626540c3c519d260be5d691d05cbbed 100644 (file)
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_unchange_all(struct zip *za)
 {
-    int ret, i;
+    int ret;
+    zip_uint64_t i;
 
     ret = 0;
     for (i=0; i<za->nentry; i++)
index ca2b67854435a065ef1a334280e7bca060b9b72d..e24ee217270025fc090f78a2b3d78157963cb217 100644 (file)
 
 \f
 
-ZIP_EXTERN(int)
+ZIP_EXTERN int
 zip_unchange_archive(struct zip *za)
 {
-    free(za->ch_comment);
-    za->ch_comment = NULL;
-    za->ch_comment_len = -1;
-
+    if (za->comment_changed) {
+       _zip_string_free(za->comment_changes);
+       za->comment_changes = NULL;
+       za->comment_changed = 0;
+    }
+    
     za->ch_flags = za->flags;
 
     return 0;
index 7dd93b768a87aab4e7628c51145f76a83b773657..fa25feb03885ff70927833fc2d7233d6b767225e 100644 (file)
@@ -1,8 +1,6 @@
 /*
-  $NiH: zip_unchange_data.c,v 1.14 2004/11/30 23:02:47 wiz Exp $
-
   zip_unchange_data.c -- undo helper function
-  Copyright (C) 1999, 2004 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -35,8 +33,6 @@
 
 \f
 
-#include <stdlib.h>
-
 #include "zipint.h"
 
 void
@@ -46,7 +42,15 @@ _zip_unchange_data(struct zip_entry *ze)
        zip_source_free(ze->source);
        ze->source = NULL;
     }
-    
-    ze->state = ze->ch_filename ? ZIP_ST_RENAMED : ZIP_ST_UNCHANGED;
+
+    if (ze->changes != NULL && (ze->changes->changed & ZIP_DIRENT_COMP_METHOD) && ze->changes->comp_method == ZIP_CM_REPLACED_DEFAULT) {
+       ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
+       if (ze->changes->changed == 0) {
+           _zip_dirent_free(ze->changes);
+           ze->changes = NULL;
+       }
+    }
+
+    ze->deleted = 0;
 }
 
diff --git a/ext/zip/lib/zip_utf-8.c b/ext/zip/lib/zip_utf-8.c
new file mode 100644 (file)
index 0000000..c36fad1
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+  zip_utf-8.c -- UTF-8 support functions for libzip
+  Copyright (C) 2011-2012 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+\f
+
+#include "zipint.h"
+
+#include <stdlib.h>
+
+\f
+
+static const zip_uint16_t _cp437_to_unicode[256] = {
+    /* 0x00 - 0x0F */
+    0x2007, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
+    0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
+
+    /* 0x10 - 0x1F */
+    0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
+    0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
+
+    /* 0x20 - 0x2F */
+    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+    0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+
+    /* 0x30 - 0x3F */
+    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+    0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+
+    /* 0x40 - 0x4F */
+    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+    0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+
+    /* 0x50 - 0x5F */
+    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+    0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+
+    /* 0x60 - 0x6F */
+    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+    0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+
+    /* 0x70 - 0x7F */
+    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+    0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x2302,
+
+    /* 0x80 - 0x8F */
+    0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+    0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+
+    /* 0x90 - 0x9F */
+    0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+    0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
+
+    /* 0xA0 - 0xAF */
+    0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+    0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+
+    /* 0xB0 - 0xBF */
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+
+    /* 0xC0 - 0xCF */
+    0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+    0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+
+    /* 0xD0 - 0xDF */
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+    0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+
+    /* 0xE0 - 0xEF */
+    0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
+    0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
+
+    /* 0xF0 - 0xFF */
+    0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
+    0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
+};
+
+#define UTF_8_LEN_2_MASK     0xe0
+#define UTF_8_LEN_2_MATCH    0xc0
+#define UTF_8_LEN_3_MASK     0xf0
+#define UTF_8_LEN_3_MATCH    0xe0
+#define UTF_8_LEN_4_MASK     0xf8
+#define UTF_8_LEN_4_MATCH    0xf0
+#define UTF_8_CONTINUE_MASK  0xc0
+#define UTF_8_CONTINUE_MATCH 0x80
+
+\f
+
+enum zip_encoding_type
+_zip_guess_encoding(struct zip_string *str, enum zip_encoding_type expected_encoding)
+{
+    enum zip_encoding_type enc;
+    const zip_uint8_t *name;
+    zip_uint32_t i, j, ulen;
+
+    if (str == NULL)
+       return ZIP_ENCODING_ASCII;
+
+    name = str->raw;
+
+    if (str->encoding != ZIP_ENCODING_UNKNOWN)
+       enc = str->encoding;
+    else {
+       enc = ZIP_ENCODING_ASCII;
+       for (i=0; i<str->length; i++) {
+           if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t')
+               continue;
+
+           enc = ZIP_ENCODING_UTF8_GUESSED;
+           if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH)
+               ulen = 1;
+           else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH)
+               ulen = 2;
+           else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH)
+               ulen = 3;
+           else {
+               enc = ZIP_ENCODING_CP437;
+               break;
+           }
+
+           if (i + ulen >= str->length) {
+               enc = ZIP_ENCODING_CP437;
+               break;
+           }
+
+           for (j=1; j<=ulen; j++) {
+               if ((name[i+j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) {
+                   enc = ZIP_ENCODING_CP437;
+                   goto done;
+               }
+           }
+           i += ulen;
+       }
+    }
+
+done:
+    str->encoding = enc;
+
+    if (expected_encoding != ZIP_ENCODING_UNKNOWN) {
+       if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED)
+           str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN;
+
+       if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII)
+           return ZIP_ENCODING_ERROR;
+    }
+    
+    return enc;
+}
+
+\f
+
+static zip_uint32_t
+_zip_unicode_to_utf8_len(zip_uint32_t codepoint)
+{
+    if (codepoint < 0x0080)
+       return 1;
+    if (codepoint < 0x0800)
+       return 2;
+    if (codepoint < 0x10000)
+       return 3;
+    return 4;
+}
+
+\f
+
+static zip_uint32_t
+_zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf)
+{
+    if (codepoint < 0x0080) {
+       buf[0] = codepoint & 0xff;
+       return 1;
+    }
+    if (codepoint < 0x0800) {
+       buf[0] = UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f);
+       buf[1] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f);
+       return 2;
+    }
+    if (codepoint < 0x10000) {
+       buf[0] = UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f);
+       buf[1] = UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f);
+       buf[2] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f);
+       return 3;
+    }
+    buf[0] = UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07);
+    buf[1] = UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f);
+    buf[2] = UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f);
+    buf[3] = UTF_8_CONTINUE_MATCH | (codepoint & 0x3f);
+    return 4;
+}
+
+\f
+
+zip_uint8_t *
+_zip_cp437_to_utf8(const zip_uint8_t * const _cp437buf, zip_uint32_t len,
+                  zip_uint32_t *utf8_lenp, struct zip_error *error)
+{
+    zip_uint8_t *cp437buf = (zip_uint8_t *)_cp437buf;
+    zip_uint8_t *utf8buf;
+    zip_uint32_t buflen, i, offset;
+
+    if (len == 0) {
+       if (utf8_lenp)
+           *utf8_lenp = 0;
+       return NULL;
+    }
+
+    buflen = 1;
+    for (i=0; i<len; i++)
+       buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]);
+
+    if ((utf8buf=(zip_uint8_t*)malloc(buflen)) == NULL) {
+       _zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+
+    offset = 0;
+    for (i=0; i<len; i++)
+       offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]],
+                                      utf8buf+offset);
+
+    utf8buf[buflen-1] = 0;
+    if (utf8_lenp)
+       *utf8_lenp = buflen-1;
+    return utf8buf;
+}
diff --git a/ext/zip/lib/zip_win32.h b/ext/zip/lib/zip_win32.h
deleted file mode 100644 (file)
index ff28d28..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#define _POSIX_
-#include <windows.h>
-#include <io.h>
-#include <fcntl.h>
-#include <string.h>
-#include <zconf.h>
-
-#ifndef strcasecmp
-# define strcmpi _strcmpi
-#endif
-
-#ifndef ssize_t
-#      define ssize_t SSIZE_T
-#endif
-
-#ifndef mode_t
-#      define mode_t int
-#endif
-
-#ifndef snprintf
-#      define snprintf _snprintf
-#endif
-
-#ifndef mkstemp
-#      define mkstemp(t) _creat(_mktemp(t), _S_IREAD|_S_IWRITE)
-#endif
-/*
-#ifndef fseeko
-#      define fseeko fseek
-#endif
-*/
index 646c0bde53f0e0d701e48742cab274e7286fb5cf..1cb5c0467aeb831d26f411bdb6d95db14cbf007b 100644 (file)
-#ifndef _HAD_ZIPCONF_H
-#define _HAD_ZIPCONF_H
-
-/*
-   zipconf.h -- platform specific include file
-
-   This file was generated automatically by ./make_zipconf.sh
-   based on ../config.h.
- */
-
-#define LIBZIP_VERSION "0.10.1"
-#define LIBZIP_VERSION_MAJOR 0
-#define LIBZIP_VERSION_MINOR 10
-#define LIBZIP_VERSION_MICRO 0
-
-#include <php_stdint.h>
-
-typedef int8_t zip_int8_t;
-#define ZIP_INT8_MIN INT8_MIN
-#define ZIP_INT8_MAX INT8_MAX
-
-typedef uint8_t zip_uint8_t;
-#define ZIP_UINT8_MAX UINT8_MAX
-
-typedef int16_t zip_int16_t;
-#define ZIP_INT16_MIN INT16_MIN
-#define ZIP_INT16_MAX INT16_MAX
-
-typedef uint16_t zip_uint16_t;
-#define ZIP_UINT16_MAX UINT16_MAX
-
-typedef int32_t zip_int32_t;
-#define ZIP_INT32_MIN INT32_MIN
-#define ZIP_INT32_MAX INT32_MAX
-
-typedef uint32_t zip_uint32_t;
-#define ZIP_UINT32_MAX UINT32_MAX
-
-typedef int64_t zip_int64_t;
-#define ZIP_INT64_MIN INT64_MIN
-#define ZIP_INT64_MAX INT64_MAX
-
-typedef uint64_t zip_uint64_t;
-#define ZIP_UINT64_MAX UINT64_MAX
-
-
-#endif /* zipconf.h */
+#ifndef _HAD_ZIPCONF_H\r
+#define _HAD_ZIPCONF_H\r
+\r
+/*\r
+   zipconf.h -- platform specific include file\r
+\r
+   This file was generated automatically by CMake\r
+   based on ../cmake-zipconf.h.in.\r
+ */\r
+#define LIBZIP_VERSION "0.11.1"\r
+/* #undef HAVE_INTTYPES_H_LIBZIP */\r
+\r
+#if defined(_WIN32)\r
+# if _MSC_VER > 1500\r
+#  define HAVE_STDINT_H_LIBZIP\r
+# else\r
+#  include "win32/php_stdint.h"\r
+# endif\r
+#else\r
+# include <inttypes.h>\r
+#endif\r
+#define HAVE_SYS_TYPES_H_LIBZIP\r
+#define HAVE___INT8_LIBZIP\r
+#define HAVE_INT8_T_LIBZIP\r
+#define HAVE_UINT8_T_LIBZIP\r
+#define HAVE___INT16_LIBZIP\r
+#define HAVE_INT16_T_LIBZIP\r
+#define HAVE_UINT16_T_LIBZIP\r
+#define HAVE___INT32_LIBZIP\r
+#define HAVE_INT32_T_LIBZIP\r
+#define HAVE_UINT32_T_LIBZIP\r
+#define HAVE___INT64_LIBZIP\r
+#define HAVE_INT64_T_LIBZIP\r
+#define HAVE_UINT64_T_LIBZIP\r
+#define SHORT_LIBZIP 2\r
+#define INT_LIBZIP 4\r
+#define LONG_LIBZIP 4\r
+#define LONG_LONG_LIBZIP 8\r
+\r
+#if defined(HAVE_STDINT_H_LIBZIP)\r
+#include <stdint.h>\r
+#elif defined(HAVE_INTTYPES_H_LIBZIP)\r
+#include <inttypes.h>\r
+#elif defined(HAVE_SYS_TYPES_H_LIBZIP)\r
+#include <sys/types.h>\r
+#endif\r
+\r
+#if defined(HAVE_INT8_T_LIBZIP)\r
+typedef int8_t zip_int8_t;\r
+#elif defined(HAVE___INT8_LIBZIP)\r
+typedef __int8 zip_int8_t;\r
+#else\r
+typedef signed char zip_int8_t;\r
+#endif\r
+#if defined(HAVE_UINT8_T_LIBZIP)\r
+typedef uint8_t zip_uint8_t;\r
+#elif defined(HAVE___INT8_LIBZIP)\r
+typedef unsigned __int8 zip_uint8_t;\r
+#else\r
+typedef unsigned char zip_uint8_t;\r
+#endif\r
+#if defined(HAVE_INT16_T_LIBZIP)\r
+typedef int16_t zip_int16_t;\r
+#elif defined(HAVE___INT16_LIBZIP)\r
+typedef __int16 zip_int16_t;\r
+#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2\r
+typedef signed short zip_int16_t;\r
+#endif\r
+#if defined(HAVE_UINT16_T_LIBZIP)\r
+typedef uint16_t zip_uint16_t;\r
+#elif defined(HAVE___INT16_LIBZIP)\r
+typedef unsigned __int16 zip_uint16_t;\r
+#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2\r
+typedef unsigned short zip_uint16_t;\r
+#endif\r
+#if defined(HAVE_INT32_T_LIBZIP)\r
+typedef int32_t zip_int32_t;\r
+#elif defined(HAVE___INT32_LIBZIP)\r
+typedef __int32 zip_int32_t;\r
+#elif defined(INT_LIBZIP) && INT_LIBZIP == 4\r
+typedef signed int zip_int32_t;\r
+#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4\r
+typedef signed long zip_int32_t;\r
+#endif\r
+#if defined(HAVE_UINT32_T_LIBZIP)\r
+typedef uint32_t zip_uint32_t;\r
+#elif defined(HAVE___INT32_LIBZIP)\r
+typedef unsigned __int32 zip_uint32_t;\r
+#elif defined(INT_LIBZIP) && INT_LIBZIP == 4\r
+typedef unsigned int zip_uint32_t;\r
+#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4\r
+typedef unsigned long zip_uint32_t;\r
+#endif\r
+#if defined(HAVE_INT64_T_LIBZIP)\r
+typedef int64_t zip_int64_t;\r
+#elif defined(HAVE___INT64_LIBZIP)\r
+typedef __int64 zip_int64_t;\r
+#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 8\r
+typedef signed long zip_int64_t;\r
+#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8\r
+typedef signed long long zip_int64_t;\r
+#endif\r
+#if defined(HAVE_UINT64_T_LIBZIP)\r
+typedef uint64_t zip_uint64_t;\r
+#elif defined(HAVE___INT64_LIBZIP)\r
+typedef unsigned __int64 zip_uint64_t;\r
+#elif defined(LONG_LIBZIP) && LONG_LONG_LIBZIP == 8\r
+typedef unsigned long zip_uint64_t;\r
+#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8\r
+typedef unsigned long long zip_uint64_t;\r
+#endif\r
+\r
+#define ZIP_INT8_MIN   -0x80\r
+#define ZIP_INT8_MAX    0x7f\r
+#define ZIP_UINT8_MAX   0xff\r
+\r
+#define ZIP_INT16_MIN  -0x8000\r
+#define ZIP_INT16_MAX   0x7fff\r
+#define ZIP_UINT16_MAX  0xffff\r
+\r
+#define ZIP_INT32_MIN  -0x80000000L\r
+#define ZIP_INT32_MAX   0x7fffffffL\r
+#define ZIP_UINT32_MAX  0xffffffffLU\r
+\r
+#define ZIP_INT64_MIN  -0x8000000000000000LL\r
+#define ZIP_INT64_MAX   0x7fffffffffffffffLL\r
+#define ZIP_UINT64_MAX  0xffffffffffffffffULL\r
+\r
+#endif /* zipconf.h */\r
index ea21dddcd425710a60ca0d3b919b4160e2d4e0f9..e8765c5b6619ffe835cca1d224896587f491cfca 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
   zipint.h -- internal declarations.
-  Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2013 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>
@@ -20,7 +20,7 @@
   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
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#include <zlib.h>
+/* to have *_MAX definitions for all types when compiling with g++ */
+#define __STDC_LIMIT_MACROS
 
-#include "zip.h"
+#include <zlib.h>
 
-#ifndef HAVE_FSEEKO
-#define fseeko(s, o, w)        (fseek((s), (long int)(o), (w)))
+#ifdef PHP_WIN32
+/* for dup(), close(), etc. */
+#include <io.h>
+#include "config.w32.h"
 #endif
 
-#ifndef HAVE_FTELLO
-#define ftello(s)      ((long)ftell((s)))
+#ifndef _ZIP_COMPILING_DEPRECATED
+#define ZIP_DISABLE_DEPRECATED
 #endif
 
-#ifndef PHP_WIN32
-#ifndef HAVE_MKSTEMP
-int _zip_mkstemp(char *);
-#define mkstemp _zip_mkstemp
-#endif
+#include "zip.h"
+#ifdef PHP_WIN32
+# include "php_zip_config.w32.h"
+#else
+# include "config.h"
 #endif
 
-#ifdef PHP_WIN32
+#if defined(HAVE_MOVEFILEEXA) && defined(_WIN32)
 #include <windows.h>
-#include <wchar.h>
 #define _zip_rename(s, t)                                              \
-       (!MoveFileExA((s), (t),                                         \
-                    MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING))
+       (!MoveFileExA((s), (t), MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING))
+#else
+#define _zip_rename    rename
+#endif
 
-/* for dup(), close(), etc. */
-#include <io.h>
+#ifdef _WIN32
+#undef strcasecmp
+#  define strcasecmp _strcmpi
+#endif
 
-#if !defined(HAVE_OPEN)
+#if defined(HAVE__CLOSE)
+#define close          _close
+#endif
+#if defined(HAVE__DUP)
+#define dup            _dup
+#endif
+/* crashes reported when using fdopen instead of _fdopen on Windows/Visual Studio 10/Win64 */
+#if defined(HAVE__FDOPEN)
+#define fdopen         _fdopen
+#endif
+#if defined(HAVE__FILENO)
+#define fileno         _fileno
+#endif
+/* Windows' open() doesn't understand Unix permissions */
 #if defined(HAVE__OPEN)
 #define open(a, b, c)  _open((a), (b))
 #endif
+#if defined(HAVE__SNPRINTF)
+#define snprintf       _snprintf
+#endif
+#if defined(HAVE__STRDUP) && !defined(strdup)
+#define strdup         _strdup
 #endif
 
-#else
-#define _zip_rename    rename
+#ifndef HAVE_FSEEKO
+#define fseeko(s, o, w)        (fseek((s), (long int)(o), (w)))
 #endif
 
-#ifndef strcasecmp
-# define strcmpi strcasecmp 
+#ifndef HAVE_FTELLO
+#define ftello(s)      ((long)ftell((s)))
 #endif
 
+#ifndef HAVE_MKSTEMP
+int _zip_mkstemp(char *);
+#define mkstemp _zip_mkstemp
+#endif
 
-\f
+#if !defined(HAVE_STRCASECMP)
+#if defined(HAVE__STRICMP)
+#define strcasecmp     _stricmp
+#endif
+#endif
+
+#if SIZEOF_OFF_T == 8
+#define ZIP_OFF_MAX ZIP_INT64_MAX
+#elif SIZEOF_OFF_T == 4
+#define ZIP_OFF_MAX ZIP_INT32_MAX
+#elif SIZEOF_OFF_T == 2
+#define ZIP_OFF_MAX ZIP_INT16_MAX
+#else
+#error unsupported size of off_t
+#endif
 
 #define CENTRAL_MAGIC "PK\1\2"
 #define LOCAL_MAGIC   "PK\3\4"
 #define EOCD_MAGIC    "PK\5\6"
 #define DATADES_MAGIC "PK\7\8"
+#define EOCD64LOC_MAGIC "PK\6\7"
+#define EOCD64_MAGIC  "PK\6\6"
 #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
-#undef MAXCOMLEN /* defined as 19 on BSD for max command name */
 #define MAXCOMLEN        65536
 #define MAXEXTLEN        65536
 #define EOCDLEN             22
-#define CDBUFSIZE       (MAXCOMLEN+EOCDLEN)
+#define EOCD64LOCLEN       20
+#define EOCD64LEN          56
+#define CDBUFSIZE       (MAXCOMLEN+EOCDLEN+EOCD64LOCLEN)
 #define BUFSIZE                8192
 
+#define ZIP_CM_REPLACED_DEFAULT (-2)
+
+#define ZIP_CM_IS_DEFAULT(x)   ((x) == ZIP_CM_DEFAULT || (x) == ZIP_CM_REPLACED_DEFAULT)
+
+#define ZIP_EF_UTF_8_COMMENT   0x6375
+#define ZIP_EF_UTF_8_NAME      0x7075
+#define ZIP_EF_ZIP64           0x0001
+
+#define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_ZIP64)
 \f
 
 /* This section contains API that won't materialize like this.  It's
@@ -104,20 +158,22 @@ int _zip_mkstemp(char *);
 
 typedef struct zip_source *(*zip_compression_implementation)(struct zip *,
                                                     struct zip_source *,
-                                                    zip_uint16_t, int);
+                                                    zip_int32_t, int);
 typedef struct zip_source *(*zip_encryption_implementation)(struct zip *,
                                                    struct zip_source *,
                                                    zip_uint16_t, int,
                                                    const char *);
 
-ZIP_EXTERN(zip_compression_implementation) zip_get_compression_implementation(
-    zip_uint16_t);
-ZIP_EXTERN(zip_encryption_implementation) zip_get_encryption_implementation(
-    zip_uint16_t);
+zip_compression_implementation _zip_get_compression_implementation(zip_int32_t);
+zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t);
 
 
 \f
 
+/* This API is not final yet, but we need it internally, so it's private for now. */
+
+const zip_uint8_t *zip_get_extra_field_by_id(struct zip *, int, int, zip_uint16_t, int, zip_uint16_t *);
+
 /* This section contains API that is of limited use until support for
    user-supplied compression/encryption implementation is finished.
    Thus we will keep it private for now. */
@@ -126,40 +182,37 @@ typedef zip_int64_t (*zip_source_layered_callback)(struct zip_source *, void *,
                                                   void *, zip_uint64_t,
                                                   enum zip_source_cmd);
 
-ZIP_EXTERN(void) zip_source_close(struct zip_source *);
-ZIP_EXTERN(struct zip_source *)zip_source_crc(struct zip *, struct zip_source *,
-                                            int);
-ZIP_EXTERN(struct zip_source *)zip_source_deflate(struct zip *,
-                                                struct zip_source *,
-                                                zip_uint16_t, int);
-ZIP_EXTERN(void) zip_source_error(struct zip_source *, int *, int *);
-ZIP_EXTERN(struct zip_source *)zip_source_layered(struct zip *,
-                                                struct zip_source *,
-                                                zip_source_layered_callback,
-                                                void *);
-ZIP_EXTERN(int) zip_source_open(struct zip_source *);
-ZIP_EXTERN(struct zip_source *)zip_source_pkware(struct zip *,
-                                               struct zip_source *,
-                                               zip_uint16_t, int,
-                                               const char *);
-ZIP_EXTERN(zip_int64_t) zip_source_read(struct zip_source *, void *,
-                                      zip_uint64_t);
-ZIP_EXTERN(int) zip_source_stat(struct zip_source *, struct zip_stat *);
+void zip_source_close(struct zip_source *);
+struct zip_source *zip_source_crc(struct zip *, struct zip_source *,
+                                 int);
+struct zip_source *zip_source_deflate(struct zip *,
+                                     struct zip_source *,
+                                     zip_int32_t, int);
+void zip_source_error(struct zip_source *, int *, int *);
+struct zip_source *zip_source_layered(struct zip *,
+                                     struct zip_source *,
+                                     zip_source_layered_callback,
+                                     void *);
+int zip_source_open(struct zip_source *);
+struct zip_source *zip_source_pkware(struct zip *,
+                                    struct zip_source *,
+                                    zip_uint16_t, int,
+                                    const char *);
+zip_int64_t zip_source_read(struct zip_source *, void *,
+                           zip_uint64_t);
+int zip_source_stat(struct zip_source *, struct zip_stat *);
+struct zip_source *zip_source_window(struct zip *, struct zip_source *,
+                                    zip_uint64_t, zip_uint64_t);
 
 
 /* This function will probably remain private.  It is not needed to
    implement compression/encryption routines.  (We should probably
    rename it to _zip_source_pop.) */
 
-ZIP_EXTERN(struct zip_source *)zip_source_pop(struct zip_source *);
+struct zip_source *zip_source_pop(struct zip_source *);
 
 \f
 
-/* state of change of a file in zip archive */
-
-enum zip_state { ZIP_ST_UNCHANGED, ZIP_ST_DELETED, ZIP_ST_REPLACED,
-                ZIP_ST_ADDED, ZIP_ST_RENAMED };
-
 /* error source for layered sources */
 
 enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL };
@@ -169,6 +222,28 @@ enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL };
 #define ZIP_GPBF_ENCRYPTED             0x0001  /* is encrypted */
 #define ZIP_GPBF_DATA_DESCRIPTOR       0x0008  /* crc/size after file data */
 #define ZIP_GPBF_STRONG_ENCRYPTION     0x0040  /* uses strong encryption */
+#define ZIP_GPBF_ENCODING_UTF_8                0x0800  /* file name encoding is UTF-8 */
+
+
+/* extra fields */
+#define ZIP_EF_LOCAL           ZIP_FL_LOCAL                    /* include in local header */
+#define ZIP_EF_CENTRAL         ZIP_FL_CENTRAL                  /* include in central directory */
+#define ZIP_EF_BOTH            (ZIP_EF_LOCAL|ZIP_EF_CENTRAL)   /* include in both */
+
+#define ZIP_FL_FORCE_ZIP64     1024  /* force zip64 extra field (_zip_dirent_write) */
+
+#define ZIP_FL_ENCODING_ALL    (ZIP_FL_ENC_GUESS|ZIP_FL_ENC_CP437|ZIP_FL_ENC_UTF_8)
+
+
+/* encoding type */
+enum zip_encoding_type {
+    ZIP_ENCODING_UNKNOWN,       /* not yet analyzed */
+    ZIP_ENCODING_ASCII,         /* plain ASCII */
+    ZIP_ENCODING_UTF8_KNOWN,    /* is UTF-8 */
+    ZIP_ENCODING_UTF8_GUESSED,  /* possibly UTF-8 */
+    ZIP_ENCODING_CP437,         /* Code Page 437 */
+    ZIP_ENCODING_ERROR          /* should be UTF-8 but isn't */
+};
 
 /* error information */
 
@@ -181,25 +256,29 @@ struct zip_error {
 /* zip archive, part of API */
 
 struct zip {
-    char *zn;                  /* file name */
-    FILE *zp;                  /* file */
-    struct zip_error error;    /* error information */
+    char *zn;                          /* file name */
+    FILE *zp;                          /* file */
+    unsigned int open_flags;           /* flags passed to zip_open */
+    struct zip_error error;            /* error information */
 
-    unsigned int flags;                /* archive global flags */
-    unsigned int ch_flags;     /* changed archive global flags */
-
-    char *default_password;    /* password used when no other supplied */
-
-    struct zip_cdir *cdir;     /* central directory */
-    char *ch_comment;          /* changed archive comment */
-    int ch_comment_len;                /* length of changed zip archive
-                                * comment, -1 if unchanged */
-    zip_uint64_t nentry;       /* number of entries */
-    zip_uint64_t nentry_alloc; /* number of entries allocated */
-    struct zip_entry *entry;   /* entries */
-    int nfile;                 /* number of opened files within archive */
-    int nfile_alloc;           /* number of files allocated */
-    struct zip_file **file;    /* opened files within archive */
+    unsigned int flags;                        /* archive global flags */
+    unsigned int ch_flags;             /* changed archive global flags */
+
+    char *default_password;            /* password used when no other supplied */
+
+    struct zip_string *comment_orig;   /* archive comment */
+    struct zip_string *comment_changes; /* changed archive comment */
+    int comment_changed;               /* whether archive comment was changed */
+
+    zip_uint64_t nentry;               /* number of entries */
+    zip_uint64_t nentry_alloc;         /* number of entries allocated */
+    struct zip_entry *entry;           /* entries */
+
+    unsigned int nfile;                        /* number of opened files within archive */
+    unsigned int nfile_alloc;          /* number of files allocated */
+    struct zip_file **file;            /* opened files within archive */
+    
+    char *tempdir;                      /* custom temp dir (needed e.g. for OS X sandboxing) */
 };
 
 /* file in zip archive, part of API */
@@ -213,37 +292,52 @@ struct zip_file {
 
 /* zip archive directory entry (central or local) */
 
+#define ZIP_DIRENT_COMP_METHOD 0x0001u
+#define ZIP_DIRENT_FILENAME    0x0002u
+#define ZIP_DIRENT_COMMENT     0x0004u
+#define ZIP_DIRENT_EXTRA_FIELD 0x0008u
+#define ZIP_DIRENT_ALL         0xffffu
+
 struct zip_dirent {
-    unsigned short version_madeby;     /* (c)  version of creator */
-    unsigned short version_needed;     /* (cl) version needed to extract */
-    unsigned short bitflags;           /* (cl) general purpose bit flag */
-    unsigned short comp_method;                /* (cl) compression method used */
-    time_t last_mod;                   /* (cl) time of last modification */
-    unsigned int crc;                  /* (cl) CRC-32 of uncompressed data */
-    unsigned int comp_size;            /* (cl) size of commpressed data */
-    unsigned int uncomp_size;          /* (cl) size of uncommpressed data */
-    char *filename;                    /* (cl) file name (NUL-terminated) */
-    unsigned short filename_len;       /* (cl) length of filename (w/o NUL) */
-    char *extrafield;                  /* (cl) extra field */
-    unsigned short extrafield_len;     /* (cl) length of extra field */
-    char *comment;                     /* (c)  file comment */
-    unsigned short comment_len;                /* (c)  length of file comment */
-    unsigned short disk_number;                /* (c)  disk number start */
-    unsigned short int_attrib;         /* (c)  internal file attributes */
-    unsigned int ext_attrib;           /* (c)  external file attributes */
-    unsigned int offset;               /* (c)  offset of local header  */
+    zip_uint32_t changed;
+    int local_extra_fields_read;               /*      whether we already read in local header extra fields */
+    int cloned;                                 /*      wether this instance is cloned, and thus shares non-changed strings */
+
+    zip_uint16_t version_madeby;               /* (c)  version of creator */
+    zip_uint16_t version_needed;               /* (cl) version needed to extract */
+    zip_uint16_t bitflags;                     /* (cl) general purpose bit flag */
+    zip_int32_t comp_method;                   /* (cl) compression method used (uint16 and ZIP_CM_DEFAULT (-1)) */
+    time_t last_mod;                           /* (cl) time of last modification */
+    zip_uint32_t crc;                          /* (cl) CRC-32 of uncompressed data */
+    zip_uint64_t comp_size;                    /* (cl) size of compressed data */
+    zip_uint64_t uncomp_size;                  /* (cl) size of uncompressed data */
+    struct zip_string *filename;               /* (cl) file name (NUL-terminated) */
+    struct zip_extra_field *extra_fields;      /* (cl) extra fields, parsed */
+    struct zip_string *comment;                        /* (c)  file comment */
+    zip_uint32_t disk_number;                  /* (c)  disk number start */
+    zip_uint16_t int_attrib;                   /* (c)  internal file attributes */
+    zip_uint32_t ext_attrib;                   /* (c)  external file attributes */
+    zip_uint64_t offset;                       /* (c)  offset of local header */
 };
 
 /* zip archive central directory */
 
 struct zip_cdir {
-    struct zip_dirent *entry;  /* directory entries */
-    int nentry;                        /* number of entries */
+    struct zip_entry *entry;                   /* directory entries */
+    zip_uint64_t nentry;                       /* number of entries */
+    zip_uint64_t nentry_alloc;                 /* number of entries allocated */
 
-    unsigned int size;         /* size of central direcotry */
-    unsigned int offset;       /* offset of central directory in file */
-    char *comment;             /* zip archive comment */
-    unsigned short comment_len;        /* length of zip archive comment */
+    off_t size;                                 /* size of central directory */
+    off_t offset;                              /* offset of central directory in file */
+    struct zip_string *comment;                        /* zip archive comment */
+};
+
+struct zip_extra_field {
+    struct zip_extra_field *next;
+    zip_flags_t flags;                         /* in local/central header */
+    zip_uint16_t id;                           /* header id */
+    zip_uint16_t size;                         /* data size */
+    zip_uint8_t *data;
 };
 
 \f
@@ -262,13 +356,31 @@ struct zip_source {
 /* entry in zip archive directory */
 
 struct zip_entry {
-    enum zip_state state;
+    struct zip_dirent *orig;
+    struct zip_dirent *changes;
     struct zip_source *source;
-    char *ch_filename;
-    char *ch_extra;
-    int ch_extra_len;
-    char *ch_comment;
-    int ch_comment_len;
+    int deleted;
+};
+
+\f
+
+/* file or archive comment, or filename */
+
+struct zip_string {
+    zip_uint8_t *raw;                  /* raw string */
+    zip_uint16_t length;               /* length of raw string */
+    enum zip_encoding_type encoding;   /* autorecognized encoding */
+    zip_uint8_t *converted;            /* autoconverted string */
+    zip_uint32_t converted_length;     /* length of converted */
+};
+
+\f
+
+/* which files to write, and in which order (name is for torrentzip sorting) */
+
+struct zip_filelist {
+    zip_uint64_t idx;
+    const char *name;
 };
 
 \f
@@ -279,66 +391,111 @@ extern const int _zip_err_type[];
 
 \f
 
-#define ZIP_ENTRY_DATA_CHANGED(x)      \
-                       ((x)->state == ZIP_ST_REPLACED  \
-                        || (x)->state == ZIP_ST_ADDED)
+#define ZIP_ENTRY_CHANGED(e, f)        ((e)->changes && ((e)->changes->changed & (f)))
+
+#define ZIP_ENTRY_DATA_CHANGED(x)      ((x)->source != NULL)
 
 #define ZIP_IS_RDONLY(za)      ((za)->ch_flags & ZIP_AFL_RDONLY)
 
 \f
 
+zip_int64_t _zip_add_entry(struct zip *);
+
 int _zip_cdir_compute_crc(struct zip *, uLong *);
 void _zip_cdir_free(struct zip_cdir *);
-int _zip_cdir_grow(struct zip_cdir *, int, struct zip_error *);
-struct zip_cdir *_zip_cdir_new(int, struct zip_error *);
-int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *);
+int _zip_cdir_grow(struct zip_cdir *, zip_uint64_t, struct zip_error *);
+struct zip_cdir *_zip_cdir_new(zip_uint64_t, struct zip_error *);
+zip_int64_t _zip_cdir_write(struct zip *, const struct zip_filelist *, zip_uint64_t, FILE *);
 
+struct zip_dirent *_zip_dirent_clone(const struct zip_dirent *);
+void _zip_dirent_free(struct zip_dirent *);
 void _zip_dirent_finalize(struct zip_dirent *);
 void _zip_dirent_init(struct zip_dirent *);
-int _zip_dirent_read(struct zip_dirent *, FILE *, unsigned char **,
-                    zip_uint32_t *, int, struct zip_error *);
+int _zip_dirent_needs_zip64(const struct zip_dirent *, zip_flags_t);
+struct zip_dirent *_zip_dirent_new(void);
+int _zip_dirent_read(struct zip_dirent *, FILE *, const unsigned char **,
+                    zip_uint64_t *, int, struct zip_error *);
+zip_int32_t _zip_dirent_size(FILE *, zip_uint16_t, 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 *);
-void _zip_entry_init(struct zip *, int);
-struct zip_entry *_zip_entry_new(struct zip *);
+int _zip_dirent_write(struct zip_dirent *, FILE *, zip_flags_t, struct zip_error *);
+
+struct zip_extra_field *_zip_ef_clone(const struct zip_extra_field *, struct zip_error *);
+struct zip_extra_field *_zip_ef_delete_by_id(struct zip_extra_field *, zip_uint16_t, zip_uint16_t, zip_flags_t);
+void _zip_ef_free(struct zip_extra_field *);
+const zip_uint8_t *_zip_ef_get_by_id(const struct zip_extra_field *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, struct zip_error *);
+struct zip_extra_field *_zip_ef_merge(struct zip_extra_field *, struct zip_extra_field *);
+struct zip_extra_field *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t);
+struct zip_extra_field *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *);
+struct zip_extra_field *_zip_ef_remove_internal(struct zip_extra_field *);
+zip_uint16_t _zip_ef_size(const struct zip_extra_field *, zip_flags_t);
+void _zip_ef_write(const struct zip_extra_field *, zip_flags_t, FILE *);
+
+void _zip_entry_finalize(struct zip_entry *);
+void _zip_entry_init(struct zip_entry *);
 
 void _zip_error_clear(struct zip_error *);
-void _zip_error_copy(struct zip_error *, struct zip_error *);
+void _zip_error_copy(struct zip_error *, const struct zip_error *);
 void _zip_error_fini(struct zip_error *);
-void _zip_error_get(struct zip_error *, int *, int *);
+void _zip_error_get(const struct zip_error *, int *, int *);
 void _zip_error_init(struct zip_error *);
 void _zip_error_set(struct zip_error *, int, int);
 void _zip_error_set_from_source(struct zip_error *, struct zip_source *);
 const char *_zip_error_strerror(struct zip_error *);
 
+const zip_uint8_t *_zip_extract_extra_field_by_id(struct zip_error *, zip_uint16_t, int, const zip_uint8_t *, zip_uint16_t, zip_uint16_t *);
+
+int _zip_file_extra_field_prepare_for_change(struct zip *, zip_uint64_t);
 int _zip_file_fillbuf(void *, size_t, struct zip_file *);
-unsigned int _zip_file_get_offset(struct zip *, int);
+zip_uint64_t _zip_file_get_offset(const struct zip *, zip_uint64_t, struct zip_error *);
 
 int _zip_filerange_crc(FILE *, off_t, off_t, uLong *, struct zip_error *);
 
-struct zip *_zip_open(const char *, FILE *, int, int, int *);
+struct zip_dirent *_zip_get_dirent(struct zip *, zip_uint64_t, zip_flags_t, struct zip_error *);
+
+enum zip_encoding_type _zip_guess_encoding(struct zip_string *, enum zip_encoding_type);
+zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t,
+                               zip_uint32_t *, struct zip_error *error);
+
+struct zip *_zip_open(const char *, FILE *, unsigned int, int *);
+
+int _zip_read_local_ef(struct zip *, zip_uint64_t);
 
 struct zip_source *_zip_source_file_or_p(struct zip *, const char *, FILE *,
                                         zip_uint64_t, zip_int64_t, int,
                                         const struct zip_stat *);
 struct zip_source *_zip_source_new(struct zip *);
-
-int _zip_changed(struct zip *, int *);
-void _zip_free(struct zip *);
-const char *_zip_get_name(struct zip *, zip_uint64_t, int, struct zip_error *);
+struct zip_source *_zip_source_zip_new(struct zip *, struct zip *, zip_uint64_t, zip_flags_t,
+                                      zip_uint64_t, zip_uint64_t, const char *);
+
+int _zip_string_equal(const struct zip_string *, const struct zip_string *);
+void _zip_string_free(struct zip_string *);
+zip_uint32_t _zip_string_crc32(const struct zip_string *);
+const zip_uint8_t *_zip_string_get(struct zip_string *, zip_uint32_t *, zip_flags_t, struct zip_error *);
+zip_uint16_t _zip_string_length(const struct zip_string *);
+struct zip_string *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *);
+void _zip_string_write(const struct zip_string *, FILE *);
+
+int _zip_changed(const struct zip *, zip_uint64_t *);
+const char *_zip_get_name(struct zip *, zip_uint64_t, zip_flags_t, struct zip_error *);
 int _zip_local_header_read(struct zip *, int);
 void *_zip_memdup(const void *, size_t, struct zip_error *);
-int _zip_name_locate(struct zip *, const char *, int, struct zip_error *);
+zip_int64_t _zip_name_locate(struct zip *, const char *, zip_flags_t, struct zip_error *);
 struct zip *_zip_new(struct zip_error *);
-unsigned short _zip_read2(unsigned char **);
-unsigned int _zip_read4(unsigned char **);
-zip_int64_t _zip_replace(struct zip *, zip_uint64_t, const char *,
-                        struct zip_source *);
-int _zip_set_name(struct zip *, zip_uint64_t, const char *);
-void _zip_u2d_time(time_t, unsigned short *, unsigned short *);
+zip_uint16_t _zip_read2(const zip_uint8_t **);
+zip_uint32_t _zip_read4(const zip_uint8_t **);
+zip_uint64_t _zip_read8(const zip_uint8_t **);
+zip_uint8_t *_zip_read_data(const zip_uint8_t **, FILE *, size_t, int, struct zip_error *);
+zip_int64_t _zip_file_replace(struct zip *, zip_uint64_t, const char *, struct zip_source *, zip_flags_t);
+int _zip_set_name(struct zip *, zip_uint64_t, const char *, zip_flags_t);
+void _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *);
 int _zip_unchange(struct zip *, zip_uint64_t, int);
 void _zip_unchange_data(struct zip_entry *);
 
+void _zip_poke4(zip_uint32_t, zip_uint8_t **);
+void _zip_poke8(zip_uint64_t, zip_uint8_t **);
+void _zip_write2(zip_uint16_t, FILE *);
+void _zip_write4(zip_uint32_t, FILE *);
+void _zip_write8(zip_uint64_t, FILE *);
+
+
 #endif /* zipint.h */
index 0b8f3fcad33047924079d2eee5351ee861ab932d..82f99b02f54848273576f750258327a617ecd40d 100644 (file)
@@ -30,8 +30,6 @@
 #include "ext/pcre/php_pcre.h"
 #include "ext/standard/php_filestat.h"
 #include "php_zip.h"
-#include "lib/zip.h"
-#include "lib/zipint.h"
 
 /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */
 static PHP_NAMED_FUNCTION(zif_zip_open);
@@ -53,6 +51,24 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_close);
 #endif
 #endif
 
+#if PHP_VERSION_ID < 50400
+#define ARG_PATH "s"
+#define KEY_ARG_DC
+#define KEY_ARG_CC
+#else
+#define ARG_PATH "p"
+#define KEY_ARG_DC , const zend_literal *key
+#define KEY_ARG_CC , key
+#endif
+
+#if PHP_VERSION_ID < 50500
+#define TYPE_ARG_DC
+#define TYPE_ARG_CC
+#else
+#define TYPE_ARG_DC , int type
+#define TYPE_ARG_CC , type
+#endif
+
 /* {{{ Resource le */
 static int le_zip_dir;
 #define le_zip_dir_name "Zip Directory"
@@ -299,7 +315,6 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam
        char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */
 {
        struct zip_source *zs;
-       int cur_idx;
        char resolved_path[MAXPATHLEN];
        zval exists_flag;
 
@@ -321,25 +336,11 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam
        if (!zs) {
                return -1;
        }
-
-       cur_idx = zip_name_locate(za, (const char *)entry_name, 0);
-       /* TODO: fix  _zip_replace */
-       if (cur_idx<0) {
-               /* reset the error */
-               if (za->error.str) {
-                       _zip_error_fini(&za->error);
-               }
-               _zip_error_init(&za->error);
-       } else {
-               if (zip_delete(za, cur_idx) == -1) {
-                       zip_source_free(zs);
-                       return -1;
-               }
-       }
-
-       if (zip_add(za, entry_name, zs) == -1) {
+       if (zip_file_add(za, entry_name, zs, ZIP_FL_OVERWRITE) < 0) { 
+               zip_source_free(zs);
                return -1;
        } else {
+               zip_error_clear(za);
                return 1;
        }
 }
@@ -780,7 +781,11 @@ static const zend_function_entry zip_functions[] = {
        PHP_FE(zip_entry_name,          arginfo_zip_entry_name)
        PHP_FE(zip_entry_compressedsize,                arginfo_zip_entry_compressedsize)
        PHP_FE(zip_entry_compressionmethod,             arginfo_zip_entry_compressionmethod)
+#ifdef  PHP_FE_END
        PHP_FE_END
+#else
+       {NULL,NULL,NULL}
+#endif
 };
 /* }}} */
 
@@ -869,7 +874,7 @@ static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zv
 }
 /* }}} */
 
-static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
+static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member TYPE_ARG_DC KEY_ARG_DC TSRMLS_DC) /* {{{ */
 {
        ze_zip_object *obj;
        zval tmp_member;
@@ -884,24 +889,27 @@ static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, int type,
                zval_copy_ctor(&tmp_member);
                convert_to_string(&tmp_member);
                member = &tmp_member;
+#if PHP_VERSION_ID >= 50400
                key = NULL;
+#endif
        }
 
        ret = FAILURE;
        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
 
        if (obj->prop_handler != NULL) {
+#if PHP_VERSION_ID >= 50400
                if (key) {
                        ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
-               } else {
+               } else
+#endif
                        ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
-               }
        }
 
 
        if (ret == FAILURE) {
                std_hnd = zend_get_std_object_handlers();
-               retval = std_hnd->get_property_ptr_ptr(object, member, type, key TSRMLS_CC);
+               retval = std_hnd->get_property_ptr_ptr(object, member TYPE_ARG_CC KEY_ARG_CC TSRMLS_CC);
        }
 
        if (member == &tmp_member) {
@@ -911,7 +919,7 @@ static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, int type,
 }
 /* }}} */
 
-static zval* php_zip_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
+static zval* php_zip_read_property(zval *object, zval *member, int type KEY_ARG_DC TSRMLS_DC) /* {{{ */
 {
        ze_zip_object *obj;
        zval tmp_member;
@@ -925,18 +933,21 @@ static zval* php_zip_read_property(zval *object, zval *member, int type, const z
                zval_copy_ctor(&tmp_member);
                convert_to_string(&tmp_member);
                member = &tmp_member;
+#if PHP_VERSION_ID >= 50400
                key = NULL;
+#endif
        }
 
        ret = FAILURE;
        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
 
        if (obj->prop_handler != NULL) {
+#if PHP_VERSION_ID >= 50400
                if (key) {
                        ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
-               } else {
+               } else
+#endif
                        ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
-               }
        }
 
        if (ret == SUCCESS) {
@@ -949,7 +960,7 @@ static zval* php_zip_read_property(zval *object, zval *member, int type, const z
                }
        } else {
                std_hnd = zend_get_std_object_handlers();
-               retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
+               retval = std_hnd->read_property(object, member, type KEY_ARG_CC TSRMLS_CC);
        }
 
        if (member == &tmp_member) {
@@ -959,7 +970,7 @@ static zval* php_zip_read_property(zval *object, zval *member, int type, const z
 }
 /* }}} */
 
-static int php_zip_has_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
+static int php_zip_has_property(zval *object, zval *member, int type KEY_ARG_DC TSRMLS_DC) /* {{{ */
 {
        ze_zip_object *obj;
        zval tmp_member;
@@ -972,18 +983,21 @@ static int php_zip_has_property(zval *object, zval *member, int type, const zend
                zval_copy_ctor(&tmp_member);
                convert_to_string(&tmp_member);
                member = &tmp_member;
+#if PHP_VERSION_ID >= 50400
                key = NULL;
+#endif
        }
 
        ret = FAILURE;
        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
 
        if (obj->prop_handler != NULL) {
+#if PHP_VERSION_ID >= 50400
                if (key) {
                        ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
-               } else {
+               } else
+#endif
                        ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
-               }
        }
 
        if (ret == SUCCESS) {
@@ -1005,7 +1019,7 @@ static int php_zip_has_property(zval *object, zval *member, int type, const zend
                zval_ptr_dtor(&tmp);
        } else {
                std_hnd = zend_get_std_object_handlers();
-               retval = std_hnd->has_property(object, member, type, key TSRMLS_CC);
+               retval = std_hnd->has_property(object, member, type KEY_ARG_CC TSRMLS_CC);
        }
 
        if (member == &tmp_member) {
@@ -1059,7 +1073,8 @@ static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
        }
        if (intern->za) {
                if (zip_close(intern->za) != 0) {
-                       _zip_free(intern->za);
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy the zip context");
+                       return;
                }
                intern->za = NULL;
        }
@@ -1096,6 +1111,9 @@ static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
 
 static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
 {
+#if PHP_VERSION_ID < 50400
+       zval *tmp;
+#endif
        ze_zip_object *intern;
        zend_object_value retval;
 
@@ -1116,8 +1134,13 @@ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_
        intern->zo.ce = class_type;
 #endif
 
-       object_properties_init(&intern->zo, class_type);
 
+#if PHP_VERSION_ID < 50400
+       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
+                                       (void *) &tmp, sizeof(zval *));
+#else
+       object_properties_init(&intern->zo, class_type);
+#endif
        retval.handle = zend_objects_store_put(intern,
                                                NULL,
                                                (zend_objects_free_object_storage_t) php_zip_object_free_storage,
@@ -1140,7 +1163,7 @@ static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        if (zip_int) {
                if (zip_int->za) {
                        if (zip_close(zip_int->za) != 0) {
-                               _zip_free(zip_int->za);
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy the zip context");
                        }
                        zip_int->za = NULL;
                }
@@ -1159,13 +1182,7 @@ static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 
        if (zr_rsrc) {
                if (zr_rsrc->zf) {
-                       if (zr_rsrc->zf->za) {
-                               zip_fclose(zr_rsrc->zf);
-                       } else {
-                               if (zr_rsrc->zf->src)
-                                       zip_source_free(zr_rsrc->zf->src);
-                               free(zr_rsrc->zf);
-                       }
+                       zip_fclose(zr_rsrc->zf);
                        zr_rsrc->zf = NULL;
                }
                efree(zr_rsrc);
@@ -1195,7 +1212,7 @@ zend_module_entry zip_module_entry = {
        NULL,
        NULL,
        PHP_MINFO(zip),
-       PHP_ZIP_VERSION_STRING,
+       PHP_ZIP_VERSION,
        STANDARD_MODULE_PROPERTIES
 };
 /* }}} */
@@ -1215,7 +1232,7 @@ static PHP_NAMED_FUNCTION(zif_zip_open)
        zip_rsrc *rsrc_int;
        int err = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &filename, &filename_len) == FAILURE) {
                return;
        }
 
@@ -1498,7 +1515,7 @@ static ZIPARCHIVE_METHOD(open)
        zval *this = getThis();
        ze_zip_object *ze_obj = NULL;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l", &filename, &filename_len, &flags) == FAILURE) {
                return;
        }
 
@@ -1523,7 +1540,8 @@ static ZIPARCHIVE_METHOD(open)
        if (ze_obj->za) {
                /* we already have an opened zip, free it */
                if (zip_close(ze_obj->za) != 0) {
-                       _zip_free(ze_obj->za);
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
+                       RETURN_FALSE;
                }
                ze_obj->za = NULL;
        }
@@ -1543,6 +1561,38 @@ static ZIPARCHIVE_METHOD(open)
 }
 /* }}} */
 
+/* {{{ proto resource ZipArchive::setPassword(string password)
+Set the password for the active archive */
+static ZIPARCHIVE_METHOD(setPassword)
+{
+       struct zip *intern;
+       zval *this = getThis();
+       char *password;
+       int     password_len;
+
+       if (!this) {
+               RETURN_FALSE;
+       }
+
+       ZIP_FROM_OBJECT(intern, this);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &password, &password_len) == FAILURE) {
+               return;
+       }
+
+       if (password_len < 1) {
+               RETURN_FALSE;
+       } else {
+               int res = zip_set_default_password(intern, (const char *)password);
+               if (res == 0) {
+                       RETURN_TRUE;
+               } else {
+                       RETURN_FALSE;
+               }
+       }
+}
+/* }}} */
+
 /* {{{ proto bool ZipArchive::close()
 close the zip archive */
 static ZIPARCHIVE_METHOD(close)
@@ -1552,7 +1602,7 @@ static ZIPARCHIVE_METHOD(close)
        ze_zip_object *ze_obj;
 
        if (!this) {
-                       RETURN_FALSE;
+               RETURN_FALSE;
        }
 
        ZIP_FROM_OBJECT(intern, this);
@@ -1560,7 +1610,7 @@ static ZIPARCHIVE_METHOD(close)
        ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
 
        if (zip_close(intern)) {
-               RETURN_FALSE;
+               zip_discard(intern);
        }
 
        efree(ze_obj->filename);
@@ -1637,6 +1687,7 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
                if (zip_add_dir(intern, (const char *)s) == -1) {
                        RETVAL_FALSE;
                }
+               zip_error_clear(intern);
                RETVAL_TRUE;
        }
 
@@ -1654,7 +1705,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
        char *path = NULL;
        char *remove_path = NULL;
        char *add_path = NULL;
-       int pattern_len, add_path_len = 0, remove_path_len = 0, path_len = 0;
+       int pattern_len, add_path_len, remove_path_len = 0, path_len = 0;
        long remove_all_path = 0;
        long flags = 0;
        zval *options = NULL;
@@ -1667,12 +1718,12 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
        ZIP_FROM_OBJECT(intern, this);
        /* 1 == glob, 2==pcre */
        if (type == 1) {
-               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|la",
                                        &pattern, &pattern_len, &flags, &options) == FAILURE) {
                        return;
                }
        } else {
-               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|sa",
                                        &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
                        return;
                }
@@ -1703,13 +1754,12 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
                zval **zval_file = NULL;
 
                for (i = 0; i < found; i++) {
-                       char *file, *file_stripped, *entry_name;
+                       char *file_stripped, *entry_name;
                        size_t entry_name_len, file_stripped_len;
                        char entry_name_buf[MAXPATHLEN];
                        char *basename = NULL;
 
                        if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) {
-                               file = Z_STRVAL_PP(zval_file);
                                if (remove_all_path) {
                                        php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0,
                                                                        &basename, (size_t *)&file_stripped_len TSRMLS_CC);
@@ -1786,7 +1836,7 @@ static ZIPARCHIVE_METHOD(addFile)
 
        ZIP_FROM_OBJECT(intern, this);
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll",
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|sll",
                        &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
                return;
        }
@@ -1856,16 +1906,18 @@ static ZIPARCHIVE_METHOD(addFromString)
        /* TODO: fix  _zip_replace */
        if (cur_idx >= 0) {
                if (zip_delete(intern, cur_idx) == -1) {
-                       goto fail;
+                       zip_source_free(zs);
+                       RETURN_FALSE;
                }
        }
 
-       if (zip_add(intern, name, zs) != -1) {
+       if (zip_add(intern, name, zs) == -1) {
+               zip_source_free(zs);
+               RETURN_FALSE;
+       } else {
+               zip_error_clear(intern);
                RETURN_TRUE;
        }
-fail:
-       zip_source_free(zs);
-       RETURN_FALSE;   
 }
 /* }}} */
 
@@ -1886,7 +1938,7 @@ static ZIPARCHIVE_METHOD(statName)
 
        ZIP_FROM_OBJECT(intern, this);
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l",
                        &name, &name_len, &flags) == FAILURE) {
                return;
        }
@@ -1942,7 +1994,7 @@ static ZIPARCHIVE_METHOD(locateName)
 
        ZIP_FROM_OBJECT(intern, this);
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l",
                        &name, &name_len, &flags) == FAILURE) {
                return;
        }
@@ -2522,7 +2574,7 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
        ZIP_FROM_OBJECT(intern, this);
 
        if (type == 1) {
-               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
                        return;
                }
                PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb);
@@ -2598,7 +2650,7 @@ static ZIPARCHIVE_METHOD(getStream)
 
        ZIP_FROM_OBJECT(intern, this);
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &filename, &filename_len) == FAILURE) {
                return;
        }
 
@@ -2621,6 +2673,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1)
        ZEND_ARG_INFO(0, flags)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setpassword, 0, 0, 1)
+       ZEND_ARG_INFO(0, password)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0)
 ZEND_END_ARG_INFO()
 
@@ -2733,6 +2789,7 @@ ZEND_END_ARG_INFO()
 /* {{{ ze_zip_object_class_functions */
 static const zend_function_entry zip_class_functions[] = {
        ZIPARCHIVE_ME(open,                                     arginfo_ziparchive_open, ZEND_ACC_PUBLIC)
+       ZIPARCHIVE_ME(setPassword,                      arginfo_ziparchive_setpassword, ZEND_ACC_PUBLIC)
        ZIPARCHIVE_ME(close,                            arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
        ZIPARCHIVE_ME(getStatusString,          arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
        ZIPARCHIVE_ME(addEmptyDir,                      arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC)
@@ -2875,7 +2932,7 @@ static PHP_MINFO_FUNCTION(zip)
 
        php_info_print_table_row(2, "Zip", "enabled");
        php_info_print_table_row(2, "Extension Version","$Id$");
-       php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING);
+       php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION);
        php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
 
        php_info_print_table_end();
index dace407d14f31ff081b739600f2114a8aa06b0da..c8da941b7a82dc0a13ad5c524599341bc85d2048 100644 (file)
@@ -28,9 +28,17 @@ extern zend_module_entry zip_module_entry;
 #include "TSRM.h"
 #endif
 
+#if defined(HAVE_LIBZIP)
+#include <zip.h>
+#else
 #include "lib/zip.h"
+#endif
 
-#define PHP_ZIP_VERSION_STRING "1.11.0"
+#ifndef ZIP_OVERWRITE
+#define ZIP_OVERWRITE ZIP_TRUNCATE
+#endif
+
+#define PHP_ZIP_VERSION "1.12.3"
 
 #if ((PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION >= 6)
 # define PHP_ZIP_USE_OO 1
@@ -67,8 +75,9 @@ typedef struct _ze_zip_read_rsrc {
 } zip_read_rsrc;
 
 #ifdef PHP_ZIP_USE_OO 
-#define ZIPARCHIVE_ME(name, arg_info, flags)   ZEND_FENTRY(name, c_ziparchive_ ##name, arg_info, flags)
-#define ZIPARCHIVE_METHOD(name)        ZEND_NAMED_FUNCTION(c_ziparchive_##name)
+#define ZIPARCHIVE_ME(name, arg_info, flags) {#name, c_ziparchive_ ##name, arg_info,(zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
+#define ZIPARCHIVE_METHOD(name)        ZEND_NAMED_FUNCTION(c_ziparchive_ ##name)
+
 
 /* Extends zend object */
 typedef struct _ze_zip_object {
diff --git a/ext/zip/tests/bug38943.inc b/ext/zip/tests/bug38943.inc
new file mode 100644 (file)
index 0000000..a6f45e8
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+class myZip extends ZipArchive {
+       private $test = 0;
+       public $testp = 1;
+       private $testarray = array();
+
+       public function __construct() {
+               $this->testarray[] = 1;
+               var_dump($this->testarray);
+       }
+}
+
+$z = new myZip;
+$z->testp = "foobar";
+var_dump($z);
+
diff --git a/ext/zip/tests/bug38943_2.phpt b/ext/zip/tests/bug38943_2.phpt
new file mode 100644 (file)
index 0000000..bdbad94
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+#38943, properties in extended class cannot be set (5.3)
+--SKIPIF--
+<?php
+/* $Id: bug38943_2.phpt 271800 2008-12-24 11:28:25Z pajoye $ */
+if(!extension_loaded('zip')) die('skip');
+if (version_compare(PHP_VERSION, "5.3", "<")) die('skip test for5.3+ only');
+?>
+--FILE--
+<?php
+include 'bug38943.inc';
+?>
+--EXPECTF--
+array(1) {
+  [0]=>
+  int(1)
+}
+object(myZip)#1 (%d) {
+  ["test":"myZip":private]=>
+  int(0)
+  ["testp"]=>
+  string(6) "foobar"
+  ["testarray":"myZip":private]=>
+  array(1) {
+    [0]=>
+    int(1)
+  }
+  ["status"]=>
+  int(0)
+  ["statusSys"]=>
+  int(0)
+  ["numFiles"]=>
+  int(0)
+  ["filename"]=>
+  string(0) ""
+  ["comment"]=>
+  string(0) ""
+}
diff --git a/ext/zip/tests/doubleclose.phpt b/ext/zip/tests/doubleclose.phpt
new file mode 100644 (file)
index 0000000..abc62c8
--- /dev/null
@@ -0,0 +1,43 @@
+--TEST--
+close() called twice
+--SKIPIF--
+<?php
+if(!extension_loaded('zip')) die('skip');
+?>
+--FILE--
+<?php
+
+echo "Procedural\n";
+$zip = zip_open(dirname(__FILE__) . '/test.zip');
+if (!is_resource($zip)) {
+       die("Failure");
+       }
+var_dump(zip_close($zip));
+var_dump(zip_close($zip));
+
+echo "Object\n";
+$zip = new ZipArchive();
+if (!$zip->open(dirname(__FILE__) . '/test.zip')) {
+       die('Failure');
+}
+if ($zip->status == ZIPARCHIVE::ER_OK) {
+       var_dump($zip->close());
+       var_dump($zip->close());
+} else {
+       die("Failure");
+}
+
+?>
+Done
+--EXPECTF--
+Procedural
+NULL
+
+Warning: zip_close(): %i is not a valid Zip Directory resource in %s
+bool(false)
+Object
+bool(true)
+
+Warning: ZipArchive::close(): Invalid or uninitialized Zip object in %s
+bool(false)
+Done
diff --git a/ext/zip/tests/zip_entry_close.phpt b/ext/zip/tests/zip_entry_close.phpt
new file mode 100644 (file)
index 0000000..82b7819
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+zip_entry_close() function: simple and double call
+--SKIPIF--
+<?php
+/* $Id$ */
+if(!extension_loaded('zip')) die('skip');
+?>
+--FILE--
+<?php
+$zip    = zip_open(dirname(__FILE__)."/test_procedural.zip");
+$entry  = zip_read($zip);
+echo "entry_open:  "; var_dump(zip_entry_open($zip, $entry, "r"));
+echo "entry_close: "; var_dump(zip_entry_close($entry));
+echo "entry_close: "; var_dump(zip_entry_close($entry));
+zip_close($zip);
+?>
+Done
+--EXPECTF--
+entry_open:  bool(true)
+entry_close: bool(true)
+entry_close: 
+Warning: zip_entry_close(): %d is not a valid Zip Entry resource in %s
+bool(false)
+Done
index 79b54cbbb0cdcf0dc28e34b73c8151a23656cee0..02fbc70f85e6086a67b02c5ae425e9cd6e7a4062 100644 (file)
@@ -1,3 +1,21 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2013 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt.                                 |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Piere-Alain Joye <pierre@php.net>                            |
+  +----------------------------------------------------------------------+
+*/
+
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
 #   include "config.h"
@@ -6,8 +24,6 @@
 #if HAVE_ZIP
 #ifdef ZEND_ENGINE_2
 
-#include "lib/zip.h"
-
 #include "php_streams.h"
 #include "ext/standard/file.h"
 #include "ext/standard/php_string.h"