2323#define PHP_STREAM_BRIGADE_RES_NAME "userfilter.bucket brigade"
2424#define PHP_STREAM_BUCKET_RES_NAME "userfilter.bucket"
2525
26- struct php_user_filter_data {
27- zend_class_entry * ce ;
28- /* variable length; this *must* be last in the structure */
29- zend_string * classname ;
30- };
31-
3226/* to provide context for calling into the next filter from user-space */
3327static int le_bucket_brigade ;
3428static int le_bucket ;
@@ -328,7 +322,6 @@ static const php_stream_filter_ops userfilter_ops = {
328322static php_stream_filter * user_filter_factory_create (const char * filtername ,
329323 zval * filterparams , bool persistent )
330324{
331- struct php_user_filter_data * fdat = NULL ;
332325 php_stream_filter * filter ;
333326 zval obj ;
334327 zval retval ;
@@ -347,8 +340,9 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
347340
348341 len = strlen (filtername );
349342
350- /* determine the classname/class entry */
351- if (NULL == (fdat = zend_hash_str_find_ptr (BG (user_filter_map ), filtername , len ))) {
343+ /* determine the class entry */
344+ /* const */ zend_class_entry * ce = zend_hash_str_find_ptr (BG (user_filter_map ), filtername , len );
345+ if (UNEXPECTED (ce == NULL )) {
352346 const char * period ;
353347
354348 /* Userspace Filters using ambiguous wildcards could cause problems.
@@ -366,7 +360,8 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
366360 ZEND_ASSERT (new_period [0 ] == '.' );
367361 new_period [1 ] = '*' ;
368362 new_period [2 ] = '\0' ;
369- if (NULL != (fdat = zend_hash_str_find_ptr (BG (user_filter_map ), wildcard , strlen (wildcard )))) {
363+ ce = zend_hash_str_find_ptr (BG (user_filter_map ), wildcard , strlen (wildcard ));
364+ if (NULL != ce ) {
370365 new_period = NULL ;
371366 } else {
372367 * new_period = '\0' ;
@@ -375,21 +370,11 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
375370 }
376371 efree (wildcard );
377372 }
378- ZEND_ASSERT (fdat );
379- }
380-
381- /* bind the classname to the actual class */
382- if (fdat -> ce == NULL ) {
383- if (NULL == (fdat -> ce = zend_lookup_class (fdat -> classname ))) {
384- php_error_docref (NULL , E_WARNING ,
385- "User-filter \"%s\" requires class \"%s\", but that class is not defined" ,
386- filtername , ZSTR_VAL (fdat -> classname ));
387- return NULL ;
388- }
373+ ZEND_ASSERT (ce );
389374 }
390375
391376 /* create the object */
392- if (object_init_ex (& obj , fdat -> ce ) == FAILURE ) {
377+ if (object_init_ex (& obj , ce ) == FAILURE ) {
393378 return NULL ;
394379 }
395380
@@ -435,13 +420,6 @@ static const php_stream_filter_factory user_filter_factory = {
435420 user_filter_factory_create
436421};
437422
438- static void filter_item_dtor (zval * zv )
439- {
440- struct php_user_filter_data * fdat = Z_PTR_P (zv );
441- zend_string_release_ex (fdat -> classname , 0 );
442- efree (fdat );
443- }
444-
445423/* {{{ Return a bucket object from the brigade for operating on */
446424PHP_FUNCTION (stream_bucket_make_writeable )
447425{
@@ -604,41 +582,37 @@ PHP_FUNCTION(stream_get_filters)
604582/* {{{ Registers a custom filter handler class */
605583PHP_FUNCTION (stream_filter_register )
606584{
607- zend_string * filtername , * classname ;
608- struct php_user_filter_data * fdat ;
585+ zend_string * filtername ;
586+ zend_class_entry * ce = NULL ;
609587
610588 ZEND_PARSE_PARAMETERS_START (2 , 2 )
611589 Z_PARAM_STR (filtername )
612- Z_PARAM_STR ( classname )
590+ Z_PARAM_CLASS ( ce )
613591 ZEND_PARSE_PARAMETERS_END ();
614592
615593 if (!ZSTR_LEN (filtername )) {
616594 zend_argument_value_error (1 , "must be a non-empty string" );
617595 RETURN_THROWS ();
618596 }
619597
620- if (!ZSTR_LEN (classname )) {
621- zend_argument_value_error (2 , "must be a non-empty string" );
598+ /* TODO: Check class is a child of php_user_filter? */
599+ if (UNEXPECTED (ce -> ce_flags & ZEND_ACC_UNINSTANTIABLE )) {
600+ zend_argument_value_error (2 , "must be a concrete class" );
622601 RETURN_THROWS ();
623602 }
624603
625604 if (!BG (user_filter_map )) {
626605 BG (user_filter_map ) = (HashTable * ) emalloc (sizeof (HashTable ));
627- zend_hash_init (BG (user_filter_map ), 8 , NULL , (dtor_func_t ) filter_item_dtor , 0 );
606+ /* We don't need a destructor as we are only storing a CE which should be never modified */
607+ zend_hash_init (BG (user_filter_map ), 8 , NULL , NULL , 0 );
628608 }
629609
630- fdat = ecalloc (1 , sizeof (struct php_user_filter_data ));
631- fdat -> classname = zend_string_copy (classname );
632-
633- if (zend_hash_add_ptr (BG (user_filter_map ), filtername , fdat ) != NULL ) {
610+ if (zend_hash_add_ptr (BG (user_filter_map ), filtername , ce ) != NULL ) {
634611 if (php_stream_filter_register_factory_volatile (filtername , & user_filter_factory ) == SUCCESS ) {
635612 RETURN_TRUE ;
636613 }
637614
638615 zend_hash_del (BG (user_filter_map ), filtername );
639- } else {
640- zend_string_release_ex (classname , 0 );
641- efree (fdat );
642616 }
643617
644618 RETURN_FALSE ;
0 commit comments