@@ -575,6 +575,68 @@ 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+
600+ /* Close and free the zip_t */
601+ static bool php_zipobj_close (ze_zip_object * obj ) /* {{{ */
602+ {
603+ struct zip * intern = obj -> za ;
604+ bool success = false;
605+
606+ if (intern ) {
607+ int err = zip_close (intern );
608+ if (err ) {
609+ php_error_docref (NULL , E_WARNING , "%s" , zip_strerror (intern ));
610+ /* Save error for property reader */
611+ zip_error_t * ziperr = zip_get_error (intern );
612+ obj -> err_zip = zip_error_code_zip (ziperr );
613+ obj -> err_sys = zip_error_code_system (ziperr );
614+ zip_error_fini (ziperr );
615+ zip_discard (intern );
616+ } else {
617+ obj -> err_zip = 0 ;
618+ obj -> err_sys = 0 ;
619+ }
620+ success = !err ;
621+ }
622+
623+ /* if we have a filename, we need to free it */
624+ if (obj -> filename ) {
625+ /* clear cache as empty zip are not created but deleted */
626+ php_clear_stat_cache (1 , obj -> filename , obj -> filename_len );
627+
628+ efree (obj -> filename );
629+ obj -> filename = NULL ;
630+ obj -> filename_len = 0 ;
631+ }
632+
633+ php_zipobj_release_buffers (obj );
634+
635+ obj -> za = NULL ;
636+ return success ;
637+ }
638+ /* }}} */
639+
578640int php_zip_glob (zend_string * spattern , zend_long flags , zval * return_value ) /* {{{ */
579641{
580642 int cwd_skip = 0 ;
@@ -1021,21 +1083,8 @@ static void php_zip_object_dtor(zend_object *object)
10211083static void php_zip_object_free_storage (zend_object * object ) /* {{{ */
10221084{
10231085 ze_zip_object * intern = php_zip_fetch_object (object );
1024- int i ;
1025-
1026- if (intern -> za ) {
1027- if (zip_close (intern -> za ) != 0 ) {
1028- php_error_docref (NULL , E_WARNING , "Cannot destroy the zip context: %s" , zip_strerror (intern -> za ));
1029- zip_discard (intern -> za );
1030- }
1031- }
10321086
1033- if (intern -> buffers_cnt > 0 ) {
1034- for (i = 0 ; i < intern -> buffers_cnt ; i ++ ) {
1035- zend_string_release (intern -> buffers [i ]);
1036- }
1037- efree (intern -> buffers );
1038- }
1087+ php_zipobj_close (intern );
10391088
10401089#ifdef HAVE_PROGRESS_CALLBACK
10411090 /* if not properly called by libzip */
@@ -1047,12 +1096,7 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */
10471096 php_zip_cancel_callback_free (intern );
10481097#endif
10491098
1050- intern -> za = NULL ;
10511099 zend_object_std_dtor (& intern -> zo );
1052-
1053- if (intern -> filename ) {
1054- efree (intern -> filename );
1055- }
10561100}
10571101/* }}} */
10581102
@@ -1448,19 +1492,8 @@ PHP_METHOD(ZipArchive, open)
14481492 RETURN_FALSE ;
14491493 }
14501494
1451- if (ze_obj -> za ) {
1452- /* we already have an opened zip, free it */
1453- if (zip_close (ze_obj -> za ) != 0 ) {
1454- php_error_docref (NULL , E_WARNING , "Empty string as source" );
1455- efree (resolved_path );
1456- RETURN_FALSE ;
1457- }
1458- ze_obj -> za = NULL ;
1459- }
1460- if (ze_obj -> filename ) {
1461- efree (ze_obj -> filename );
1462- ze_obj -> filename = NULL ;
1463- }
1495+ /* If we already have an opened zip, free it */
1496+ php_zipobj_close (ze_obj );
14641497
14651498 /* open for write without option to empty the archive */
14661499 if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY )) == 0 ) {
@@ -1488,6 +1521,48 @@ PHP_METHOD(ZipArchive, open)
14881521}
14891522/* }}} */
14901523
1524+ /* {{{ Create new read-only zip using given string */
1525+ PHP_METHOD (ZipArchive , openString )
1526+ {
1527+ zend_string * buffer ;
1528+ zval * self = ZEND_THIS ;
1529+
1530+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "S" , & buffer ) == FAILURE ) {
1531+ RETURN_THROWS ();
1532+ }
1533+
1534+ ze_zip_object * ze_obj = Z_ZIP_P (self );
1535+
1536+ zip_error_t err ;
1537+ zip_error_init (& err );
1538+
1539+ zip_source_t * zip_source = zip_source_buffer_create (ZSTR_VAL (buffer ), ZSTR_LEN (buffer ), 0 , & err );
1540+
1541+ if (!zip_source ) {
1542+ ze_obj -> err_zip = zip_error_code_zip (& err );
1543+ ze_obj -> err_sys = zip_error_code_system (& err );
1544+ zip_error_fini (& err );
1545+ RETURN_LONG (ze_obj -> err_zip );
1546+ }
1547+
1548+ php_zipobj_close (ze_obj );
1549+
1550+ struct zip * intern = zip_open_from_source (zip_source , ZIP_RDONLY , & err );
1551+ if (!intern ) {
1552+ ze_obj -> err_zip = zip_error_code_zip (& err );
1553+ ze_obj -> err_sys = zip_error_code_system (& err );
1554+ zip_error_fini (& err );
1555+ zip_source_free (zip_source );
1556+ RETURN_LONG (ze_obj -> err_zip );
1557+ }
1558+
1559+ php_zipobj_add_buffer (ze_obj , buffer );
1560+ ze_obj -> za = intern ;
1561+ zip_error_fini (& err );
1562+ RETURN_TRUE ;
1563+ }
1564+ /* }}} */
1565+
14911566/* {{{ Set the password for the active archive */
14921567PHP_METHOD (ZipArchive , setPassword )
14931568{
@@ -1515,42 +1590,14 @@ PHP_METHOD(ZipArchive, close)
15151590{
15161591 struct zip * intern ;
15171592 zval * self = ZEND_THIS ;
1518- ze_zip_object * ze_obj ;
1519- int err ;
15201593
15211594 if (zend_parse_parameters_none () == FAILURE ) {
15221595 RETURN_THROWS ();
15231596 }
15241597
15251598 ZIP_FROM_OBJECT (intern , self );
15261599
1527- ze_obj = Z_ZIP_P (self );
1528-
1529- err = zip_close (intern );
1530- if (err ) {
1531- php_error_docref (NULL , E_WARNING , "%s" , zip_strerror (intern ));
1532- /* Save error for property reader */
1533- zip_error_t * ziperr ;
1534-
1535- ziperr = zip_get_error (intern );
1536- ze_obj -> err_zip = zip_error_code_zip (ziperr );
1537- ze_obj -> err_sys = zip_error_code_system (ziperr );
1538- zip_error_fini (ziperr );
1539- zip_discard (intern );
1540- } else {
1541- ze_obj -> err_zip = 0 ;
1542- ze_obj -> err_sys = 0 ;
1543- }
1544-
1545- /* clear cache as empty zip are not created but deleted */
1546- php_clear_stat_cache (1 , ze_obj -> filename , ze_obj -> filename_len );
1547-
1548- efree (ze_obj -> filename );
1549- ze_obj -> filename = NULL ;
1550- ze_obj -> filename_len = 0 ;
1551- ze_obj -> za = NULL ;
1552-
1553- RETURN_BOOL (!err );
1600+ RETURN_BOOL (php_zipobj_close (Z_ZIP_P (self )));
15541601}
15551602/* }}} */
15561603
@@ -1864,7 +1911,6 @@ PHP_METHOD(ZipArchive, addFromString)
18641911 size_t name_len ;
18651912 ze_zip_object * ze_obj ;
18661913 struct zip_source * zs ;
1867- int pos = 0 ;
18681914 zend_long flags = ZIP_FL_OVERWRITE ;
18691915
18701916 if (zend_parse_parameters (ZEND_NUM_ARGS (), "sS|l" ,
@@ -1875,15 +1921,7 @@ PHP_METHOD(ZipArchive, addFromString)
18751921 ZIP_FROM_OBJECT (intern , self );
18761922
18771923 ze_obj = Z_ZIP_P (self );
1878- if (ze_obj -> buffers_cnt ) {
1879- ze_obj -> buffers = safe_erealloc (ze_obj -> buffers , sizeof (* ze_obj -> buffers ), (ze_obj -> buffers_cnt + 1 ), 0 );
1880- pos = ze_obj -> buffers_cnt ++ ;
1881- } else {
1882- ze_obj -> buffers = emalloc (sizeof (* ze_obj -> buffers ));
1883- ze_obj -> buffers_cnt ++ ;
1884- pos = 0 ;
1885- }
1886- ze_obj -> buffers [pos ] = zend_string_copy (buffer );
1924+ php_zipobj_add_buffer (ze_obj , buffer );
18871925
18881926 zs = zip_source_buffer (intern , ZSTR_VAL (buffer ), ZSTR_LEN (buffer ), 0 );
18891927
0 commit comments