LTP GCOV extension - code coverage report
Current view: directory - ext/standard - user_filters.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 226
Code covered: 8.8 % Executed lines: 20
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5