LTP GCOV extension - code coverage report
Current view: directory - main/streams - filter.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 256
Code covered: 38.7 % Executed lines: 99
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: Wez Furlong <wez@thebrainroom.com>                          |
      16                 :    +----------------------------------------------------------------------+
      17                 :  */
      18                 : 
      19                 : /* $Id: filter.c,v 1.17.2.3.2.9 2007/01/15 17:07:07 tony2001 Exp $ */
      20                 : 
      21                 : #include "php.h"
      22                 : #include "php_globals.h"
      23                 : #include "php_network.h"
      24                 : #include "php_open_temporary_file.h"
      25                 : #include "ext/standard/file.h"
      26                 : #include <stddef.h>
      27                 : #include <fcntl.h>
      28                 : 
      29                 : #include "php_streams_int.h"
      30                 : 
      31                 : /* Global filter hash, copied to FG(stream_filters) on registration of volatile filter */
      32                 : static HashTable stream_filters_hash;
      33                 : 
      34                 : /* Should only be used during core initialization */
      35                 : PHPAPI HashTable *php_get_stream_filters_hash_global()
      36             439 : {
      37             439 :         return &stream_filters_hash;
      38                 : }
      39                 : 
      40                 : /* Normal hash selection/retrieval call */
      41                 : PHPAPI HashTable *_php_get_stream_filters_hash(TSRMLS_D)
      42               0 : {
      43               0 :         return (FG(stream_filters) ? FG(stream_filters) : &stream_filters_hash);
      44                 : }
      45                 : 
      46                 : /* API for registering GLOBAL filters */
      47                 : PHPAPI int php_stream_filter_register_factory(const char *filterpattern, php_stream_filter_factory *factory TSRMLS_DC)
      48            1760 : {
      49            1760 :         return zend_hash_add(&stream_filters_hash, (char*)filterpattern, strlen(filterpattern) + 1, factory, sizeof(*factory), NULL);
      50                 : }
      51                 : 
      52                 : PHPAPI int php_stream_filter_unregister_factory(const char *filterpattern TSRMLS_DC)
      53            1533 : {
      54            1533 :         return zend_hash_del(&stream_filters_hash, (char*)filterpattern, strlen(filterpattern) + 1);
      55                 : }
      56                 : 
      57                 : /* API for registering VOLATILE wrappers */
      58                 : PHPAPI int php_stream_filter_register_factory_volatile(const char *filterpattern, php_stream_filter_factory *factory TSRMLS_DC)
      59               0 : {
      60               0 :         if (!FG(stream_filters)) {
      61                 :                 php_stream_filter_factory tmpfactory;
      62                 : 
      63               0 :                 ALLOC_HASHTABLE(FG(stream_filters));
      64               0 :                 zend_hash_init(FG(stream_filters), zend_hash_num_elements(&stream_filters_hash), NULL, NULL, 1);
      65               0 :                 zend_hash_copy(FG(stream_filters), &stream_filters_hash, NULL, &tmpfactory, sizeof(php_stream_filter_factory));
      66                 :         }
      67                 : 
      68               0 :         return zend_hash_add(FG(stream_filters), (char*)filterpattern, strlen(filterpattern) + 1, factory, sizeof(*factory), NULL);
      69                 : }
      70                 : 
      71                 : /* Buckets */
      72                 : 
      73                 : PHPAPI php_stream_bucket *php_stream_bucket_new(php_stream *stream, char *buf, size_t buflen, int own_buf, int buf_persistent TSRMLS_DC)
      74             133 : {
      75             133 :         int is_persistent = php_stream_is_persistent(stream);
      76                 :         php_stream_bucket *bucket;
      77                 : 
      78             133 :         bucket = (php_stream_bucket*)pemalloc(sizeof(php_stream_bucket), is_persistent);
      79                 : 
      80             133 :         if (bucket == NULL) {
      81               0 :                 return NULL;
      82                 :         }
      83                 :         
      84             133 :         bucket->next = bucket->prev = NULL;
      85                 : 
      86             133 :         if (is_persistent && !buf_persistent) {
      87                 :                 /* all data in a persistent bucket must also be persistent */
      88               0 :                 bucket->buf = pemalloc(buflen, 1);
      89                 :                 
      90               0 :                 if (bucket->buf == NULL) {
      91               0 :                         pefree(bucket, 1);
      92               0 :                         return NULL;
      93                 :                 }
      94                 :                 
      95               0 :                 memcpy(bucket->buf, buf, buflen);
      96               0 :                 bucket->buflen = buflen;
      97               0 :                 bucket->own_buf = 1;
      98                 :         } else {
      99             133 :                 bucket->buf = buf;
     100             133 :                 bucket->buflen = buflen;
     101             133 :                 bucket->own_buf = own_buf;
     102                 :         }
     103             133 :         bucket->is_persistent = is_persistent;
     104             133 :         bucket->refcount = 1;
     105             133 :         bucket->brigade = NULL;
     106                 : 
     107             133 :         return bucket;
     108                 : }
     109                 : 
     110                 : /* Given a bucket, returns a version of that bucket with a writeable buffer.
     111                 :  * If the original bucket has a refcount of 1 and owns its buffer, then it
     112                 :  * is returned unchanged.
     113                 :  * Otherwise, a copy of the buffer is made.
     114                 :  * In both cases, the original bucket is unlinked from its brigade.
     115                 :  * If a copy is made, the original bucket is delref'd.
     116                 :  * */
     117                 : PHPAPI php_stream_bucket *php_stream_bucket_make_writeable(php_stream_bucket *bucket TSRMLS_DC)
     118               0 : {
     119                 :         php_stream_bucket *retval;
     120                 : 
     121               0 :         php_stream_bucket_unlink(bucket TSRMLS_CC);
     122                 :         
     123               0 :         if (bucket->refcount == 1 && bucket->own_buf) {
     124               0 :                 return bucket;
     125                 :         }
     126                 : 
     127               0 :         retval = (php_stream_bucket*)pemalloc(sizeof(php_stream_bucket), bucket->is_persistent);
     128               0 :         memcpy(retval, bucket, sizeof(*retval));
     129                 : 
     130               0 :         retval->buf = pemalloc(retval->buflen, retval->is_persistent);
     131               0 :         memcpy(retval->buf, bucket->buf, retval->buflen);
     132                 : 
     133               0 :         retval->refcount = 1;
     134               0 :         retval->own_buf = 1;
     135                 : 
     136               0 :         php_stream_bucket_delref(bucket TSRMLS_CC);
     137                 :         
     138               0 :         return retval;
     139                 : }
     140                 : 
     141                 : PHPAPI int php_stream_bucket_split(php_stream_bucket *in, php_stream_bucket **left, php_stream_bucket **right, size_t length TSRMLS_DC)
     142               0 : {
     143               0 :         *left = (php_stream_bucket*)pecalloc(1, sizeof(php_stream_bucket), in->is_persistent);
     144               0 :         *right = (php_stream_bucket*)pecalloc(1, sizeof(php_stream_bucket), in->is_persistent);
     145                 : 
     146               0 :         if (*left == NULL || *right == NULL) {
     147                 :                 goto exit_fail;
     148                 :         }
     149                 : 
     150               0 :         (*left)->buf = pemalloc(length, in->is_persistent);
     151               0 :         (*left)->buflen = length;
     152               0 :         memcpy((*left)->buf, in->buf, length);
     153               0 :         (*left)->refcount = 1;
     154               0 :         (*left)->own_buf = 1;
     155               0 :         (*left)->is_persistent = in->is_persistent;
     156                 :         
     157               0 :         (*right)->buflen = in->buflen - length;
     158               0 :         (*right)->buf = pemalloc((*right)->buflen, in->is_persistent);
     159               0 :         memcpy((*right)->buf, in->buf + length, (*right)->buflen);
     160               0 :         (*right)->refcount = 1;
     161               0 :         (*right)->own_buf = 1;
     162               0 :         (*right)->is_persistent = in->is_persistent;
     163                 :         
     164               0 :         return SUCCESS;
     165                 :         
     166               0 : exit_fail:
     167               0 :         if (*right) {
     168               0 :                 if ((*right)->buf) {
     169               0 :                         pefree((*right)->buf, in->is_persistent);
     170                 :                 }
     171               0 :                 pefree(*right, in->is_persistent);
     172                 :         }
     173               0 :         if (*left) {
     174               0 :                 if ((*left)->buf) {
     175               0 :                         pefree((*left)->buf, in->is_persistent);
     176                 :                 }
     177               0 :                 pefree(*left, in->is_persistent);
     178                 :         }
     179               0 :         return FAILURE;
     180                 : }
     181                 : 
     182                 : PHPAPI void php_stream_bucket_delref(php_stream_bucket *bucket TSRMLS_DC)
     183             133 : {
     184             133 :         if (--bucket->refcount == 0) {
     185             133 :                 if (bucket->own_buf) {
     186              91 :                         pefree(bucket->buf, bucket->is_persistent);
     187                 :                 }
     188             133 :                 pefree(bucket, bucket->is_persistent);
     189                 :         }
     190             133 : }
     191                 : 
     192                 : PHPAPI void php_stream_bucket_prepend(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket TSRMLS_DC)
     193               0 : {
     194               0 :         bucket->next = brigade->head;
     195               0 :         bucket->prev = NULL;
     196                 : 
     197               0 :         if (brigade->head) {
     198               0 :                 brigade->head->prev = bucket;
     199                 :         } else {
     200               0 :                 brigade->tail = bucket;
     201                 :         }
     202               0 :         brigade->head = bucket;
     203               0 :         bucket->brigade = brigade;
     204               0 : }
     205                 : 
     206                 : PHPAPI void php_stream_bucket_append(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket TSRMLS_DC)
     207             133 : {
     208             133 :         if (brigade->tail == bucket) {
     209               0 :                 return;
     210                 :         }
     211                 : 
     212             133 :         bucket->prev = brigade->tail;
     213             133 :         bucket->next = NULL;
     214                 : 
     215             133 :         if (brigade->tail) {
     216              35 :                 brigade->tail->next = bucket;
     217                 :         } else {
     218              98 :                 brigade->head = bucket;
     219                 :         }
     220             133 :         brigade->tail = bucket;
     221             133 :         bucket->brigade = brigade;
     222                 : }
     223                 : 
     224                 : PHPAPI void php_stream_bucket_unlink(php_stream_bucket *bucket TSRMLS_DC)
     225             133 : {
     226             133 :         if (bucket->prev) {
     227               0 :                 bucket->prev->next = bucket->next;
     228             133 :         } else if (bucket->brigade) {
     229             133 :                 bucket->brigade->head = bucket->next;
     230                 :         }
     231             133 :         if (bucket->next) {
     232              35 :                 bucket->next->prev = bucket->prev;
     233              98 :         } else if (bucket->brigade) {
     234              98 :                 bucket->brigade->tail = bucket->prev;
     235                 :         }
     236             133 :         bucket->brigade = NULL;
     237             133 :         bucket->next = bucket->prev = NULL;
     238             133 : }
     239                 :         
     240                 : 
     241                 : 
     242                 : 
     243                 : 
     244                 : 
     245                 : 
     246                 : 
     247                 : /* We allow very simple pattern matching for filter factories:
     248                 :  * if "convert.charset.utf-8/sjis" is requested, we search first for an exact
     249                 :  * match. If that fails, we try "convert.charset.*", then "convert.*"
     250                 :  * This means that we don't need to clog up the hashtable with a zillion
     251                 :  * charsets (for example) but still be able to provide them all as filters */
     252                 : PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
     253              13 : {
     254              13 :         HashTable *filter_hash = (FG(stream_filters) ? FG(stream_filters) : &stream_filters_hash);
     255              13 :         php_stream_filter_factory *factory = NULL;
     256              13 :         php_stream_filter *filter = NULL;
     257                 :         int n;
     258                 :         char *period;
     259                 : 
     260              13 :         n = strlen(filtername);
     261                 :         
     262              13 :         if (SUCCESS == zend_hash_find(filter_hash, (char*)filtername, n + 1, (void**)&factory)) {
     263               0 :                 filter = factory->create_filter(filtername, filterparams, persistent TSRMLS_CC);
     264              13 :         } else if ((period = strrchr(filtername, '.'))) {
     265                 :                 /* try a wildcard */
     266                 :                 char *wildname;
     267                 : 
     268              13 :                 wildname = emalloc(n+3);
     269              13 :                 memcpy(wildname, filtername, n+1);
     270              13 :                 period = wildname + (period - filtername);
     271              39 :                 while (period && !filter) {
     272              13 :                         *period = '\0';
     273              13 :                         strcat(wildname, ".*");
     274              13 :                         if (SUCCESS == zend_hash_find(filter_hash, wildname, strlen(wildname) + 1, (void**)&factory)) {
     275              13 :                                 filter = factory->create_filter(filtername, filterparams, persistent TSRMLS_CC);
     276                 :                         }
     277                 : 
     278              13 :                         *period = '\0';
     279              13 :                         period = strrchr(wildname, '.');
     280                 :                 }
     281              13 :                 efree(wildname);
     282                 :         }
     283                 : 
     284              13 :         if (filter == NULL) {
     285                 :                 /* TODO: these need correct docrefs */
     286               0 :                 if (factory == NULL)
     287               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to locate filter \"%s\"", filtername);
     288                 :                 else
     289               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to create or locate filter \"%s\"", filtername);
     290                 :         }
     291                 :         
     292              13 :         return filter;
     293                 : }
     294                 : 
     295                 : PHPAPI php_stream_filter *_php_stream_filter_alloc(php_stream_filter_ops *fops, void *abstract, int persistent STREAMS_DC TSRMLS_DC)
     296              13 : {
     297                 :         php_stream_filter *filter;
     298                 : 
     299              13 :         filter = (php_stream_filter*) pemalloc_rel_orig(sizeof(php_stream_filter), persistent);
     300              13 :         memset(filter, 0, sizeof(php_stream_filter));
     301                 : 
     302              13 :         filter->fops = fops;
     303              13 :         filter->abstract = abstract;
     304              13 :         filter->is_persistent = persistent;
     305                 :         
     306              13 :         return filter;
     307                 : }
     308                 : 
     309                 : PHPAPI void php_stream_filter_free(php_stream_filter *filter TSRMLS_DC)
     310              13 : {
     311              13 :         if (filter->fops->dtor)
     312              10 :                 filter->fops->dtor(filter TSRMLS_CC);
     313              13 :         pefree(filter, filter->is_persistent);
     314              13 : }
     315                 : 
     316                 : PHPAPI void _php_stream_filter_prepend(php_stream_filter_chain *chain, php_stream_filter *filter TSRMLS_DC)
     317               0 : {
     318               0 :         filter->next = chain->head;
     319               0 :         filter->prev = NULL;
     320                 : 
     321               0 :         if (chain->head) {
     322               0 :                 chain->head->prev = filter;
     323                 :         } else {
     324               0 :                 chain->tail = filter;
     325                 :         }
     326               0 :         chain->head = filter;
     327               0 :         filter->chain = chain;
     328               0 : }
     329                 : 
     330                 : PHPAPI void _php_stream_filter_append(php_stream_filter_chain *chain, php_stream_filter *filter TSRMLS_DC)
     331              13 : {
     332              13 :         php_stream *stream = chain->stream;
     333                 : 
     334              13 :         filter->prev = chain->tail;
     335              13 :         filter->next = NULL;
     336              13 :         if (chain->tail) {
     337               7 :                 chain->tail->next = filter;
     338                 :         } else {
     339               6 :                 chain->head = filter;
     340                 :         }
     341              13 :         chain->tail = filter;
     342              13 :         filter->chain = chain;
     343                 : 
     344              13 :         if (&(stream->readfilters) == chain && (stream->writepos - stream->readpos) > 0) {
     345                 :                 /* Let's going ahead and wind anything in the buffer through this filter */
     346               0 :                 php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL };
     347               0 :                 php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out;
     348                 :                 php_stream_filter_status_t status;
     349                 :                 php_stream_bucket *bucket;
     350               0 :                 size_t consumed = 0;
     351                 : 
     352               0 :                 bucket = php_stream_bucket_new(stream, stream->readbuf + stream->readpos, stream->writepos - stream->readpos, 0, 0 TSRMLS_CC);
     353               0 :                 php_stream_bucket_append(brig_inp, bucket TSRMLS_CC);
     354               0 :                 status = filter->fops->filter(stream, filter, brig_inp, brig_outp, &consumed, PSFS_FLAG_NORMAL TSRMLS_CC);
     355                 : 
     356               0 :                 if (stream->readpos + consumed > (uint)stream->writepos || consumed < 0) {
     357                 :                         /* No behaving filter should cause this. */
     358               0 :                         status = PSFS_ERR_FATAL;
     359                 :                 }
     360                 : 
     361               0 :                 switch (status) {
     362                 :                         case PSFS_ERR_FATAL:
     363                 :                                 /* If this first cycle simply fails then there's something wrong with the filter.
     364                 :                                    Pull the filter off the chain and leave the read buffer alone. */
     365               0 :                                 if (chain->head == filter) {
     366               0 :                                         chain->head = NULL;
     367               0 :                                         chain->tail = NULL;
     368                 :                                 } else {
     369               0 :                                         filter->prev->next = NULL;
     370               0 :                                         chain->tail = filter->prev;
     371                 :                                 }
     372               0 :                                 php_stream_bucket_unlink(bucket TSRMLS_CC);
     373               0 :                                 php_stream_bucket_delref(bucket TSRMLS_CC);
     374               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter failed to process pre-buffered data.  Not adding to filterchain.");
     375               0 :                                 break;
     376                 :                         case PSFS_FEED_ME:
     377                 :                                 /* We don't actually need data yet,
     378                 :                                    leave this filter in a feed me state until data is needed. 
     379                 :                                    Reset stream's internal read buffer since the filter is "holding" it. */
     380               0 :                                 stream->readpos = 0;
     381               0 :                                 stream->writepos = 0;
     382               0 :                                 break;
     383                 :                         case PSFS_PASS_ON:
     384                 :                                 /* Put any filtered data onto the readbuffer stack.
     385                 :                                    Previously read data has been at least partially consumed. */
     386               0 :                                 stream->readpos += consumed;
     387                 : 
     388               0 :                                 if (stream->writepos == stream->readpos) {
     389                 :                                         /* Entirely consumed */
     390               0 :                                         stream->writepos = 0;
     391               0 :                                         stream->readpos = 0;
     392                 :                                 }
     393                 : 
     394               0 :                                 while (brig_outp->head) {
     395               0 :                                         bucket = brig_outp->head;
     396                 :                                         /* Grow buffer to hold this bucket if need be.
     397                 :                                            TODO: See warning in main/stream/streams.c::php_stream_fill_read_buffer */
     398               0 :                                         if (stream->readbuflen - stream->writepos < bucket->buflen) {
     399               0 :                                                 stream->readbuflen += bucket->buflen;
     400               0 :                                                 stream->readbuf = perealloc(stream->readbuf, stream->readbuflen, stream->is_persistent);
     401                 :                                         }
     402               0 :                                         memcpy(stream->readbuf + stream->writepos, bucket->buf, bucket->buflen);
     403               0 :                                         stream->writepos += bucket->buflen;
     404                 : 
     405               0 :                                         php_stream_bucket_unlink(bucket TSRMLS_CC);
     406               0 :                                         php_stream_bucket_delref(bucket TSRMLS_CC);
     407                 :                                 }
     408                 :                                 break;
     409                 :                 }
     410                 :         }
     411                 : 
     412              13 : }
     413                 : 
     414                 : PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish TSRMLS_DC)
     415               0 : {
     416               0 :         php_stream_bucket_brigade brig_a = { NULL, NULL }, brig_b = { NULL, NULL }, *inp = &brig_a, *outp = &brig_b, *brig_temp;
     417                 :         php_stream_bucket *bucket;
     418                 :         php_stream_filter_chain *chain;
     419                 :         php_stream_filter *current;
     420                 :         php_stream *stream;
     421               0 :         size_t flushed_size = 0;
     422               0 :         long flags = (finish ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC);
     423                 : 
     424               0 :         if (!filter->chain || !filter->chain->stream) {
     425                 :                 /* Filter is not attached to a chain, or chain is somehow not part of a stream */
     426               0 :                 return FAILURE;
     427                 :         }
     428                 : 
     429               0 :         chain = filter->chain;
     430               0 :         stream = chain->stream;
     431                 : 
     432               0 :         for(current = filter; current; current = current->next) {
     433                 :                 php_stream_filter_status_t status;
     434                 : 
     435               0 :                 status = filter->fops->filter(stream, filter, inp, outp, NULL, flags TSRMLS_CC);
     436               0 :                 if (status == PSFS_FEED_ME) {
     437                 :                         /* We've flushed the data far enough */
     438               0 :                         return SUCCESS;
     439                 :                 }
     440               0 :                 if (status == PSFS_ERR_FATAL) {
     441               0 :                         return FAILURE;
     442                 :                 }
     443                 :                 /* Otherwise we have data available to PASS_ON
     444                 :                         Swap the brigades and continue */
     445               0 :                 brig_temp = inp;
     446               0 :                 inp = outp;
     447               0 :                 outp = brig_temp;
     448               0 :                 outp->head = NULL;
     449               0 :                 outp->tail = NULL;
     450                 : 
     451               0 :                 flags = PSFS_FLAG_NORMAL;
     452                 :         }
     453                 : 
     454                 :         /* Last filter returned data via PSFS_PASS_ON
     455                 :                 Do something with it */
     456                 : 
     457               0 :         for(bucket = inp->head; bucket; bucket = bucket->next) {
     458               0 :                 flushed_size += bucket->buflen;
     459                 :         }
     460                 : 
     461               0 :         if (flushed_size == 0) {
     462                 :                 /* Unlikely, but possible */
     463               0 :                 return SUCCESS;
     464                 :         }
     465                 : 
     466               0 :         if (chain == &(stream->readfilters)) {
     467                 :                 /* Dump any newly flushed data to the read buffer */
     468               0 :                 if (stream->readpos > 0) {
     469                 :                         /* Back the buffer up */
     470               0 :                         memcpy(stream->readbuf, stream->readbuf + stream->readpos, stream->writepos - stream->readpos);
     471               0 :                         stream->readpos = 0;
     472               0 :                         stream->writepos -= stream->readpos;
     473                 :                 }
     474               0 :                 if (flushed_size > (stream->readbuflen - stream->writepos)) {
     475                 :                         /* Grow the buffer */
     476               0 :                         stream->readbuf = perealloc(stream->readbuf, stream->writepos + flushed_size + stream->chunk_size, stream->is_persistent);
     477                 :                 }
     478               0 :                 while ((bucket = inp->head)) {
     479               0 :                         memcpy(stream->readbuf + stream->writepos, bucket->buf, bucket->buflen);
     480               0 :                         stream->writepos += bucket->buflen;
     481               0 :                         php_stream_bucket_unlink(bucket TSRMLS_CC);
     482               0 :                         php_stream_bucket_delref(bucket TSRMLS_CC);
     483                 :                 }
     484               0 :         } else if (chain == &(stream->writefilters)) {
     485                 :                 /* Send flushed data to the stream */
     486               0 :                 while ((bucket = inp->head)) {
     487               0 :                         stream->ops->write(stream, bucket->buf, bucket->buflen TSRMLS_CC);
     488               0 :                         php_stream_bucket_unlink(bucket TSRMLS_CC);
     489               0 :                         php_stream_bucket_delref(bucket TSRMLS_CC);
     490                 :                 }
     491                 :         }
     492                 : 
     493               0 :         return SUCCESS;
     494                 : }
     495                 : 
     496                 : PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor TSRMLS_DC)
     497              13 : {
     498              13 :         if (filter->prev) {
     499               0 :                 filter->prev->next = filter->next;
     500                 :         } else {
     501              13 :                 filter->chain->head = filter->next;
     502                 :         }
     503              13 :         if (filter->next) {
     504               7 :                 filter->next->prev = filter->prev;
     505                 :         } else {
     506               6 :                 filter->chain->tail = filter->prev;
     507                 :         }
     508                 : 
     509              13 :         if (filter->rsrc_id > 0) {
     510              13 :                 zend_list_delete(filter->rsrc_id);
     511                 :         }
     512                 : 
     513              13 :         if (call_dtor) {
     514              13 :                 php_stream_filter_free(filter TSRMLS_CC);
     515              13 :                 return NULL;
     516                 :         }
     517               0 :         return filter;
     518                 : }
     519                 : 
     520                 : /*
     521                 :  * Local variables:
     522                 :  * tab-width: 4
     523                 :  * c-basic-offset: 4
     524                 :  * End:
     525                 :  * vim600: noet sw=4 ts=4 fdm=marker
     526                 :  * vim<600: noet sw=4 ts=4
     527                 :  */

Generated by: LTP GCOV extension version 1.5