PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/standard - user_filters.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 200 248 80.6 %
Date: 2014-07-21 Functions: 14 15 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors:                                                             |
      16             :    | Wez Furlong (wez@thebrainroom.com)                                   |
      17             :    | Sara Golemon (pollita@php.net)                                       |
      18             :    +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #include "php.h"
      24             : #include "php_globals.h"
      25             : #include "ext/standard/basic_functions.h"
      26             : #include "ext/standard/file.h"
      27             : 
      28             : #define PHP_STREAM_BRIGADE_RES_NAME     "userfilter.bucket brigade"
      29             : #define PHP_STREAM_BUCKET_RES_NAME "userfilter.bucket"
      30             : #define PHP_STREAM_FILTER_RES_NAME "userfilter.filter"
      31             : 
      32             : struct php_user_filter_data {
      33             :         zend_class_entry *ce;
      34             :         /* variable length; this *must* be last in the structure */
      35             :         char classname[1];
      36             : };
      37             : 
      38             : /* to provide context for calling into the next filter from user-space */
      39             : static int le_userfilters;
      40             : static int le_bucket_brigade;
      41             : static int le_bucket;
      42             : 
      43             : #define GET_FILTER_FROM_OBJ()   { \
      44             :         zval **tmp; \
      45             :         if (FAILURE == zend_hash_index_find(Z_OBJPROP_P(this_ptr), 0, (void**)&tmp)) { \
      46             :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "filter property vanished"); \
      47             :                 RETURN_FALSE; \
      48             :         } \
      49             :         ZEND_FETCH_RESOURCE(filter, php_stream_filter*, tmp, -1, "filter", le_userfilters); \
      50             : }
      51             : 
      52             : /* define the base filter class */
      53             : 
      54         107 : PHP_FUNCTION(user_filter_nop)
      55             : {
      56         107 : }
      57             : ZEND_BEGIN_ARG_INFO(arginfo_php_user_filter_filter, 0)
      58             :         ZEND_ARG_INFO(0, in)
      59             :         ZEND_ARG_INFO(0, out)
      60             :         ZEND_ARG_INFO(1, consumed)
      61             :         ZEND_ARG_INFO(0, closing)
      62             : ZEND_END_ARG_INFO()
      63             : 
      64             : ZEND_BEGIN_ARG_INFO(arginfo_php_user_filter_onCreate, 0)
      65             : ZEND_END_ARG_INFO()
      66             : 
      67             : ZEND_BEGIN_ARG_INFO(arginfo_php_user_filter_onClose, 0)
      68             : ZEND_END_ARG_INFO()
      69             : 
      70             : static const zend_function_entry user_filter_class_funcs[] = {
      71             :         PHP_NAMED_FE(filter,    PHP_FN(user_filter_nop),                arginfo_php_user_filter_filter)
      72             :         PHP_NAMED_FE(onCreate,  PHP_FN(user_filter_nop),                arginfo_php_user_filter_onCreate)
      73             :         PHP_NAMED_FE(onClose,   PHP_FN(user_filter_nop),                arginfo_php_user_filter_onClose)
      74             :         PHP_FE_END
      75             : };
      76             : 
      77             : static zend_class_entry user_filter_class_entry;
      78             : 
      79          23 : static ZEND_RSRC_DTOR_FUNC(php_bucket_dtor)
      80             : {
      81          23 :         php_stream_bucket *bucket = (php_stream_bucket *)rsrc->ptr;
      82          23 :         if (bucket) {
      83          23 :                 php_stream_bucket_delref(bucket TSRMLS_CC);
      84          23 :                 bucket = NULL;
      85             :         }
      86          23 : }
      87             : 
      88       21257 : PHP_MINIT_FUNCTION(user_filters)
      89             : {
      90             :         zend_class_entry *php_user_filter;
      91             :         /* init the filter class ancestor */
      92       21257 :         INIT_CLASS_ENTRY(user_filter_class_entry, "php_user_filter", user_filter_class_funcs);
      93       21257 :         if ((php_user_filter = zend_register_internal_class(&user_filter_class_entry TSRMLS_CC)) == NULL) {
      94           0 :                 return FAILURE;
      95             :         }
      96       21257 :         zend_declare_property_string(php_user_filter, "filtername", sizeof("filtername")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
      97       21257 :         zend_declare_property_string(php_user_filter, "params", sizeof("params")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
      98             : 
      99             :         /* init the filter resource; it has no dtor, as streams will always clean it up
     100             :          * at the correct time */
     101       21257 :         le_userfilters = zend_register_list_destructors_ex(NULL, NULL, PHP_STREAM_FILTER_RES_NAME, 0);
     102             : 
     103       21257 :         if (le_userfilters == FAILURE) {
     104           0 :                 return FAILURE;
     105             :         }
     106             : 
     107             :         /* Filters will dispose of their brigades */
     108       21257 :         le_bucket_brigade = zend_register_list_destructors_ex(NULL, NULL, PHP_STREAM_BRIGADE_RES_NAME, module_number);
     109             :         /* Brigades will dispose of their buckets */
     110       21257 :         le_bucket = zend_register_list_destructors_ex(php_bucket_dtor, NULL, PHP_STREAM_BUCKET_RES_NAME, module_number);
     111             :         
     112       21257 :         if (le_bucket_brigade == FAILURE) {
     113           0 :                 return FAILURE;
     114             :         }
     115             : 
     116       21257 :         REGISTER_LONG_CONSTANT("PSFS_PASS_ON",                        PSFS_PASS_ON,                   CONST_CS | CONST_PERSISTENT);
     117       21257 :         REGISTER_LONG_CONSTANT("PSFS_FEED_ME",                        PSFS_FEED_ME,                   CONST_CS | CONST_PERSISTENT);
     118       21257 :         REGISTER_LONG_CONSTANT("PSFS_ERR_FATAL",              PSFS_ERR_FATAL,                 CONST_CS | CONST_PERSISTENT);
     119             : 
     120       21257 :         REGISTER_LONG_CONSTANT("PSFS_FLAG_NORMAL",            PSFS_FLAG_NORMAL,               CONST_CS | CONST_PERSISTENT);
     121       21257 :         REGISTER_LONG_CONSTANT("PSFS_FLAG_FLUSH_INC", PSFS_FLAG_FLUSH_INC,    CONST_CS | CONST_PERSISTENT);
     122       21257 :         REGISTER_LONG_CONSTANT("PSFS_FLAG_FLUSH_CLOSE",       PSFS_FLAG_FLUSH_CLOSE,  CONST_CS | CONST_PERSISTENT);
     123             :         
     124       21257 :         return SUCCESS;
     125             : }
     126             : 
     127       21249 : PHP_RSHUTDOWN_FUNCTION(user_filters)
     128             : {
     129       21249 :         if (BG(user_filter_map)) {
     130           9 :                 zend_hash_destroy(BG(user_filter_map));
     131           9 :                 efree(BG(user_filter_map));
     132           9 :                 BG(user_filter_map) = NULL;
     133             :         }
     134             : 
     135       21249 :         return SUCCESS;
     136             : }
     137             : 
     138          57 : static void userfilter_dtor(php_stream_filter *thisfilter TSRMLS_DC)
     139             : {
     140          57 :         zval *obj = (zval*)thisfilter->abstract;
     141             :         zval func_name;
     142          57 :         zval *retval = NULL;
     143             : 
     144          57 :         if (obj == NULL) {
     145             :                 /* If there's no object associated then there's nothing to dispose of */
     146           0 :                 return;
     147             :         }
     148             : 
     149          57 :         ZVAL_STRINGL(&func_name, "onclose", sizeof("onclose")-1, 0);
     150             : 
     151          57 :         call_user_function_ex(NULL,
     152             :                         &obj,
     153             :                         &func_name,
     154             :                         &retval,
     155             :                         0, NULL,
     156             :                         0, NULL TSRMLS_CC);
     157             : 
     158          57 :         if (retval)
     159          55 :                 zval_ptr_dtor(&retval);
     160             : 
     161             :         /* kill the object */
     162          57 :         zval_ptr_dtor(&obj);
     163             : }
     164             : 
     165          57 : php_stream_filter_status_t userfilter_filter(
     166             :                         php_stream *stream,
     167             :                         php_stream_filter *thisfilter,
     168             :                         php_stream_bucket_brigade *buckets_in,
     169             :                         php_stream_bucket_brigade *buckets_out,
     170             :                         size_t *bytes_consumed,
     171             :                         int flags
     172             :                         TSRMLS_DC)
     173             : {
     174          57 :         int ret = PSFS_ERR_FATAL;
     175          57 :         zval *obj = (zval*)thisfilter->abstract;
     176             :         zval func_name;
     177          57 :         zval *retval = NULL;
     178             :         zval **args[4];
     179             :         zval *zclosing, *zconsumed, *zin, *zout, *zstream;
     180             :         zval zpropname;
     181             :         int call_result;
     182             : 
     183             :         /* the userfilter object probably doesn't exist anymore */
     184          57 :         if (CG(unclean_shutdown)) {
     185           0 :                 return ret;
     186             :         }
     187             : 
     188          57 :         if (FAILURE == zend_hash_find(Z_OBJPROP_P(obj), "stream", sizeof("stream"), (void**)&zstream)) {
     189             :                 /* Give the userfilter class a hook back to the stream */
     190          57 :                 ALLOC_INIT_ZVAL(zstream);
     191          57 :                 php_stream_to_zval(stream, zstream);
     192          57 :                 zval_copy_ctor(zstream);
     193          57 :                 add_property_zval(obj, "stream", zstream);
     194             :                 /* add_property_zval increments the refcount which is unwanted here */
     195          57 :                 zval_ptr_dtor(&zstream);
     196             :         }
     197             : 
     198          57 :         ZVAL_STRINGL(&func_name, "filter", sizeof("filter")-1, 0);
     199             : 
     200             :         /* Setup calling arguments */
     201          57 :         ALLOC_INIT_ZVAL(zin);
     202          57 :         ZEND_REGISTER_RESOURCE(zin, buckets_in, le_bucket_brigade);
     203          57 :         args[0] = &zin;
     204             : 
     205          57 :         ALLOC_INIT_ZVAL(zout);
     206          57 :         ZEND_REGISTER_RESOURCE(zout, buckets_out, le_bucket_brigade);
     207          57 :         args[1] = &zout;
     208             : 
     209          57 :         ALLOC_INIT_ZVAL(zconsumed);
     210          57 :         if (bytes_consumed) {
     211          25 :                 ZVAL_LONG(zconsumed, *bytes_consumed);
     212             :         } else {
     213          32 :                 ZVAL_NULL(zconsumed);
     214             :         }
     215          57 :         args[2] = &zconsumed;
     216             : 
     217          57 :         ALLOC_INIT_ZVAL(zclosing);
     218          57 :         ZVAL_BOOL(zclosing, flags & PSFS_FLAG_FLUSH_CLOSE);
     219          57 :         args[3] = &zclosing;
     220             : 
     221          57 :         call_result = call_user_function_ex(NULL,
     222             :                         &obj,
     223             :                         &func_name,
     224             :                         &retval,
     225             :                         4, args,
     226             :                         0, NULL TSRMLS_CC);
     227             : 
     228         114 :         if (call_result == SUCCESS && retval != NULL) {
     229          57 :                 convert_to_long(retval);
     230          57 :                 ret = Z_LVAL_P(retval);
     231           0 :         } else if (call_result == FAILURE) {
     232           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to call filter function");
     233             :         }
     234             : 
     235          57 :         if (bytes_consumed) {
     236          25 :                 *bytes_consumed = Z_LVAL_P(zconsumed);
     237             :         }
     238             : 
     239          57 :         if (retval) {
     240          57 :                 zval_ptr_dtor(&retval);
     241             :         }
     242             : 
     243          57 :         if (buckets_in->head) {
     244          11 :                 php_stream_bucket *bucket = buckets_in->head;
     245             : 
     246          11 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unprocessed filter buckets remaining on input brigade");
     247          33 :                 while ((bucket = buckets_in->head)) {
     248             :                         /* Remove unconsumed buckets from the brigade */
     249          11 :                         php_stream_bucket_unlink(bucket TSRMLS_CC);
     250          11 :                         php_stream_bucket_delref(bucket TSRMLS_CC);
     251             :                 }
     252             :         }
     253          57 :         if (ret != PSFS_PASS_ON) {
     254          39 :                 php_stream_bucket *bucket = buckets_out->head;
     255          84 :                 while (bucket != NULL) {
     256           6 :                         php_stream_bucket_unlink(bucket TSRMLS_CC);
     257           6 :                         php_stream_bucket_delref(bucket TSRMLS_CC);
     258           6 :                         bucket = buckets_out->head;
     259             :                 }
     260             :         }
     261             : 
     262             :         /* filter resources are cleaned up by the stream destructor,
     263             :          * keeping a reference to the stream resource here would prevent it
     264             :          * from being destroyed properly */
     265          57 :         INIT_ZVAL(zpropname);
     266          57 :         ZVAL_STRINGL(&zpropname, "stream", sizeof("stream")-1, 0);
     267          57 :         Z_OBJ_HANDLER_P(obj, unset_property)(obj, &zpropname, 0 TSRMLS_CC);
     268             : 
     269          57 :         zval_ptr_dtor(&zclosing);
     270          57 :         zval_ptr_dtor(&zconsumed);
     271          57 :         zval_ptr_dtor(&zout);
     272          57 :         zval_ptr_dtor(&zin);
     273             : 
     274          57 :         return ret;
     275             : }
     276             : 
     277             : static php_stream_filter_ops userfilter_ops = {
     278             :         userfilter_filter,
     279             :         userfilter_dtor,
     280             :         "user-filter"
     281             : };
     282             : 
     283          57 : static php_stream_filter *user_filter_factory_create(const char *filtername,
     284             :                 zval *filterparams, int persistent TSRMLS_DC)
     285             : {
     286          57 :         struct php_user_filter_data *fdat = NULL;
     287             :         php_stream_filter *filter;
     288             :         zval *obj, *zfilter;
     289             :         zval func_name;
     290          57 :         zval *retval = NULL;
     291             :         int len;
     292             :         
     293             :         /* some sanity checks */
     294          57 :         if (persistent) {
     295           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING,
     296             :                                 "cannot use a user-space filter with a persistent stream");
     297           0 :                 return NULL;
     298             :         }
     299             : 
     300          57 :         len = strlen(filtername);
     301             : 
     302             :         /* determine the classname/class entry */
     303          57 :         if (FAILURE == zend_hash_find(BG(user_filter_map), (char*)filtername, len + 1, (void**)&fdat)) {
     304             :                 char *period;
     305             : 
     306             :                 /* Userspace Filters using ambiguous wildcards could cause problems.
     307             :            i.e.: myfilter.foo.bar will always call into myfilter.foo.*
     308             :                  never seeing myfilter.* 
     309             :            TODO: Allow failed userfilter creations to continue
     310             :                  scanning through the list */
     311           0 :                 if ((period = strrchr(filtername, '.'))) {
     312           0 :                         char *wildcard = emalloc(len + 3);
     313             : 
     314             :                         /* Search for wildcard matches instead */
     315           0 :                         memcpy(wildcard, filtername, len + 1); /* copy \0 */
     316           0 :                         period = wildcard + (period - filtername);
     317           0 :                         while (period) {
     318           0 :                                 *period = '\0';
     319           0 :                                 strncat(wildcard, ".*", 2);
     320           0 :                                 if (SUCCESS == zend_hash_find(BG(user_filter_map), wildcard, strlen(wildcard) + 1, (void**)&fdat)) {
     321           0 :                                         period = NULL;
     322             :                                 } else {
     323           0 :                                         *period = '\0';
     324           0 :                                         period = strrchr(wildcard, '.');
     325             :                                 }
     326             :                         }
     327           0 :                         efree(wildcard);
     328             :                 }
     329           0 :                 if (fdat == NULL) {
     330           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
     331             :                                         "Err, filter \"%s\" is not in the user-filter map, but somehow the user-filter-factory was invoked for it!?", filtername);
     332           0 :                         return NULL;
     333             :                 }
     334             :         }
     335             : 
     336             :         /* bind the classname to the actual class */
     337          57 :         if (fdat->ce == NULL) {
     338          12 :                 if (FAILURE == zend_lookup_class(fdat->classname, strlen(fdat->classname),
     339          12 :                                         (zend_class_entry ***)&fdat->ce TSRMLS_CC)) {
     340           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
     341             :                                         "user-filter \"%s\" requires class \"%s\", but that class is not defined",
     342           0 :                                         filtername, fdat->classname);
     343           0 :                         return NULL;
     344             :                 }
     345          12 :                 fdat->ce = *(zend_class_entry**)fdat->ce;
     346             : 
     347             :         }
     348             : 
     349          57 :         filter = php_stream_filter_alloc(&userfilter_ops, NULL, 0);
     350          57 :         if (filter == NULL) {
     351           0 :                 return NULL;
     352             :         }
     353             : 
     354             :         /* create the object */
     355          57 :         ALLOC_ZVAL(obj);
     356          57 :         object_init_ex(obj, fdat->ce);
     357          57 :         Z_SET_REFCOUNT_P(obj, 1);
     358          57 :         Z_SET_ISREF_P(obj);
     359             : 
     360             :         /* filtername */
     361          57 :         add_property_string(obj, "filtername", (char*)filtername, 1);
     362             :         
     363             :         /* and the parameters, if any */
     364          57 :         if (filterparams) {
     365           1 :                 add_property_zval(obj, "params", filterparams);
     366             :         } else {
     367          56 :                 add_property_null(obj, "params");
     368             :         }
     369             : 
     370             :         /* invoke the constructor */
     371          57 :         ZVAL_STRINGL(&func_name, "oncreate", sizeof("oncreate")-1, 0);
     372             : 
     373          57 :         call_user_function_ex(NULL,
     374             :                         &obj,
     375             :                         &func_name,
     376             :                         &retval,
     377             :                         0, NULL,
     378             :                         0, NULL TSRMLS_CC);
     379             : 
     380          57 :         if (retval) {
     381          55 :                 if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) {
     382             :                         /* User reported filter creation error "return false;" */
     383           0 :                         zval_ptr_dtor(&retval);
     384             : 
     385             :                         /* Kill the filter (safely) */
     386           0 :                         filter->abstract = NULL;
     387           0 :                         php_stream_filter_free(filter TSRMLS_CC);
     388             : 
     389             :                         /* Kill the object */
     390           0 :                         zval_ptr_dtor(&obj);
     391             : 
     392             :                         /* Report failure to filter_alloc */
     393           0 :                         return NULL;
     394             :                 }                       
     395          55 :                 zval_ptr_dtor(&retval);
     396             :         }
     397             : 
     398             :         /* set the filter property, this will be used during cleanup */
     399          57 :         ALLOC_INIT_ZVAL(zfilter);
     400          57 :         ZEND_REGISTER_RESOURCE(zfilter, filter, le_userfilters);
     401          57 :         filter->abstract = obj;
     402          57 :         add_property_zval(obj, "filter", zfilter);
     403             :         /* add_property_zval increments the refcount which is unwanted here */
     404          57 :         zval_ptr_dtor(&zfilter);
     405             : 
     406          57 :         return filter;
     407             : }
     408             : 
     409             : static php_stream_filter_factory user_filter_factory = {
     410             :         user_filter_factory_create
     411             : };
     412             : 
     413          13 : static void filter_item_dtor(struct php_user_filter_data *fdat)
     414             : {
     415          13 : }
     416             : 
     417             : /* {{{ proto object stream_bucket_make_writeable(resource brigade)
     418             :    Return a bucket object from the brigade for operating on */
     419          40 : PHP_FUNCTION(stream_bucket_make_writeable)
     420             : {
     421             :         zval *zbrigade, *zbucket;
     422             :         php_stream_bucket_brigade *brigade;
     423             :         php_stream_bucket *bucket;
     424             : 
     425          40 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zbrigade) == FAILURE) {
     426           0 :                 RETURN_FALSE;
     427             :         }
     428             : 
     429          40 :         ZEND_FETCH_RESOURCE(brigade, php_stream_bucket_brigade *, &zbrigade, -1, PHP_STREAM_BRIGADE_RES_NAME, le_bucket_brigade); 
     430             : 
     431          40 :         ZVAL_NULL(return_value);
     432             : 
     433          40 :         if (brigade->head && (bucket = php_stream_bucket_make_writeable(brigade->head TSRMLS_CC))) {
     434          13 :                 ALLOC_INIT_ZVAL(zbucket);
     435          13 :                 ZEND_REGISTER_RESOURCE(zbucket, bucket, le_bucket);
     436          13 :                 object_init(return_value);
     437          13 :                 add_property_zval(return_value, "bucket", zbucket);
     438             :                 /* add_property_zval increments the refcount which is unwanted here */
     439          13 :                 zval_ptr_dtor(&zbucket);
     440          13 :                 add_property_stringl(return_value, "data", bucket->buf, bucket->buflen, 1);
     441          13 :                 add_property_long(return_value, "datalen", bucket->buflen);
     442             :         }
     443             : }
     444             : /* }}} */
     445             : 
     446             : /* {{{ php_stream_bucket_attach */
     447          17 : static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS)
     448             : {
     449             :         zval *zbrigade, *zobject;
     450             :         zval **pzbucket, **pzdata;
     451             :         php_stream_bucket_brigade *brigade;
     452             :         php_stream_bucket *bucket;
     453             : 
     454          17 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zo", &zbrigade, &zobject) == FAILURE) {
     455           0 :                 RETURN_FALSE;
     456             :         }
     457             : 
     458          17 :         if (FAILURE == zend_hash_find(Z_OBJPROP_P(zobject), "bucket", 7, (void**)&pzbucket)) {
     459           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Object has no bucket property");
     460           0 :                 RETURN_FALSE;
     461             :         }
     462             : 
     463          17 :         ZEND_FETCH_RESOURCE(brigade, php_stream_bucket_brigade *, &zbrigade, -1, PHP_STREAM_BRIGADE_RES_NAME, le_bucket_brigade);
     464          17 :         ZEND_FETCH_RESOURCE(bucket, php_stream_bucket *, pzbucket, -1, PHP_STREAM_BUCKET_RES_NAME, le_bucket);
     465             : 
     466          17 :         if (SUCCESS == zend_hash_find(Z_OBJPROP_P(zobject), "data", 5, (void**)&pzdata) && (*pzdata)->type == IS_STRING) {
     467          17 :                 if (!bucket->own_buf) {
     468           0 :                         bucket = php_stream_bucket_make_writeable(bucket TSRMLS_CC);
     469             :                 }
     470          17 :                 if ((int)bucket->buflen != Z_STRLEN_PP(pzdata)) {
     471           0 :                         bucket->buf = perealloc(bucket->buf, Z_STRLEN_PP(pzdata), bucket->is_persistent);
     472           0 :                         bucket->buflen = Z_STRLEN_PP(pzdata);
     473             :                 }
     474          17 :                 memcpy(bucket->buf, Z_STRVAL_PP(pzdata), bucket->buflen);
     475             :         }
     476             : 
     477          17 :         if (append) {
     478          17 :                 php_stream_bucket_append(brigade, bucket TSRMLS_CC);
     479             :         } else {
     480           0 :                 php_stream_bucket_prepend(brigade, bucket TSRMLS_CC);
     481             :         }
     482             :         /* This is a hack necessary to accommodate situations where bucket is appended to the stream
     483             :          * multiple times. See bug35916.phpt for reference.
     484             :          */
     485          17 :         if (bucket->refcount == 1) {
     486          16 :                 bucket->refcount++;
     487             :         }
     488             : }
     489             : /* }}} */
     490             : 
     491             : /* {{{ proto void stream_bucket_prepend(resource brigade, resource bucket)
     492             :    Prepend bucket to brigade */
     493           0 : PHP_FUNCTION(stream_bucket_prepend)
     494             : {
     495           0 :         php_stream_bucket_attach(0, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     496           0 : }
     497             : /* }}} */
     498             : 
     499             : /* {{{ proto void stream_bucket_append(resource brigade, resource bucket)
     500             :    Append bucket to brigade */
     501          17 : PHP_FUNCTION(stream_bucket_append)
     502             : {
     503          17 :         php_stream_bucket_attach(1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
     504          17 : }
     505             : /* }}} */
     506             : 
     507             : /* {{{ proto resource stream_bucket_new(resource stream, string buffer)
     508             :    Create a new bucket for use on the current stream */
     509          10 : PHP_FUNCTION(stream_bucket_new)
     510             : {
     511             :         zval *zstream, *zbucket;
     512             :         php_stream *stream;
     513             :         char *buffer;
     514             :         char *pbuffer;
     515             :         int buffer_len;
     516             :         php_stream_bucket *bucket;
     517             : 
     518          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &zstream, &buffer, &buffer_len) == FAILURE) {
     519           0 :                 RETURN_FALSE;
     520             :         }
     521             : 
     522          10 :         php_stream_from_zval(stream, &zstream);
     523             : 
     524          10 :         if (!(pbuffer = pemalloc(buffer_len, php_stream_is_persistent(stream)))) {
     525           0 :                 RETURN_FALSE;
     526             :         }
     527             : 
     528          10 :         memcpy(pbuffer, buffer, buffer_len);
     529             : 
     530          10 :         bucket = php_stream_bucket_new(stream, pbuffer, buffer_len, 1, php_stream_is_persistent(stream) TSRMLS_CC);
     531             :         
     532          10 :         if (bucket == NULL) {
     533           0 :                 RETURN_FALSE;
     534             :         }
     535             : 
     536          10 :         ALLOC_INIT_ZVAL(zbucket);
     537          10 :         ZEND_REGISTER_RESOURCE(zbucket, bucket, le_bucket);
     538          10 :         object_init(return_value);
     539          10 :         add_property_zval(return_value, "bucket", zbucket);
     540             :         /* add_property_zval increments the refcount which is unwanted here */
     541          10 :         zval_ptr_dtor(&zbucket);
     542          10 :         add_property_stringl(return_value, "data", bucket->buf, bucket->buflen, 1);
     543          10 :         add_property_long(return_value, "datalen", bucket->buflen);
     544             : }
     545             : /* }}} */
     546             : 
     547             : /* {{{ proto array stream_get_filters(void)
     548             :    Returns a list of registered filters */
     549           6 : PHP_FUNCTION(stream_get_filters)
     550             : {
     551             :         char *filter_name;
     552             :         int key_flags;
     553           6 :         uint filter_name_len = 0;
     554             :         HashTable *filters_hash;
     555             :         ulong num_key;
     556             : 
     557           6 :         if (zend_parse_parameters_none() == FAILURE) {
     558           0 :                 return;
     559             :         }
     560             : 
     561           6 :         array_init(return_value);
     562             : 
     563           6 :         filters_hash = php_get_stream_filters_hash();
     564             : 
     565           6 :         if (filters_hash) {
     566          84 :                 for(zend_hash_internal_pointer_reset(filters_hash);
     567          78 :                         (key_flags = zend_hash_get_current_key_ex(filters_hash, &filter_name, &filter_name_len, &num_key, 0, NULL)) != HASH_KEY_NON_EXISTENT;
     568          72 :                         zend_hash_move_forward(filters_hash))
     569          72 :                                 if (key_flags == HASH_KEY_IS_STRING) {
     570          72 :                                         add_next_index_stringl(return_value, filter_name, filter_name_len - 1, 1);
     571             :                                 }
     572             :         }
     573             :         /* It's okay to return an empty array if no filters are registered */
     574             : }
     575             : /* }}} */       
     576             : 
     577             : /* {{{ proto bool stream_filter_register(string filtername, string classname)
     578             :    Registers a custom filter handler class */
     579          18 : PHP_FUNCTION(stream_filter_register)
     580             : {
     581             :         char *filtername, *classname;
     582             :         int filtername_len, classname_len;
     583             :         struct php_user_filter_data *fdat;
     584             :         
     585          18 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &filtername, &filtername_len,
     586             :                                 &classname, &classname_len) == FAILURE) {
     587           2 :                 RETURN_FALSE;
     588             :         }
     589             : 
     590          16 :         RETVAL_FALSE;
     591             : 
     592          16 :         if (!filtername_len) {
     593           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter name cannot be empty");
     594           2 :                 return;
     595             :         }
     596             : 
     597          14 :         if (!classname_len) {
     598           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class name cannot be empty");
     599           1 :                 return;
     600             :         }
     601             : 
     602          13 :         if (!BG(user_filter_map)) {
     603           9 :                 BG(user_filter_map) = (HashTable*) emalloc(sizeof(HashTable));
     604           9 :                 zend_hash_init(BG(user_filter_map), 5, NULL, (dtor_func_t) filter_item_dtor, 0);
     605             :         }
     606             : 
     607          13 :         fdat = ecalloc(1, sizeof(struct php_user_filter_data) + classname_len);
     608          13 :         memcpy(fdat->classname, classname, classname_len);
     609             : 
     610          39 :         if (zend_hash_add(BG(user_filter_map), filtername, filtername_len + 1, (void*)fdat,
     611          26 :                                 sizeof(*fdat) + classname_len, NULL) == SUCCESS &&
     612          13 :                         php_stream_filter_register_factory_volatile(filtername, &user_filter_factory TSRMLS_CC) == SUCCESS) {
     613          13 :                 RETVAL_TRUE;
     614             :         }
     615             : 
     616          13 :         efree(fdat);
     617             : }
     618             : /* }}} */
     619             : 
     620             : 
     621             : /*
     622             :  * Local variables:
     623             :  * tab-width: 4
     624             :  * c-basic-offset: 4
     625             :  * End:
     626             :  * vim600: sw=4 ts=4 fdm=marker
     627             :  * vim<600: sw=4 ts=4
     628             :  */

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:20 +0000 (6 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.