diff options
Diffstat (limited to 'ext/zip')
-rw-r--r-- | ext/zip/config.m4 | 30 | ||||
-rw-r--r-- | ext/zip/config.w32 | 15 | ||||
-rw-r--r-- | ext/zip/examples/encryption.php | 49 | ||||
-rw-r--r-- | ext/zip/lib/mkstemp.c | 3 | ||||
-rw-r--r-- | ext/zip/php_zip.c | 126 | ||||
-rw-r--r-- | ext/zip/php_zip.h | 2 | ||||
-rw-r--r-- | ext/zip/tests/bug38943_2.phpt | 1 | ||||
-rw-r--r-- | ext/zip/tests/oo_encryption.phpt | 66 | ||||
-rw-r--r-- | ext/zip/zip_stream.c | 13 |
9 files changed, 272 insertions, 33 deletions
diff --git a/ext/zip/config.m4 b/ext/zip/config.m4 index bb653c2068..6422b8f593 100644 --- a/ext/zip/config.m4 +++ b/ext/zip/config.m4 @@ -99,10 +99,25 @@ if test "$PHP_ZIP" != "no"; then -L$LIBZIP_LIBDIR ]) + PHP_CHECK_LIBRARY(zip, zip_file_set_encryption, + [ + PHP_ADD_LIBRARY_WITH_PATH(zip, $LIBZIP_LIBDIR, ZIP_SHARED_LIBADD) + AC_DEFINE(HAVE_ENCRYPTION, 1, [Libzip >= 1.2.0 with encryption support]) + ], [ + AC_MSG_WARN(Libzip >= 1.2.0 needed for encryption support) + ], [ + -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 + AC_MSG_WARN(========================================================) + AC_MSG_WARN(Use of bundled libzip is deprecated and will be removed.) + AC_MSG_WARN(Some features such as encryption are not available.) + AC_MSG_WARN(Use system library and --with-libzip is recommended.) + AC_MSG_WARN(========================================================) PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_add_dir.c lib/zip_add_entry.c\ @@ -173,21 +188,6 @@ in 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 fi diff --git a/ext/zip/config.w32 b/ext/zip/config.w32 index 5460b6d6bd..4a4107535d 100644 --- a/ext/zip/config.w32 +++ b/ext/zip/config.w32 @@ -4,7 +4,20 @@ ARG_ENABLE("zip", "ZIP support", "yes"); if (PHP_ZIP != "no") { - if (CHECK_HEADER_ADD_INCLUDE("zlib.h", "CFLAGS_ZIP", "..\\zlib;" + PHP_ZIP) && + if (CHECK_HEADER_ADD_INCLUDE("zip.h", "CFLAGS_ZIP", PHP_PHP_BUILD + "\\include;" + PHP_EXTRA_INCLUDES) && + CHECK_HEADER_ADD_INCLUDE("zipconf.h", "CFLAGS_ZIP", PHP_PHP_BUILD + "\\lib\\libzip\\include;" + PHP_EXTRA_LIBS + "\\libzip\\include;" + PHP_ZIP) && + (PHP_ZIP_SHARED && CHECK_LIB("libzip.lib", "zip", PHP_ZIP) || CHECK_LIB("libzip_a.lib", "zip", PHP_ZIP)) + ) { + EXTENSION('zip', 'php_zip.c zip_stream.c'); + + if (!PHP_ZIP_SHARED) { + AC_DEFINE("ZIP_STATIC", 1); + } + + AC_DEFINE('HAVE_ZIP', 1); + AC_DEFINE('HAVE_LIBZIP', 1); + ADD_FLAG("CFLAGS_ZIP", "/D _WIN32"); + } else if (CHECK_HEADER_ADD_INCLUDE("zlib.h", "CFLAGS_ZIP", "..\\zlib;" + PHP_ZIP) && CHECK_HEADER_ADD_INCLUDE("zipconf.h", "CFLAGS_ZIP", configure_module_dirname + "\\lib;" + PHP_ZIP) && (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib", "zip", PHP_ZIP) || CHECK_LIB("zlib.lib", "zip", PHP_ZIP))) || (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "zip", PHP_ZIP)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED))) diff --git a/ext/zip/examples/encryption.php b/ext/zip/examples/encryption.php new file mode 100644 index 0000000000..69888170a9 --- /dev/null +++ b/ext/zip/examples/encryption.php @@ -0,0 +1,49 @@ +<?php +error_reporting(E_ALL); +if (!extension_loaded('zip')) { + dl('zip.so'); +} + +$name = __DIR__ . '/encrypted.zip'; +$pass = 'secret'; +$file = 'foo.php'; + +echo "== Create with per file password\n"; + +$zip = new ZipArchive; +$zip->open($name, ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE); +$zip->addFile(__FILE__, $file); +$zip->setEncryptionName($file, ZipArchive::EM_AES_256, $pass); +$zip->close(); + +echo "== Create with global password\n"; + +$zip = new ZipArchive; +$zip->open($name, ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE); +$zip->setPassword($pass); +$zip->addFile(__FILE__, $file); +$zip->setEncryptionName($file, ZipArchive::EM_AES_256); +$zip->close(); + +echo "== Stat\n"; + +$zip->open($name); +print_r($zip->statName($file)); + +echo "== Read\n"; + +$zip->setPassword($pass); +$text = $zip->getFromName($file); +printf("Size = %d\n", strlen($text)); +$zip->close(); + +echo "== Stream with context\n"; + +$ctx = stream_context_create(array( + 'zip' => array( + 'password' => $pass + ) +)); +$text = file_get_contents("zip://$name#$file", false, $ctx); +printf("Size = %d\n", strlen($text)); + diff --git a/ext/zip/lib/mkstemp.c b/ext/zip/lib/mkstemp.c index 2ccd3a4878..d1df8a5ca4 100644 --- a/ext/zip/lib/mkstemp.c +++ b/ext/zip/lib/mkstemp.c @@ -43,6 +43,9 @@ #endif #include <stdio.h> #include <stdlib.h> +#ifndef _WIN32 +#include <unistd.h> +#endif #ifndef O_BINARY #define O_BINARY 0 diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 28527cbee1..394819cf34 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -379,6 +379,7 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char /* }}} */ /* {{{ RETURN_SB(sb) */ +#ifdef HAVE_ENCRYPTION #define RETURN_SB(sb) \ { \ array_init(return_value); \ @@ -389,7 +390,21 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \ add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \ add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \ + add_ascii_assoc_long(return_value, "encryption_method", (zend_long) (sb)->encryption_method); \ } +#else +#define RETURN_SB(sb) \ + { \ + array_init(return_value); \ + add_ascii_assoc_string(return_value, "name", (char *)(sb)->name); \ + add_ascii_assoc_long(return_value, "index", (zend_long) (sb)->index); \ + add_ascii_assoc_long(return_value, "crc", (zend_long) (sb)->crc); \ + add_ascii_assoc_long(return_value, "size", (zend_long) (sb)->size); \ + add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \ + add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \ + add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \ + } +#endif /* }}} */ static int php_zip_status(struct zip *za) /* {{{ */ @@ -786,6 +801,9 @@ static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, z hnd.read_const_char_from_obj_func = read_char_from_obj_func; hnd.type = rettype; zend_hash_str_add_mem(prop_handler, name, strlen(name), &hnd, sizeof(zip_prop_handler)); + + /* Register for reflection */ + zend_declare_property_null(zip_class_entry, name, strlen(name), ZEND_ACC_PUBLIC); } /* }}} */ @@ -2222,6 +2240,74 @@ static ZIPARCHIVE_METHOD(getExternalAttributesIndex) /* }}} */ #endif /* ifdef ZIP_OPSYS_DEFAULT */ +#ifdef HAVE_ENCRYPTION +/* {{{ proto bool ZipArchive::setEncryptionName(string name, int method, [string password]) +Set encryption method for file in zip, using its name */ +static ZIPARCHIVE_METHOD(setEncryptionName) +{ + struct zip *intern; + zval *self = getThis(); + zend_long method; + zip_int64_t idx; + char *name, *password = NULL; + size_t name_len, password_len; + + if (!self) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, self); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s", + &name, &name_len, &method, &password, &password_len) == FAILURE) { + return; + } + + if (name_len < 1) { + php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); + } + + idx = zip_name_locate(intern, name, 0); + if (idx < 0) { + RETURN_FALSE; + } + + if (zip_file_set_encryption(intern, idx, (zip_uint16_t)method, password)) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool ZipArchive::setEncryptionIndex(int index, int method, [string password]) +Set encryption method for file in zip, using its index */ +static ZIPARCHIVE_METHOD(setEncryptionIndex) +{ + struct zip *intern; + zval *self = getThis(); + zend_long index, method; + char *password = NULL; + size_t password_len; + + if (!self) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, self); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|s", + &index, &method, &password, &password_len) == FAILURE) { + return; + } + + if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ +#endif + /* {{{ proto string ZipArchive::getCommentName(string name[, int flags]) Returns the comment of an entry using its name */ static ZIPARCHIVE_METHOD(getCommentName) @@ -2952,6 +3038,20 @@ ZEND_END_ARG_INFO() #endif /* ifdef ZIP_OPSYS_DEFAULT */ /* }}} */ +#ifdef HAVE_ENCRYPTION +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setencryption_name, 0, 0, 2) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, method) + ZEND_ARG_INFO(0, password) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setencryption_index, 0, 0, 2) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, method) + ZEND_ARG_INFO(0, password) +ZEND_END_ARG_INFO() +#endif + ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcompname, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, method) @@ -3003,6 +3103,10 @@ static const zend_function_entry zip_class_functions[] = { ZIPARCHIVE_ME(getExternalAttributesIndex, arginfo_ziparchive_getextattrindex, ZEND_ACC_PUBLIC) ZIPARCHIVE_ME(setCompressionName, arginfo_ziparchive_setcompname, ZEND_ACC_PUBLIC) ZIPARCHIVE_ME(setCompressionIndex, arginfo_ziparchive_setcompindex, ZEND_ACC_PUBLIC) +#ifdef HAVE_ENCRYPTION + ZIPARCHIVE_ME(setEncryptionName, arginfo_ziparchive_setencryption_name, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(setEncryptionIndex, arginfo_ziparchive_setencryption_index, ZEND_ACC_PUBLIC) +#endif PHP_FE_END }; /* }}} */ @@ -3047,6 +3151,7 @@ static PHP_MINIT_FUNCTION(zip) REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR); REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED); REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED); + #ifdef ZIP_FL_ENC_GUESS /* Default filename encoding policy. */ REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_GUESS", ZIP_FL_ENC_GUESS); @@ -3064,20 +3169,6 @@ static PHP_MINIT_FUNCTION(zip) REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_CP437", ZIP_FL_ENC_CP437); #endif -/* XXX The below are rather not implemented or to check whether makes sense to expose. */ -/*#ifdef ZIP_FL_RECOMPRESS - REGISTER_ZIP_CLASS_CONST_LONG("FL_RECOMPRESS", ZIP_FL_RECOMPRESS); -#endif -#ifdef ZIP_FL_ENCRYPTED - REGISTER_ZIP_CLASS_CONST_LONG("FL_ENCRYPTED", ZIP_FL_ENCRYPTED); -#endif -#ifdef ZIP_FL_LOCAL - REGISTER_ZIP_CLASS_CONST_LONG("FL_LOCAL", ZIP_FL_LOCAL); -#endif -#ifdef ZIP_FL_CENTRAL - REGISTER_ZIP_CLASS_CONST_LONG("FL_CENTRAL", ZIP_FL_CENTRAL); -#endif */ - REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT); REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE); REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK); @@ -3147,6 +3238,13 @@ static PHP_MINIT_FUNCTION(zip) REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT); #endif /* ifdef ZIP_OPSYS_DEFAULT */ +#ifdef HAVE_ENCRYPTION + REGISTER_ZIP_CLASS_CONST_LONG("EM_NONE", ZIP_EM_NONE); + REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_128", ZIP_EM_AES_128); + REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_192", ZIP_EM_AES_192); + REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_256", ZIP_EM_AES_256); +#endif + php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper); le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number); diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index f886da3400..123c064a33 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -37,7 +37,7 @@ extern zend_module_entry zip_module_entry; #define ZIP_OVERWRITE ZIP_TRUNCATE #endif -#define PHP_ZIP_VERSION "1.13.5" +#define PHP_ZIP_VERSION "1.14.0" #define ZIP_OPENBASEDIR_CHECKPATH(filename) php_check_open_basedir(filename) diff --git a/ext/zip/tests/bug38943_2.phpt b/ext/zip/tests/bug38943_2.phpt index bdbad94517..95722e3532 100644 --- a/ext/zip/tests/bug38943_2.phpt +++ b/ext/zip/tests/bug38943_2.phpt @@ -4,7 +4,6 @@ <?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 diff --git a/ext/zip/tests/oo_encryption.phpt b/ext/zip/tests/oo_encryption.phpt new file mode 100644 index 0000000000..b703611667 --- /dev/null +++ b/ext/zip/tests/oo_encryption.phpt @@ -0,0 +1,66 @@ +--TEST-- +ZipArchive::setEncryption*() functions +--SKIPIF-- +<?php +/* $Id$ */ +if (!extension_loaded('zip')) die('skip'); +if (!method_exists('ZipArchive', 'setEncryptionName')) die('skip encrytion not supported'); +?> +--FILE-- +<?php + +$name = __DIR__ . '/encrypted.zip'; +$pass = 'secret'; + +echo "== Write\n"; +$zip = new ZipArchive; +$r = $zip->open($name, ZIPARCHIVE::CREATE); +// Clear +$zip->addFromString('foo.txt', 'foo'); +// Encrypted +$zip->addFromString('bar.txt', 'bar'); +var_dump($zip->setEncryptionName('bar.txt', 9999, $pass)); // Fails +var_dump($zip->setEncryptionName('bar.txt', ZipArchive::EM_AES_256, $pass)); +$zip->close(); + +echo "== Read\n"; +$r = $zip->open($name); +$s = $zip->statName('foo.txt'); +var_dump($s['encryption_method'] === ZipArchive::EM_NONE); +$s = $zip->statName('bar.txt'); +var_dump($s['encryption_method'] === ZipArchive::EM_AES_256); +var_dump($zip->getFromName('foo.txt')); // Clear, ok +var_dump($zip->getFromName('bar.txt')); // Encrypted, fails +$zip->setPassword($pass); +var_dump($zip->getFromName('bar.txt')); // Ecnrypted, ok +$zip->close(); + +echo "== Stream\n"; +var_dump(file_get_contents("zip://$name#foo.txt")); // Clear, ok +var_dump(file_get_contents("zip://$name#bar.txt")); // Encrypted, fails +$ctx = stream_context_create(array('zip' => array('password' => $pass))); +var_dump(file_get_contents("zip://$name#bar.txt", false, $ctx)); // Ecnrypted, ok +?> +== Done +--CLEAN-- +<?php +$name = __DIR__ . '/encrypted.zip'; +@unlink($name); +?> +--EXPECTF-- +== Write +bool(false) +bool(true) +== Read +bool(true) +bool(true) +string(3) "foo" +bool(false) +string(3) "bar" +== Stream +string(3) "foo" + +Warning: file_get_contents(%s): failed to open stream: operation failed in %s on line %d +bool(false) +string(3) "bar" +== Done diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c index 2fa828a572..8e7dbcf769 100644 --- a/ext/zip/zip_stream.c +++ b/ext/zip/zip_stream.c @@ -30,6 +30,9 @@ #include "ext/standard/url.h" +/* needed for ssize_t definition */ +#include <sys/types.h> + struct php_zip_stream_data_t { struct zip *za; struct zip_file *zf; @@ -309,6 +312,14 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, za = zip_open(file_dirname, ZIP_CREATE, &err); if (za) { + zval *tmpzval; + + if (NULL != (tmpzval = php_stream_context_get_option(context, "zip", "password"))) { + if (Z_TYPE_P(tmpzval) != IS_STRING || zip_set_default_password(za, Z_STRVAL_P(tmpzval))) { + php_error_docref(NULL, E_WARNING, "Can't set zip password"); + } + } + zf = zip_fopen(za, fragment, 0); if (zf) { self = emalloc(sizeof(*self)); @@ -348,7 +359,7 @@ static php_stream_wrapper_ops zip_stream_wops = { NULL, /* rename */ NULL, /* mkdir */ NULL, /* rmdir */ - NULL + NULL /* metadata */ }; php_stream_wrapper php_stream_zip_wrapper = { |