@@ -573,8 +573,10 @@ static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */
573573}
574574/* }}} */
575575
576- /* Close and free the zip_t */
577- static bool php_zipobj_close (ze_zip_object * obj ) /* {{{ */
576+ /* Close and free the zip_t. If out_str is non-null and the archive was opened
577+ * as a string, the final contents of the archive will be assigned to *out_str
578+ * and that string will afterwards be owned by the caller. */
579+ static bool php_zipobj_close (ze_zip_object * obj , zend_string * * out_str ) /* {{{ */
578580{
579581 struct zip * intern = obj -> za ;
580582 bool success = false;
@@ -606,7 +608,19 @@ static bool php_zipobj_close(ze_zip_object *obj) /* {{{ */
606608 obj -> filename_len = 0 ;
607609 }
608610
611+ if (obj -> out_str ) {
612+ if (out_str ) {
613+ * out_str = obj -> out_str ;
614+ } else {
615+ zend_string_release (obj -> out_str );
616+ }
617+ obj -> out_str = NULL ;
618+ } else {
619+ ZEND_ASSERT (!out_str );
620+ }
621+
609622 obj -> za = NULL ;
623+ obj -> from_string = false;
610624 return success ;
611625}
612626/* }}} */
@@ -1060,7 +1074,7 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */
10601074{
10611075 ze_zip_object * intern = php_zip_fetch_object (object );
10621076
1063- php_zipobj_close (intern );
1077+ php_zipobj_close (intern , NULL );
10641078
10651079#ifdef HAVE_PROGRESS_CALLBACK
10661080 /* if not properly called by libzip */
@@ -1467,7 +1481,7 @@ PHP_METHOD(ZipArchive, open)
14671481 }
14681482
14691483 /* If we already have an opened zip, free it */
1470- php_zipobj_close (ze_obj );
1484+ php_zipobj_close (ze_obj , NULL );
14711485
14721486 /* open for write without option to empty the archive */
14731487 if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY )) == 0 ) {
@@ -1491,28 +1505,34 @@ PHP_METHOD(ZipArchive, open)
14911505 ze_obj -> filename = resolved_path ;
14921506 ze_obj -> filename_len = strlen (resolved_path );
14931507 ze_obj -> za = intern ;
1508+ ze_obj -> from_string = false;
14941509 RETURN_TRUE ;
14951510}
14961511/* }}} */
14971512
1498- /* {{{ Create new read-only zip using given string */
1513+ /* {{{ Create new zip from a string, or a create an empty zip to be saved to a string */
14991514PHP_METHOD (ZipArchive , openString )
15001515{
1501- zend_string * buffer ;
1516+ zend_string * buffer = NULL ;
1517+ zend_long flags = 0 ;
15021518 zval * self = ZEND_THIS ;
15031519
1504- if (zend_parse_parameters (ZEND_NUM_ARGS (), "S " , & buffer ) == FAILURE ) {
1520+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "|Sl " , & buffer , & flags ) == FAILURE ) {
15051521 RETURN_THROWS ();
15061522 }
15071523
1524+ if (!buffer ) {
1525+ buffer = ZSTR_EMPTY_ALLOC ();
1526+ }
1527+
15081528 ze_zip_object * ze_obj = Z_ZIP_P (self );
15091529
1510- php_zipobj_close (ze_obj );
1530+ php_zipobj_close (ze_obj , NULL );
15111531
15121532 zip_error_t err ;
15131533 zip_error_init (& err );
15141534
1515- zip_source_t * zip_source = php_zip_create_string_source (buffer , NULL , & err );
1535+ zip_source_t * zip_source = php_zip_create_string_source (buffer , & ze_obj -> out_str , & err );
15161536
15171537 if (!zip_source ) {
15181538 ze_obj -> err_zip = zip_error_code_zip (& err );
@@ -1521,7 +1541,7 @@ PHP_METHOD(ZipArchive, openString)
15211541 RETURN_LONG (ze_obj -> err_zip );
15221542 }
15231543
1524- struct zip * intern = zip_open_from_source (zip_source , ZIP_RDONLY , & err );
1544+ struct zip * intern = zip_open_from_source (zip_source , flags , & err );
15251545 if (!intern ) {
15261546 ze_obj -> err_zip = zip_error_code_zip (& err );
15271547 ze_obj -> err_sys = zip_error_code_system (& err );
@@ -1530,6 +1550,7 @@ PHP_METHOD(ZipArchive, openString)
15301550 RETURN_LONG (ze_obj -> err_zip );
15311551 }
15321552
1553+ ze_obj -> from_string = true;
15331554 ze_obj -> za = intern ;
15341555 zip_error_fini (& err );
15351556 RETURN_TRUE ;
@@ -1568,7 +1589,32 @@ PHP_METHOD(ZipArchive, close)
15681589
15691590 ZIP_FROM_OBJECT (intern , self );
15701591
1571- RETURN_BOOL (php_zipobj_close (Z_ZIP_P (self )));
1592+ RETURN_BOOL (php_zipobj_close (Z_ZIP_P (self ), NULL ));
1593+ }
1594+ /* }}} */
1595+
1596+ /* {{{ close the zip archive and get the result as a string */
1597+ PHP_METHOD (ZipArchive , closeString )
1598+ {
1599+ struct zip * intern ;
1600+ zval * self = ZEND_THIS ;
1601+
1602+ ZEND_PARSE_PARAMETERS_NONE ();
1603+
1604+ ZIP_FROM_OBJECT (intern , self );
1605+
1606+ if (!Z_ZIP_P (self )-> from_string ) {
1607+ zend_throw_error (NULL , "ZipArchive::closeString can only be called on "
1608+ "an archive opened with ZipArchive::openString" );
1609+ RETURN_THROWS ();
1610+ }
1611+
1612+ zend_string * ret = NULL ;
1613+ bool success = php_zipobj_close (Z_ZIP_P (self ), & ret );
1614+ if (success ) {
1615+ RETURN_STR (ret ? ret : ZSTR_EMPTY_ALLOC ());
1616+ }
1617+ RETURN_FALSE ;
15721618}
15731619/* }}} */
15741620
0 commit comments