@@ -181,6 +181,9 @@ static zend_object *arch_ce_create_object(zend_class_entry *ce)
181181 zobj -> arch_disk = NULL ;
182182 zobj -> write_disk_options = 0 ;
183183 zobj -> entry_generation = 0 ;
184+ memset (& zobj -> password_fci , 0 , sizeof (zobj -> password_fci ));
185+ memset (& zobj -> password_fcc , 0 , sizeof (zobj -> password_fcc ));
186+ zobj -> password_cb_last_result = NULL ;
184187 zend_object_std_init (& zobj -> parent , ce );
185188 zobj -> parent .handlers = & arch_oh ;
186189
@@ -219,6 +222,14 @@ static void arch_oh_free_obj(zend_object *zobj)
219222 (void )archive_write_free (obj -> arch_disk );
220223 obj -> arch_disk = NULL ;
221224 }
225+ if (obj -> password_fci .size != 0 ) {
226+ zval_ptr_dtor (& obj -> password_fci .function_name );
227+ obj -> password_fci .size = 0 ;
228+ }
229+ if (obj -> password_cb_last_result ) {
230+ zend_string_release (obj -> password_cb_last_result );
231+ obj -> password_cb_last_result = NULL ;
232+ }
222233 zend_object_std_dtor (zobj );
223234}
224235
@@ -239,6 +250,36 @@ PHP_METHOD(libarchive_Archive, __construct)
239250
240251static bool arch_obj_open_read_stream (arch_object * arch_obj );
241252
253+ static const char * arch_passphrase_callback (struct archive * a , void * _client_data )
254+ {
255+ (void )a ;
256+ arch_object * arch_obj = (arch_object * )_client_data ;
257+
258+ zval retval ;
259+ ZVAL_UNDEF (& retval );
260+ arch_obj -> password_fci .retval = & retval ;
261+ arch_obj -> password_fci .param_count = 0 ;
262+ arch_obj -> password_fci .params = NULL ;
263+
264+ if (zend_call_function (& arch_obj -> password_fci , & arch_obj -> password_fcc ) == FAILURE
265+ || Z_TYPE (retval ) == IS_UNDEF ) {
266+ return NULL ;
267+ }
268+
269+ if (arch_obj -> password_cb_last_result ) {
270+ zend_string_release (arch_obj -> password_cb_last_result );
271+ arch_obj -> password_cb_last_result = NULL ;
272+ }
273+
274+ if (Z_TYPE (retval ) == IS_NULL ) {
275+ return NULL ;
276+ }
277+
278+ arch_obj -> password_cb_last_result = zval_get_string (& retval );
279+ zval_ptr_dtor (& retval );
280+ return ZSTR_VAL (arch_obj -> password_cb_last_result );
281+ }
282+
242283static void arch_obj_setup_support (arch_object * arch_obj )
243284{
244285 if (arch_obj -> filters == NULL ) {
@@ -276,6 +317,10 @@ static bool arch_obj_open_read(arch_object *arch_obj)
276317 php_stream_cast (stream , PHP_STREAM_AS_FD , (void * * )& fd , 0 ) == SUCCESS ) {
277318 arch_obj -> archive = archive_read_new ();
278319 arch_obj_setup_support (arch_obj );
320+ if (arch_obj -> password_fci .size != 0 ) {
321+ archive_read_set_passphrase_callback (arch_obj -> archive , arch_obj ,
322+ arch_passphrase_callback );
323+ }
279324 int res = archive_read_open_fd (arch_obj -> archive , fd , 10240 );
280325 if (res != ARCHIVE_OK ) {
281326 zend_throw_exception_ex (
@@ -315,6 +360,10 @@ static bool arch_obj_open_read_stream(arch_object *arch_obj)
315360
316361 arch_obj -> archive = archive_read_new ();
317362 arch_obj_setup_support (arch_obj );
363+ if (arch_obj -> password_fci .size != 0 ) {
364+ archive_read_set_passphrase_callback (arch_obj -> archive , arch_obj ,
365+ arch_passphrase_callback );
366+ }
318367 res = archive_read_open_FILE (arch_obj -> archive , fp );
319368 if (res != ARCHIVE_OK ) {
320369 zend_throw_exception_ex (
@@ -343,6 +392,31 @@ PHP_METHOD(libarchive_Archive, fromStream)
343392 arch_obj -> write_disk_options = (int )flags ;
344393}
345394
395+ PHP_METHOD (libarchive_Archive , withPasswordCallback )
396+ {
397+ zend_fcall_info fci ;
398+ zend_fcall_info_cache fcc ;
399+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
400+ Z_PARAM_FUNC (fci , fcc )
401+ ZEND_PARSE_PARAMETERS_END ();
402+
403+ arch_object * arch_obj = arch_object_from_zv (getThis ());
404+ if (arch_obj -> archive != NULL ) {
405+ zend_throw_exception (except_ce ,
406+ "Cannot set password callback after archive has been opened" , -1 );
407+ return ;
408+ }
409+
410+ Z_TRY_ADDREF (fci .function_name );
411+ if (arch_obj -> password_fci .size != 0 ) {
412+ zval_ptr_dtor (& arch_obj -> password_fci .function_name );
413+ }
414+ arch_obj -> password_fci = fci ;
415+ arch_obj -> password_fcc = fcc ;
416+
417+ RETURN_THIS ();
418+ }
419+
346420PHP_METHOD (libarchive_Archive , supportFormats )
347421{
348422 zval * args ;
0 commit comments