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

LTP GCOV extension - code coverage report
Current view: directory - standard - user_filters.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 268
Code covered: 78.4 % Executed lines: 210
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:42 +0000 (34 hours ago)

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