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 ;
@@ -324,7 +318,6 @@ static const php_stream_filter_ops userfilter_ops = {
324318static php_stream_filter * user_filter_factory_create (const char * filtername ,
325319 zval * filterparams , bool persistent )
326320{
327- struct php_user_filter_data * fdat = NULL ;
328321 php_stream_filter * filter ;
329322 zval obj ;
330323 zval retval ;
@@ -343,8 +336,9 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
343336
344337 len = strlen (filtername );
345338
346- /* determine the classname/class entry */
347- if (NULL == (fdat = zend_hash_str_find_ptr (BG (user_filter_map ), filtername , len ))) {
339+ /* determine the class entry */
340+ /* const */ zend_class_entry * ce = zend_hash_str_find_ptr (BG (user_filter_map ), filtername , len );
341+ if (UNEXPECTED (ce == NULL )) {
348342 const char * period ;
349343
350344 /* Userspace Filters using ambiguous wildcards could cause problems.
@@ -362,7 +356,8 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
362356 ZEND_ASSERT (new_period [0 ] == '.' );
363357 new_period [1 ] = '*' ;
364358 new_period [2 ] = '\0' ;
365- if (NULL != (fdat = zend_hash_str_find_ptr (BG (user_filter_map ), wildcard , strlen (wildcard )))) {
359+ ce = zend_hash_str_find_ptr (BG (user_filter_map ), wildcard , strlen (wildcard ));
360+ if (NULL != ce ) {
366361 new_period = NULL ;
367362 } else {
368363 * new_period = '\0' ;
@@ -371,21 +366,11 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
371366 }
372367 efree (wildcard );
373368 }
374- ZEND_ASSERT (fdat );
375- }
376-
377- /* bind the classname to the actual class */
378- if (fdat -> ce == NULL ) {
379- if (NULL == (fdat -> ce = zend_lookup_class (fdat -> classname ))) {
380- php_error_docref (NULL , E_WARNING ,
381- "User-filter \"%s\" requires class \"%s\", but that class is not defined" ,
382- filtername , ZSTR_VAL (fdat -> classname ));
383- return NULL ;
384- }
369+ ZEND_ASSERT (ce );
385370 }
386371
387372 /* create the object */
388- if (object_init_ex (& obj , fdat -> ce ) == FAILURE ) {
373+ if (object_init_ex (& obj , ce ) == FAILURE ) {
389374 return NULL ;
390375 }
391376
@@ -431,13 +416,6 @@ static const php_stream_filter_factory user_filter_factory = {
431416 user_filter_factory_create
432417};
433418
434- static void filter_item_dtor (zval * zv )
435- {
436- struct php_user_filter_data * fdat = Z_PTR_P (zv );
437- zend_string_release_ex (fdat -> classname , 0 );
438- efree (fdat );
439- }
440-
441419/* {{{ Return a bucket object from the brigade for operating on */
442420PHP_FUNCTION (stream_bucket_make_writeable )
443421{
@@ -600,41 +578,37 @@ PHP_FUNCTION(stream_get_filters)
600578/* {{{ Registers a custom filter handler class */
601579PHP_FUNCTION (stream_filter_register )
602580{
603- zend_string * filtername , * classname ;
604- struct php_user_filter_data * fdat ;
581+ zend_string * filtername ;
582+ zend_class_entry * ce ;
605583
606584 ZEND_PARSE_PARAMETERS_START (2 , 2 )
607585 Z_PARAM_STR (filtername )
608- Z_PARAM_STR ( classname )
586+ Z_PARAM_CLASS ( ce )
609587 ZEND_PARSE_PARAMETERS_END ();
610588
611589 if (!ZSTR_LEN (filtername )) {
612590 zend_argument_value_error (1 , "must be a non-empty string" );
613591 RETURN_THROWS ();
614592 }
615593
616- if (!ZSTR_LEN (classname )) {
617- zend_argument_value_error (2 , "must be a non-empty string" );
594+ /* TODO: Check class is a child of php_user_filter? */
595+ if (UNEXPECTED (ce -> ce_flags & ZEND_ACC_UNINSTANTIABLE )) {
596+ zend_argument_value_error (2 , "must be a concrete class" );
618597 RETURN_THROWS ();
619598 }
620599
621600 if (!BG (user_filter_map )) {
622601 BG (user_filter_map ) = (HashTable * ) emalloc (sizeof (HashTable ));
623- zend_hash_init (BG (user_filter_map ), 8 , NULL , (dtor_func_t ) filter_item_dtor , 0 );
602+ /* We don't need a destructor as we are only storing a CE which should be never modified */
603+ zend_hash_init (BG (user_filter_map ), 8 , NULL , NULL , 0 );
624604 }
625605
626- fdat = ecalloc (1 , sizeof (struct php_user_filter_data ));
627- fdat -> classname = zend_string_copy (classname );
628-
629- if (zend_hash_add_ptr (BG (user_filter_map ), filtername , fdat ) != NULL ) {
606+ if (zend_hash_add_ptr (BG (user_filter_map ), filtername , ce ) != NULL ) {
630607 if (php_stream_filter_register_factory_volatile (filtername , & user_filter_factory ) == SUCCESS ) {
631608 RETURN_TRUE ;
632609 }
633610
634611 zend_hash_del (BG (user_filter_map ), filtername );
635- } else {
636- zend_string_release_ex (classname , 0 );
637- efree (fdat );
638612 }
639613
640614 RETURN_FALSE ;
0 commit comments