Sync ext/zip with pecl/zip version 1.3.2

- 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
This commit is contained in:
Remi Collet 2013-11-04 13:23:36 +01:00
parent 2f555b8e60
commit 5dc37b3510
99 changed files with 4820 additions and 1877 deletions

View file

@ -1,2 +1,2 @@
Zip
Pierre-Alain Joye
Pierre-Alain Joye, Remi Collet

View 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
])
])
CPPFLAGS=$old_CPPFLAGS
if test "$PHP_LIBZIP" != "no"; then
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_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
])
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

View 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");
}
}

View file

@ -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();

View file

@ -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();

151
ext/zip/lib/mkstemp.c Normal file
View file

@ -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
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
}

View file

@ -0,0 +1,57 @@
#ifndef HAD_CONFIG_H
#define HAD_CONFIG_H
#define HAVE__CLOSE
#define HAVE__DUP
#define HAVE__FDOPEN
#define HAVE__FILENO
#define HAVE__OPEN
#define HAVE__SNPRINTF
/* #undef HAVE__STRCMPI */
#define HAVE__STRDUP
#define HAVE__STRICMP
/* #undef HAVE_FSEEKO */
/* #undef HAVE_FTELLO */
/* #undef HAVE_MKSTEMP */
#define HAVE_MOVEFILEEXA
/* #undef HAVE_SNPRINTF */
/* #undef HAVE_STRCASECMP */
/* #undef HAVE_STRINGS_H */
/* #undef HAVE_STRUCT_TM_TM_ZONE */
/* #undef HAVE_UNISTD_H */
#define PACKAGE "libzip"
#define VERSION "0.10.b"
/* #undef HAVE_SSIZE_T */
#ifndef HAVE_SSIZE_T
#ifndef SIZE_T_LIBZIP
#define SIZE_T_LIBZIP 4
#endif
#ifndef INT_LIBZIP
#define INT_LIBZIP 4
#endif
#ifndef LONG_LIBZIP
#define LONG_LIBZIP 4
#endif
#ifndef LONG_LONG_LIBZIP
#define LONG_LONG_LIBZIP 8
#endif
#ifndef SIZEOF_OFF_T
#define SIZEOF_OFF_T 4
#endif
# if SIZE_T_LIBZIP == INT_LIBZIP
# ifndef ssize_t
typedef int ssize_t;
# endif
# elif SIZE_T_LIBZIP == LONG_LIBZIP
typedef long ssize_t;
# elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP
typedef long long ssize_t;
# else
#error no suitable type for ssize_t found
# endif
#endif
#endif /* HAD_CONFIG_H */

View 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>
@ -38,18 +38,30 @@
#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);
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 */

View 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 @@
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
@ -44,13 +45,8 @@
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);
}

View 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>
@ -33,56 +33,15 @@
#include <stdlib.h>
#include <string.h>
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
/* 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);
}

View file

@ -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.
*/
#include <stdlib.h>
#include "zipint.h"
/* 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;
}

View 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>
@ -49,110 +52,106 @@
#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 *);
/* 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 *);
struct filelist {
int idx;
const char *name;
};
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++) {
i = filelist[j].idx;
int new_data;
struct zip_entry *entry;
struct zip_dirent *de;
_zip_dirent_init(&de);
i = filelist[j].idx;
entry = za->entry+i;
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 (_zip_read_local_ef(za, i) < 0) {
error = 1;
break;
}
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_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
_zip_dirent_torrent_normalize(entry->changes);
if (za->entry[i].ch_extra_len != -1) {
free(de.extrafield);
if ((de.extrafield=malloc(za->entry[i].ch_extra_len)) == NULL) {
error = 1;
break;
}
memcpy(de.extrafield, za->entry[i].ch_extra, za->entry[i].ch_extra_len);
de.extrafield_len = za->entry[i].ch_extra_len;
/* as the rest of cd entries, its malloc/free is done by za */
/* TODO unsure if this should also be set in the CD --
* not done for now
cd->entry[j].extrafield = za->entry[i].ch_extra;
cd->entry[j].extrafield_len = za->entry[i].ch_extra_len;
*/
}
if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0
&& za->entry[i].ch_comment_len != -1) {
/* as the rest of cd entries, its malloc/free is done by za */
cd->entry[j].comment = za->entry[i].ch_comment;
cd->entry[j].comment_len = za->entry[i].ch_comment_len;
}
de->offset = (zip_uint64_t)ftello(out); /* XXX: check for errors */
cd->entry[j].offset = ftello(out);
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);
if (!error) {
if (write_cdir(za, filelist, survivors, out) < 0)
error = 1;
}
free(filelist);
if (!error) {
if (write_cdir(za, cd, out) < 0)
error = 1;
}
/* pointers in cd entries are owned by za */
cd->nentry = 0;
_zip_cdir_free(cd);
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;
}
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);
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;
}
}
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;
}
if ((s2=comp_impl(za, s2, ZIP_CM_DEFLATE, ZIP_CODEC_ENCODE))
== NULL) {
/* XXX: set error? */
zip_source_pop(s2);
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,
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)
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)
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;
}
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);
}

View file

@ -37,7 +37,7 @@
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;
}

View 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>
@ -34,48 +34,55 @@
#include <stdlib.h>
#include <string.h>
#include "zipint.h"
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;
}
}
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;
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;
}
ze->state = ZIP_ST_UNCHANGED;
if (name == NULL) {
_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
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;
s = NULL;
len = strlen(name);
if (za)
za->nentry++;
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';
}
return ze;
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);
free(s);
if (ret < 0)
zip_source_free(source);
return ret;
}

File diff suppressed because it is too large Load diff

View 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>
@ -39,14 +39,14 @@
/* _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);
}

View 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>
@ -33,23 +33,23 @@
#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);
}
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;
}

View 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)
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)
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;

View file

@ -37,8 +37,11 @@
ZIP_EXTERN(void)
ZIP_EXTERN void
zip_error_clear(struct zip *za)
{
if (za == NULL)
return;
_zip_error_clear(&za->error);
}

View file

@ -37,7 +37,7 @@
ZIP_EXTERN(void)
ZIP_EXTERN void
zip_error_get(struct zip *za, int *zep, int *sep)
{
_zip_error_get(&za->error, zep, sep);

View file

@ -37,7 +37,7 @@
ZIP_EXTERN(int)
ZIP_EXTERN int
zip_error_get_sys_type(int ze)
{
if (ze < 0 || ze >= _zip_nerr_str)

View file

@ -42,7 +42,7 @@
ZIP_EXTERN(int)
ZIP_EXTERN int
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se)
{
const char *zs, *ss;

View file

@ -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.
*/
#include "zipint.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
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;
}
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;
}
}
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;
}
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;
}
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;
}
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;
}
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;
}
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);
}
}
}
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;
}

View file

@ -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.
*/
#include "zipint.h"
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;
}
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;
}
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;
}
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);
}
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;
}
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;
}
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;
}

View file

@ -39,20 +39,23 @@
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;

View file

@ -37,11 +37,24 @@
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);
}

View file

@ -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.
*/
#include "zipint.h"
/*
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);
}

View file

@ -37,8 +37,11 @@
ZIP_EXTERN(void)
ZIP_EXTERN void
zip_file_error_clear(struct zip_file *zf)
{
if (zf == NULL)
return;
_zip_error_clear(&zf->error);
}

View file

@ -37,7 +37,7 @@
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);

View 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
@ -31,28 +31,28 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
/* 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 ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
return NULL;
if (lenp != NULL)
*lenp = za->entry[idx].ch_extra_len;
return za->entry[idx].ch_extra;
if (lenp)
*lenp = len;
return (const char *)str;
}

View file

@ -50,25 +50,27 @@
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;
}

View 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
@ -31,23 +31,21 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include "zipint.h"
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;
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] == '/');
if (new_is_dir != old_is_dir) {
_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
else
tmpext = NULL;
free(za->entry[idx].ch_extra);
za->entry[idx].ch_extra = tmpext;
za->entry[idx].ch_extra_len = len;
return 0;
return _zip_set_name(za, idx, name, flags);
}

View file

@ -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.
*/
#include "zipint.h"
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;
}
/* 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;
}

View file

@ -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.
*/
#include <stdlib.h>
#include "zipint.h"
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;
}

View file

@ -37,7 +37,7 @@
ZIP_EXTERN(const char *)
ZIP_EXTERN const char *
zip_file_strerror(struct zip_file *zf)
{
return _zip_error_strerror(&zf->error);

View 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;
}

View file

@ -37,13 +37,13 @@
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);
}

View file

@ -37,14 +37,13 @@
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);
}

View 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 @@
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);
}

View 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);
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;
struct zip_source *src;
if (fileno >= za->nentry) {
_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
if ((src=_zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
return NULL;
}
if ((flags & ZIP_FL_UNCHANGED) == 0
&& ZIP_ENTRY_DATA_CHANGED(za->entry+fileno)) {
_zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
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 *));

View file

@ -37,7 +37,7 @@
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;

View 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>
@ -33,28 +33,29 @@
#include <string.h>
#include "zipint.h"
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;
}

View file

@ -37,10 +37,10 @@
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;

View file

@ -37,10 +37,10 @@
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;
}

View file

@ -37,8 +37,8 @@
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;

View 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>
@ -33,26 +33,21 @@
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
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 ((s=zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
if (lenp)
*lenp = (int)len;
}
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 (lenp != NULL)
*lenp = za->entry[idx].ch_comment_len;
return za->entry[idx].ch_comment;
return s;
}

View 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>
@ -33,12 +33,14 @@
#include <string.h>
#include "zipint.h"
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)
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 (za->cdir == NULL || idx >= za->cdir->nentry) {
_zip_error_set(error, ZIP_ER_INVAL, 0);
if ((de=_zip_get_dirent(za, idx, flags, error)) == NULL)
return NULL;
}
return za->cdir->entry[idx].filename;
if ((str=_zip_string_get(de->filename, NULL, flags, error)) == NULL)
return NULL;
return (const char *)str;
}

View file

@ -37,16 +37,19 @@
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;
}

View file

@ -33,15 +33,17 @@
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
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;
}

View 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);

View file

@ -34,26 +34,28 @@
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "zipint.h"
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);
}
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) ? strcasecmp : strcmp;
cmp = (flags & ZIP_FL_NOCASE) ? strcmpi : strcmp;
for (i=0; i<za->nentry; i++) {
fn = _zip_get_name(za, i, flags, error);
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);
/* 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;
}

View 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;
}

View 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>
@ -42,38 +42,53 @@
#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 *);
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;
}
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;
}
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;
}
/* _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)
/* _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,
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;
}
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)
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)
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;
}
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;
}
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;
}

View 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>
@ -35,36 +35,13 @@
#include <string.h>
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
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);
}

View 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>
@ -33,53 +33,13 @@
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
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;
}
/* 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);
}

View 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>
@ -39,32 +39,46 @@
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;
if (len < 0 || len > MAXCOMLEN
|| (len > 0 && comment == NULL)) {
_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
struct zip_string *cstr;
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 ((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;
free(za->ch_comment);
za->ch_comment = tmpcom;
za->ch_comment_len = len;
_zip_string_free(za->comment_changes);
za->comment_changes = NULL;
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;
}

View file

@ -37,8 +37,8 @@
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;

View file

@ -40,7 +40,7 @@
ZIP_EXTERN(int)
ZIP_EXTERN int
zip_set_default_password(struct zip *za, const char *passwd)
{
if (za == NULL)

View 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>
@ -35,38 +35,17 @@
#include <stdlib.h>
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
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 (len < 0 || len > ZIP_UINT16_MAX) {
_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (ZIP_IS_RDONLY(za)) {
_zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (len > 0) {
if ((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);
}

View file

@ -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.
*/
#include "zipint.h"
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;
}

View 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>
@ -41,35 +41,77 @@
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;
}

View file

@ -48,7 +48,7 @@ static zip_int64_t read_data(void *, void *, zip_uint64_t, enum zip_source_cmd);
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;

View file

@ -37,7 +37,7 @@
ZIP_EXTERN(void)
void
zip_source_close(struct zip_source *src)
{
if (!src->is_open)

View 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 *
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;

View file

@ -60,14 +60,14 @@ static void deflate_free(struct deflate *);
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) {

View 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>
@ -37,24 +37,21 @@
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;
}
}

View file

@ -40,7 +40,7 @@
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)
{

View file

@ -58,14 +58,14 @@ static zip_int64_t read_file(void *state, void *data, zip_uint64_t len,
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;
}
}

View file

@ -39,7 +39,7 @@
ZIP_EXTERN(void)
ZIP_EXTERN void
zip_source_free(struct zip_source *src)
{
if (src == NULL)

View file

@ -39,7 +39,7 @@
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;

View file

@ -39,7 +39,7 @@
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)
{

View 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 @@
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;

View 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))
static void decrypt(struct trad_pkware *, zip_uint8_t *,
@ -64,7 +60,7 @@ static void pkware_free(struct trad_pkware *);
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;

View file

@ -39,7 +39,7 @@
ZIP_EXTERN(struct zip_source *)
struct zip_source *
zip_source_pop(struct zip_source *src)
{
struct zip_source *lower;

View file

@ -37,7 +37,7 @@
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;

View file

@ -37,7 +37,7 @@
ZIP_EXTERN(int)
int
zip_source_stat(struct zip_source *src, struct zip_stat *st)
{
zip_int64_t ret;

View file

@ -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.
*/
#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);
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);
}
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;
}
}

View file

@ -38,153 +38,24 @@
#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);
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;
}
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);
}

View file

@ -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.
*/
#include <stdlib.h>
#include "zipint.h"
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;
}

View file

@ -37,13 +37,13 @@
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);
}

View file

@ -37,16 +37,15 @@
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;
}

View file

@ -37,7 +37,7 @@
ZIP_EXTERN(void)
ZIP_EXTERN void
zip_stat_init(struct zip_stat *st)
{
st->valid = 0;

View file

@ -36,7 +36,8 @@
#include "zipint.h"
ZIP_EXTERN(const char *)
ZIP_EXTERN const char *
zip_strerror(struct zip *za)
{
return _zip_error_strerror(&za->error);

196
ext/zip/lib/zip_string.c Normal file
View file

@ -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.
*/
#include <stdlib.h>
#include <string.h>
#include "zipint.h"
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;
}
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);
}
void
_zip_string_free(struct zip_string *s)
{
if (s == NULL)
return;
free(s->raw);
free(s->converted);
free(s);
}
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;
}
zip_uint16_t
_zip_string_length(const struct zip_string *s)
{
if (s == NULL)
return 0;
return s->length;
}
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;
}
void
_zip_string_write(const struct zip_string *s, FILE *f)
{
if (s == NULL)
return;
fwrite(s->raw, s->length, 1, f);
}

View file

@ -39,7 +39,7 @@
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);

View file

@ -39,10 +39,11 @@
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++)

View file

@ -39,13 +39,15 @@
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;

View 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 @@
#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;
}

255
ext/zip/lib/zip_utf-8.c Normal file
View file

@ -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.
*/
#include "zipint.h"
#include <stdlib.h>
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
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;
}
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;
}
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;
}
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;
}

View file

@ -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
*/

View file

@ -1,47 +1,129 @@
#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
#define _HAD_ZIPCONF_H
/*
zipconf.h -- platform specific include file
This file was generated automatically by CMake
based on ../cmake-zipconf.h.in.
*/
#define LIBZIP_VERSION "0.11.1"
/* #undef HAVE_INTTYPES_H_LIBZIP */
#if defined(_WIN32)
# if _MSC_VER > 1500
# define HAVE_STDINT_H_LIBZIP
# else
# include "win32/php_stdint.h"
# endif
#else
# include <inttypes.h>
#endif
#define HAVE_SYS_TYPES_H_LIBZIP
#define HAVE___INT8_LIBZIP
#define HAVE_INT8_T_LIBZIP
#define HAVE_UINT8_T_LIBZIP
#define HAVE___INT16_LIBZIP
#define HAVE_INT16_T_LIBZIP
#define HAVE_UINT16_T_LIBZIP
#define HAVE___INT32_LIBZIP
#define HAVE_INT32_T_LIBZIP
#define HAVE_UINT32_T_LIBZIP
#define HAVE___INT64_LIBZIP
#define HAVE_INT64_T_LIBZIP
#define HAVE_UINT64_T_LIBZIP
#define SHORT_LIBZIP 2
#define INT_LIBZIP 4
#define LONG_LIBZIP 4
#define LONG_LONG_LIBZIP 8
#if defined(HAVE_STDINT_H_LIBZIP)
#include <stdint.h>
#elif defined(HAVE_INTTYPES_H_LIBZIP)
#include <inttypes.h>
#elif defined(HAVE_SYS_TYPES_H_LIBZIP)
#include <sys/types.h>
#endif
#if defined(HAVE_INT8_T_LIBZIP)
typedef int8_t zip_int8_t;
#elif defined(HAVE___INT8_LIBZIP)
typedef __int8 zip_int8_t;
#else
typedef signed char zip_int8_t;
#endif
#if defined(HAVE_UINT8_T_LIBZIP)
typedef uint8_t zip_uint8_t;
#elif defined(HAVE___INT8_LIBZIP)
typedef unsigned __int8 zip_uint8_t;
#else
typedef unsigned char zip_uint8_t;
#endif
#if defined(HAVE_INT16_T_LIBZIP)
typedef int16_t zip_int16_t;
#elif defined(HAVE___INT16_LIBZIP)
typedef __int16 zip_int16_t;
#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2
typedef signed short zip_int16_t;
#endif
#if defined(HAVE_UINT16_T_LIBZIP)
typedef uint16_t zip_uint16_t;
#elif defined(HAVE___INT16_LIBZIP)
typedef unsigned __int16 zip_uint16_t;
#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2
typedef unsigned short zip_uint16_t;
#endif
#if defined(HAVE_INT32_T_LIBZIP)
typedef int32_t zip_int32_t;
#elif defined(HAVE___INT32_LIBZIP)
typedef __int32 zip_int32_t;
#elif defined(INT_LIBZIP) && INT_LIBZIP == 4
typedef signed int zip_int32_t;
#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4
typedef signed long zip_int32_t;
#endif
#if defined(HAVE_UINT32_T_LIBZIP)
typedef uint32_t zip_uint32_t;
#elif defined(HAVE___INT32_LIBZIP)
typedef unsigned __int32 zip_uint32_t;
#elif defined(INT_LIBZIP) && INT_LIBZIP == 4
typedef unsigned int zip_uint32_t;
#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4
typedef unsigned long zip_uint32_t;
#endif
#if defined(HAVE_INT64_T_LIBZIP)
typedef int64_t zip_int64_t;
#elif defined(HAVE___INT64_LIBZIP)
typedef __int64 zip_int64_t;
#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 8
typedef signed long zip_int64_t;
#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8
typedef signed long long zip_int64_t;
#endif
#if defined(HAVE_UINT64_T_LIBZIP)
typedef uint64_t zip_uint64_t;
#elif defined(HAVE___INT64_LIBZIP)
typedef unsigned __int64 zip_uint64_t;
#elif defined(LONG_LIBZIP) && LONG_LONG_LIBZIP == 8
typedef unsigned long zip_uint64_t;
#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8
typedef unsigned long long zip_uint64_t;
#endif
#define ZIP_INT8_MIN -0x80
#define ZIP_INT8_MAX 0x7f
#define ZIP_UINT8_MAX 0xff
#define ZIP_INT16_MIN -0x8000
#define ZIP_INT16_MAX 0x7fff
#define ZIP_UINT16_MAX 0xffff
#define ZIP_INT32_MIN -0x80000000L
#define ZIP_INT32_MAX 0x7fffffffL
#define ZIP_UINT32_MAX 0xffffffffLU
#define ZIP_INT64_MIN -0x8000000000000000LL
#define ZIP_INT64_MAX 0x7fffffffffffffffLL
#define ZIP_UINT64_MAX 0xffffffffffffffffULL
#endif /* zipconf.h */

View 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
@ -34,9 +34,64 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* to have *_MAX definitions for all types when compiling with g++ */
#define __STDC_LIMIT_MACROS
#include <zlib.h>
#ifdef PHP_WIN32
/* for dup(), close(), etc. */
#include <io.h>
#include "config.w32.h"
#endif
#ifndef _ZIP_COMPILING_DEPRECATED
#define ZIP_DISABLE_DEPRECATED
#endif
#include "zip.h"
#ifdef PHP_WIN32
# include "php_zip_config.w32.h"
#else
# include "config.h"
#endif
#if defined(HAVE_MOVEFILEEXA) && defined(_WIN32)
#include <windows.h>
#define _zip_rename(s, t) \
(!MoveFileExA((s), (t), MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING))
#else
#define _zip_rename rename
#endif
#ifdef _WIN32
#undef strcasecmp
# define strcasecmp _strcmpi
#endif
#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
#ifndef HAVE_FSEEKO
#define fseeko(s, o, w) (fseek((s), (long int)(o), (w)))
@ -46,57 +101,56 @@
#define ftello(s) ((long)ftell((s)))
#endif
#ifndef PHP_WIN32
#ifndef HAVE_MKSTEMP
int _zip_mkstemp(char *);
#define mkstemp _zip_mkstemp
#endif
#endif
#ifdef PHP_WIN32
#include <windows.h>
#include <wchar.h>
#define _zip_rename(s, t) \
(!MoveFileExA((s), (t), \
MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING))
/* for dup(), close(), etc. */
#include <io.h>
#if !defined(HAVE_OPEN)
#if defined(HAVE__OPEN)
#define open(a, b, c) _open((a), (b))
#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
#define _zip_rename rename
#error unsupported size of off_t
#endif
#ifndef strcasecmp
# define strcmpi strcasecmp
#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)
/* 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);
/* 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 *);
/* 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 */
unsigned int flags; /* archive global flags */
unsigned int ch_flags; /* changed archive global flags */
char *default_password; /* password used when no other supplied */
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 */
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;
};
@ -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;
};
/* 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 */
};
/* which files to write, and in which order (name is for torrentzip sorting) */
struct zip_filelist {
zip_uint64_t idx;
const char *name;
};
@ -279,66 +391,111 @@ extern const int _zip_err_type[];
#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)
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 *);
int _zip_dirent_write(struct zip_dirent *, FILE *, zip_flags_t, 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 *);
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 *);
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_changed(struct zip *, int *);
void _zip_free(struct zip *);
const char *_zip_get_name(struct zip *, zip_uint64_t, int, struct zip_error *);
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 */

View 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();

View 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 {

View file

@ -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);

View file

@ -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) ""
}

View file

@ -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

View file

@ -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

View 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"