summaryrefslogtreecommitdiff
path: root/ext/zip
diff options
context:
space:
mode:
Diffstat (limited to 'ext/zip')
-rw-r--r--ext/zip/config.m430
-rw-r--r--ext/zip/config.w3215
-rw-r--r--ext/zip/examples/encryption.php49
-rw-r--r--ext/zip/lib/mkstemp.c3
-rw-r--r--ext/zip/php_zip.c126
-rw-r--r--ext/zip/php_zip.h2
-rw-r--r--ext/zip/tests/bug38943_2.phpt1
-rw-r--r--ext/zip/tests/oo_encryption.phpt66
-rw-r--r--ext/zip/zip_stream.c13
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 = {