]> granicus.if.org Git - php/commitdiff
add lastId property to ZipArchive
authorRemi Collet <remi@remirepo.net>
Wed, 4 Mar 2020 14:29:59 +0000 (15:29 +0100)
committerRemi Collet <remi@php.net>
Wed, 4 Mar 2020 14:31:06 +0000 (15:31 +0100)
ext/zip/php_zip.c
ext/zip/php_zip.h
ext/zip/tests/bug11216.phpt
ext/zip/tests/bug38943.phpt
ext/zip/tests/bug38943_2.phpt
ext/zip/tests/bug38944.phpt
ext/zip/tests/oo_addemptydir.phpt
ext/zip/tests/oo_addfile.phpt
ext/zip/tests/oo_setcomment.phpt

index 634219000fad43bda3d98a9256c007669dd325eb..ed562eae6d7968e05f371c4e3d3168ee809a3c8f 100644 (file)
@@ -275,7 +275,7 @@ done:
 }
 /* }}} */
 
-static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len,
+static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t filename_len,
        char *entry_name, size_t entry_name_len, /* unused if replace >= 0 */
        zip_uint64_t offset_start, zip_uint64_t offset_len,
        zend_long replace, /* index to replace, add new file if < 0 */
@@ -300,25 +300,26 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam
                return -1;
        }
 
-       zs = zip_source_file(za, resolved_path, offset_start, offset_len);
+       zs = zip_source_file(obj->za, resolved_path, offset_start, offset_len);
        if (!zs) {
                return -1;
        }
        // Replace
        if (replace >= 0) {
-               if (zip_file_replace(za, replace, zs, flags) < 0) {
+               if (zip_file_replace(obj->za, replace, zs, flags) < 0) {
                        zip_source_free(zs);
                        return -1;
                }
-               zip_error_clear(za);
+               zip_error_clear(obj->za);
                return 1;
        }
        // Add
-       if (zip_file_add(za, entry_name, zs, flags) < 0) {
+       obj->last_id = zip_file_add(obj->za, entry_name, zs, flags);
+       if (obj->last_id < 0) {
                zip_source_free(zs);
                return -1;
        }
-       zip_error_clear(za);
+       zip_error_clear(obj->za);
        return 1;
 }
 /* }}} */
@@ -433,17 +434,17 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path,
 #endif
 /* }}} */
 
-static zend_long php_zip_status(struct zip *za) /* {{{ */
+static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */
 {
 #if LIBZIP_VERSION_MAJOR < 1
        int zep, syp;
 
-       zip_error_get(za, &zep, &syp);
+       zip_error_get(obj->za, &zep, &syp);
 #else
        int zep;
        zip_error_t *err;
 
-       err = zip_get_error(za);
+       err = zip_get_error(obj->za);
        zep = zip_error_code_zip(err);
        zip_error_fini(err);
 #endif
@@ -451,17 +452,23 @@ static zend_long php_zip_status(struct zip *za) /* {{{ */
 }
 /* }}} */
 
-static zend_long php_zip_status_sys(struct zip *za) /* {{{ */
+static zend_long php_zip_last_id(ze_zip_object *obj) /* {{{ */
+{
+       return obj->last_id;
+}
+/* }}} */
+
+static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */
 {
 #if LIBZIP_VERSION_MAJOR < 1
        int zep, syp;
 
-       zip_error_get(za, &zep, &syp);
+       zip_error_get(obj->za, &zep, &syp);
 #else
        int syp;
        zip_error_t *err;
 
-       err = zip_get_error(za);
+       err = zip_get_error(obj->za);
        syp = zip_error_code_system(err);
        zip_error_fini(err);
 #endif
@@ -469,31 +476,27 @@ static zend_long php_zip_status_sys(struct zip *za) /* {{{ */
 }
 /* }}} */
 
-static zend_long php_zip_get_num_files(struct zip *za) /* {{{ */
+static zend_long php_zip_get_num_files(ze_zip_object *obj) /* {{{ */
 {
-       zip_int64_t num = zip_get_num_entries(za, 0);
+       zip_int64_t num = zip_get_num_entries(obj->za, 0);
        return MIN(num, ZEND_LONG_MAX);
 }
 /* }}} */
 
-static char * php_zipobj_get_filename(ze_zip_object *obj) /* {{{ */
+static char * php_zipobj_get_filename(ze_zip_object *obj, int *len) /* {{{ */
 {
-
-       if (!obj) {
-               return NULL;
-       }
-
-       if (obj->filename) {
+       if (obj && obj->filename) {
+               *len = strlen(obj->filename);
                return obj->filename;
        }
        return NULL;
 }
 /* }}} */
 
-static char * php_zipobj_get_zip_comment(struct zip *za, int *len) /* {{{ */
+static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */
 {
-       if (za) {
-               return (char *)zip_get_archive_comment(za, len, 0);
+       if (obj->za) {
+               return (char *)zip_get_archive_comment(obj->za, len, 0);
        }
        return NULL;
 }
@@ -764,20 +767,18 @@ static zend_object_handlers zip_object_handlers;
 
 static HashTable zip_prop_handlers;
 
-typedef zend_long (*zip_read_int_t)(struct zip *za);
-typedef char *(*zip_read_const_char_t)(struct zip *za, int *len);
-typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj);
+typedef zend_long (*zip_read_int_t)(ze_zip_object *obj);
+typedef char *(*zip_read_const_char_t)(ze_zip_object *obj, int *len);
 
 typedef struct _zip_prop_handler {
        zip_read_int_t read_int_func;
        zip_read_const_char_t read_const_char_func;
-       zip_read_const_char_from_ze_t read_const_char_from_obj_func;
 
        int type;
 } zip_prop_handler;
 /* }}} */
 
-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) /* {{{ */
+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, int rettype) /* {{{ */
 {
        zip_prop_handler hnd;
        zend_string *str;
@@ -785,7 +786,6 @@ static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, z
 
        hnd.read_const_char_func = read_char_func;
        hnd.read_int_func = read_int_func;
-       hnd.read_const_char_from_obj_func = read_char_from_obj_func;
        hnd.type = rettype;
        str = zend_string_init_interned(name, strlen(name), 1);
        zend_hash_add_mem(prop_handler, str, &hnd, sizeof(zip_prop_handler));
@@ -805,20 +805,9 @@ static zval *php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd,
 
        if (obj && obj->za != NULL) {
                if (hnd->read_const_char_func) {
-                       retchar = hnd->read_const_char_func(obj->za, &len);
-               } else {
-                       if (hnd->read_int_func) {
-                               retint = hnd->read_int_func(obj->za);
-                               if (retint == -1) {
-                                       php_error_docref(NULL, E_WARNING, "Internal zip error returned");
-                                       return NULL;
-                               }
-                       } else {
-                               if (hnd->read_const_char_from_obj_func) {
-                                       retchar = hnd->read_const_char_from_obj_func(obj);
-                                       len = strlen(retchar);
-                               }
-                       }
+                       retchar = hnd->read_const_char_func(obj, &len);
+               } else if (hnd->read_int_func) {
+                       retint = hnd->read_int_func(obj);
                }
        }
 
@@ -1037,6 +1026,7 @@ static zend_object *php_zip_object_new(zend_class_entry *class_type) /* {{{ */
        zend_object_std_init(&intern->zo, class_type);
        object_properties_init(&intern->zo, class_type);
        intern->zo.handlers = &zip_object_handlers;
+       intern->last_id = -1;
 
        return &intern->zo;
 }
@@ -1579,8 +1569,6 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
        zval *self = ZEND_THIS;
        char *dirname;
        size_t   dirname_len;
-       int idx;
-       struct zip_stat sb;
        char *s;
        zend_long flags = 0;
 
@@ -1604,16 +1592,11 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
                s = dirname;
        }
 
-       idx = zip_stat(intern, s, 0, &sb);
-       if (idx >= 0) {
+       if ((Z_ZIP_P(self)->last_id = zip_dir_add(intern, (const char *)s, flags)) == -1) {
                RETVAL_FALSE;
        } else {
-               if (zip_dir_add(intern, (const char *)s, flags) == -1) {
-                       RETVAL_FALSE;
-               } else {
-                       zip_error_clear(intern);
-                       RETVAL_TRUE;
-               }
+               zip_error_clear(intern);
+               RETVAL_TRUE;
        }
 
        if (s != dirname) {
@@ -1624,7 +1607,6 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
 
 static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
 {
-       struct zip *intern;
        zval *self = ZEND_THIS;
        char *path = ".";
        char *remove_path = NULL, *save_remove_path;
@@ -1637,7 +1619,6 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
        int found;
        zend_string *pattern;
 
-       ZIP_FROM_OBJECT(intern, self);
        /* 1 == glob, 2 == pcre */
        if (type == 1) {
                if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|la",
@@ -1717,7 +1698,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
                                        basename = NULL;
                                }
 
-                               if (php_zip_add_file(intern, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file),
+                               if (php_zip_add_file(Z_ZIP_P(self), Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file),
                                        entry_name, entry_name_len, 0, 0, -1, zip_flags) < 0) {
                                        zend_array_destroy(Z_ARR_P(return_value));
                                        RETURN_FALSE;
@@ -1751,7 +1732,6 @@ static ZIPARCHIVE_METHOD(addPattern)
 Add a file in a Zip archive using its path and the name to use. */
 static ZIPARCHIVE_METHOD(addFile)
 {
-       struct zip *intern;
        zval *self = ZEND_THIS;
        char *entry_name = NULL;
        size_t entry_name_len = 0;
@@ -1759,8 +1739,6 @@ static ZIPARCHIVE_METHOD(addFile)
        zend_string *filename;
        zend_long flags = ZIP_FL_OVERWRITE;
 
-       ZIP_FROM_OBJECT(intern, self);
-
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|slll",
                        &filename, &entry_name, &entry_name_len, &offset_start, &offset_len, &flags) == FAILURE) {
                RETURN_THROWS();
@@ -1776,7 +1754,7 @@ static ZIPARCHIVE_METHOD(addFile)
                entry_name_len = ZSTR_LEN(filename);
        }
 
-       if (php_zip_add_file(intern, ZSTR_VAL(filename), ZSTR_LEN(filename),
+       if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
                        entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) {
                RETURN_FALSE;
        } else {
@@ -1789,15 +1767,12 @@ static ZIPARCHIVE_METHOD(addFile)
 Add a file in a Zip archive using its path and the name to use. */
 static ZIPARCHIVE_METHOD(replaceFile)
 {
-       struct zip *intern;
        zval *self = ZEND_THIS;
        zend_long index;
        zend_long offset_start = 0, offset_len = 0;
        zend_string *filename;
        zend_long flags = 0;
 
-       ZIP_FROM_OBJECT(intern, self);
-
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "Pl|lll",
                        &filename, &index, &offset_start, &offset_len, &flags) == FAILURE) {
                RETURN_THROWS();
@@ -1813,7 +1788,7 @@ static ZIPARCHIVE_METHOD(replaceFile)
                RETURN_FALSE;
        }
 
-       if (php_zip_add_file(intern, ZSTR_VAL(filename), ZSTR_LEN(filename),
+       if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
                        NULL, 0, offset_start, offset_len, index, flags) < 0) {
                RETURN_FALSE;
        } else {
@@ -1861,7 +1836,8 @@ static ZIPARCHIVE_METHOD(addFromString)
                RETURN_FALSE;
        }
 
-       if (zip_file_add(intern, name, zs, flags) == -1) {
+       ze_obj->last_id = zip_file_add(intern, name, zs, flags);
+       if (ze_obj->last_id == -1) {
                zip_source_free(zs);
                RETURN_FALSE;
        } else {
@@ -3069,11 +3045,12 @@ static PHP_MINIT_FUNCTION(zip)
        zip_class_entry = zend_register_internal_class(&ce);
 
        zend_hash_init(&zip_prop_handlers, 0, NULL, php_zip_free_prop_handler, 1);
-       php_zip_register_prop_handler(&zip_prop_handlers, "status",    php_zip_status, NULL, NULL, IS_LONG);
-       php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG);
-       php_zip_register_prop_handler(&zip_prop_handlers, "numFiles",  php_zip_get_num_files, NULL, NULL, IS_LONG);
-       php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING);
-       php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING);
+       php_zip_register_prop_handler(&zip_prop_handlers, "lastId",    php_zip_last_id, NULL, IS_LONG);
+       php_zip_register_prop_handler(&zip_prop_handlers, "status",    php_zip_status, NULL, IS_LONG);
+       php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, IS_LONG);
+       php_zip_register_prop_handler(&zip_prop_handlers, "numFiles",  php_zip_get_num_files, NULL, IS_LONG);
+       php_zip_register_prop_handler(&zip_prop_handlers, "filename",  NULL, php_zipobj_get_filename, IS_STRING);
+       php_zip_register_prop_handler(&zip_prop_handlers, "comment",   NULL, php_zipobj_get_zip_comment, IS_STRING);
        zend_class_implements(zip_class_entry, 1, zend_ce_countable);
 
        REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
index 96390e025a185babefef4a9bfe65732dc9cb9678..f28937ebe266f9b7ea53aaeeab3783183cafdb39 100644 (file)
@@ -59,13 +59,14 @@ typedef struct _ze_zip_object {
        char *filename;
        int filename_len;
        int buffers_cnt;
-       zend_object zo;
+       zip_int64_t last_id;
 #ifdef HAVE_PROGRESS_CALLBACK
        zval progress_callback;
 #endif
 #ifdef HAVE_CANCEL_CALLBACK
        zval cancel_callback;
 #endif
+       zend_object zo;
 } ze_zip_object;
 
 static inline ze_zip_object *php_zip_fetch_object(zend_object *obj) {
index e6f76af2187d8dcd10d740706b8573bba181d8ee..a32e42d4e423302f8bd896340bfd14ab37aa761c 100644 (file)
@@ -18,6 +18,7 @@ unlink('__test.zip');
 bool(true)
 ZipArchive Object
 (
+    [lastId] => 0
     [status] => 0
     [statusSys] => 0
     [numFiles] => 1
index ffd0f8dc1649848d5e76996125a3f302e46374fc..e2819d0948a15735f224b2147ed21570104e8035 100644 (file)
@@ -37,6 +37,8 @@ object(myZip)#1 (%d) {
     [0]=>
     int(1)
   }
+  ["lastId"]=>
+  int(0)
   ["status"]=>
   int(0)
   ["statusSys"]=>
index 01147a1825d4b0aaac1998b178e877d606c4a867..0b6612f254fdcec187b9f8b2427c3b4e368e7a25 100644 (file)
@@ -23,6 +23,8 @@ object(myZip)#1 (%d) {
     [0]=>
     int(1)
   }
+  ["lastId"]=>
+  int(0)
   ["status"]=>
   int(0)
   ["statusSys"]=>
index d016fa6268aaa4efdae5aa39b6c8391e660bce0d..b47d06daa8b946256b1556c9926ef82cf4f6b683 100644 (file)
@@ -25,7 +25,9 @@ int(0)
 int(0)
 string(%d) "%s"
 string(0) ""
-object(ZipArchive)#%d (5) {
+object(ZipArchive)#%d (6) {
+  ["lastId"]=>
+  int(-1)
   ["status"]=>
   int(0)
   ["statusSys"]=>
index 1a95662b15cf1b7c328c3f1d8081436d78189364..901af852010c7c89ff360297e1c550d895486d35 100644 (file)
@@ -18,7 +18,13 @@ if (!$zip->open($file)) {
     exit('failed');
 }
 
+var_dump($zip->lastId); // -1 (nothing added)
 $zip->addEmptyDir('emptydir');
+var_dump($zip->lastId); // 4
+$zip->addEmptyDir('emptydir');
+var_dump($zip->lastId); // -1 (already exists)
+$zip->addEmptyDir('emptydir', ZipArchive::FL_OVERWRITE);
+var_dump($zip->lastId); // 4
 if ($zip->status == ZIPARCHIVE::ER_OK) {
     if (!verify_entries($zip, [
         "bar",
@@ -38,4 +44,8 @@ if ($zip->status == ZIPARCHIVE::ER_OK) {
 @unlink($file);
 ?>
 --EXPECT--
+int(-1)
+int(4)
+int(-1)
+int(4)
 OK
index 5ee47256ce0d7fad763d5a249733022a25879f98..4ca302a5eb5d1baae69ee0b2a0939e1ec59f7cb2 100644 (file)
@@ -17,12 +17,15 @@ $zip = new ZipArchive;
 if (!$zip->open($file)) {
     exit('failed');
 }
+var_dump($zip->lastId);
 if (!$zip->addFile($dirname . 'utils.inc', 'test.php')) {
     echo "failed\n";
 }
+var_dump($zip->lastId);
 if (!$zip->addFile($dirname . 'utils.inc', 'mini.txt', 12, 34)) {
        echo "failed\n";
 }
+var_dump($zip->lastId);
 if ($zip->status == ZIPARCHIVE::ER_OK) {
     if (!verify_entries($zip, [
         "bar",
@@ -48,6 +51,9 @@ var_dump(strlen($zip->getFromName('mini.txt')) == 34);
 @unlink($file);
 ?>
 --EXPECT--
+int(-1)
+int(4)
+int(5)
 OK
 bool(true)
 bool(true)
index 4518e68647313c2516511799e00c39bed121375f..5e1975be3f5d5aa5c3328fdd0f89e83ebfd5cf3b 100644 (file)
@@ -21,7 +21,9 @@ $zip->addFromString('entry1.txt', 'entry #1');
 $zip->addFromString('entry2.txt', 'entry #2');
 $zip->addFromString('dir/entry2d.txt', 'entry #2');
 $zip->addFromString('entry4.txt', 'entry #1');
+var_dump($zip->setCommentIndex($zip->lastId, 'entry4.txt'));
 $zip->addFromString('entry5.txt', 'entry #2');
+var_dump($zip->setCommentIndex($zip->lastId, 'entry5.txt'));
 
 
 var_dump($zip->setCommentName('entry1.txt', 'entry1.txt'));
@@ -29,8 +31,6 @@ var_dump($zip->setCommentName('entry2.txt', 'entry2.txt'));
 var_dump($zip->setCommentName('dir/entry2d.txt', 'dir/entry2d.txt'));
 var_dump($zip->setArchiveComment('archive'));
 
-var_dump($zip->setCommentIndex(3, 'entry4.txt'));
-var_dump($zip->setCommentIndex(4, 'entry5.txt'));
 var_dump($zip->setArchiveComment('archive'));
 
 if (!$zip->status == ZIPARCHIVE::ER_OK) {