@@ -437,9 +437,20 @@ static void arch_oh_free_obj(zend_object *zobj)
437437 case ARCH_SOURCE_FILE :
438438 zend_string_release (obj -> source .file_location );
439439 break ;
440+ #ifndef HAVE_LIBARCHIVE_STREAM_CALLBACKS
440441 case ARCH_SOURCE_STREAM :
441442 zval_ptr_dtor (& obj -> source .stream_zv );
442443 break ;
444+ #else
445+ case ARCH_SOURCE_STREAM_CB :
446+ if (obj -> archive == NULL ) {
447+ /* Archive never opened; stream_close_cb won't fire. */
448+ zval_ptr_dtor (& obj -> source .stream_cb -> stream_zv );
449+ efree (obj -> source .stream_cb );
450+ }
451+ /* else: archive_read_free below triggers stream_close_cb. */
452+ break ;
453+ #endif
443454 case ARCH_SOURCE_NONE :
444455 break ;
445456 }
@@ -579,36 +590,63 @@ static bool arch_obj_open_read(arch_object *arch_obj)
579590 * Switch the source so arch_obj_open_read_stream can take over and
580591 * the stream resource is kept alive for the lifetime of the archive. */
581592 zend_string_release (arch_obj -> source .file_location );
593+ #ifdef HAVE_LIBARCHIVE_STREAM_CALLBACKS
594+ arch_stream_cb * d = emalloc (sizeof * d );
595+ php_stream_to_zval (stream , & d -> stream_zv ); /* transfer the only ref */
596+ arch_obj -> source .stream_cb = d ;
597+ arch_obj -> source_kind = ARCH_SOURCE_STREAM_CB ;
598+ #else
582599 arch_obj -> source_kind = ARCH_SOURCE_STREAM ;
583600 php_stream_to_zval (stream , & arch_obj -> source .stream_zv );
601+ #endif
584602 return arch_obj_open_read_stream (arch_obj );
585603 }
586604
587605 return true;
588606}
589607
608+ #ifdef HAVE_LIBARCHIVE_STREAM_CALLBACKS
609+ extern bool arch_open_archive_with_stream_callbacks (arch_object * arch_obj );
610+ #endif
611+
590612static bool arch_obj_open_read_stream (arch_object * arch_obj )
591613{
592614 php_stream * stream ;
615+ #ifdef HAVE_LIBARCHIVE_STREAM_CALLBACKS
616+ php_stream_from_zval_no_verify (stream , & arch_obj -> source .stream_cb -> stream_zv );
617+ #else
593618 php_stream_from_zval_no_verify (stream , & arch_obj -> source .stream_zv );
619+ #endif
594620 if (!stream ) {
595621 zend_throw_exception (except_ce , "Invalid stream resource" , -1 );
596622 return false;
597623 }
598624
599- FILE * fp ;
600- int res = php_stream_cast (stream , PHP_STREAM_AS_STDIO , (void * * )& fp , REPORT_ERRORS );
601- if (res != SUCCESS ) {
602- zend_throw_exception (except_ce , "Could not cast stream to FILE*" , -1 );
603- return false;
604- }
605-
606625 arch_obj -> archive = archive_read_new ();
607626 arch_obj_setup_support (arch_obj );
608627 if (arch_obj -> password_fci .size != 0 ) {
609628 archive_read_set_passphrase_callback (arch_obj -> archive , arch_obj ,
610629 arch_passphrase_callback );
611630 }
631+
632+ #ifdef HAVE_LIBARCHIVE_STREAM_CALLBACKS
633+ if (!arch_open_archive_with_stream_callbacks (arch_obj )) {
634+ zend_throw_exception_ex (
635+ except_ce , archive_errno (arch_obj -> archive ),
636+ "Could not open archive from stream: %s" ,
637+ archive_error_string (arch_obj -> archive ));
638+ return false;
639+ }
640+ return true;
641+ #else
642+ FILE * fp ;
643+ int res = php_stream_cast (stream , PHP_STREAM_AS_STDIO , (void * * )& fp ,
644+ REPORT_ERRORS );
645+ if (res != SUCCESS ) {
646+ zend_throw_exception (except_ce , "Could not cast stream to FILE*" , -1 );
647+ return false;
648+ }
649+
612650 res = archive_read_open_FILE (arch_obj -> archive , fp );
613651 if (res != ARCHIVE_OK ) {
614652 zend_throw_exception_ex (
@@ -617,8 +655,8 @@ static bool arch_obj_open_read_stream(arch_object *arch_obj)
617655 archive_error_string (arch_obj -> archive ));
618656 return false;
619657 }
620-
621658 return true;
659+ #endif
622660}
623661
624662PHP_METHOD (libarchive_Archive , fromStream )
@@ -632,8 +670,15 @@ PHP_METHOD(libarchive_Archive, fromStream)
632670
633671 object_init_ex (return_value , arch_ce );
634672 arch_object * arch_obj = arch_object_from_zv (return_value );
673+ #ifdef HAVE_LIBARCHIVE_STREAM_CALLBACKS
674+ arch_stream_cb * d = emalloc (sizeof * d );
675+ ZVAL_COPY (& d -> stream_zv , stream_zv );
676+ arch_obj -> source .stream_cb = d ;
677+ arch_obj -> source_kind = ARCH_SOURCE_STREAM_CB ;
678+ #else
635679 arch_obj -> source_kind = ARCH_SOURCE_STREAM ;
636680 ZVAL_COPY (& arch_obj -> source .stream_zv , stream_zv );
681+ #endif
637682 arch_obj -> write_disk_options = (int )flags ;
638683}
639684
0 commit comments