@@ -575,30 +575,8 @@ static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */
575575}
576576/* }}} */
577577
578- /* Add a string to the list of buffers to be released when the object is destroyed.*/
579- static void php_zipobj_add_buffer (ze_zip_object * obj , zend_string * str ) /* {{{ */
580- {
581- size_t pos = obj -> buffers_cnt ++ ;
582- obj -> buffers = safe_erealloc (obj -> buffers , sizeof (* obj -> buffers ), obj -> buffers_cnt , 0 );
583- obj -> buffers [pos ] = zend_string_copy (str );
584- }
585- /* }}} */
586-
587- static void php_zipobj_release_buffers (ze_zip_object * obj ) /* {{{ */
588- {
589- if (obj -> buffers_cnt > 0 ) {
590- for (size_t i = 0 ; i < obj -> buffers_cnt ; i ++ ) {
591- zend_string_release (obj -> buffers [i ]);
592- }
593- efree (obj -> buffers );
594- obj -> buffers = NULL ;
595- }
596- obj -> buffers_cnt = 0 ;
597- }
598- /* }}} */
599-
600578/* Close and free the zip_t */
601- static bool php_zipobj_close (ze_zip_object * obj ) /* {{{ */
579+ static bool php_zipobj_close (ze_zip_object * obj , zend_string * * out_str ) /* {{{ */
602580{
603581 struct zip * intern = obj -> za ;
604582 bool success = false;
@@ -630,9 +608,17 @@ static bool php_zipobj_close(ze_zip_object *obj) /* {{{ */
630608 obj -> filename_len = 0 ;
631609 }
632610
633- php_zipobj_release_buffers (obj );
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+ }
634619
635620 obj -> za = NULL ;
621+ obj -> from_string = false;
636622 return success ;
637623}
638624/* }}} */
@@ -1084,7 +1070,7 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */
10841070{
10851071 ze_zip_object * intern = php_zip_fetch_object (object );
10861072
1087- php_zipobj_close (intern );
1073+ php_zipobj_close (intern , NULL );
10881074
10891075#ifdef HAVE_PROGRESS_CALLBACK
10901076 /* if not properly called by libzip */
@@ -1491,7 +1477,7 @@ PHP_METHOD(ZipArchive, open)
14911477 }
14921478
14931479 /* If we already have an opened zip, free it */
1494- php_zipobj_close (ze_obj );
1480+ php_zipobj_close (ze_obj , NULL );
14951481
14961482 /* open for write without option to empty the archive */
14971483 if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY )) == 0 ) {
@@ -1515,26 +1501,34 @@ PHP_METHOD(ZipArchive, open)
15151501 ze_obj -> filename = resolved_path ;
15161502 ze_obj -> filename_len = strlen (resolved_path );
15171503 ze_obj -> za = intern ;
1504+ ze_obj -> from_string = false;
15181505 RETURN_TRUE ;
15191506}
15201507/* }}} */
15211508
15221509/* {{{ Create new read-only zip using given string */
15231510PHP_METHOD (ZipArchive , openString )
15241511{
1525- zend_string * buffer ;
1512+ zend_string * buffer = NULL ;
1513+ zend_long flags = 0 ;
15261514 zval * self = ZEND_THIS ;
15271515
1528- if (zend_parse_parameters (ZEND_NUM_ARGS (), "S " , & buffer ) == FAILURE ) {
1516+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "|Sl " , & buffer , & flags ) == FAILURE ) {
15291517 RETURN_THROWS ();
15301518 }
15311519
1520+ if (!buffer ) {
1521+ buffer = ZSTR_EMPTY_ALLOC ();
1522+ }
1523+
15321524 ze_zip_object * ze_obj = Z_ZIP_P (self );
15331525
1526+ php_zipobj_close (ze_obj , NULL );
1527+
15341528 zip_error_t err ;
15351529 zip_error_init (& err );
15361530
1537- zip_source_t * zip_source = zip_source_buffer_create ( ZSTR_VAL ( buffer ), ZSTR_LEN ( buffer ), 0 , & err );
1531+ zip_source_t * zip_source = php_zip_create_string_source ( buffer , & ze_obj -> out_str , & err );
15381532
15391533 if (!zip_source ) {
15401534 ze_obj -> err_zip = zip_error_code_zip (& err );
@@ -1543,9 +1537,7 @@ PHP_METHOD(ZipArchive, openString)
15431537 RETURN_LONG (ze_obj -> err_zip );
15441538 }
15451539
1546- php_zipobj_close (ze_obj );
1547-
1548- struct zip * intern = zip_open_from_source (zip_source , ZIP_RDONLY , & err );
1540+ struct zip * intern = zip_open_from_source (zip_source , flags , & err );
15491541 if (!intern ) {
15501542 ze_obj -> err_zip = zip_error_code_zip (& err );
15511543 ze_obj -> err_sys = zip_error_code_system (& err );
@@ -1554,7 +1546,7 @@ PHP_METHOD(ZipArchive, openString)
15541546 RETURN_LONG (ze_obj -> err_zip );
15551547 }
15561548
1557- php_zipobj_add_buffer ( ze_obj , buffer ) ;
1549+ ze_obj -> from_string = true ;
15581550 ze_obj -> za = intern ;
15591551 zip_error_fini (& err );
15601552 RETURN_TRUE ;
@@ -1593,11 +1585,36 @@ PHP_METHOD(ZipArchive, close)
15931585
15941586 ZIP_FROM_OBJECT (intern , self );
15951587
1596- RETURN_BOOL (php_zipobj_close (Z_ZIP_P (self )));
1588+ RETURN_BOOL (php_zipobj_close (Z_ZIP_P (self ), NULL ));
15971589}
15981590/* }}} */
15991591
1600- /* {{{ close the zip archive */
1592+ /* {{{ close the zip archive and get the result as a string */
1593+ PHP_METHOD (ZipArchive , closeToString )
1594+ {
1595+ struct zip * intern ;
1596+ zval * self = ZEND_THIS ;
1597+
1598+ ZEND_PARSE_PARAMETERS_NONE ();
1599+
1600+ ZIP_FROM_OBJECT (intern , self );
1601+
1602+ if (!Z_ZIP_P (self )-> from_string ) {
1603+ zend_throw_error (NULL , "ZipArchive::closeToString can only be called on "
1604+ "an archive opened with ZipArchive::openString" );
1605+ RETURN_THROWS ();
1606+ }
1607+
1608+ zend_string * ret = NULL ;
1609+ bool success = php_zipobj_close (Z_ZIP_P (self ), & ret );
1610+ if (success ) {
1611+ RETURN_STR (ret ? ret : ZSTR_EMPTY_ALLOC ());
1612+ }
1613+ RETURN_FALSE ;
1614+ }
1615+ /* }}} */
1616+
1617+ /* {{{ get the number of entries */
16011618PHP_METHOD (ZipArchive , count )
16021619{
16031620 struct zip * intern ;
@@ -1911,9 +1928,7 @@ PHP_METHOD(ZipArchive, addFromString)
19111928 ZIP_FROM_OBJECT (intern , self );
19121929
19131930 ze_obj = Z_ZIP_P (self );
1914- php_zipobj_add_buffer (ze_obj , buffer );
1915-
1916- zs = zip_source_buffer (intern , ZSTR_VAL (buffer ), ZSTR_LEN (buffer ), 0 );
1931+ zs = php_zip_create_string_source (buffer , NULL , NULL );
19171932
19181933 if (zs == NULL ) {
19191934 RETURN_FALSE ;
0 commit comments