Skip to content

Commit fb8e221

Browse files
committed
- add ZipArchive::FL_RECOMPRESS, FL_ENCRYPTED, FL_OVERWRITE, FL_LOCAL, FL_CENTRAL constants
- add optional "flags" parameter to ZipArchive::addEmptyDir, addFile and addFromString methods - add "flags" options to ZipArchive::addGlob and addPattern methods keeping previous behavior having FL_OVERWRITE by default - add ZipArchive::replaceFile() method
1 parent c932db8 commit fb8e221

File tree

9 files changed

+305
-49
lines changed

9 files changed

+305
-49
lines changed

ext/zip/php_zip.c

Lines changed: 96 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,11 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, size_t
276276
/* }}} */
277277

278278
static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len,
279-
char *entry_name, size_t entry_name_len, long offset_start, long offset_len) /* {{{ */
279+
char *entry_name, size_t entry_name_len, /* unused if replace >= 0 */
280+
zip_uint64_t offset_start, zip_uint64_t offset_len,
281+
zend_long replace, /* index to replace, add new file if < 0 */
282+
zip_flags_t flags
283+
) /* {{{ */
280284
{
281285
struct zip_source *zs;
282286
char resolved_path[MAXPATHLEN];
@@ -300,17 +304,30 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam
300304
if (!zs) {
301305
return -1;
302306
}
303-
if (zip_file_add(za, entry_name, zs, ZIP_FL_OVERWRITE) < 0) {
304-
zip_source_free(zs);
305-
return -1;
306-
} else {
307+
// Replace
308+
if (replace >= 0) {
309+
if (zip_file_replace(za, replace, zs, flags) < 0) {
310+
zip_source_free(zs);
311+
return -1;
312+
}
307313
zip_error_clear(za);
308314
return 1;
309315
}
316+
// Add
317+
if (zip_file_add(za, entry_name, zs, flags) < 0) {
318+
zip_source_free(zs);
319+
return -1;
320+
}
321+
zip_error_clear(za);
322+
return 1;
310323
}
311324
/* }}} */
312325

313-
static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char **remove_path, size_t *remove_path_len, char **add_path, size_t *add_path_len) /* {{{ */
326+
static int php_zip_parse_options(zval *options, zend_long *remove_all_path,
327+
char **remove_path, size_t *remove_path_len,
328+
char **add_path, size_t *add_path_len,
329+
zend_long *flags
330+
) /* {{{ */
314331
{
315332
zval *option;
316333
if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) {
@@ -357,6 +374,15 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char
357374
*add_path_len = Z_STRLEN_P(option);
358375
*add_path = Z_STRVAL_P(option);
359376
}
377+
378+
if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "flags", sizeof("flags") - 1)) != NULL) {
379+
if (Z_TYPE_P(option) != IS_LONG) {
380+
php_error_docref(NULL, E_WARNING, "flags option expected to be a integer");
381+
return -1;
382+
}
383+
*flags = Z_LVAL_P(option);
384+
}
385+
360386
return 1;
361387
}
362388
/* }}} */
@@ -1545,7 +1571,7 @@ static ZIPARCHIVE_METHOD(getStatusString)
15451571
}
15461572
/* }}} */
15471573

1548-
/* {{{ proto bool ZipArchive::createEmptyDir(string dirname)
1574+
/* {{{ proto bool ZipArchive::addEmptyDir(string dirname [, bool flags = 0])
15491575
Returns the index of the entry named filename in the archive */
15501576
static ZIPARCHIVE_METHOD(addEmptyDir)
15511577
{
@@ -1556,11 +1582,12 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
15561582
int idx;
15571583
struct zip_stat sb;
15581584
char *s;
1585+
zend_long flags = 0;
15591586

15601587
ZIP_FROM_OBJECT(intern, self);
15611588

1562-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
1563-
&dirname, &dirname_len) == FAILURE) {
1589+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l",
1590+
&dirname, &dirname_len, &flags) == FAILURE) {
15641591
RETURN_THROWS();
15651592
}
15661593

@@ -1581,7 +1608,7 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
15811608
if (idx >= 0) {
15821609
RETVAL_FALSE;
15831610
} else {
1584-
if (zip_dir_add(intern, (const char *)s, 0) == -1) {
1611+
if (zip_dir_add(intern, (const char *)s, flags) == -1) {
15851612
RETVAL_FALSE;
15861613
} else {
15871614
zip_error_clear(intern);
@@ -1604,7 +1631,8 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
16041631
char *add_path = NULL;
16051632
size_t add_path_len, remove_path_len = 0, path_len = 1;
16061633
zend_long remove_all_path = 0;
1607-
zend_long flags = 0;
1634+
zend_long glob_flags = 0;
1635+
zend_long zip_flags = ZIP_FL_OVERWRITE;
16081636
zval *options = NULL;
16091637
int found;
16101638
zend_string *pattern;
@@ -1613,7 +1641,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
16131641
/* 1 == glob, 2 == pcre */
16141642
if (type == 1) {
16151643
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|la",
1616-
&pattern, &flags, &options) == FAILURE) {
1644+
&pattern, &glob_flags, &options) == FAILURE) {
16171645
RETURN_THROWS();
16181646
}
16191647
} else {
@@ -1628,7 +1656,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
16281656
RETURN_FALSE;
16291657
}
16301658
if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len,
1631-
&add_path, &add_path_len) < 0)) {
1659+
&add_path, &add_path_len, &zip_flags) < 0)) {
16321660
RETURN_FALSE;
16331661
}
16341662

@@ -1642,7 +1670,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
16421670
}
16431671

16441672
if (type == 1) {
1645-
found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), flags, return_value);
1673+
found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), glob_flags, return_value);
16461674
} else {
16471675
found = php_zip_pcre(pattern, path, path_len, return_value);
16481676
}
@@ -1690,7 +1718,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
16901718
}
16911719

16921720
if (php_zip_add_file(intern, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file),
1693-
entry_name, entry_name_len, 0, 0) < 0) {
1721+
entry_name, entry_name_len, 0, 0, -1, zip_flags) < 0) {
16941722
zend_array_destroy(Z_ARR_P(return_value));
16951723
RETURN_FALSE;
16961724
}
@@ -1719,7 +1747,7 @@ static ZIPARCHIVE_METHOD(addPattern)
17191747
}
17201748
/* }}} */
17211749

1722-
/* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]])
1750+
/* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length [, int flags = FL_OVERWRITE]]]])
17231751
Add a file in a Zip archive using its path and the name to use. */
17241752
static ZIPARCHIVE_METHOD(addFile)
17251753
{
@@ -1729,11 +1757,12 @@ static ZIPARCHIVE_METHOD(addFile)
17291757
size_t entry_name_len = 0;
17301758
zend_long offset_start = 0, offset_len = 0;
17311759
zend_string *filename;
1760+
zend_long flags = ZIP_FL_OVERWRITE;
17321761

17331762
ZIP_FROM_OBJECT(intern, self);
17341763

1735-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|sll",
1736-
&filename, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
1764+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|slll",
1765+
&filename, &entry_name, &entry_name_len, &offset_start, &offset_len, &flags) == FAILURE) {
17371766
RETURN_THROWS();
17381767
}
17391768

@@ -1748,15 +1777,52 @@ static ZIPARCHIVE_METHOD(addFile)
17481777
}
17491778

17501779
if (php_zip_add_file(intern, ZSTR_VAL(filename), ZSTR_LEN(filename),
1751-
entry_name, entry_name_len, offset_start, offset_len) < 0) {
1780+
entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) {
1781+
RETURN_FALSE;
1782+
} else {
1783+
RETURN_TRUE;
1784+
}
1785+
}
1786+
/* }}} */
1787+
1788+
/* {{{ proto bool ZipArchive::replaceFile(string filepath, int index[, int start [, int length [, int flags = 0]]])
1789+
Add a file in a Zip archive using its path and the name to use. */
1790+
static ZIPARCHIVE_METHOD(replaceFile)
1791+
{
1792+
struct zip *intern;
1793+
zval *self = ZEND_THIS;
1794+
zend_long index;
1795+
zend_long offset_start = 0, offset_len = 0;
1796+
zend_string *filename;
1797+
zend_long flags = ZIP_FL_OVERWRITE;
1798+
1799+
ZIP_FROM_OBJECT(intern, self);
1800+
1801+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Pl|lll",
1802+
&filename, &index, &offset_start, &offset_len, &flags) == FAILURE) {
1803+
RETURN_THROWS();
1804+
}
1805+
1806+
if (ZSTR_LEN(filename) == 0) {
1807+
php_error_docref(NULL, E_NOTICE, "Empty string as filename");
1808+
RETURN_FALSE;
1809+
}
1810+
1811+
if (index < 0) {
1812+
php_error_docref(NULL, E_NOTICE, "Invalid negative index");
1813+
RETURN_FALSE;
1814+
}
1815+
1816+
if (php_zip_add_file(intern, ZSTR_VAL(filename), ZSTR_LEN(filename),
1817+
NULL, 0, offset_start, offset_len, index, flags) < 0) {
17521818
RETURN_FALSE;
17531819
} else {
17541820
RETURN_TRUE;
17551821
}
17561822
}
17571823
/* }}} */
17581824

1759-
/* {{{ proto bool ZipArchive::addFromString(string name, string content)
1825+
/* {{{ proto bool ZipArchive::addFromString(string name, string content [, int flags = FL_OVERWRITE])
17601826
Add a file using content and the entry name */
17611827
static ZIPARCHIVE_METHOD(addFromString)
17621828
{
@@ -1768,12 +1834,12 @@ static ZIPARCHIVE_METHOD(addFromString)
17681834
ze_zip_object *ze_obj;
17691835
struct zip_source *zs;
17701836
int pos = 0;
1771-
int cur_idx;
1837+
zend_long flags = ZIP_FL_OVERWRITE;
17721838

17731839
ZIP_FROM_OBJECT(intern, self);
17741840

1775-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS",
1776-
&name, &name_len, &buffer) == FAILURE) {
1841+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS|l",
1842+
&name, &name_len, &buffer, &flags) == FAILURE) {
17771843
RETURN_THROWS();
17781844
}
17791845

@@ -1795,16 +1861,7 @@ static ZIPARCHIVE_METHOD(addFromString)
17951861
RETURN_FALSE;
17961862
}
17971863

1798-
cur_idx = zip_name_locate(intern, (const char *)name, 0);
1799-
/* TODO: fix _zip_replace */
1800-
if (cur_idx >= 0) {
1801-
if (zip_delete(intern, cur_idx) == -1) {
1802-
zip_source_free(zs);
1803-
RETURN_FALSE;
1804-
}
1805-
}
1806-
1807-
if (zip_file_add(intern, name, zs, 0) == -1) {
1864+
if (zip_file_add(intern, name, zs, flags) == -1) {
18081865
zip_source_free(zs);
18091866
RETURN_FALSE;
18101867
} else {
@@ -2939,6 +2996,7 @@ static const zend_function_entry zip_class_functions[] = {
29392996
ZIPARCHIVE_ME(addPattern, arginfo_class_ZipArchive_addPattern, ZEND_ACC_PUBLIC)
29402997
ZIPARCHIVE_ME(renameIndex, arginfo_class_ZipArchive_renameIndex, ZEND_ACC_PUBLIC)
29412998
ZIPARCHIVE_ME(renameName, arginfo_class_ZipArchive_renameName, ZEND_ACC_PUBLIC)
2999+
ZIPARCHIVE_ME(replaceFile, arginfo_class_ZipArchive_replaceFile, ZEND_ACC_PUBLIC)
29423000
ZIPARCHIVE_ME(setArchiveComment, arginfo_class_ZipArchive_setArchiveComment, ZEND_ACC_PUBLIC)
29433001
ZIPARCHIVE_ME(getArchiveComment, arginfo_class_ZipArchive_getArchiveComment, ZEND_ACC_PUBLIC)
29443002
ZIPARCHIVE_ME(setCommentIndex, arginfo_class_ZipArchive_setCommentIndex, ZEND_ACC_PUBLIC)
@@ -3030,23 +3088,18 @@ static PHP_MINIT_FUNCTION(zip)
30303088
REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
30313089
REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
30323090
REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
3091+
REGISTER_ZIP_CLASS_CONST_LONG("FL_RECOMPRESS", ZIP_FL_RECOMPRESS);
3092+
REGISTER_ZIP_CLASS_CONST_LONG("FL_ENCRYPTED", ZIP_FL_ENCRYPTED);
3093+
REGISTER_ZIP_CLASS_CONST_LONG("FL_OVERWRITE", ZIP_FL_OVERWRITE);
3094+
REGISTER_ZIP_CLASS_CONST_LONG("FL_LOCAL", ZIP_FL_LOCAL);
3095+
REGISTER_ZIP_CLASS_CONST_LONG("FL_CENTRAL", ZIP_FL_CENTRAL);
30333096

3034-
#ifdef ZIP_FL_ENC_GUESS
30353097
/* Default filename encoding policy. */
30363098
REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_GUESS", ZIP_FL_ENC_GUESS);
3037-
#endif
3038-
#ifdef ZIP_FL_ENC_RAW
30393099
REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_RAW", ZIP_FL_ENC_RAW);
3040-
#endif
3041-
#ifdef ZIP_FL_ENC_STRICT
30423100
REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_STRICT", ZIP_FL_ENC_STRICT);
3043-
#endif
3044-
#ifdef ZIP_FL_ENC_UTF_8
30453101
REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_UTF_8", ZIP_FL_ENC_UTF_8);
3046-
#endif
3047-
#ifdef ZIP_FL_ENC_CP437
30483102
REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_CP437", ZIP_FL_ENC_CP437);
3049-
#endif
30503103

30513104
REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
30523105
REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);

ext/zip/php_zip.stub.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,16 @@ public function count() {}
5858
public function getStatusString() {}
5959

6060
/** @return bool */
61-
public function addEmptyDir(string $dirname) {}
61+
public function addEmptyDir(string $dirname, int $flags = 0) {}
6262

6363
/** @return bool */
64-
public function addFromString(string $name, string $content) {}
64+
public function addFromString(string $name, string $content, int $flags = ZipArchive::FL_OVERWRITE) {}
6565

6666
/** @return bool */
67-
public function addFile(string $filepath, string $entryname = UNKNOWN, int $start = 0, int $length = 0) {}
67+
public function addFile(string $filepath, string $entryname = UNKNOWN, int $start = 0, int $length = 0, int $flags = ZipArchive::FL_OVERWRITE) {}
68+
69+
/** @return bool */
70+
public function replaceFile(string $filepath, string $index, int $start = 0, int $length = 0, int $flags = 0) {}
6871

6972
/** @return array|false */
7073
public function addGlob(string $pattern, int $flags = 0, $options = UNKNOWN) {}

ext/zip/php_zip_arginfo.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,29 @@ ZEND_END_ARG_INFO()
5757

5858
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_addEmptyDir, 0, 0, 1)
5959
ZEND_ARG_TYPE_INFO(0, dirname, IS_STRING, 0)
60+
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
6061
ZEND_END_ARG_INFO()
6162

6263
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_addFromString, 0, 0, 2)
6364
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0)
6465
ZEND_ARG_TYPE_INFO(0, content, IS_STRING, 0)
66+
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
6567
ZEND_END_ARG_INFO()
6668

6769
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_addFile, 0, 0, 1)
6870
ZEND_ARG_TYPE_INFO(0, filepath, IS_STRING, 0)
6971
ZEND_ARG_TYPE_INFO(0, entryname, IS_STRING, 0)
7072
ZEND_ARG_TYPE_INFO(0, start, IS_LONG, 0)
7173
ZEND_ARG_TYPE_INFO(0, length, IS_LONG, 0)
74+
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
75+
ZEND_END_ARG_INFO()
76+
77+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_replaceFile, 0, 0, 2)
78+
ZEND_ARG_TYPE_INFO(0, filepath, IS_STRING, 0)
79+
ZEND_ARG_TYPE_INFO(0, index, IS_STRING, 0)
80+
ZEND_ARG_TYPE_INFO(0, start, IS_LONG, 0)
81+
ZEND_ARG_TYPE_INFO(0, length, IS_LONG, 0)
82+
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
7283
ZEND_END_ARG_INFO()
7384

7485
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_addGlob, 0, 0, 1)

ext/zip/tests/oo_add_encoding.phpt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
ziparchive::addEmptyDir with encoding option
3+
--SKIPIF--
4+
<?php
5+
/* $Id$ */
6+
if(!extension_loaded('zip')) die('skip');
7+
?>
8+
--FILE--
9+
<?php
10+
11+
include __DIR__ . '/utils.inc';
12+
$dirname = __DIR__ . '/oo_add_encoding_dir/';
13+
$file = $dirname . 'tmp.zip';
14+
15+
@mkdir($dirname);
16+
$zip = new ZipArchive;
17+
if (!$zip->open($file, ZipArchive::CREATE)) {
18+
exit('failed');
19+
}
20+
21+
$zip->addEmptyDir('foo');
22+
$zip->addEmptyDir(chr(0x82), ZipArchive::FL_ENC_CP437);
23+
$zip->addEmptyDir('è', ZipArchive::FL_ENC_UTF_8);
24+
25+
$zip->addFromString('bar', __FILE__);
26+
$zip->addFromString(chr(0x91), __FILE__, ZipArchive::FL_ENC_CP437);
27+
$zip->addFromString('', __FILE__, ZipArchive::FL_ENC_UTF_8);
28+
29+
if ($zip->status == ZIPARCHIVE::ER_OK) {
30+
dump_entries_name($zip);
31+
$zip->close();
32+
} else {
33+
echo "failed\n";
34+
}
35+
?>
36+
--CLEAN--
37+
<?php
38+
$dirname = __DIR__ . '/oo_add_encoding_dir/';
39+
unlink($dirname . 'tmp.zip');
40+
rmdir($dirname);
41+
?>
42+
--EXPECTF--
43+
0 foo/
44+
1 é/
45+
2 è/
46+
3 bar
47+
4 æ
48+
5 €

0 commit comments

Comments
 (0)