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: 179 232 77.2 %
Date: 2015-06-27 Functions: 14 15 93.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 27 Jun 2015 09:41:20 +0000 (7 days ago)

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