summaryrefslogtreecommitdiff
path: root/ext/zip/php_zip.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/zip/php_zip.c')
-rw-r--r--ext/zip/php_zip.c161
1 files changed, 55 insertions, 106 deletions
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 8faa0cf0f9..79ac46df2b 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -95,99 +95,51 @@ static int le_zip_entry;
# define add_ascii_assoc_long add_assoc_long
#endif
-/* Flatten a path by making a relative path (to .)*/
-static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
-{
- char *path_begin = path;
- size_t i;
-
- if (IS_SLASH(path[0])) {
- return path + 1;
- }
-
- if (path_len < 1 || path == NULL) {
- return NULL;
- }
-
- i = path_len;
-
- while (1) {
- while (i > 0 && !IS_SLASH(path[i])) {
- i--;
- }
-
- if (!i) {
- return path;
- }
-
- if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) {
- /* i is the position of . or :, add 1 for / */
- path_begin = path + i + 1;
- break;
- }
- i--;
- }
-
- return path_begin;
-}
-/* }}} */
-
-#ifdef PHP_ZIP_USE_OO
+#ifdef ZEND_ENGINE_2_1
/* {{{ php_zip_extract_file */
+/* TODO: Simplify it */
static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC)
{
php_stream_statbuf ssb;
struct zip_file *zf;
struct zip_stat sb;
char b[8192];
+
int n, len, ret;
+
php_stream *stream;
+
char *fullpath;
char *file_dirname_fullpath;
char file_dirname[MAXPATHLEN];
size_t dir_len;
+
char *file_basename;
size_t file_basename_len;
int is_dir_only = 0;
- char *path_cleaned;
- size_t path_cleaned_len;
- cwd_state new_state;
- new_state.cwd = (char*)malloc(1);
- new_state.cwd[0] = '\0';
- new_state.cwd_length = 0;
-
- /* Clean/normlize the path and then transform any path (absolute or relative)
- to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
- */
- virtual_file_ex(&new_state, file, NULL, CWD_EXPAND);
- path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
- path_cleaned_len = strlen(path_cleaned);
-
- if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
+ if (file_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
return 0;
}
-
/* it is a directory only, see #40228 */
- if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
+ if (file_len > 1 && file[file_len - 1] == '/') {
len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file);
is_dir_only = 1;
} else {
- memcpy(file_dirname, path_cleaned, path_cleaned_len);
- dir_len = php_dirname(file_dirname, path_cleaned_len);
+ memcpy(file_dirname, file, file_len);
+ dir_len = php_dirname(file_dirname, file_len);
- if (dir_len <= 0 || (dir_len == 1 && file_dirname[0] == '.')) {
- len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
- } else {
+ if (dir_len > 0) {
len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
+ } else {
+ len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
}
- php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (unsigned int *)&file_basename_len TSRMLS_CC);
+ php_basename(file, file_len, NULL, 0, &file_basename, (unsigned int *)&file_basename_len TSRMLS_CC);
if (OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
efree(file_dirname_fullpath);
efree(file_basename);
- free(new_state.cwd);
return 0;
}
}
@@ -206,32 +158,28 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
}
#endif
- ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
+ ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
if (!ret) {
efree(file_dirname_fullpath);
- if (!is_dir_only) {
- efree(file_basename);
- free(new_state.cwd);
- }
+ efree(file_basename);
return 0;
}
}
/* it is a standalone directory, job done */
- if (is_dir_only) {
+ if (file[file_len - 1] == '/') {
efree(file_dirname_fullpath);
- free(new_state.cwd);
+ if (!is_dir_only) {
+ efree(file_basename);
+ }
return 1;
}
- len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, file_basename);
+ len = spprintf(&fullpath, 0, "%s/%s/%s", dest, file_dirname, file_basename);
if (!len) {
efree(file_dirname_fullpath);
efree(file_basename);
- free(new_state.cwd);
return 0;
- } else if (len > MAXPATHLEN) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
}
/* check again the full path, not sure if it
@@ -239,10 +187,8 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
* safemode status as its parent folder?
*/
if (OPENBASEDIR_CHECKPATH(fullpath)) {
- efree(fullpath);
efree(file_dirname_fullpath);
efree(file_basename);
- free(new_state.cwd);
return 0;
}
@@ -251,10 +197,8 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
efree(fullpath);
efree(file_dirname_fullpath);
efree(file_basename);
- free(new_state.cwd);
return 0;
}
-
#if (PHP_MAJOR_VERSION < 6)
stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
#else
@@ -270,7 +214,6 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
efree(fullpath);
efree(file_basename);
efree(file_dirname_fullpath);
- free(new_state.cwd);
if (n<0) {
return 0;
@@ -529,7 +472,10 @@ int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value
/* we assume that any glob pattern will match files from one directory only
so checking the dirname of the first match should be sufficient */
strncpy(cwd, globbuf.gl_pathv[0], MAXPATHLEN);
- if (OPENBASEDIR_CHECKPATH(cwd)) {
+ if (PG(safe_mode) && (!php_checkuid(cwd, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
+ return -1;
+ }
+ if (php_check_open_basedir(cwd TSRMLS_CC)) {
return -1;
}
@@ -591,10 +537,14 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
}
#endif
- if (OPENBASEDIR_CHECKPATH(path)) {
+ /* we assume that any glob pattern will match files from one directory only
+ so checking the dirname of the first match should be sufficient */
+ if (PG(safe_mode) && (!php_checkuid(path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
+ return -1;
+ }
+ if (php_check_open_basedir(path TSRMLS_CC)) {
return -1;
}
-
files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
if (files_cnt > 0) {
@@ -665,52 +615,62 @@ int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *r
#endif
/* {{{ arginfo */
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_close, 0, 0, 1)
ZEND_ARG_INFO(0, zip)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_read, 0, 0, 1)
ZEND_ARG_INFO(0, zip)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_open, 0, 0, 2)
ZEND_ARG_INFO(0, zip_dp)
ZEND_ARG_INFO(0, zip_entry)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_close, 0, 0, 1)
ZEND_ARG_INFO(0, zip_ent)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_read, 0, 0, 1)
ZEND_ARG_INFO(0, zip_entry)
ZEND_ARG_INFO(0, len)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_name, 0, 0, 1)
ZEND_ARG_INFO(0, zip_entry)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressedsize, 0, 0, 1)
ZEND_ARG_INFO(0, zip_entry)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_filesize, 0, 0, 1)
ZEND_ARG_INFO(0, zip_entry)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressionmethod, 0, 0, 1)
ZEND_ARG_INFO(0, zip_entry)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ zend_function_entry */
-static const zend_function_entry zip_functions[] = {
+static zend_function_entry zip_functions[] = {
ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0)
ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0)
ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0)
@@ -727,7 +687,7 @@ static const zend_function_entry zip_functions[] = {
/* }}} */
/* {{{ ZE2 OO definitions */
-#ifdef PHP_ZIP_USE_OO
+#ifdef ZEND_ENGINE_2_1
static zend_class_entry *zip_class_entry;
static zend_object_handlers zip_object_handlers;
@@ -747,7 +707,7 @@ typedef struct _zip_prop_handler {
#endif
/* }}} */
-#ifdef PHP_ZIP_USE_OO
+#ifdef ZEND_ENGINE_2_1
static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, zip_read_int_t read_int_func, zip_read_const_char_t read_char_func, zip_read_const_char_from_ze_t read_char_from_obj_func, int rettype TSRMLS_DC) /* {{{ */
{
zip_prop_handler hnd;
@@ -1131,7 +1091,6 @@ static PHP_NAMED_FUNCTION(zif_zip_open)
{
char *filename;
int filename_len;
- char resolved_path[MAXPATHLEN + 1];
zip_rsrc *rsrc_int;
int err = 0;
@@ -1139,22 +1098,13 @@ static PHP_NAMED_FUNCTION(zif_zip_open)
return;
}
- if (filename_len == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
- RETURN_FALSE;
- }
-
if (OPENBASEDIR_CHECKPATH(filename)) {
RETURN_FALSE;
}
- if(!expand_filepath(filename, resolved_path TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
- rsrc_int->za = zip_open(resolved_path, 0, &err);
+ rsrc_int->za = zip_open(filename, 0, &err);
if (rsrc_int->za == NULL) {
efree(rsrc_int);
RETURN_LONG((long)err);
@@ -1234,8 +1184,8 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_open)
{
zval * zip;
zval * zip_entry;
- char *mode = NULL;
- int mode_len = 0;
+ char *mode;
+ int mode_len;
zip_read_rsrc * zr_rsrc;
zip_rsrc *z_rsrc;
@@ -1404,7 +1354,7 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
}
/* }}} */
-#ifdef PHP_ZIP_USE_OO
+#ifdef ZEND_ENGINE_2_1
/* {{{ proto mixed ZipArchive::open(string source [, int flags])
Create new zip using source uri for output, return TRUE on success or the error code */
static ZIPARCHIVE_METHOD(open)
@@ -1452,7 +1402,6 @@ static ZIPARCHIVE_METHOD(open)
efree(ze_obj->filename);
ze_obj->filename = NULL;
}
-
intern = zip_open(resolved_path, flags, &err);
if (!intern || err) {
RETURN_LONG((long)err);
@@ -1537,11 +1486,11 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
&dirname, &dirname_len) == FAILURE) {
return;
}
-
if (dirname_len<1) {
RETURN_FALSE;
}
+
if (dirname[dirname_len-1] != '/') {
s=(char *)emalloc(dirname_len+2);
strcpy(s, dirname);
@@ -1572,10 +1521,10 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
struct zip *intern;
zval *this = getThis();
char *pattern;
- char *path = NULL;
+ char *path;
char *remove_path = NULL;
char *add_path = NULL;
- int pattern_len, add_path_len, remove_path_len, path_len = 0;
+ int pattern_len, add_path_len, remove_path_len, path_len;
long remove_all_path = 0;
long flags = 0;
zval *options = NULL;
@@ -2364,7 +2313,7 @@ static ZIPARCHIVE_METHOD(extractTo)
}
ZIP_FROM_OBJECT(intern, this);
- if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) {
+ if (zval_files) {
switch (Z_TYPE_P(zval_files)) {
case IS_STRING:
if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files) TSRMLS_CC)) {
@@ -2411,6 +2360,7 @@ static ZIPARCHIVE_METHOD(extractTo)
}
}
}
+
RETURN_TRUE;
}
/* }}} */
@@ -2470,7 +2420,6 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
buffer = safe_emalloc(len, 1, 2);
n = zip_fread(zf, buffer, len);
if (n < 1) {
- efree(buffer);
RETURN_EMPTY_STRING();
}
@@ -2572,7 +2521,7 @@ static const zend_function_entry zip_class_functions[] = {
/* {{{ PHP_MINIT_FUNCTION */
static PHP_MINIT_FUNCTION(zip)
{
-#ifdef PHP_ZIP_USE_OO
+#ifdef ZEND_ENGINE_2_1
zend_class_entry ce;
memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
@@ -2655,7 +2604,7 @@ static PHP_MINIT_FUNCTION(zip)
*/
static PHP_MSHUTDOWN_FUNCTION(zip)
{
-#ifdef PHP_ZIP_USE_OO
+#ifdef ZEND_ENGINE_2_1
zend_hash_destroy(&zip_prop_handlers);
php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
#endif