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

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors:                                                             |
      16                 :    | Wez Furlong (wez@thebrainroom.com)                                   |
      17                 :    | Sara Golemon (pollita@php.net)                                       |
      18                 :    | Moriyoshi Koizumi (moriyoshi@php.net)                                |
      19                 :    | Marcus Boerger (helly@php.net)                                       |
      20                 :    +----------------------------------------------------------------------+
      21                 : */
      22                 : 
      23                 : /* $Id: filters.c,v 1.44.2.6.2.4 2007/01/01 09:36:08 sebastian Exp $ */
      24                 : 
      25                 : #include "php.h"
      26                 : #include "php_globals.h"
      27                 : #include "ext/standard/basic_functions.h"
      28                 : #include "ext/standard/file.h"
      29                 : #include "ext/standard/php_string.h"
      30                 : #include "ext/standard/php_smart_str.h"
      31                 : 
      32                 : /* {{{ rot13 stream filter implementation */
      33                 : static char rot13_from[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
      34                 : static char rot13_to[] = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
      35                 : 
      36                 : static php_stream_filter_status_t strfilter_rot13_filter(
      37                 :         php_stream *stream,
      38                 :         php_stream_filter *thisfilter,
      39                 :         php_stream_bucket_brigade *buckets_in,
      40                 :         php_stream_bucket_brigade *buckets_out,
      41                 :         size_t *bytes_consumed,
      42                 :         int flags
      43                 :         TSRMLS_DC)
      44               0 : {
      45                 :         php_stream_bucket *bucket;
      46               0 :         size_t consumed = 0;
      47                 : 
      48               0 :         while (buckets_in->head) {
      49               0 :                 bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
      50                 :                 
      51               0 :                 php_strtr(bucket->buf, bucket->buflen, rot13_from, rot13_to, 52);
      52               0 :                 consumed += bucket->buflen;
      53                 :                 
      54               0 :                 php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
      55                 :         }
      56                 : 
      57               0 :         if (bytes_consumed) {
      58               0 :                 *bytes_consumed = consumed;
      59                 :         }
      60                 :         
      61               0 :         return PSFS_PASS_ON;
      62                 : }
      63                 : 
      64                 : static php_stream_filter_ops strfilter_rot13_ops = {
      65                 :         strfilter_rot13_filter,
      66                 :         NULL,
      67                 :         "string.rot13"
      68                 : };
      69                 : 
      70                 : static php_stream_filter *strfilter_rot13_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
      71               0 : {
      72               0 :         return php_stream_filter_alloc(&strfilter_rot13_ops, NULL, persistent);
      73                 : }
      74                 : 
      75                 : static php_stream_filter_factory strfilter_rot13_factory = {
      76                 :         strfilter_rot13_create
      77                 : };
      78                 : /* }}} */
      79                 : 
      80                 : /* {{{ string.toupper / string.tolower stream filter implementation */
      81                 : static char lowercase[] = "abcdefghijklmnopqrstuvwxyz";
      82                 : static char uppercase[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      83                 : 
      84                 : static php_stream_filter_status_t strfilter_toupper_filter(
      85                 :         php_stream *stream,
      86                 :         php_stream_filter *thisfilter,
      87                 :         php_stream_bucket_brigade *buckets_in,
      88                 :         php_stream_bucket_brigade *buckets_out,
      89                 :         size_t *bytes_consumed,
      90                 :         int flags
      91                 :         TSRMLS_DC)
      92               0 : {
      93                 :         php_stream_bucket *bucket;
      94               0 :         size_t consumed = 0;
      95                 : 
      96               0 :         while (buckets_in->head) {
      97               0 :                 bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
      98                 :                 
      99               0 :                 php_strtr(bucket->buf, bucket->buflen, lowercase, uppercase, 26);
     100               0 :                 consumed += bucket->buflen;
     101                 :                 
     102               0 :                 php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
     103                 :         }
     104                 : 
     105               0 :         if (bytes_consumed) {
     106               0 :                 *bytes_consumed = consumed;
     107                 :         }
     108                 : 
     109               0 :         return PSFS_PASS_ON;
     110                 : }
     111                 : 
     112                 : static php_stream_filter_status_t strfilter_tolower_filter(
     113                 :         php_stream *stream,
     114                 :         php_stream_filter *thisfilter,
     115                 :         php_stream_bucket_brigade *buckets_in,
     116                 :         php_stream_bucket_brigade *buckets_out,
     117                 :         size_t *bytes_consumed,
     118                 :         int flags
     119                 :         TSRMLS_DC)
     120               0 : {
     121                 :         php_stream_bucket *bucket;
     122               0 :         size_t consumed = 0;
     123                 : 
     124               0 :         while (buckets_in->head) {
     125               0 :                 bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
     126                 :                 
     127               0 :                 php_strtr(bucket->buf, bucket->buflen, uppercase, lowercase, 26);
     128               0 :                 consumed += bucket->buflen;
     129                 :                 
     130               0 :                 php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
     131                 :         }
     132                 : 
     133               0 :         if (bytes_consumed) {
     134               0 :                 *bytes_consumed = consumed;
     135                 :         }
     136                 : 
     137               0 :         return PSFS_PASS_ON;
     138                 : }
     139                 : 
     140                 : static php_stream_filter_ops strfilter_toupper_ops = {
     141                 :         strfilter_toupper_filter,
     142                 :         NULL,
     143                 :         "string.toupper"
     144                 : };
     145                 : 
     146                 : static php_stream_filter_ops strfilter_tolower_ops = {
     147                 :         strfilter_tolower_filter,
     148                 :         NULL,
     149                 :         "string.tolower"
     150                 : };
     151                 : 
     152                 : static php_stream_filter *strfilter_toupper_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
     153               0 : {
     154               0 :         return php_stream_filter_alloc(&strfilter_toupper_ops, NULL, persistent);
     155                 : }
     156                 : 
     157                 : static php_stream_filter *strfilter_tolower_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
     158               0 : {
     159               0 :         return php_stream_filter_alloc(&strfilter_tolower_ops, NULL, persistent);
     160                 : }
     161                 : 
     162                 : static php_stream_filter_factory strfilter_toupper_factory = {
     163                 :         strfilter_toupper_create
     164                 : };
     165                 : 
     166                 : static php_stream_filter_factory strfilter_tolower_factory = {
     167                 :         strfilter_tolower_create
     168                 : };
     169                 : /* }}} */
     170                 : 
     171                 : /* {{{ strip_tags filter implementation */
     172                 : typedef struct _php_strip_tags_filter {
     173                 :         const char *allowed_tags;
     174                 :         int allowed_tags_len;
     175                 :         int state;
     176                 :         int persistent;
     177                 : } php_strip_tags_filter;
     178                 : 
     179                 : static int php_strip_tags_filter_ctor(php_strip_tags_filter *inst, const char *allowed_tags, int allowed_tags_len, int persistent)
     180               0 : {
     181               0 :         if (allowed_tags != NULL) {
     182               0 :                 if (NULL == (inst->allowed_tags = pemalloc(allowed_tags_len, persistent))) {
     183               0 :                         return FAILURE;
     184                 :                 }
     185               0 :                 memcpy((char *)inst->allowed_tags, allowed_tags, allowed_tags_len);
     186               0 :                 inst->allowed_tags_len = allowed_tags_len; 
     187                 :         } else {
     188               0 :                 inst->allowed_tags = NULL;
     189                 :         }
     190               0 :         inst->state = 0;
     191               0 :         inst->persistent = persistent;
     192                 : 
     193               0 :         return SUCCESS;
     194                 : }       
     195                 : 
     196                 : static void php_strip_tags_filter_dtor(php_strip_tags_filter *inst)
     197               0 : {
     198               0 :         if (inst->allowed_tags != NULL) {
     199               0 :                 pefree((void *)inst->allowed_tags, inst->persistent);
     200                 :         }
     201               0 : }
     202                 : 
     203                 : static php_stream_filter_status_t strfilter_strip_tags_filter(
     204                 :         php_stream *stream,
     205                 :         php_stream_filter *thisfilter,
     206                 :         php_stream_bucket_brigade *buckets_in,
     207                 :         php_stream_bucket_brigade *buckets_out,
     208                 :         size_t *bytes_consumed,
     209                 :         int flags
     210                 :         TSRMLS_DC)
     211               0 : {
     212                 :         php_stream_bucket *bucket;
     213               0 :         size_t consumed = 0;
     214               0 :         php_strip_tags_filter *inst = (php_strip_tags_filter *) thisfilter->abstract;
     215                 : 
     216               0 :         while (buckets_in->head) {
     217               0 :                 bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
     218               0 :                 consumed = bucket->buflen;
     219                 :                 
     220               0 :                 bucket->buflen = php_strip_tags(bucket->buf, bucket->buflen, &(inst->state), (char *)inst->allowed_tags, inst->allowed_tags_len);
     221                 :         
     222               0 :                 php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
     223                 :         }
     224                 : 
     225               0 :         if (bytes_consumed) {
     226               0 :                 *bytes_consumed = consumed;
     227                 :         }
     228                 :         
     229               0 :         return PSFS_PASS_ON;
     230                 : }
     231                 : 
     232                 : static void strfilter_strip_tags_dtor(php_stream_filter *thisfilter TSRMLS_DC)
     233               0 : {
     234                 :         assert(thisfilter->abstract != NULL);
     235                 : 
     236               0 :         php_strip_tags_filter_dtor((php_strip_tags_filter *)thisfilter->abstract);
     237                 : 
     238               0 :         pefree(thisfilter->abstract, ((php_strip_tags_filter *)thisfilter->abstract)->persistent);
     239               0 : }
     240                 : 
     241                 : static php_stream_filter_ops strfilter_strip_tags_ops = {
     242                 :         strfilter_strip_tags_filter,
     243                 :         strfilter_strip_tags_dtor,
     244                 :         "string.strip_tags"
     245                 : };
     246                 : 
     247                 : static php_stream_filter *strfilter_strip_tags_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
     248               0 : {
     249                 :         php_strip_tags_filter *inst;
     250               0 :         smart_str tags_ss = { 0, 0, 0 };
     251                 :         
     252               0 :         inst = pemalloc(sizeof(php_strip_tags_filter), persistent);
     253                 : 
     254               0 :         if (inst == NULL) { /* it's possible pemalloc returns NULL
     255                 :                                                    instead of causing it to bail out */
     256               0 :                 return NULL;
     257                 :         }
     258                 :         
     259               0 :         if (filterparams != NULL) {
     260               0 :                 if (Z_TYPE_P(filterparams) == IS_ARRAY) {
     261                 :                         HashPosition pos;
     262                 :                         zval **tmp;
     263                 : 
     264               0 :                         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(filterparams), &pos);
     265               0 :                         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(filterparams), (void **) &tmp, &pos) == SUCCESS) {
     266               0 :                                 convert_to_string_ex(tmp);
     267               0 :                                 smart_str_appendc(&tags_ss, '<');
     268               0 :                                 smart_str_appendl(&tags_ss, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     269               0 :                                 smart_str_appendc(&tags_ss, '>');
     270               0 :                                 zend_hash_move_forward_ex(Z_ARRVAL_P(filterparams), &pos);
     271                 :                         }
     272               0 :                         smart_str_0(&tags_ss);
     273                 :                 } else {
     274                 :                         /* FIXME: convert_to_* may clutter zvals and lead it into segfault ? */
     275               0 :                         convert_to_string_ex(&filterparams);
     276                 : 
     277               0 :                         tags_ss.c = Z_STRVAL_P(filterparams);
     278               0 :                         tags_ss.len = Z_STRLEN_P(filterparams);
     279               0 :                         tags_ss.a = 0;
     280                 :                 }
     281                 :         }
     282                 : 
     283               0 :         if (php_strip_tags_filter_ctor(inst, tags_ss.c, tags_ss.len, persistent) != SUCCESS) {
     284               0 :                 if (tags_ss.a != 0) {
     285               0 :                         STR_FREE(tags_ss.c);
     286                 :                 }
     287               0 :                 pefree(inst, persistent);
     288               0 :                 return NULL;
     289                 :         }
     290                 : 
     291               0 :         if (tags_ss.a != 0) {
     292               0 :                 STR_FREE(tags_ss.c);
     293                 :         }
     294                 : 
     295               0 :         return php_stream_filter_alloc(&strfilter_strip_tags_ops, inst, persistent);
     296                 : }
     297                 : 
     298                 : static php_stream_filter_factory strfilter_strip_tags_factory = {
     299                 :         strfilter_strip_tags_create
     300                 : };
     301                 : 
     302                 : /* }}} */
     303                 : 
     304                 : /* {{{ base64 / quoted_printable stream filter implementation */
     305                 : 
     306                 : typedef enum _php_conv_err_t {
     307                 :         PHP_CONV_ERR_SUCCESS = SUCCESS,
     308                 :         PHP_CONV_ERR_UNKNOWN,
     309                 :         PHP_CONV_ERR_TOO_BIG,
     310                 :         PHP_CONV_ERR_INVALID_SEQ,
     311                 :         PHP_CONV_ERR_UNEXPECTED_EOS,
     312                 :         PHP_CONV_ERR_EXISTS,
     313                 :         PHP_CONV_ERR_MORE,
     314                 :         PHP_CONV_ERR_ALLOC,
     315                 :         PHP_CONV_ERR_NOT_FOUND
     316                 : } php_conv_err_t;
     317                 : 
     318                 : typedef struct _php_conv php_conv;
     319                 : 
     320                 : typedef php_conv_err_t (*php_conv_convert_func)(php_conv *, const char **, size_t *, char **, size_t *);
     321                 : typedef void (*php_conv_dtor_func)(php_conv *);
     322                 : 
     323                 : struct _php_conv {
     324                 :         php_conv_convert_func convert_op;
     325                 :         php_conv_dtor_func dtor;
     326                 : };
     327                 : 
     328                 : #define php_conv_convert(a, b, c, d, e) ((php_conv *)(a))->convert_op((php_conv *)(a), (b), (c), (d), (e))
     329                 : #define php_conv_dtor(a) ((php_conv *)a)->dtor((a))
     330                 : 
     331                 : /* {{{ php_conv_base64_encode */
     332                 : typedef struct _php_conv_base64_encode {
     333                 :         php_conv _super;
     334                 : 
     335                 :         unsigned char erem[3];
     336                 :         size_t erem_len;
     337                 :         unsigned int line_ccnt;
     338                 :         unsigned int line_len;
     339                 :         const char *lbchars;
     340                 :         int lbchars_dup;
     341                 :         size_t lbchars_len;
     342                 :         int persistent;
     343                 : } php_conv_base64_encode;
     344                 : 
     345                 : static php_conv_err_t php_conv_base64_encode_convert(php_conv_base64_encode *inst, const char **in_p, size_t *in_left, char **out_p, size_t *out_left);
     346                 : static void php_conv_base64_encode_dtor(php_conv_base64_encode *inst);
     347                 : 
     348                 : static unsigned char b64_tbl_enc[256] = {
     349                 :         'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
     350                 :         'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
     351                 :         'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
     352                 :         'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
     353                 :         'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
     354                 :         'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
     355                 :         'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
     356                 :         'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
     357                 :         'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
     358                 :         'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
     359                 :         'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
     360                 :         'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
     361                 :         'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
     362                 :         'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
     363                 :         'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
     364                 :         'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
     365                 : };
     366                 : 
     367                 : static php_conv_err_t php_conv_base64_encode_ctor(php_conv_base64_encode *inst, unsigned int line_len, const char *lbchars, size_t lbchars_len, int lbchars_dup, int persistent)
     368               0 : {
     369               0 :         inst->_super.convert_op = (php_conv_convert_func) php_conv_base64_encode_convert;
     370               0 :         inst->_super.dtor = (php_conv_dtor_func) php_conv_base64_encode_dtor;
     371               0 :         inst->erem_len = 0;
     372               0 :         inst->line_ccnt = line_len;
     373               0 :         inst->line_len = line_len;
     374               0 :         if (lbchars != NULL) {
     375               0 :                 inst->lbchars = (lbchars_dup ? pestrdup(lbchars, persistent) : lbchars);
     376               0 :                 inst->lbchars_len = lbchars_len;
     377                 :         } else {
     378               0 :                 inst->lbchars = NULL;
     379                 :         }
     380               0 :         inst->lbchars_dup = lbchars_dup;
     381               0 :         inst->persistent = persistent;
     382               0 :         return PHP_CONV_ERR_SUCCESS;
     383                 : }
     384                 : 
     385                 : static void php_conv_base64_encode_dtor(php_conv_base64_encode *inst)
     386               0 : {
     387                 :         assert(inst != NULL);
     388               0 :         if (inst->lbchars_dup && inst->lbchars != NULL) {
     389               0 :                 pefree((void *)inst->lbchars, inst->persistent);
     390                 :         }
     391               0 : }
     392                 : 
     393                 : static php_conv_err_t php_conv_base64_encode_flush(php_conv_base64_encode *inst, const char **in_pp, size_t *in_left_p, char **out_pp, size_t *out_left_p)
     394               0 : {
     395               0 :         volatile php_conv_err_t err = PHP_CONV_ERR_SUCCESS;
     396                 :         register unsigned char *pd;
     397                 :         register size_t ocnt;
     398                 :         unsigned int line_ccnt;
     399                 : 
     400               0 :         pd = (unsigned char *)(*out_pp);
     401               0 :         ocnt = *out_left_p;
     402               0 :         line_ccnt = inst->line_ccnt;
     403                 : 
     404               0 :         switch (inst->erem_len) {
     405                 :                 case 0:
     406                 :                         /* do nothing */
     407               0 :                         break;
     408                 : 
     409                 :                 case 1:
     410               0 :                         if (line_ccnt < 4 && inst->lbchars != NULL) {
     411               0 :                                 if (ocnt < inst->lbchars_len) {
     412               0 :                                         return PHP_CONV_ERR_TOO_BIG;
     413                 :                                 }
     414               0 :                                 memcpy(pd, inst->lbchars, inst->lbchars_len);
     415               0 :                                 pd += inst->lbchars_len;
     416               0 :                                 ocnt -= inst->lbchars_len;
     417               0 :                                 line_ccnt = inst->line_len;
     418                 :                         }
     419               0 :                         if (ocnt < 4) {
     420               0 :                                 err = PHP_CONV_ERR_TOO_BIG;
     421               0 :                                 goto out;
     422                 :                         }
     423               0 :                         *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)];
     424               0 :                         *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4)];
     425               0 :                         *(pd++) = '=';
     426               0 :                         *(pd++) = '=';
     427               0 :                         inst->erem_len = 0;
     428               0 :                         ocnt -= 4;
     429               0 :                         line_ccnt -= 4;
     430               0 :                         break;
     431                 : 
     432                 :                 case 2: 
     433               0 :                         if (line_ccnt < 4 && inst->lbchars != NULL) {
     434               0 :                                 if (ocnt < inst->lbchars_len) {
     435               0 :                                         return PHP_CONV_ERR_TOO_BIG;
     436                 :                                 }
     437               0 :                                 memcpy(pd, inst->lbchars, inst->lbchars_len);
     438               0 :                                 pd += inst->lbchars_len;
     439               0 :                                 ocnt -= inst->lbchars_len;
     440               0 :                                 line_ccnt = inst->line_len;
     441                 :                         }
     442               0 :                         if (ocnt < 4) {
     443               0 :                                 err = PHP_CONV_ERR_TOO_BIG;
     444               0 :                                 goto out;
     445                 :                         }
     446               0 :                         *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)];
     447               0 :                         *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4) | (inst->erem[1] >> 4)];
     448               0 :                         *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[1] << 2)];
     449               0 :                         *(pd++) = '=';
     450               0 :                         inst->erem_len = 0;
     451               0 :                         ocnt -=4;
     452               0 :                         line_ccnt -= 4;
     453               0 :                         break;
     454                 : 
     455                 :                 default:
     456                 :                         /* should not happen... */
     457               0 :                         err = PHP_CONV_ERR_UNKNOWN;
     458                 :                         break;
     459                 :         }
     460               0 : out:
     461               0 :         *out_pp = (char *)pd;
     462               0 :         *out_left_p = ocnt;
     463               0 :         inst->line_ccnt = line_ccnt;
     464               0 :         return err;
     465                 : }
     466                 : 
     467                 : static php_conv_err_t php_conv_base64_encode_convert(php_conv_base64_encode *inst, const char **in_pp, size_t *in_left_p, char **out_pp, size_t *out_left_p)
     468               0 : {
     469               0 :         volatile php_conv_err_t err = PHP_CONV_ERR_SUCCESS;
     470                 :         register size_t ocnt, icnt;
     471                 :         register unsigned char *ps, *pd;
     472                 :         register unsigned int line_ccnt;
     473                 : 
     474               0 :         if (in_pp == NULL || in_left_p == NULL) { 
     475               0 :                 return php_conv_base64_encode_flush(inst, in_pp, in_left_p, out_pp, out_left_p);
     476                 :         }
     477                 : 
     478               0 :         pd = (unsigned char *)(*out_pp);
     479               0 :         ocnt = *out_left_p;
     480               0 :         ps = (unsigned char *)(*in_pp);
     481               0 :         icnt = *in_left_p;
     482               0 :         line_ccnt = inst->line_ccnt;
     483                 : 
     484                 :         /* consume the remainder first */
     485               0 :         switch (inst->erem_len) {
     486                 :                 case 1:
     487               0 :                         if (icnt >= 2) {
     488               0 :                                 if (line_ccnt < 4 && inst->lbchars != NULL) {
     489               0 :                                         if (ocnt < inst->lbchars_len) {
     490               0 :                                                 return PHP_CONV_ERR_TOO_BIG;
     491                 :                                         }
     492               0 :                                         memcpy(pd, inst->lbchars, inst->lbchars_len);
     493               0 :                                         pd += inst->lbchars_len;
     494               0 :                                         ocnt -= inst->lbchars_len;
     495               0 :                                         line_ccnt = inst->line_len;
     496                 :                                 }
     497               0 :                                 if (ocnt < 4) {
     498               0 :                                         err = PHP_CONV_ERR_TOO_BIG;
     499               0 :                                         goto out;
     500                 :                                 }
     501               0 :                                 *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)];
     502               0 :                                 *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4) | (ps[0] >> 4)];
     503               0 :                                 *(pd++) = b64_tbl_enc[(unsigned char)(ps[0] << 2) | (ps[1] >> 6)];
     504               0 :                                 *(pd++) = b64_tbl_enc[ps[1]];
     505               0 :                                 ocnt -= 4;
     506               0 :                                 ps += 2;
     507               0 :                                 icnt -= 2;
     508               0 :                                 inst->erem_len = 0;
     509               0 :                                 line_ccnt -= 4;
     510                 :                         }
     511               0 :                         break;
     512                 : 
     513                 :                 case 2: 
     514               0 :                         if (icnt >= 1) {
     515               0 :                                 if (inst->line_ccnt < 4 && inst->lbchars != NULL) {
     516               0 :                                         if (ocnt < inst->lbchars_len) {
     517               0 :                                                 return PHP_CONV_ERR_TOO_BIG;
     518                 :                                         }
     519               0 :                                         memcpy(pd, inst->lbchars, inst->lbchars_len);
     520               0 :                                         pd += inst->lbchars_len;
     521               0 :                                         ocnt -= inst->lbchars_len;
     522               0 :                                         line_ccnt = inst->line_len;
     523                 :                                 }
     524               0 :                                 if (ocnt < 4) {
     525               0 :                                         err = PHP_CONV_ERR_TOO_BIG;
     526               0 :                                         goto out;
     527                 :                                 }
     528               0 :                                 *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)];
     529               0 :                                 *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4) | (inst->erem[1] >> 4)];
     530               0 :                                 *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[1] << 2) | (ps[0] >> 6)];
     531               0 :                                 *(pd++) = b64_tbl_enc[ps[0]];
     532               0 :                                 ocnt -= 4;
     533               0 :                                 ps += 1;
     534               0 :                                 icnt -= 1;
     535               0 :                                 inst->erem_len = 0;
     536               0 :                                 line_ccnt -= 4;
     537                 :                         }
     538                 :                         break;
     539                 :         }
     540                 : 
     541               0 :         while (icnt >= 3) {
     542               0 :                 if (line_ccnt < 4 && inst->lbchars != NULL) {
     543               0 :                         if (ocnt < inst->lbchars_len) {
     544               0 :                                 err = PHP_CONV_ERR_TOO_BIG;
     545               0 :                                 goto out;
     546                 :                         }
     547               0 :                         memcpy(pd, inst->lbchars, inst->lbchars_len);
     548               0 :                         pd += inst->lbchars_len;
     549               0 :                         ocnt -= inst->lbchars_len;
     550               0 :                         line_ccnt = inst->line_len;
     551                 :                 }
     552               0 :                 if (ocnt < 4) {
     553               0 :                         err = PHP_CONV_ERR_TOO_BIG;
     554               0 :                         goto out;
     555                 :                 }
     556               0 :                 *(pd++) = b64_tbl_enc[ps[0] >> 2];
     557               0 :                 *(pd++) = b64_tbl_enc[(unsigned char)(ps[0] << 4) | (ps[1] >> 4)];
     558               0 :                 *(pd++) = b64_tbl_enc[(unsigned char)(ps[1] << 2) | (ps[2] >> 6)];
     559               0 :                 *(pd++) = b64_tbl_enc[ps[2]];
     560                 : 
     561               0 :                 ps += 3;
     562               0 :                 icnt -=3;
     563               0 :                 ocnt -= 4;
     564               0 :                 line_ccnt -= 4;
     565                 :         }
     566               0 :         for (;icnt > 0; icnt--) {
     567               0 :                 inst->erem[inst->erem_len++] = *(ps++);
     568                 :         }
     569                 : 
     570               0 : out:
     571               0 :         *in_pp = (const char *)ps;
     572               0 :         *in_left_p = icnt;
     573               0 :         *out_pp = (char *)pd;
     574               0 :         *out_left_p = ocnt;
     575               0 :         inst->line_ccnt = line_ccnt;
     576                 : 
     577               0 :         return err;
     578                 : }
     579                 : 
     580                 : /* }}} */
     581                 : 
     582                 : /* {{{ php_conv_base64_decode */
     583                 : typedef struct _php_conv_base64_decode {
     584                 :         php_conv _super;
     585                 : 
     586                 :         unsigned int urem;
     587                 :         unsigned int urem_nbits;
     588                 :         unsigned int ustat;
     589                 :         int eos;
     590                 : } php_conv_base64_decode;
     591                 : 
     592                 : static php_conv_err_t php_conv_base64_decode_convert(php_conv_base64_decode *inst, const char **in_p, size_t *in_left, char **out_p, size_t *out_left);
     593                 : static void php_conv_base64_decode_dtor(php_conv_base64_decode *inst);
     594                 : 
     595                 : static unsigned int b64_tbl_dec[256] = {
     596                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     597                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     598                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
     599                 :         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64,128, 64, 64,
     600                 :         64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
     601                 :         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
     602                 :         64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
     603                 :         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
     604                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     605                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     606                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     607                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     608                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     609                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     610                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
     611                 :         64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
     612                 : };
     613                 : 
     614                 : static int php_conv_base64_decode_ctor(php_conv_base64_decode *inst)
     615               0 : {
     616               0 :         inst->_super.convert_op = (php_conv_convert_func) php_conv_base64_decode_convert;
     617               0 :         inst->_super.dtor = (php_conv_dtor_func) php_conv_base64_decode_dtor;
     618                 : 
     619               0 :         inst->urem = 0;
     620               0 :         inst->urem_nbits = 0;
     621               0 :         inst->ustat = 0;
     622               0 :         inst->eos = 0;
     623               0 :         return SUCCESS;
     624                 : }
     625                 : 
     626                 : static void php_conv_base64_decode_dtor(php_conv_base64_decode *inst)
     627               0 : {
     628                 :         /* do nothing */
     629               0 : }
     630                 : 
     631                 : #define bmask(a) (0xffff >> (16 - a))
     632                 : static php_conv_err_t php_conv_base64_decode_convert(php_conv_base64_decode *inst, const char **in_pp, size_t *in_left_p, char **out_pp, size_t *out_left_p)
     633               0 : {
     634                 :         php_conv_err_t err;
     635                 : 
     636                 :         unsigned int urem, urem_nbits;
     637                 :         unsigned int pack, pack_bcnt;
     638                 :         unsigned char *ps, *pd;
     639                 :         size_t icnt, ocnt;
     640                 :         unsigned int ustat;
     641                 : 
     642                 :         static const unsigned int nbitsof_pack = 8;
     643                 : 
     644               0 :         if (in_pp == NULL || in_left_p == NULL) {
     645               0 :                 if (inst->eos || inst->urem_nbits == 0) { 
     646               0 :                         return PHP_CONV_ERR_SUCCESS;
     647                 :                 }
     648               0 :                 return PHP_CONV_ERR_UNEXPECTED_EOS;
     649                 :         }
     650                 : 
     651               0 :         err = PHP_CONV_ERR_SUCCESS;
     652                 : 
     653               0 :         ps = (unsigned char *)*in_pp;
     654               0 :         pd = (unsigned char *)*out_pp;
     655               0 :         icnt = *in_left_p;
     656               0 :         ocnt = *out_left_p;
     657                 : 
     658               0 :         urem = inst->urem;
     659               0 :         urem_nbits = inst->urem_nbits;
     660               0 :         ustat = inst->ustat;
     661                 : 
     662               0 :         pack = 0;
     663               0 :         pack_bcnt = nbitsof_pack;
     664                 : 
     665                 :         for (;;) {
     666               0 :                 if (pack_bcnt >= urem_nbits) {
     667               0 :                         pack_bcnt -= urem_nbits;
     668               0 :                         pack |= (urem << pack_bcnt);
     669               0 :                         urem_nbits = 0;
     670                 :                 } else {
     671               0 :                         urem_nbits -= pack_bcnt;
     672               0 :                         pack |= (urem >> urem_nbits);
     673               0 :                         urem &= bmask(urem_nbits);
     674               0 :                         pack_bcnt = 0;
     675                 :                 }
     676               0 :                 if (pack_bcnt > 0) {
     677                 :                         unsigned int i;
     678                 : 
     679               0 :                         if (icnt < 1) {
     680               0 :                                 break;
     681                 :                         }
     682                 : 
     683               0 :                         i = b64_tbl_dec[(unsigned int)*(ps++)];
     684               0 :                         icnt--;
     685               0 :                         ustat |= i & 0x80;
     686                 : 
     687               0 :                         if (!(i & 0xc0)) {
     688               0 :                                 if (ustat) {
     689               0 :                                         err = PHP_CONV_ERR_INVALID_SEQ;
     690               0 :                                         break;
     691                 :                                 }
     692               0 :                                 if (6 <= pack_bcnt) {
     693               0 :                                         pack_bcnt -= 6;
     694               0 :                                         pack |= (i << pack_bcnt);
     695               0 :                                         urem = 0;
     696                 :                                 } else {
     697               0 :                                         urem_nbits = 6 - pack_bcnt;
     698               0 :                                         pack |= (i >> urem_nbits);
     699               0 :                                         urem = i & bmask(urem_nbits);
     700               0 :                                         pack_bcnt = 0;
     701                 :                                 }
     702               0 :                         } else if (ustat) {
     703               0 :                                 if (pack_bcnt == 8 || pack_bcnt == 2) {
     704               0 :                                         err = PHP_CONV_ERR_INVALID_SEQ;
     705               0 :                                         break;
     706                 :                                 }
     707               0 :                                 inst->eos = 1;
     708                 :                         }
     709                 :                 }
     710               0 :                 if ((pack_bcnt | ustat) == 0) {
     711               0 :                         if (ocnt < 1) {
     712               0 :                                 err = PHP_CONV_ERR_TOO_BIG;
     713               0 :                                 break;
     714                 :                         }
     715               0 :                         *(pd++) = pack;
     716               0 :                         ocnt--;
     717               0 :                         pack = 0;
     718               0 :                         pack_bcnt = nbitsof_pack;
     719                 :                 }
     720               0 :         }
     721                 : 
     722               0 :         if (urem_nbits >= pack_bcnt) {
     723               0 :                 urem |= (pack << (urem_nbits - pack_bcnt));
     724               0 :                 urem_nbits += (nbitsof_pack - pack_bcnt);
     725                 :         } else {
     726               0 :                 urem |= (pack >> (pack_bcnt - urem_nbits));
     727               0 :                 urem_nbits += (nbitsof_pack - pack_bcnt);
     728                 :         }
     729                 : 
     730               0 :         inst->urem = urem;
     731               0 :         inst->urem_nbits = urem_nbits;
     732               0 :         inst->ustat = ustat;
     733                 : 
     734               0 :         *in_pp = (const char *)ps;
     735               0 :         *in_left_p = icnt;
     736               0 :         *out_pp = (char *)pd;
     737               0 :         *out_left_p = ocnt;
     738                 : 
     739               0 :         return err;
     740                 : }
     741                 : #undef bmask
     742                 : /* }}} */
     743                 : 
     744                 : /* {{{ php_conv_qprint_encode */
     745                 : typedef struct _php_conv_qprint_encode {
     746                 :         php_conv _super;
     747                 : 
     748                 :         int opts;
     749                 :         unsigned int line_ccnt;
     750                 :         unsigned int line_len;
     751                 :         const char *lbchars;
     752                 :         int lbchars_dup;
     753                 :         size_t lbchars_len;
     754                 :         int persistent;
     755                 :         unsigned int lb_ptr;
     756                 :         unsigned int lb_cnt;
     757                 : } php_conv_qprint_encode;
     758                 : 
     759                 : #define PHP_CONV_QPRINT_OPT_BINARY             0x00000001
     760                 : #define PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST 0x00000002
     761                 : 
     762                 : static void php_conv_qprint_encode_dtor(php_conv_qprint_encode *inst);
     763                 : static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *inst, const char **in_pp, size_t *in_left_p, char **out_pp, size_t *out_left_p);
     764                 : 
     765                 : static void php_conv_qprint_encode_dtor(php_conv_qprint_encode *inst)
     766               0 : {
     767                 :         assert(inst != NULL);
     768               0 :         if (inst->lbchars_dup && inst->lbchars != NULL) {
     769               0 :                 pefree((void *)inst->lbchars, inst->persistent);
     770                 :         }
     771               0 : }
     772                 : 
     773                 : #define NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, lbchars) \
     774                 :         ((lb_ptr) < (lb_cnt) ? (lbchars)[(lb_ptr)] : *(ps)) 
     775                 : 
     776                 : #define CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt) \
     777                 :         if ((lb_ptr) < (lb_cnt)) { \
     778                 :                 (lb_ptr)++; \
     779                 :         } else { \
     780                 :                 (lb_cnt) = (lb_ptr) = 0; \
     781                 :                 --(icnt); \
     782                 :                 (ps)++; \
     783                 :         }
     784                 : 
     785                 : static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *inst, const char **in_pp, size_t *in_left_p, char **out_pp, size_t *out_left_p)
     786               0 : {
     787               0 :         php_conv_err_t err = PHP_CONV_ERR_SUCCESS;
     788                 :         unsigned char *ps, *pd;
     789                 :         size_t icnt, ocnt;
     790                 :         unsigned int c;
     791                 :         unsigned int line_ccnt;
     792                 :         unsigned int lb_ptr;
     793                 :         unsigned int lb_cnt;
     794                 :         int opts;
     795                 :         static char qp_digits[] = "0123456789ABCDEF";
     796                 : 
     797               0 :         line_ccnt = inst->line_ccnt;
     798               0 :         opts = inst->opts;
     799               0 :         lb_ptr = inst->lb_ptr;
     800               0 :         lb_cnt = inst->lb_cnt;
     801                 : 
     802               0 :         if ((in_pp == NULL || in_left_p == NULL) && (lb_ptr >=lb_cnt)) {
     803               0 :                 return PHP_CONV_ERR_SUCCESS;
     804                 :         }
     805                 : 
     806               0 :         ps = (unsigned char *)(*in_pp);
     807               0 :         icnt = *in_left_p;
     808               0 :         pd = (unsigned char *)(*out_pp);
     809               0 :         ocnt = *out_left_p;
     810                 : 
     811                 :         for (;;) {
     812               0 :                 if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && inst->lbchars != NULL && inst->lbchars_len > 0) {
     813                 :                         /* look ahead for the line break chars to make a right decision
     814                 :                          * how to consume incoming characters */
     815                 : 
     816               0 :                         if (icnt > 0 && *ps == inst->lbchars[lb_cnt]) {
     817               0 :                                 lb_cnt++;
     818                 : 
     819               0 :                                 if (lb_cnt >= inst->lbchars_len) {
     820                 :                                         unsigned int i;
     821                 : 
     822               0 :                                         if (ocnt < lb_cnt) {
     823               0 :                                                 lb_cnt--;
     824               0 :                                                 err = PHP_CONV_ERR_TOO_BIG;
     825               0 :                                                 break;
     826                 :                                         }
     827                 : 
     828               0 :                                         for (i = 0; i < lb_cnt; i++) {
     829               0 :                                                 *(pd++) = inst->lbchars[i];
     830               0 :                                                 ocnt--;
     831                 :                                         }
     832               0 :                                         line_ccnt = inst->line_len;
     833               0 :                                         lb_ptr = lb_cnt = 0;
     834                 :                                 }
     835               0 :                                 ps++, icnt--;
     836               0 :                                 continue;
     837                 :                         }
     838                 :                 }
     839                 : 
     840               0 :                 if (lb_ptr >= lb_cnt && icnt <= 0) {
     841               0 :                         break;
     842                 :                 } 
     843                 : 
     844               0 :                 c = NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, inst->lbchars);
     845                 : 
     846               0 :                 if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && (c == '\t' || c == ' ')) {
     847               0 :                         if (line_ccnt < 2 && inst->lbchars != NULL) {
     848               0 :                                 if (ocnt < inst->lbchars_len + 1) {
     849               0 :                                         err = PHP_CONV_ERR_TOO_BIG;
     850               0 :                                         break;
     851                 :                                 }
     852                 : 
     853               0 :                                 *(pd++) = '=';
     854               0 :                                 ocnt--;
     855               0 :                                 line_ccnt--;
     856                 : 
     857               0 :                                 memcpy(pd, inst->lbchars, inst->lbchars_len);
     858               0 :                                 pd += inst->lbchars_len;
     859               0 :                                 ocnt -= inst->lbchars_len;
     860               0 :                                 line_ccnt = inst->line_len;
     861                 :                         } else {
     862               0 :                                 if (ocnt < 1) {
     863               0 :                                         err = PHP_CONV_ERR_TOO_BIG;
     864               0 :                                         break;
     865                 :                                 }
     866               0 :                                 *(pd++) = c;
     867               0 :                                 ocnt--;
     868               0 :                                 line_ccnt--;
     869               0 :                                 CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
     870                 :                         }
     871               0 :                 } else if ((!(opts & PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST) || line_ccnt < inst->line_len) && ((c >= 33 && c <= 60) || (c >= 62 && c <= 126))) { 
     872               0 :                         if (line_ccnt < 2 && inst->lbchars != NULL) {
     873               0 :                                 if (ocnt < inst->lbchars_len + 1) {
     874               0 :                                         err = PHP_CONV_ERR_TOO_BIG;
     875               0 :                                         break;
     876                 :                                 }
     877               0 :                                 *(pd++) = '=';
     878               0 :                                 ocnt--;
     879               0 :                                 line_ccnt--;
     880                 : 
     881               0 :                                 memcpy(pd, inst->lbchars, inst->lbchars_len);
     882               0 :                                 pd += inst->lbchars_len;
     883               0 :                                 ocnt -= inst->lbchars_len;
     884               0 :                                 line_ccnt = inst->line_len;
     885                 :                         }
     886               0 :                         if (ocnt < 1) {
     887               0 :                                 err = PHP_CONV_ERR_TOO_BIG;
     888               0 :                                 break;
     889                 :                         }
     890               0 :                         *(pd++) = c;
     891               0 :                         ocnt--;
     892               0 :                         line_ccnt--;
     893               0 :                         CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
     894                 :                 } else {
     895               0 :                         if (line_ccnt < 4) {
     896               0 :                                 if (ocnt < inst->lbchars_len + 1) {
     897               0 :                                         err = PHP_CONV_ERR_TOO_BIG;
     898               0 :                                         break;
     899                 :                                 }
     900               0 :                                 *(pd++) = '=';
     901               0 :                                 ocnt--;
     902               0 :                                 line_ccnt--;
     903                 : 
     904               0 :                                 memcpy(pd, inst->lbchars, inst->lbchars_len);
     905               0 :                                 pd += inst->lbchars_len;
     906               0 :                                 ocnt -= inst->lbchars_len;
     907               0 :                                 line_ccnt = inst->line_len;
     908                 :                         }
     909               0 :                         if (ocnt < 3) {
     910               0 :                                 err = PHP_CONV_ERR_TOO_BIG;
     911               0 :                                 break;
     912                 :                         }
     913               0 :                         *(pd++) = '=';
     914               0 :                         *(pd++) = qp_digits[(c >> 4)];
     915               0 :                         *(pd++) = qp_digits[(c & 0x0f)]; 
     916               0 :                         ocnt -= 3;
     917               0 :                         line_ccnt -= 3;
     918               0 :                         CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
     919                 :                 }
     920               0 :         }
     921                 : 
     922               0 :         *in_pp = (const char *)ps;
     923               0 :         *in_left_p = icnt;
     924               0 :         *out_pp = (char *)pd;
     925               0 :         *out_left_p = ocnt; 
     926               0 :         inst->line_ccnt = line_ccnt;
     927               0 :         inst->lb_ptr = lb_ptr;
     928               0 :         inst->lb_cnt = lb_cnt;
     929               0 :         return err;
     930                 : }
     931                 : #undef NEXT_CHAR
     932                 : #undef CONSUME_CHAR
     933                 : 
     934                 : static php_conv_err_t php_conv_qprint_encode_ctor(php_conv_qprint_encode *inst, unsigned int line_len, const char *lbchars, size_t lbchars_len, int lbchars_dup, int opts, int persistent)
     935               0 : {
     936               0 :         if (line_len < 4 && lbchars != NULL) {
     937               0 :                 return PHP_CONV_ERR_TOO_BIG;
     938                 :         }
     939               0 :         inst->_super.convert_op = (php_conv_convert_func) php_conv_qprint_encode_convert;
     940               0 :         inst->_super.dtor = (php_conv_dtor_func) php_conv_qprint_encode_dtor;
     941               0 :         inst->line_ccnt = line_len;
     942               0 :         inst->line_len = line_len;
     943               0 :         if (lbchars != NULL) {
     944               0 :                 inst->lbchars = (lbchars_dup ? pestrdup(lbchars, persistent) : lbchars);
     945               0 :                 inst->lbchars_len = lbchars_len;
     946                 :         } else {
     947               0 :                 inst->lbchars = NULL;
     948                 :         }
     949               0 :         inst->lbchars_dup = lbchars_dup;
     950               0 :         inst->persistent = persistent;
     951               0 :         inst->opts = opts;
     952               0 :         inst->lb_cnt = inst->lb_ptr = 0;
     953               0 :         return PHP_CONV_ERR_SUCCESS;
     954                 : }
     955                 : /* }}} */
     956                 : 
     957                 : /* {{{ php_conv_qprint_decode */
     958                 : typedef struct _php_conv_qprint_decode {
     959                 :         php_conv _super;
     960                 : 
     961                 :         int scan_stat;
     962                 :         unsigned int next_char;
     963                 :         const char *lbchars;
     964                 :         int lbchars_dup;
     965                 :         size_t lbchars_len;
     966                 :         int persistent;
     967                 :         unsigned int lb_ptr;
     968                 :         unsigned int lb_cnt;    
     969                 : } php_conv_qprint_decode;
     970                 : 
     971                 : static void php_conv_qprint_decode_dtor(php_conv_qprint_decode *inst)
     972               0 : {
     973                 :         assert(inst != NULL);
     974               0 :         if (inst->lbchars_dup && inst->lbchars != NULL) {
     975               0 :                 pefree((void *)inst->lbchars, inst->persistent);
     976                 :         }
     977               0 : }
     978                 : 
     979                 : static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *inst, const char **in_pp, size_t *in_left_p, char **out_pp, size_t *out_left_p)
     980               0 : {
     981               0 :         php_conv_err_t err = PHP_CONV_ERR_SUCCESS;
     982                 :         size_t icnt, ocnt;
     983                 :         unsigned char *ps, *pd;
     984                 :         unsigned int scan_stat;
     985                 :         unsigned int next_char;
     986                 :         unsigned int lb_ptr, lb_cnt;
     987                 : 
     988               0 :         lb_ptr = inst->lb_ptr;
     989               0 :         lb_cnt = inst->lb_cnt;
     990                 : 
     991               0 :         if ((in_pp == NULL || in_left_p == NULL) && lb_cnt == lb_ptr) {
     992               0 :                 if (inst->scan_stat != 0) {
     993               0 :                         return PHP_CONV_ERR_UNEXPECTED_EOS;
     994                 :                 }
     995               0 :                 return PHP_CONV_ERR_SUCCESS;
     996                 :         }
     997                 : 
     998               0 :         ps = (unsigned char *)(*in_pp);
     999               0 :         icnt = *in_left_p;
    1000               0 :         pd = (unsigned char *)(*out_pp);
    1001               0 :         ocnt = *out_left_p;
    1002               0 :         scan_stat = inst->scan_stat;
    1003               0 :         next_char = inst->next_char;
    1004                 : 
    1005                 :         for (;;) {
    1006               0 :                 switch (scan_stat) {
    1007                 :                         case 0: {
    1008               0 :                                 if (icnt <= 0) {
    1009               0 :                                         goto out;
    1010                 :                                 }
    1011               0 :                                 if (*ps == '=') {
    1012               0 :                                         scan_stat = 1;
    1013                 :                                 } else {
    1014               0 :                                         if (ocnt < 1) {
    1015               0 :                                                 err = PHP_CONV_ERR_TOO_BIG;
    1016               0 :                                                 goto out;
    1017                 :                                         }
    1018               0 :                                         *(pd++) = *ps;
    1019               0 :                                         ocnt--;
    1020                 :                                 }
    1021               0 :                                 ps++, icnt--;
    1022               0 :                         } break;
    1023                 : 
    1024                 :                         case 1: {
    1025               0 :                                 if (icnt <= 0) {
    1026               0 :                                         goto out;
    1027                 :                                 }
    1028               0 :                                 if (*ps == ' ' || *ps == '\t') {
    1029               0 :                                         scan_stat = 4;
    1030               0 :                                         ps++, icnt--;
    1031               0 :                                         break;
    1032               0 :                                 } else if (!inst->lbchars && lb_cnt == 0 && *ps == '\r') {
    1033                 :                                         /* auto-detect line endings, looks like network line ending \r\n (could be mac \r) */
    1034               0 :                                         lb_cnt++;
    1035               0 :                                         scan_stat = 5;
    1036               0 :                                         ps++, icnt--;
    1037               0 :                                         break;
    1038               0 :                                 } else if (!inst->lbchars && lb_cnt == 0 && *ps == '\n') {
    1039                 :                                         /* auto-detect line endings, looks like unix-lineendings, not to spec, but it is seem in the wild, a lot */
    1040               0 :                                         lb_cnt = lb_ptr = 0;
    1041               0 :                                         scan_stat = 0;
    1042               0 :                                         ps++, icnt--;
    1043               0 :                                         break;
    1044               0 :                                 } else if (lb_cnt < inst->lbchars_len &&
    1045                 :                                                         *ps == (unsigned char)inst->lbchars[lb_cnt]) {
    1046               0 :                                         lb_cnt++;
    1047               0 :                                         scan_stat = 5;
    1048               0 :                                         ps++, icnt--;
    1049               0 :                                         break;
    1050                 :                                 }
    1051                 :                         } /* break is missing intentionally */
    1052                 : 
    1053                 :                         case 2: {
    1054                 :                                 unsigned int nbl;
    1055                 :         
    1056               0 :                                 if (icnt <= 0) {
    1057               0 :                                         goto out;
    1058                 :                                 }
    1059               0 :                                 nbl = (*ps >= 'A' ? *ps - 0x37 : *ps - 0x30);
    1060                 : 
    1061               0 :                                 if (nbl > 15) {
    1062               0 :                                         err = PHP_CONV_ERR_INVALID_SEQ;
    1063               0 :                                         goto out;
    1064                 :                                 }
    1065               0 :                                 next_char = (next_char << 4) | nbl;
    1066                 : 
    1067               0 :                                 scan_stat++;
    1068               0 :                                 ps++, icnt--;
    1069               0 :                                 if (scan_stat != 3) {
    1070               0 :                                         break;
    1071                 :                                 }
    1072                 :                         } /* break is missing intentionally */
    1073                 : 
    1074                 :                         case 3: {
    1075               0 :                                 if (ocnt < 1) {
    1076               0 :                                         err = PHP_CONV_ERR_TOO_BIG;
    1077               0 :                                         goto out;
    1078                 :                                 }
    1079               0 :                                 *(pd++) = next_char;
    1080               0 :                                 ocnt--;
    1081               0 :                                 scan_stat = 0;
    1082               0 :                         } break;
    1083                 : 
    1084                 :                         case 4: {
    1085               0 :                                 if (icnt <= 0) {
    1086               0 :                                         goto out;
    1087                 :                                 }
    1088               0 :                                 if (lb_cnt < inst->lbchars_len &&
    1089                 :                                         *ps == (unsigned char)inst->lbchars[lb_cnt]) {
    1090               0 :                                         lb_cnt++;
    1091               0 :                                         scan_stat = 5;
    1092                 :                                 }
    1093               0 :                                 if (*ps != '\t' && *ps != ' ') {
    1094               0 :                                         err = PHP_CONV_ERR_INVALID_SEQ;
    1095               0 :                                         goto out;
    1096                 :                                 }
    1097               0 :                                 ps++, icnt--;
    1098               0 :                         } break;
    1099                 : 
    1100                 :                         case 5: {
    1101               0 :                                 if (!inst->lbchars && lb_cnt == 1 && *ps == '\n') {
    1102                 :                                         /* auto-detect soft line breaks, found network line break */
    1103               0 :                                         lb_cnt = lb_ptr = 0;
    1104               0 :                                         scan_stat = 0;
    1105               0 :                                         ps++, icnt--; /* consume \n */
    1106               0 :                                 } else if (!inst->lbchars && lb_cnt > 0) {
    1107                 :                                         /* auto-detect soft line breaks, found mac line break */
    1108               0 :                                         lb_cnt = lb_ptr = 0;
    1109               0 :                                         scan_stat = 0;
    1110               0 :                                 } else if (lb_cnt >= inst->lbchars_len) {
    1111                 :                                         /* soft line break */
    1112               0 :                                         lb_cnt = lb_ptr = 0;
    1113               0 :                                         scan_stat = 0;
    1114               0 :                                 } else if (icnt > 0) {
    1115               0 :                                         if (*ps == (unsigned char)inst->lbchars[lb_cnt]) {
    1116               0 :                                                 lb_cnt++;
    1117               0 :                                                 ps++, icnt--;
    1118                 :                                         } else {
    1119               0 :                                                 scan_stat = 6; /* no break for short-cut */
    1120                 :                                         }
    1121                 :                                 } else {
    1122               0 :                                         goto out;
    1123                 :                                 }
    1124               0 :                         } break;
    1125                 : 
    1126                 :                         case 6: {
    1127               0 :                                 if (lb_ptr < lb_cnt) {
    1128               0 :                                         if (ocnt < 1) {
    1129               0 :                                                 err = PHP_CONV_ERR_TOO_BIG;
    1130               0 :                                                 goto out;
    1131                 :                                         }
    1132               0 :                                         *(pd++) = inst->lbchars[lb_ptr++];
    1133               0 :                                         ocnt--;
    1134                 :                                 } else {
    1135               0 :                                         scan_stat = 0;
    1136               0 :                                         lb_cnt = lb_ptr = 0;
    1137                 :                                 }
    1138                 :                         } break;
    1139                 :                 }
    1140               0 :         }
    1141               0 : out:
    1142               0 :         *in_pp = (const char *)ps;
    1143               0 :         *in_left_p = icnt;
    1144               0 :         *out_pp = (char *)pd;
    1145               0 :         *out_left_p = ocnt;
    1146               0 :         inst->scan_stat = scan_stat;
    1147               0 :         inst->lb_ptr = lb_ptr;
    1148               0 :         inst->lb_cnt = lb_cnt;
    1149               0 :         inst->next_char = next_char;
    1150                 : 
    1151               0 :         return err;
    1152                 : }
    1153                 : static php_conv_err_t php_conv_qprint_decode_ctor(php_conv_qprint_decode *inst, const char *lbchars, size_t lbchars_len, int lbchars_dup, int persistent)
    1154               0 : {
    1155               0 :         inst->_super.convert_op = (php_conv_convert_func) php_conv_qprint_decode_convert;
    1156               0 :         inst->_super.dtor = (php_conv_dtor_func) php_conv_qprint_decode_dtor;
    1157               0 :         inst->scan_stat = 0;
    1158               0 :         inst->next_char = 0;
    1159               0 :         inst->lb_ptr = inst->lb_cnt = 0;
    1160               0 :         if (lbchars != NULL) {
    1161               0 :                 inst->lbchars = (lbchars_dup ? pestrdup(lbchars, persistent) : lbchars);
    1162               0 :                 inst->lbchars_len = lbchars_len;
    1163                 :         } else {
    1164               0 :                 inst->lbchars = NULL;
    1165               0 :                 inst->lbchars_len = 0;
    1166                 :         }
    1167               0 :         inst->lbchars_dup = lbchars_dup;
    1168               0 :         inst->persistent = persistent;
    1169               0 :         return PHP_CONV_ERR_SUCCESS;
    1170                 : }
    1171                 : /* }}} */
    1172                 : 
    1173                 : typedef struct _php_convert_filter {
    1174                 :         php_conv *cd;
    1175                 :         int persistent;
    1176                 :         char *filtername;
    1177                 :         char stub[128];
    1178                 :         size_t stub_len;
    1179                 : } php_convert_filter;
    1180                 : 
    1181                 : #define PHP_CONV_BASE64_ENCODE 1
    1182                 : #define PHP_CONV_BASE64_DECODE 2
    1183                 : #define PHP_CONV_QPRINT_ENCODE 3 
    1184                 : #define PHP_CONV_QPRINT_DECODE 4
    1185                 : 
    1186                 : static php_conv_err_t php_conv_get_string_prop_ex(const HashTable *ht, char **pretval, size_t *pretval_len, char *field_name, size_t field_name_len, int persistent)
    1187               0 : {
    1188                 :         zval **tmpval;
    1189                 : 
    1190               0 :         *pretval = NULL;
    1191               0 :         *pretval_len = 0;
    1192                 :  
    1193               0 :         if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) {
    1194               0 :                 if (Z_TYPE_PP(tmpval) != IS_STRING) {
    1195               0 :                         zval zt = **tmpval;
    1196                 : 
    1197               0 :                         convert_to_string(&zt);
    1198                 : 
    1199               0 :                         if (NULL == (*pretval = pemalloc(Z_STRLEN(zt) + 1, persistent))) {
    1200               0 :                                 return PHP_CONV_ERR_ALLOC;
    1201                 :                         }
    1202                 : 
    1203               0 :                         *pretval_len = Z_STRLEN(zt);
    1204               0 :                         memcpy(*pretval, Z_STRVAL(zt), Z_STRLEN(zt) + 1);
    1205               0 :                         zval_dtor(&zt);
    1206                 :                 } else {
    1207               0 :                         if (NULL == (*pretval = pemalloc(Z_STRLEN_PP(tmpval) + 1, persistent))) {
    1208               0 :                                 return PHP_CONV_ERR_ALLOC;
    1209                 :                         }
    1210               0 :                         *pretval_len = Z_STRLEN_PP(tmpval);
    1211               0 :                         memcpy(*pretval, Z_STRVAL_PP(tmpval), Z_STRLEN_PP(tmpval) + 1);
    1212                 :                 }
    1213                 :         } else {
    1214               0 :                 return PHP_CONV_ERR_NOT_FOUND;
    1215                 :         }
    1216               0 :         return PHP_CONV_ERR_SUCCESS;
    1217                 : }
    1218                 : 
    1219                 : #if IT_WAS_USED
    1220                 : static php_conv_err_t php_conv_get_long_prop_ex(const HashTable *ht, long *pretval, char *field_name, size_t field_name_len)
    1221                 : {
    1222                 :         zval **tmpval;
    1223                 : 
    1224                 :         *pretval = 0;
    1225                 : 
    1226                 :         if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) {
    1227                 :                 zval tmp, *ztval = *tmpval;
    1228                 : 
    1229                 :                 if (Z_TYPE_PP(tmpval) != IS_LONG) {
    1230                 :                         tmp = *ztval;
    1231                 :                         zval_copy_ctor(&tmp);
    1232                 :                         convert_to_long(&tmp);
    1233                 :                         ztval = &tmp;
    1234                 :                 }
    1235                 :                 *pretval = Z_LVAL_P(ztval);
    1236                 :         } else {
    1237                 :                 return PHP_CONV_ERR_NOT_FOUND;
    1238                 :         } 
    1239                 :         return PHP_CONV_ERR_SUCCESS;
    1240                 : }
    1241                 : #endif
    1242                 : 
    1243                 : static php_conv_err_t php_conv_get_ulong_prop_ex(const HashTable *ht, unsigned long *pretval, char *field_name, size_t field_name_len)
    1244               0 : {
    1245                 :         zval **tmpval;
    1246                 : 
    1247               0 :         *pretval = 0;
    1248                 : 
    1249               0 :         if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) {
    1250               0 :                 zval tmp, *ztval = *tmpval;
    1251                 : 
    1252               0 :                 if (Z_TYPE_PP(tmpval) != IS_LONG) {
    1253               0 :                         tmp = *ztval;
    1254               0 :                         zval_copy_ctor(&tmp);
    1255               0 :                         convert_to_long(&tmp);
    1256               0 :                         ztval = &tmp;
    1257                 :                 }
    1258               0 :                 if (Z_LVAL_P(ztval) < 0) {
    1259               0 :                         *pretval = 0;
    1260                 :                 } else {
    1261               0 :                         *pretval = Z_LVAL_P(ztval);
    1262                 :                 }
    1263                 :         } else {
    1264               0 :                 return PHP_CONV_ERR_NOT_FOUND;
    1265                 :         } 
    1266               0 :         return PHP_CONV_ERR_SUCCESS;
    1267                 : }
    1268                 : 
    1269                 : static php_conv_err_t php_conv_get_bool_prop_ex(const HashTable *ht, int *pretval, char *field_name, size_t field_name_len)
    1270               0 : {
    1271                 :         zval **tmpval;
    1272                 : 
    1273               0 :         *pretval = 0;
    1274                 : 
    1275               0 :         if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) {
    1276               0 :                 zval tmp, *ztval = *tmpval;
    1277                 : 
    1278               0 :                 if (Z_TYPE_PP(tmpval) != IS_BOOL) {
    1279               0 :                         tmp = *ztval;
    1280               0 :                         zval_copy_ctor(&tmp);
    1281               0 :                         convert_to_boolean(&tmp);
    1282               0 :                         ztval = &tmp;
    1283                 :                 }
    1284               0 :                 *pretval = Z_BVAL_P(ztval);
    1285                 :         } else {
    1286               0 :                 return PHP_CONV_ERR_NOT_FOUND;
    1287                 :         } 
    1288               0 :         return PHP_CONV_ERR_SUCCESS;
    1289                 : }
    1290                 : 
    1291                 : 
    1292                 : #if IT_WAS_USED
    1293                 : static int php_conv_get_int_prop_ex(const HashTable *ht, int *pretval, char *field_name, size_t field_name_len)
    1294                 : {
    1295                 :         long l;
    1296                 :         php_conv_err_t err;
    1297                 : 
    1298                 :         *pretval = 0;
    1299                 : 
    1300                 :         if ((err = php_conv_get_long_prop_ex(ht, &l, field_name, field_name_len)) == PHP_CONV_ERR_SUCCESS) {
    1301                 :                 *pretval = l;
    1302                 :         }
    1303                 :         return err;
    1304                 : }
    1305                 : #endif
    1306                 : 
    1307                 : static int php_conv_get_uint_prop_ex(const HashTable *ht, unsigned int *pretval, char *field_name, size_t field_name_len)
    1308               0 : {
    1309                 :         long l;
    1310                 :         php_conv_err_t err;
    1311                 : 
    1312               0 :         *pretval = 0;
    1313                 : 
    1314               0 :         if ((err = php_conv_get_ulong_prop_ex(ht, &l, field_name, field_name_len)) == PHP_CONV_ERR_SUCCESS) {
    1315               0 :                 *pretval = l;
    1316                 :         }
    1317               0 :         return err;
    1318                 : }
    1319                 : 
    1320                 : #define GET_STR_PROP(ht, var, var_len, fldname, persistent) \
    1321                 :         php_conv_get_string_prop_ex(ht, &var, &var_len, fldname, sizeof(fldname), persistent) 
    1322                 : 
    1323                 : #define GET_INT_PROP(ht, var, fldname) \
    1324                 :         php_conv_get_int_prop_ex(ht, &var, fldname, sizeof(fldname))
    1325                 : 
    1326                 : #define GET_UINT_PROP(ht, var, fldname) \
    1327                 :         php_conv_get_uint_prop_ex(ht, &var, fldname, sizeof(fldname))
    1328                 : 
    1329                 : #define GET_BOOL_PROP(ht, var, fldname) \
    1330                 :         php_conv_get_bool_prop_ex(ht, &var, fldname, sizeof(fldname))
    1331                 : 
    1332                 : static php_conv *php_conv_open(int conv_mode, const HashTable *options, int persistent)
    1333               0 : {
    1334                 :         /* FIXME: I'll have to replace this ugly code by something neat
    1335                 :            (factories?) in the near future. */ 
    1336               0 :         php_conv *retval = NULL;
    1337                 : 
    1338               0 :         switch (conv_mode) {
    1339                 :                 case PHP_CONV_BASE64_ENCODE: {
    1340               0 :                         unsigned int line_len = 0;
    1341               0 :                         char *lbchars = NULL;
    1342                 :                         size_t lbchars_len;
    1343                 : 
    1344               0 :                         if (options != NULL) {
    1345               0 :                                 GET_STR_PROP(options, lbchars, lbchars_len, "line-break-chars", 0);
    1346               0 :                                 GET_UINT_PROP(options, line_len, "line-length");
    1347               0 :                                 if (line_len < 4) {
    1348               0 :                                         if (lbchars != NULL) {
    1349               0 :                                                 pefree(lbchars, 0);
    1350                 :                                         }
    1351               0 :                                         lbchars = NULL;
    1352                 :                                 } else {
    1353               0 :                                         if (lbchars == NULL) {
    1354               0 :                                                 lbchars = pestrdup("\r\n", 0);
    1355               0 :                                                 lbchars_len = 2;
    1356                 :                                         }
    1357                 :                                 }
    1358                 :                         }
    1359               0 :                         retval = pemalloc(sizeof(php_conv_base64_encode), persistent);
    1360               0 :                         if (lbchars != NULL) {
    1361               0 :                                 if (php_conv_base64_encode_ctor((php_conv_base64_encode *)retval, line_len, lbchars, lbchars_len, 1, persistent)) {
    1362               0 :                                         if (lbchars != NULL) {
    1363               0 :                                                 pefree(lbchars, 0);
    1364                 :                                         }
    1365               0 :                                         goto out_failure;
    1366                 :                                 }
    1367               0 :                                 pefree(lbchars, 0);
    1368                 :                         } else {
    1369               0 :                                 if (php_conv_base64_encode_ctor((php_conv_base64_encode *)retval, 0, NULL, 0, 0, persistent)) {
    1370               0 :                                         goto out_failure;
    1371                 :                                 }
    1372                 :                         }
    1373               0 :                 } break;
    1374                 : 
    1375                 :                 case PHP_CONV_BASE64_DECODE:
    1376               0 :                         retval = pemalloc(sizeof(php_conv_base64_decode), persistent);
    1377               0 :                         if (php_conv_base64_decode_ctor((php_conv_base64_decode *)retval)) {
    1378               0 :                                 goto out_failure;
    1379                 :                         }
    1380               0 :                         break;
    1381                 : 
    1382                 :                 case PHP_CONV_QPRINT_ENCODE: {
    1383               0 :                         unsigned int line_len = 0;
    1384               0 :                         char *lbchars = NULL;
    1385                 :                         size_t lbchars_len;
    1386               0 :                         int opts = 0;
    1387                 : 
    1388               0 :                         if (options != NULL) {
    1389               0 :                                 int opt_binary = 0;
    1390               0 :                                 int opt_force_encode_first = 0;
    1391                 : 
    1392               0 :                                 GET_STR_PROP(options, lbchars, lbchars_len, "line-break-chars", 0);
    1393               0 :                                 GET_UINT_PROP(options, line_len, "line-length");
    1394               0 :                                 GET_BOOL_PROP(options, opt_binary, "binary"); 
    1395               0 :                                 GET_BOOL_PROP(options, opt_force_encode_first, "force-encode-first"); 
    1396                 : 
    1397               0 :                                 if (line_len < 4) {
    1398               0 :                                         if (lbchars != NULL) {
    1399               0 :                                                 pefree(lbchars, 0);
    1400                 :                                         }
    1401               0 :                                         lbchars = NULL;
    1402                 :                                 } else {
    1403               0 :                                         if (lbchars == NULL) {
    1404               0 :                                                 lbchars = pestrdup("\r\n", 0);
    1405               0 :                                                 lbchars_len = 2;
    1406                 :                                         }
    1407                 :                                 }
    1408               0 :                                 opts |= (opt_binary ? PHP_CONV_QPRINT_OPT_BINARY : 0);
    1409               0 :                                 opts |= (opt_force_encode_first ? PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST : 0);
    1410                 :                         }
    1411               0 :                         retval = pemalloc(sizeof(php_conv_qprint_encode), persistent);
    1412               0 :                         if (lbchars != NULL) {
    1413               0 :                                 if (php_conv_qprint_encode_ctor((php_conv_qprint_encode *)retval, line_len, lbchars, lbchars_len, 1, opts, persistent)) {
    1414               0 :                                         pefree(lbchars, 0);
    1415               0 :                                         goto out_failure;
    1416                 :                                 }
    1417               0 :                                 pefree(lbchars, 0);
    1418                 :                         } else {
    1419               0 :                                 if (php_conv_qprint_encode_ctor((php_conv_qprint_encode *)retval, 0, NULL, 0, 0, opts, persistent)) {
    1420               0 :                                         goto out_failure;
    1421                 :                                 }
    1422                 :                         }
    1423               0 :                 } break;
    1424                 :         
    1425                 :                 case PHP_CONV_QPRINT_DECODE: {
    1426               0 :                         char *lbchars = NULL;
    1427                 :                         size_t lbchars_len;
    1428                 : 
    1429               0 :                         if (options != NULL) {
    1430                 :                                 /* If line-break-chars are not specified, filter will attempt to detect line endings (\r, \n, or \r\n) */
    1431               0 :                                 GET_STR_PROP(options, lbchars, lbchars_len, "line-break-chars", 0);
    1432                 :                         }
    1433                 : 
    1434               0 :                         retval = pemalloc(sizeof(php_conv_qprint_decode), persistent);
    1435               0 :                         if (lbchars != NULL) {
    1436               0 :                                 if (php_conv_qprint_decode_ctor((php_conv_qprint_decode *)retval, lbchars, lbchars_len, 1, persistent)) {
    1437               0 :                                         pefree(lbchars, 0);
    1438               0 :                                         goto out_failure;
    1439                 :                                 }
    1440               0 :                                 pefree(lbchars, 0);
    1441                 :                         } else {
    1442               0 :                                 if (php_conv_qprint_decode_ctor((php_conv_qprint_decode *)retval, NULL, 0, 0, persistent)) {
    1443               0 :                                         goto out_failure;
    1444                 :                                 }
    1445                 :                         }
    1446               0 :                 } break;
    1447                 : 
    1448                 :                 default:
    1449               0 :                         retval = NULL;
    1450                 :                         break;
    1451                 :         }
    1452               0 :         return retval;
    1453                 : 
    1454               0 : out_failure:
    1455               0 :         if (retval != NULL) {
    1456               0 :                 pefree(retval, persistent);
    1457                 :         }
    1458               0 :         return NULL;    
    1459                 : }
    1460                 : 
    1461                 : #undef GET_STR_PROP
    1462                 : #undef GET_INT_PROP
    1463                 : #undef GET_UINT_PROP
    1464                 : #undef GET_BOOL_PROP
    1465                 : 
    1466                 : static int php_convert_filter_ctor(php_convert_filter *inst,
    1467                 :         int conv_mode, HashTable *conv_opts,
    1468                 :         const char *filtername, int persistent)
    1469               0 : {
    1470               0 :         inst->persistent = persistent;
    1471               0 :         inst->filtername = pestrdup(filtername, persistent);
    1472               0 :         inst->stub_len = 0;
    1473                 : 
    1474               0 :         if ((inst->cd = php_conv_open(conv_mode, conv_opts, persistent)) == NULL) {
    1475               0 :                 goto out_failure;
    1476                 :         }
    1477                 : 
    1478               0 :         return SUCCESS;
    1479                 : 
    1480               0 : out_failure:
    1481               0 :         if (inst->cd != NULL) {
    1482               0 :                 php_conv_dtor(inst->cd);
    1483               0 :                 pefree(inst->cd, persistent);
    1484                 :         }
    1485               0 :         if (inst->filtername != NULL) {
    1486               0 :                 pefree(inst->filtername, persistent);
    1487                 :         }
    1488               0 :         return FAILURE;
    1489                 : }
    1490                 : 
    1491                 : static void php_convert_filter_dtor(php_convert_filter *inst)
    1492               0 : {
    1493               0 :         if (inst->cd != NULL) {
    1494               0 :                 php_conv_dtor(inst->cd);
    1495               0 :                 pefree(inst->cd, inst->persistent);
    1496                 :         }
    1497                 : 
    1498               0 :         if (inst->filtername != NULL) {
    1499               0 :                 pefree(inst->filtername, inst->persistent);
    1500                 :         }
    1501               0 : }
    1502                 : 
    1503                 : /* {{{ strfilter_convert_append_bucket */
    1504                 : static int strfilter_convert_append_bucket(
    1505                 :                 php_convert_filter *inst,
    1506                 :                 php_stream *stream, php_stream_filter *filter,
    1507                 :                 php_stream_bucket_brigade *buckets_out,
    1508                 :                 const char *ps, size_t buf_len, size_t *consumed,
    1509                 :                 int persistent TSRMLS_DC)
    1510               0 : {
    1511                 :         php_conv_err_t err;
    1512                 :         php_stream_bucket *new_bucket;
    1513               0 :         char *out_buf = NULL;
    1514                 :         size_t out_buf_size;
    1515                 :         char *pd;
    1516                 :         const char *pt;
    1517                 :         size_t ocnt, icnt, tcnt;
    1518                 :         size_t initial_out_buf_size;
    1519                 :         
    1520               0 :         if (ps == NULL) {
    1521               0 :                 initial_out_buf_size = 64;
    1522               0 :                 icnt = 1;
    1523                 :         } else {
    1524               0 :                 initial_out_buf_size = buf_len;
    1525               0 :                 icnt = buf_len;
    1526                 :         }
    1527                 : 
    1528               0 :         out_buf_size = ocnt = initial_out_buf_size; 
    1529               0 :         if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) {
    1530               0 :                 return FAILURE;
    1531                 :         }
    1532                 : 
    1533               0 :         pd = out_buf;
    1534                 : 
    1535               0 :         if (inst->stub_len > 0) {
    1536               0 :                 pt = inst->stub;
    1537               0 :                 tcnt = inst->stub_len;
    1538                 : 
    1539               0 :                 while (tcnt > 0) {
    1540               0 :                         err = php_conv_convert(inst->cd, &pt, &tcnt, &pd, &ocnt);
    1541                 : 
    1542               0 :                         switch (err) {
    1543                 :                                 case PHP_CONV_ERR_INVALID_SEQ:
    1544               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid byte sequence", inst->filtername);
    1545               0 :                                         goto out_failure;
    1546                 : 
    1547                 :                                 case PHP_CONV_ERR_MORE:
    1548               0 :                                         if (ps != NULL) {
    1549               0 :                                                 if (icnt > 0) {
    1550               0 :                                                         if (inst->stub_len >= sizeof(inst->stub)) {
    1551               0 :                                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): insufficient buffer", inst->filtername);
    1552               0 :                                                                 goto out_failure;
    1553                 :                                                         }
    1554               0 :                                                         inst->stub[inst->stub_len++] = *(ps++);
    1555               0 :                                                         icnt--;
    1556               0 :                                                         pt = inst->stub;
    1557               0 :                                                         tcnt = inst->stub_len;
    1558                 :                                                 } else {
    1559               0 :                                                         tcnt = 0;
    1560               0 :                                                         break;
    1561                 :                                                 }
    1562                 :                                         }
    1563               0 :                                         break;
    1564                 : 
    1565                 :                                 case PHP_CONV_ERR_UNEXPECTED_EOS:
    1566               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected end of stream", inst->filtername);
    1567               0 :                                         goto out_failure;
    1568                 : 
    1569                 :                                 case PHP_CONV_ERR_TOO_BIG: {
    1570                 :                                         char *new_out_buf;
    1571                 :                                         size_t new_out_buf_size;
    1572                 : 
    1573               0 :                                         new_out_buf_size = out_buf_size << 1;
    1574                 : 
    1575               0 :                                         if (new_out_buf_size < out_buf_size) {
    1576                 :                                                 /* whoa! no bigger buckets are sold anywhere... */
    1577               0 :                                                 if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) {
    1578               0 :                                                         goto out_failure;
    1579                 :                                                 }
    1580                 : 
    1581               0 :                                                 php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
    1582                 : 
    1583               0 :                                                 out_buf_size = ocnt = initial_out_buf_size;
    1584               0 :                                                 if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) {
    1585               0 :                                                         return FAILURE;
    1586                 :                                                 }
    1587               0 :                                                 pd = out_buf;
    1588                 :                                         } else {
    1589               0 :                                                 if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) {
    1590               0 :                                                         if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) {
    1591               0 :                                                                 goto out_failure;
    1592                 :                                                         }
    1593                 : 
    1594               0 :                                                         php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
    1595               0 :                                                         return FAILURE;
    1596                 :                                                 }
    1597                 : 
    1598               0 :                                                 pd = new_out_buf + (pd - out_buf);
    1599               0 :                                                 ocnt += (new_out_buf_size - out_buf_size);
    1600               0 :                                                 out_buf = new_out_buf;
    1601               0 :                                                 out_buf_size = new_out_buf_size;
    1602                 :                                         }
    1603               0 :                                 } break;
    1604                 : 
    1605                 :                                 case PHP_CONV_ERR_UNKNOWN:
    1606               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername);
    1607               0 :                                         goto out_failure;
    1608                 : 
    1609                 :                                 default:
    1610                 :                                         break;
    1611                 :                         }
    1612                 :                 }
    1613               0 :                 memmove(inst->stub, pt, tcnt);
    1614               0 :                 inst->stub_len = tcnt;
    1615                 :         }
    1616                 : 
    1617               0 :         while (icnt > 0) {
    1618               0 :                 err = ((ps == NULL ? php_conv_convert(inst->cd, NULL, NULL, &pd, &ocnt):
    1619                 :                                 php_conv_convert(inst->cd, &ps, &icnt, &pd, &ocnt)));
    1620               0 :                 switch (err) {
    1621                 :                         case PHP_CONV_ERR_INVALID_SEQ:
    1622               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid byte sequence", inst->filtername);
    1623               0 :                                 goto out_failure;
    1624                 : 
    1625                 :                         case PHP_CONV_ERR_MORE:
    1626               0 :                                 if (ps != NULL) {
    1627               0 :                                         if (icnt > sizeof(inst->stub)) {
    1628               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): insufficient buffer", inst->filtername);
    1629               0 :                                                 goto out_failure;
    1630                 :                                         }
    1631               0 :                                         memcpy(inst->stub, ps, icnt);
    1632               0 :                                         inst->stub_len = icnt;
    1633               0 :                                         ps += icnt;
    1634               0 :                                         icnt = 0;
    1635                 :                                 } else {
    1636               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected octet values", inst->filtername);
    1637               0 :                                         goto out_failure;
    1638                 :                                 }
    1639               0 :                                 break;
    1640                 : 
    1641                 :                         case PHP_CONV_ERR_TOO_BIG: {
    1642                 :                                 char *new_out_buf;
    1643                 :                                 size_t new_out_buf_size;
    1644                 : 
    1645               0 :                                 new_out_buf_size = out_buf_size << 1;
    1646                 : 
    1647               0 :                                 if (new_out_buf_size < out_buf_size) {
    1648                 :                                         /* whoa! no bigger buckets are sold anywhere... */
    1649               0 :                                         if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) {
    1650               0 :                                                 goto out_failure;
    1651                 :                                         }
    1652                 : 
    1653               0 :                                         php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
    1654                 : 
    1655               0 :                                         out_buf_size = ocnt = initial_out_buf_size;
    1656               0 :                                         if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) {
    1657               0 :                                                 return FAILURE;
    1658                 :                                         }
    1659               0 :                                         pd = out_buf;
    1660                 :                                 } else {
    1661               0 :                                         if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) {
    1662               0 :                                                 if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) {
    1663               0 :                                                         goto out_failure;
    1664                 :                                                 }
    1665                 : 
    1666               0 :                                                 php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
    1667               0 :                                                 return FAILURE;
    1668                 :                                         }
    1669               0 :                                         pd = new_out_buf + (pd - out_buf);
    1670               0 :                                         ocnt += (new_out_buf_size - out_buf_size);
    1671               0 :                                         out_buf = new_out_buf;
    1672               0 :                                         out_buf_size = new_out_buf_size;
    1673                 :                                 }
    1674               0 :                         } break;
    1675                 : 
    1676                 :                         case PHP_CONV_ERR_UNKNOWN:
    1677               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername);
    1678               0 :                                 goto out_failure;
    1679                 : 
    1680                 :                         default:
    1681               0 :                                 if (ps == NULL) {
    1682               0 :                                         icnt = 0;
    1683                 :                                 }
    1684                 :                                 break;
    1685                 :                 }
    1686                 :         }
    1687                 : 
    1688               0 :         if (out_buf_size - ocnt > 0) {
    1689               0 :                 if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) {
    1690               0 :                         goto out_failure;
    1691                 :                 }
    1692               0 :                 php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC);
    1693                 :         } else {
    1694               0 :                 pefree(out_buf, persistent);
    1695                 :         }
    1696               0 :         *consumed += buf_len - icnt;
    1697                 : 
    1698               0 :         return SUCCESS;
    1699                 : 
    1700               0 : out_failure:
    1701               0 :         pefree(out_buf, persistent);
    1702               0 :         return FAILURE;
    1703                 : }
    1704                 : /* }}} */
    1705                 : 
    1706                 : static php_stream_filter_status_t strfilter_convert_filter(
    1707                 :         php_stream *stream,
    1708                 :         php_stream_filter *thisfilter,
    1709                 :         php_stream_bucket_brigade *buckets_in,
    1710                 :         php_stream_bucket_brigade *buckets_out,
    1711                 :         size_t *bytes_consumed,
    1712                 :         int flags
    1713                 :         TSRMLS_DC)
    1714               0 : {
    1715               0 :         php_stream_bucket *bucket = NULL;
    1716               0 :         size_t consumed = 0;
    1717               0 :         php_convert_filter *inst = (php_convert_filter *)thisfilter->abstract;
    1718                 : 
    1719               0 :         while (buckets_in->head != NULL) {
    1720               0 :                 bucket = buckets_in->head;
    1721                 : 
    1722               0 :                 php_stream_bucket_unlink(bucket TSRMLS_CC);
    1723                 : 
    1724               0 :                 if (strfilter_convert_append_bucket(inst, stream, thisfilter,
    1725                 :                                 buckets_out, bucket->buf, bucket->buflen, &consumed,
    1726                 :                                 php_stream_is_persistent(stream) TSRMLS_CC) != SUCCESS) {
    1727               0 :                         goto out_failure;
    1728                 :                 }
    1729                 : 
    1730               0 :                 php_stream_bucket_delref(bucket TSRMLS_CC);
    1731                 :         }
    1732                 : 
    1733               0 :         if (flags != PSFS_FLAG_NORMAL) {
    1734               0 :                 if (strfilter_convert_append_bucket(inst, stream, thisfilter,
    1735                 :                                 buckets_out, NULL, 0, &consumed,
    1736                 :                                 php_stream_is_persistent(stream) TSRMLS_CC) != SUCCESS) {
    1737               0 :                         goto out_failure;
    1738                 :                 }
    1739                 :         }
    1740                 : 
    1741               0 :         if (bytes_consumed) {
    1742               0 :                 *bytes_consumed = consumed;
    1743                 :         }
    1744                 : 
    1745               0 :         return PSFS_PASS_ON;
    1746                 : 
    1747               0 : out_failure:
    1748               0 :         if (bucket != NULL) {
    1749               0 :                 php_stream_bucket_delref(bucket TSRMLS_CC);
    1750                 :         }
    1751               0 :         return PSFS_ERR_FATAL;
    1752                 : }
    1753                 : 
    1754                 : static void strfilter_convert_dtor(php_stream_filter *thisfilter TSRMLS_DC)
    1755               0 : {
    1756                 :         assert(thisfilter->abstract != NULL);
    1757                 : 
    1758               0 :         php_convert_filter_dtor((php_convert_filter *)thisfilter->abstract);
    1759               0 :         pefree(thisfilter->abstract, ((php_convert_filter *)thisfilter->abstract)->persistent);
    1760               0 : }
    1761                 : 
    1762                 : static php_stream_filter_ops strfilter_convert_ops = {
    1763                 :         strfilter_convert_filter,
    1764                 :         strfilter_convert_dtor,
    1765                 :         "convert.*"
    1766                 : };
    1767                 : 
    1768                 : static php_stream_filter *strfilter_convert_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
    1769               0 : {
    1770                 :         php_convert_filter *inst;
    1771               0 :         php_stream_filter *retval = NULL;
    1772                 : 
    1773                 :         char *dot;
    1774               0 :         int conv_mode = 0;
    1775                 : 
    1776               0 :         if (filterparams != NULL && Z_TYPE_P(filterparams) != IS_ARRAY) {
    1777               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid filter parameter", filtername);
    1778               0 :                 return NULL;
    1779                 :         }
    1780                 : 
    1781               0 :         if ((dot = strchr(filtername, '.')) == NULL) {
    1782               0 :                 return NULL;
    1783                 :         }
    1784               0 :         ++dot;
    1785                 : 
    1786               0 :         inst = pemalloc(sizeof(php_convert_filter), persistent);
    1787                 : 
    1788               0 :         if (strcasecmp(dot, "base64-encode") == 0) {
    1789               0 :                 conv_mode = PHP_CONV_BASE64_ENCODE;
    1790               0 :         } else if (strcasecmp(dot, "base64-decode") == 0) {
    1791               0 :                 conv_mode = PHP_CONV_BASE64_DECODE;
    1792               0 :         } else if (strcasecmp(dot, "quoted-printable-encode") == 0) {
    1793               0 :                 conv_mode = PHP_CONV_QPRINT_ENCODE;
    1794               0 :         } else if (strcasecmp(dot, "quoted-printable-decode") == 0) {
    1795               0 :                 conv_mode = PHP_CONV_QPRINT_DECODE;
    1796                 :         }
    1797                 :         
    1798               0 :         if (php_convert_filter_ctor(inst, conv_mode,
    1799                 :                 (filterparams != NULL ? Z_ARRVAL_P(filterparams) : NULL),
    1800                 :                 filtername, persistent) != SUCCESS) {
    1801               0 :                 goto out;
    1802                 :         }       
    1803                 : 
    1804               0 :         retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent);
    1805               0 : out:
    1806               0 :         if (retval == NULL) {
    1807               0 :                 pefree(inst, persistent);
    1808                 :         }
    1809                 : 
    1810               0 :         return retval;
    1811                 : }
    1812                 : 
    1813                 : static php_stream_filter_factory strfilter_convert_factory = {
    1814                 :         strfilter_convert_create
    1815                 : };
    1816                 : /* }}} */
    1817                 : 
    1818                 : /* {{{ consumed filter implementation */
    1819                 : typedef struct _php_consumed_filter_data {
    1820                 :         int persistent;
    1821                 :         size_t consumed;
    1822                 :         off_t offset;
    1823                 : } php_consumed_filter_data;
    1824                 : 
    1825                 : static php_stream_filter_status_t consumed_filter_filter(
    1826                 :         php_stream *stream,
    1827                 :         php_stream_filter *thisfilter,
    1828                 :         php_stream_bucket_brigade *buckets_in,
    1829                 :         php_stream_bucket_brigade *buckets_out,
    1830                 :         size_t *bytes_consumed,
    1831                 :         int flags
    1832                 :         TSRMLS_DC)
    1833               0 : {
    1834               0 :         php_consumed_filter_data *data = (php_consumed_filter_data *)(thisfilter->abstract);
    1835                 :         php_stream_bucket *bucket;
    1836               0 :         size_t consumed = 0;
    1837                 : 
    1838               0 :         if (data->offset == ~0) {
    1839               0 :                 data->offset = php_stream_tell(stream);
    1840                 :         }
    1841               0 :         while ((bucket = buckets_in->head) != NULL) {
    1842               0 :                 php_stream_bucket_unlink(bucket TSRMLS_CC);
    1843               0 :                 consumed += bucket->buflen;
    1844               0 :                 php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
    1845                 :         }
    1846               0 :         if (bytes_consumed) {
    1847               0 :                 *bytes_consumed = consumed;
    1848                 :         }
    1849               0 :         if (flags & PSFS_FLAG_FLUSH_CLOSE) {
    1850               0 :                 php_stream_seek(stream, data->offset + data->consumed, SEEK_SET);
    1851                 :         }
    1852               0 :         data->consumed += consumed;
    1853                 :         
    1854               0 :         return PSFS_PASS_ON;
    1855                 : }
    1856                 : 
    1857                 : static void consumed_filter_dtor(php_stream_filter *thisfilter TSRMLS_DC)
    1858               0 : {
    1859               0 :         if (thisfilter && thisfilter->abstract) {
    1860               0 :                 php_consumed_filter_data *data = (php_consumed_filter_data*)thisfilter->abstract;
    1861               0 :                 pefree(data, data->persistent);
    1862                 :         }
    1863               0 : }
    1864                 : 
    1865                 : static php_stream_filter_ops consumed_filter_ops = {
    1866                 :         consumed_filter_filter,
    1867                 :         consumed_filter_dtor,
    1868                 :         "consumed"
    1869                 : };
    1870                 : 
    1871                 : static php_stream_filter *consumed_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
    1872               0 : {
    1873               0 :         php_stream_filter_ops *fops = NULL;
    1874                 :         php_consumed_filter_data *data;
    1875                 : 
    1876               0 :         if (strcasecmp(filtername, "consumed")) {
    1877               0 :                 return NULL;
    1878                 :         }
    1879                 : 
    1880                 :         /* Create this filter */
    1881               0 :         data = pecalloc(1, sizeof(php_consumed_filter_data), persistent);
    1882               0 :         if (!data) {
    1883               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zd bytes.", sizeof(php_consumed_filter_data));
    1884               0 :                 return NULL;
    1885                 :         }
    1886               0 :         data->persistent = persistent;
    1887               0 :         data->consumed = 0;
    1888               0 :         data->offset = ~0;
    1889               0 :         fops = &consumed_filter_ops;
    1890                 : 
    1891               0 :         return php_stream_filter_alloc(fops, data, persistent);
    1892                 : }
    1893                 : 
    1894                 : php_stream_filter_factory consumed_filter_factory = {
    1895                 :         consumed_filter_create
    1896                 : };
    1897                 : 
    1898                 : /* }}} */
    1899                 : 
    1900                 : static const struct {
    1901                 :         php_stream_filter_ops *ops;
    1902                 :         php_stream_filter_factory *factory;
    1903                 : } standard_filters[] = {
    1904                 :         { &strfilter_rot13_ops, &strfilter_rot13_factory },
    1905                 :         { &strfilter_toupper_ops, &strfilter_toupper_factory },
    1906                 :         { &strfilter_tolower_ops, &strfilter_tolower_factory },
    1907                 :         { &strfilter_strip_tags_ops, &strfilter_strip_tags_factory },
    1908                 :         { &strfilter_convert_ops, &strfilter_convert_factory },
    1909                 :         { &consumed_filter_ops, &consumed_filter_factory },
    1910                 :         /* additional filters to go here */
    1911                 :         { NULL, NULL }
    1912                 : };
    1913                 : 
    1914                 : /* {{{ filter MINIT and MSHUTDOWN */
    1915                 : PHP_MINIT_FUNCTION(standard_filters)
    1916             220 : {
    1917                 :         int i;
    1918                 : 
    1919            1540 :         for (i = 0; standard_filters[i].ops; i++) {
    1920            1320 :                 if (FAILURE == php_stream_filter_register_factory(
    1921                 :                                         standard_filters[i].ops->label,
    1922                 :                                         standard_filters[i].factory
    1923                 :                                         TSRMLS_CC)) {
    1924               0 :                         return FAILURE;
    1925                 :                 }
    1926                 :         }
    1927             220 :         return SUCCESS;
    1928                 : }
    1929                 : 
    1930                 : PHP_MSHUTDOWN_FUNCTION(standard_filters)
    1931             219 : {
    1932                 :         int i;
    1933                 : 
    1934            1533 :         for (i = 0; standard_filters[i].ops; i++) {
    1935            1314 :                 php_stream_filter_unregister_factory(standard_filters[i].ops->label TSRMLS_CC);
    1936                 :         }
    1937             219 :         return SUCCESS;
    1938                 : }
    1939                 : /* }}} */
    1940                 : 
    1941                 : /*
    1942                 :  * Local variables:
    1943                 :  * tab-width: 4
    1944                 :  * c-basic-offset: 4
    1945                 :  * End:
    1946                 :  * vim600: sw=4 ts=4 fdm=marker
    1947                 :  * vim<600: sw=4 ts=4
    1948                 :  */

Generated by: LTP GCOV extension version 1.5