@@ -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,17 @@ 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+ }
619+
609620 obj -> za = NULL ;
621+ obj -> from_string = false;
610622 return success ;
611623}
612624/* }}} */
@@ -1060,7 +1072,7 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */
10601072{
10611073 ze_zip_object * intern = php_zip_fetch_object (object );
10621074
1063- php_zipobj_close (intern );
1075+ php_zipobj_close (intern , NULL );
10641076
10651077#ifdef HAVE_PROGRESS_CALLBACK
10661078 /* if not properly called by libzip */
@@ -1467,7 +1479,7 @@ PHP_METHOD(ZipArchive, open)
14671479 }
14681480
14691481 /* If we already have an opened zip, free it */
1470- php_zipobj_close (ze_obj );
1482+ php_zipobj_close (ze_obj , NULL );
14711483
14721484 /* open for write without option to empty the archive */
14731485 if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY )) == 0 ) {
@@ -1491,28 +1503,34 @@ PHP_METHOD(ZipArchive, open)
14911503 ze_obj -> filename = resolved_path ;
14921504 ze_obj -> filename_len = strlen (resolved_path );
14931505 ze_obj -> za = intern ;
1506+ ze_obj -> from_string = false;
14941507 RETURN_TRUE ;
14951508}
14961509/* }}} */
14971510
1498- /* {{{ Create new read-only zip using given string */
1511+ /* {{{ Create new zip from a string, or a create an empty zip to be saved to a string */
14991512PHP_METHOD (ZipArchive , openString )
15001513{
1501- zend_string * buffer ;
1514+ zend_string * buffer = NULL ;
1515+ zend_long flags = 0 ;
15021516 zval * self = ZEND_THIS ;
15031517
1504- if (zend_parse_parameters (ZEND_NUM_ARGS (), "S " , & buffer ) == FAILURE ) {
1518+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "|Sl " , & buffer , & flags ) == FAILURE ) {
15051519 RETURN_THROWS ();
15061520 }
15071521
1522+ if (!buffer ) {
1523+ buffer = ZSTR_EMPTY_ALLOC ();
1524+ }
1525+
15081526 ze_zip_object * ze_obj = Z_ZIP_P (self );
15091527
1510- php_zipobj_close (ze_obj );
1528+ php_zipobj_close (ze_obj , NULL );
15111529
15121530 zip_error_t err ;
15131531 zip_error_init (& err );
15141532
1515- zip_source_t * zip_source = php_zip_create_string_source (buffer , NULL , & err );
1533+ zip_source_t * zip_source = php_zip_create_string_source (buffer , & ze_obj -> out_str , & err );
15161534
15171535 if (!zip_source ) {
15181536 ze_obj -> err_zip = zip_error_code_zip (& err );
@@ -1521,7 +1539,7 @@ PHP_METHOD(ZipArchive, openString)
15211539 RETURN_LONG (ze_obj -> err_zip );
15221540 }
15231541
1524- struct zip * intern = zip_open_from_source (zip_source , ZIP_RDONLY , & err );
1542+ struct zip * intern = zip_open_from_source (zip_source , flags , & err );
15251543 if (!intern ) {
15261544 ze_obj -> err_zip = zip_error_code_zip (& err );
15271545 ze_obj -> err_sys = zip_error_code_system (& err );
@@ -1530,6 +1548,7 @@ PHP_METHOD(ZipArchive, openString)
15301548 RETURN_LONG (ze_obj -> err_zip );
15311549 }
15321550
1551+ ze_obj -> from_string = true;
15331552 ze_obj -> za = intern ;
15341553 zip_error_fini (& err );
15351554 RETURN_TRUE ;
@@ -1568,7 +1587,32 @@ PHP_METHOD(ZipArchive, close)
15681587
15691588 ZIP_FROM_OBJECT (intern , self );
15701589
1571- RETURN_BOOL (php_zipobj_close (Z_ZIP_P (self )));
1590+ RETURN_BOOL (php_zipobj_close (Z_ZIP_P (self ), NULL ));
1591+ }
1592+ /* }}} */
1593+
1594+ /* {{{ close the zip archive and get the result as a string */
1595+ PHP_METHOD (ZipArchive , closeString )
1596+ {
1597+ struct zip * intern ;
1598+ zval * self = ZEND_THIS ;
1599+
1600+ ZEND_PARSE_PARAMETERS_NONE ();
1601+
1602+ ZIP_FROM_OBJECT (intern , self );
1603+
1604+ if (!Z_ZIP_P (self )-> from_string ) {
1605+ zend_throw_error (NULL , "ZipArchive::closeString can only be called on "
1606+ "an archive opened with ZipArchive::openString" );
1607+ RETURN_THROWS ();
1608+ }
1609+
1610+ zend_string * ret = NULL ;
1611+ bool success = php_zipobj_close (Z_ZIP_P (self ), & ret );
1612+ if (success ) {
1613+ RETURN_STR (ret ? ret : ZSTR_EMPTY_ALLOC ());
1614+ }
1615+ RETURN_FALSE ;
15721616}
15731617/* }}} */
15741618
0 commit comments