https://bugzilla.redhat.com/show_bug.cgi?id=551513 https://bugs.php.net/bug.php?id=39388 http://spot.fedorapeople.org/php-5.3.6-libzip.patch pld fixes: link with -lzip when using system lib, -lz otherwise diff -up php-5.4.5RC1/ext/zip/config.m4.systzip php-5.4.5RC1/ext/zip/config.m4 --- php-5.4.5RC1/ext/zip/config.m4.systzip 2012-07-04 07:43:14.000000000 +0200 +++ php-5.4.5RC1/ext/zip/config.m4 2012-07-07 15:56:41.418171233 +0200 @@ -13,65 +13,105 @@ fi PHP_ARG_WITH(pcre-dir, pcre install prefix, [ --with-pcre-dir ZIP: pcre install prefix], no, no) -if test "$PHP_ZIP" != "no"; then +PHP_ARG_WITH(libzip, libzip, +[ --with-libzip[=DIR] ZIP: use libzip], no, no) - 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" - PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include/zlib" - elif test -f "$PHP_ZLIB_DIR/include/zlib.h"; then - PHP_ZLIB_DIR="$PHP_ZLIB_DIR" - PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include" +if test "$PHP_ZIP" != "no"; then + if test "$PHP_LIBZIP" != "no"; then + dnl system libzip, depends on libzip + if test -r $PHP_LIBZIP/include/zip.h; then + LIBZIP_DIR=$PHP_LIBZIP else - AC_MSG_ERROR([Can not find zlib headers under "$PHP_ZLIB_DIR"]) + AC_MSG_CHECKING(for libzip in default path) + for i in /usr/local /usr; do + if test -r $i/include/zip.h; then + LIBZIP_DIR=$i + AC_MSG_RESULT(found in $i) + break + fi + done + fi + + if test -z "$LIBZIP_DIR"; 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_INCLUDE($LIBZIP_DIR/include) + PHP_ADD_LIBRARY_WITH_PATH(zip, $LIBZIP_DIR/$PHP_LIBDIR, ZIP_SHARED_LIBADD) + AC_DEFINE(HAVE_LIBZIP,1,[ ]) + ], [ + AC_MSG_ERROR(could not find usable libzip) + ], [ + -L$LIBZIP_DIR/$PHP_LIBDIR + ]) + + AC_DEFINE(HAVE_ZIP,1,[ ]) + PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c, $ext_shared) + PHP_SUBST(ZIP_SHARED_LIBADD) else - for i in /usr/local /usr; do - if test -f "$i/include/zlib/zlib.h"; then - PHP_ZLIB_DIR="$i" - PHP_ZLIB_INCDIR="$i/include/zlib" - elif test -f "$i/include/zlib.h"; then - PHP_ZLIB_DIR="$i" - PHP_ZLIB_INCDIR="$i/include" + + dnl bundled 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" + PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include/zlib" + elif test -f "$PHP_ZLIB_DIR/include/zlib.h"; then + PHP_ZLIB_DIR="$PHP_ZLIB_DIR" + PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include" + else + AC_MSG_ERROR([Can not find zlib headers under "$PHP_ZLIB_DIR"]) fi - done - fi + else + for i in /usr/local /usr; do + if test -f "$i/include/zlib/zlib.h"; then + PHP_ZLIB_DIR="$i" + PHP_ZLIB_INCDIR="$i/include/zlib" + elif test -f "$i/include/zlib.h"; then + PHP_ZLIB_DIR="$i" + PHP_ZLIB_INCDIR="$i/include" + fi + done + fi - dnl # zlib - AC_MSG_CHECKING([for the location of zlib]) - if test "$PHP_ZLIB_DIR" = "no"; then - AC_MSG_ERROR([zip support requires ZLIB. Use --with-zlib-dir= to specify prefix where ZLIB include and library are located]) - else - AC_MSG_RESULT([$PHP_ZLIB_DIR]) - PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, ZIP_SHARED_LIBADD) - PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR) - fi + dnl # zlib + AC_MSG_CHECKING([for the location of zlib]) + if test "$PHP_ZLIB_DIR" = "no"; then + AC_MSG_ERROR([zip support requires ZLIB. Use --with-zlib-dir= to specify prefix where ZLIB include and library are located]) + else + AC_MSG_RESULT([$PHP_ZLIB_DIR]) + PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, ZIP_SHARED_LIBADD) + 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,[ + dnl This is PECL build, check if bundled PCRE library is used + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=$INCLUDES + AC_EGREP_CPP(yes,[ #include
#if defined(HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) yes #endif - ],[ - PHP_PCRE_REGEX=yes - ],[ - AC_EGREP_CPP(yes,[ + ],[ + PHP_PCRE_REGEX=yes + ],[ + AC_EGREP_CPP(yes,[ #include
#if defined(HAVE_PCRE) && !defined(COMPILE_DL_PCRE) yes #endif - ],[ - PHP_PCRE_REGEX=pecl - ],[ - PHP_PCRE_REGEX=no + ],[ + PHP_PCRE_REGEX=pecl + ],[ + PHP_PCRE_REGEX=no + ]) ]) - ]) - CPPFLAGS=$old_CPPFLAGS + CPPFLAGS=$old_CPPFLAGS - PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_error.c lib/zip_fclose.c \ + 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 \ @@ -98,10 +138,11 @@ yes lib/zip_source_open.c lib/zip_source_pkware.c lib/zip_source_pop.c \ lib/zip_source_read.c lib/zip_source_stat.c" - AC_DEFINE(HAVE_ZIP,1,[ ]) - PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c $PHP_ZIP_SOURCES, $ext_shared) - PHP_ADD_BUILD_DIR($ext_builddir/lib, 1) - PHP_SUBST(ZIP_SHARED_LIBADD) + 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 dnl so we always include the known-good working hack. PHP_ADD_MAKEFILE_FRAGMENT diff -up php-5.4.5RC1/ext/zip/php_zip.c.systzip php-5.4.5RC1/ext/zip/php_zip.c --- php-5.4.5RC1/ext/zip/php_zip.c.systzip 2012-07-04 07:43:14.000000000 +0200 +++ php-5.4.5RC1/ext/zip/php_zip.c 2012-07-07 15:59:12.728676026 +0200 @@ -29,8 +29,232 @@ #include "ext/standard/php_string.h" #include "ext/pcre/php_pcre.h" #include "php_zip.h" +#if defined(HAVE_LIBZIP) +#include + +/* Copied from libzip 0.10 */ + +/* 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 }; + +typedef zip_int64_t (*zip_source_layered_callback)(struct zip_source *, void *, + void *, zip_uint64_t, + enum zip_source_cmd); + +struct zip_error { + int zip_err; /* libzip error code (ZIP_ER_*) */ + int sys_err; /* copy of errno (E*) or zlib error code */ + char *str; /* string representation or NULL */ +}; + +/* zip archive, part of API */ + +struct zip { + char *zn; /* file name */ + FILE *zp; /* file */ + struct zip_error error; /* error information */ + + unsigned int flags; /* archive global flags */ + unsigned int ch_flags; /* changed archive global flags */ + + char *default_password; /* password used when no other supplied */ + + struct zip_cdir *cdir; /* central directory */ + char *ch_comment; /* changed archive comment */ + int ch_comment_len; /* length of changed zip archive + * comment, -1 if unchanged */ + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ + struct zip_entry *entry; /* entries */ + int nfile; /* number of opened files within archive */ + int nfile_alloc; /* number of files allocated */ + struct zip_file **file; /* opened files within archive */ +}; + +/* file in zip archive, part of API */ + +struct zip_file { + struct zip *za; /* zip archive containing this file */ + struct zip_error error; /* error information */ + int eof; + struct zip_source *src; /* data source */ +}; + +/* zip archive directory entry (central or local) */ + +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 archive central directory */ + +struct zip_cdir { + struct zip_dirent *entry; /* directory entries */ + int nentry; /* number of entries */ + + 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 */ +}; + +struct zip_source { + struct zip_source *src; + union { + zip_source_callback f; + zip_source_layered_callback l; + } cb; + void *ud; + enum zip_les error_source; + int is_open; +}; + +/* entry in zip archive directory */ + +struct zip_entry { + enum zip_state state; + struct zip_source *source; + char *ch_filename; + char *ch_extra; + int ch_extra_len; + char *ch_comment; + int ch_comment_len; +}; + +void _zip_dirent_finalize(struct zip_dirent *zde) +{ + free(zde->filename); + zde->filename = NULL; + free(zde->extrafield); + zde->extrafield = NULL; + free(zde->comment); + zde->comment = NULL; +} + +void _zip_cdir_free(struct zip_cdir *cd) +{ + int i; + + if (!cd) + return; + + for (i=0; inentry; i++) + _zip_dirent_finalize(cd->entry+i); + free(cd->comment); + free(cd->entry); + free(cd); +} + +void _zip_error_fini(struct zip_error *err) +{ + free(err->str); + err->str = NULL; +} + +void _zip_error_init(struct zip_error *err) +{ + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; + err->str = NULL; +} + +void _zip_unchange_data(struct zip_entry *ze) +{ + if (ze->source) { + zip_source_free(ze->source); + ze->source = NULL; + } + + ze->state = ze->ch_filename ? ZIP_ST_RENAMED : ZIP_ST_UNCHANGED; +} + +void _zip_entry_free(struct zip_entry *ze) +{ + 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); +} + +void +_zip_error_set(struct zip_error *err, int ze, int se) +{ + if (err) { + err->zip_err = ze; + err->sys_err = se; + } +} + +void _zip_free(struct zip *za) +{ + int i; + + if (za == NULL) + return; + + if (za->zn) + free(za->zn); + + if (za->zp) + fclose(za->zp); + + free(za->default_password); + _zip_cdir_free(za->cdir); + free(za->ch_comment); + + if (za->entry) { + for (i=0; inentry; i++) { + _zip_entry_free(za->entry+i); + } + free(za->entry); + } + + for (i=0; infile; i++) { + if (za->file[i]->error.zip_err == ZIP_ER_OK) { + _zip_error_set(&za->file[i]->error, ZIP_ER_ZIPCLOSED, 0); + za->file[i]->za = NULL; + } + } + + free(za->file); + free(za); + return; +} + + +#else #include "lib/zip.h" #include "lib/zipint.h" +#endif /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */ static PHP_NAMED_FUNCTION(zif_zip_open); @@ -1624,6 +1848,10 @@ static ZIPARCHIVE_METHOD(addEmptyDir) } idx = zip_stat(intern, s, 0, &sb); + /* We don't care about the NOENT status error here. */ + if (intern->error.zip_err == ZIP_ER_NOENT) { + _zip_error_set(&intern->error, ZIP_ER_OK, 0); + } if (idx >= 0) { RETVAL_FALSE; } else { @@ -1846,6 +2074,10 @@ static ZIPARCHIVE_METHOD(addFromString) } cur_idx = zip_name_locate(intern, (const char *)name, 0); + /* We don't care about the NOENT status error here. */ + if (intern->error.zip_err == ZIP_ER_NOENT) { + _zip_error_set(&intern->error, ZIP_ER_OK, 0); + } /* TODO: fix _zip_replace */ if (cur_idx >= 0) { if (zip_delete(intern, cur_idx) == -1) { @@ -2868,7 +3100,11 @@ 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, "Libzip version", LIBZIP_VERSION); +#if defined(HAVE_LIBZIP) + php_info_print_table_row(2, "Compiled against libzip version", LIBZIP_VERSION); +#else + php_info_print_table_row(2, "Bundled libzip version", LIBZIP_VERSION); +#endif php_info_print_table_end(); } diff -up php-5.4.5RC1/ext/zip/php_zip.h.systzip php-5.4.5RC1/ext/zip/php_zip.h --- php-5.4.5RC1/ext/zip/php_zip.h.systzip 2012-07-04 07:43:14.000000000 +0200 +++ php-5.4.5RC1/ext/zip/php_zip.h 2012-07-07 15:57:34.845319432 +0200 @@ -28,7 +28,11 @@ extern zend_module_entry zip_module_entr #include "TSRM.h" #endif +#if defined(HAVE_LIBZIP) +#include +#else #include "lib/zip.h" +#endif #define PHP_ZIP_VERSION_STRING "1.11.0" diff -up php-5.4.5RC1/ext/zip/tests/bug38943.phpt.systzip php-5.4.5RC1/ext/zip/tests/bug38943.phpt --- php-5.4.5RC1/ext/zip/tests/bug38943.phpt.systzip 2012-07-04 07:43:14.000000000 +0200 +++ php-5.4.5RC1/ext/zip/tests/bug38943.phpt 2012-07-07 15:56:41.422171242 +0200 @@ -27,7 +27,7 @@ array(1) { [0]=> int(1) } -object(myZip)#1 (%d) { +object(myZip)#%d (%d) { ["test":"myZip":private]=> int(0) ["testp"]=> diff -up php-5.4.5RC1/ext/zip/tests/pecl12414.phpt.systzip php-5.4.5RC1/ext/zip/tests/pecl12414.phpt --- php-5.4.5RC1/ext/zip/tests/pecl12414.phpt.systzip 2012-07-04 07:43:14.000000000 +0200 +++ php-5.4.5RC1/ext/zip/tests/pecl12414.phpt 2012-07-07 15:56:41.422171242 +0200 @@ -5,6 +5,8 @@ Bug #12414 ( extracting files from damag /*$ */ if(!extension_loaded('zip')) die('skip'); ?> +--XFAIL-- +Doesn't work with system libzip (zip_readfile could not read from ...) --FILE-- +#else #include "lib/zip.h" +#endif #include "php_streams.h" #include "ext/standard/file.h"