Skip to content

Commit c5eb818

Browse files
committed
ext/zip: add ZipArchive::openBuffer method
Signed-off-by: Soner Sayakci <[email protected]>
1 parent 03e2613 commit c5eb818

File tree

5 files changed

+94
-5
lines changed

5 files changed

+94
-5
lines changed

ext/zip/php_zip.c

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,47 @@ PHP_METHOD(ZipArchive, open)
14831483
}
14841484
/* }}} */
14851485

1486+
/* {{{ Create new read-only zip using given buffer */
1487+
PHP_METHOD(ZipArchive, openBuffer)
1488+
{
1489+
struct zip *intern;
1490+
zend_string *buffer;
1491+
zval *self = ZEND_THIS;
1492+
ze_zip_object *ze_obj;
1493+
1494+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &buffer) == FAILURE) {
1495+
RETURN_THROWS();
1496+
}
1497+
1498+
zip_error_t err;
1499+
zip_error_init(&err);
1500+
1501+
zip_source_t * zip_source = zip_source_buffer_create(ZSTR_VAL(buffer), ZSTR_LEN(buffer), 0, &err);
1502+
1503+
if (!zip_source) {
1504+
zend_throw_error(NULL, "Cannot open zip: %s", zip_error_strerror(&err));
1505+
zip_error_fini(&err);
1506+
RETURN_THROWS();
1507+
}
1508+
1509+
ze_obj = Z_ZIP_P(self);
1510+
1511+
intern = zip_open_from_source(zip_source, ZIP_RDONLY, &err);
1512+
if (!intern) {
1513+
zip_source_free(zip_source);
1514+
zend_throw_error(NULL, "Cannot open zip: %s", zip_error_strerror(&err));
1515+
zip_error_fini(&err);
1516+
RETURN_THROWS();
1517+
}
1518+
1519+
zip_source_keep(zip_source);
1520+
zip_error_fini(&err);
1521+
1522+
ze_obj->za = intern;
1523+
ze_obj->source = zip_source;
1524+
}
1525+
/* }}} */
1526+
14861527
/* {{{ Set the password for the active archive */
14871528
PHP_METHOD(ZipArchive, setPassword)
14881529
{
@@ -1548,12 +1589,22 @@ PHP_METHOD(ZipArchive, close)
15481589
ze_obj->err_sys = 0;
15491590
}
15501591

1551-
/* clear cache as empty zip are not created but deleted */
1552-
php_clear_stat_cache(1, ze_obj->filename, ze_obj->filename_len);
1592+
// if we have a filename, we need to free it
1593+
if (ze_obj->filename) {
1594+
/* clear cache as empty zip are not created but deleted */
1595+
php_clear_stat_cache(1, ze_obj->filename, ze_obj->filename_len);
1596+
1597+
efree(ze_obj->filename);
1598+
ze_obj->filename = NULL;
1599+
ze_obj->filename_len = 0;
1600+
}
1601+
1602+
if (ze_obj->source) {
1603+
zip_source_close(ze_obj->source);
1604+
zip_source_free(ze_obj->source);
1605+
ze_obj->source = NULL;
1606+
}
15531607

1554-
efree(ze_obj->filename);
1555-
ze_obj->filename = NULL;
1556-
ze_obj->filename_len = 0;
15571608
ze_obj->za = NULL;
15581609

15591610
if (!err) {

ext/zip/php_zip.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ typedef struct _ze_zip_read_rsrc {
6868
/* Extends zend object */
6969
typedef struct _ze_zip_object {
7070
struct zip *za;
71+
zip_source_t *source;
7172
char **buffers;
7273
HashTable *prop_handler;
7374
char *filename;

ext/zip/php_zip.stub.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,9 @@ class ZipArchive implements Countable
648648
/** @tentative-return-type */
649649
public function open(string $filename, int $flags = 0): bool|int {}
650650

651+
/** @tentative-return-type */
652+
public function openBuffer(string $data): void {}
653+
651654
/**
652655
* @tentative-return-type
653656
*/

ext/zip/php_zip_arginfo.h

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
ZipArchive::openBuffer() method
3+
--EXTENSIONS--
4+
zip
5+
--FILE--
6+
<?php
7+
$zip = new ZipArchive();
8+
$zip->openBuffer(file_get_contents(__DIR__."/test_procedural.zip"));
9+
10+
for ($i = 0; $i < $zip->numFiles; $i++) {
11+
$stat = $zip->statIndex($i);
12+
echo $stat['name'] . "\n";
13+
}
14+
15+
// Zip is read-only, not allowed
16+
var_dump($zip->addFromString("foobar/baz", "baz"));
17+
var_dump($zip->addEmptyDir("blub"));
18+
19+
var_dump($zip->close());
20+
?>
21+
--EXPECTF--
22+
foo
23+
bar
24+
foobar/
25+
foobar/baz
26+
bool(false)
27+
bool(false)
28+
bool(true)

0 commit comments

Comments
 (0)