diff options
Diffstat (limited to 'ext/standard/filters.c')
-rw-r--r-- | ext/standard/filters.c | 1845 |
1 files changed, 0 insertions, 1845 deletions
diff --git a/ext/standard/filters.c b/ext/standard/filters.c deleted file mode 100644 index adad37cf61..0000000000 --- a/ext/standard/filters.c +++ /dev/null @@ -1,1845 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2005 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: | - | Wez Furlong (wez@thebrainroom.com) | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "php_globals.h" -#include "ext/standard/basic_functions.h" -#include "ext/standard/file.h" -#include "ext/standard/php_string.h" -#include "ext/standard/php_smart_str.h" - -/* {{{ rot13 stream filter implementation */ -static char rot13_from[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static char rot13_to[] = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"; - -static php_stream_filter_status_t strfilter_rot13_filter( - php_stream *stream, - php_stream_filter *thisfilter, - php_stream_bucket_brigade *buckets_in, - php_stream_bucket_brigade *buckets_out, - size_t *bytes_consumed, - int flags - TSRMLS_DC) -{ - php_stream_bucket *bucket; - size_t consumed = 0; - - while (buckets_in->head) { - bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC); - - php_strtr(bucket->buf, bucket->buflen, rot13_from, rot13_to, 52); - consumed += bucket->buflen; - - php_stream_bucket_append(buckets_out, bucket TSRMLS_CC); - } - - if (bytes_consumed) { - *bytes_consumed = consumed; - } - - return PSFS_PASS_ON; -} - -static php_stream_filter_ops strfilter_rot13_ops = { - strfilter_rot13_filter, - NULL, - "string.rot13" -}; - -static php_stream_filter *strfilter_rot13_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC) -{ - return php_stream_filter_alloc(&strfilter_rot13_ops, NULL, persistent); -} - -static php_stream_filter_factory strfilter_rot13_factory = { - strfilter_rot13_create -}; -/* }}} */ - -/* {{{ string.toupper / string.tolower stream filter implementation */ -static char lowercase[] = "abcdefghijklmnopqrstuvwxyz"; -static char uppercase[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -static php_stream_filter_status_t strfilter_toupper_filter( - php_stream *stream, - php_stream_filter *thisfilter, - php_stream_bucket_brigade *buckets_in, - php_stream_bucket_brigade *buckets_out, - size_t *bytes_consumed, - int flags - TSRMLS_DC) -{ - php_stream_bucket *bucket; - size_t consumed = 0; - - while (buckets_in->head) { - bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC); - - php_strtr(bucket->buf, bucket->buflen, lowercase, uppercase, 26); - consumed += bucket->buflen; - - php_stream_bucket_append(buckets_out, bucket TSRMLS_CC); - } - - if (bytes_consumed) { - *bytes_consumed = consumed; - } - - return PSFS_PASS_ON; -} - -static php_stream_filter_status_t strfilter_tolower_filter( - php_stream *stream, - php_stream_filter *thisfilter, - php_stream_bucket_brigade *buckets_in, - php_stream_bucket_brigade *buckets_out, - size_t *bytes_consumed, - int flags - TSRMLS_DC) -{ - php_stream_bucket *bucket; - size_t consumed = 0; - - while (buckets_in->head) { - bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC); - - php_strtr(bucket->buf, bucket->buflen, uppercase, lowercase, 26); - consumed += bucket->buflen; - - php_stream_bucket_append(buckets_out, bucket TSRMLS_CC); - } - - if (bytes_consumed) { - *bytes_consumed = consumed; - } - - return PSFS_PASS_ON; -} - -static php_stream_filter_ops strfilter_toupper_ops = { - strfilter_toupper_filter, - NULL, - "string.toupper" -}; - -static php_stream_filter_ops strfilter_tolower_ops = { - strfilter_tolower_filter, - NULL, - "string.tolower" -}; - -static php_stream_filter *strfilter_toupper_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC) -{ - return php_stream_filter_alloc(&strfilter_toupper_ops, NULL, persistent); -} - -static php_stream_filter *strfilter_tolower_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC) -{ - return php_stream_filter_alloc(&strfilter_tolower_ops, NULL, persistent); -} - -static php_stream_filter_factory strfilter_toupper_factory = { - strfilter_toupper_create -}; - -static php_stream_filter_factory strfilter_tolower_factory = { - strfilter_tolower_create -}; -/* }}} */ - -/* {{{ strip_tags filter implementation */ -typedef struct _php_strip_tags_filter { - const char *allowed_tags; - int allowed_tags_len; - int state; - int persistent; -} php_strip_tags_filter; - -static int php_strip_tags_filter_ctor(php_strip_tags_filter *inst, const char *allowed_tags, int allowed_tags_len, int persistent) -{ - if (allowed_tags != NULL) { - if (NULL == (inst->allowed_tags = pemalloc(allowed_tags_len, persistent))) { - return FAILURE; - } - memcpy((char *)inst->allowed_tags, allowed_tags, allowed_tags_len); - inst->allowed_tags_len = allowed_tags_len; - } else { - inst->allowed_tags = NULL; - } - inst->state = 0; - inst->persistent = persistent; - - return SUCCESS; -} - -static void php_strip_tags_filter_dtor(php_strip_tags_filter *inst) -{ - if (inst->allowed_tags != NULL) { - pefree((void *)inst->allowed_tags, inst->persistent); - } -} - -static php_stream_filter_status_t strfilter_strip_tags_filter( - php_stream *stream, - php_stream_filter *thisfilter, - php_stream_bucket_brigade *buckets_in, - php_stream_bucket_brigade *buckets_out, - size_t *bytes_consumed, - int flags - TSRMLS_DC) -{ - php_stream_bucket *bucket; - size_t consumed = 0; - php_strip_tags_filter *inst = (php_strip_tags_filter *) thisfilter->abstract; - - while (buckets_in->head) { - bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC); - consumed = bucket->buflen; - - bucket->buflen = php_strip_tags(bucket->buf, bucket->buflen, &(inst->state), (char *)inst->allowed_tags, inst->allowed_tags_len); - - php_stream_bucket_append(buckets_out, bucket TSRMLS_CC); - } - - if (bytes_consumed) { - *bytes_consumed = consumed; - } - - return PSFS_PASS_ON; -} - -static void strfilter_strip_tags_dtor(php_stream_filter *thisfilter TSRMLS_DC) -{ - assert(thisfilter->abstract != NULL); - - php_strip_tags_filter_dtor((php_strip_tags_filter *)thisfilter->abstract); - - pefree(thisfilter->abstract, ((php_strip_tags_filter *)thisfilter->abstract)->persistent); -} - -static php_stream_filter_ops strfilter_strip_tags_ops = { - strfilter_strip_tags_filter, - strfilter_strip_tags_dtor, - "string.strip_tags" -}; - -static php_stream_filter *strfilter_strip_tags_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC) -{ - php_strip_tags_filter *inst; - smart_str tags_ss = { 0, 0, 0 }; - - inst = pemalloc(sizeof(php_strip_tags_filter), persistent); - - if (inst == NULL) { /* it's possible pemalloc returns NULL - instead of causing it to bail out */ - return NULL; - } - - if (filterparams != NULL) { - if (Z_TYPE_P(filterparams) == IS_ARRAY) { - HashPosition pos; - zval **tmp; - - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(filterparams), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_P(filterparams), (void **) &tmp, &pos) == SUCCESS) { - convert_to_string_ex(tmp); - smart_str_appendc(&tags_ss, '<'); - smart_str_appendl(&tags_ss, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); - smart_str_appendc(&tags_ss, '>'); - zend_hash_move_forward_ex(Z_ARRVAL_P(filterparams), &pos); - } - smart_str_0(&tags_ss); - } else { - /* FIXME: convert_to_* may clutter zvals and lead it into segfault ? */ - convert_to_string_ex(&filterparams); - - tags_ss.c = Z_STRVAL_P(filterparams); - tags_ss.len = Z_STRLEN_P(filterparams); - tags_ss.a = 0; - } - } - - if (php_strip_tags_filter_ctor(inst, tags_ss.c, tags_ss.len, persistent) != SUCCESS) { - if (tags_ss.a != 0) { - STR_FREE(tags_ss.c); - } - pefree(inst, persistent); - return NULL; - } - - if (tags_ss.a != 0) { - STR_FREE(tags_ss.c); - } - - return php_stream_filter_alloc(&strfilter_strip_tags_ops, inst, persistent); -} - -static php_stream_filter_factory strfilter_strip_tags_factory = { - strfilter_strip_tags_create -}; - -/* }}} */ - -/* {{{ base64 / quoted_printable stream filter implementation */ - -typedef enum _php_conv_err_t { - PHP_CONV_ERR_SUCCESS = SUCCESS, - PHP_CONV_ERR_UNKNOWN, - PHP_CONV_ERR_TOO_BIG, - PHP_CONV_ERR_INVALID_SEQ, - PHP_CONV_ERR_UNEXPECTED_EOS, - PHP_CONV_ERR_EXISTS, - PHP_CONV_ERR_MORE, - PHP_CONV_ERR_ALLOC, - PHP_CONV_ERR_NOT_FOUND -} php_conv_err_t; - -typedef struct _php_conv php_conv; - -typedef php_conv_err_t (*php_conv_convert_func)(php_conv *, const char **, size_t *, char **, size_t *); -typedef void (*php_conv_dtor_func)(php_conv *); - -struct _php_conv { - php_conv_convert_func convert_op; - php_conv_dtor_func dtor; -}; - -#define php_conv_convert(a, b, c, d, e) ((php_conv *)(a))->convert_op((php_conv *)(a), (b), (c), (d), (e)) -#define php_conv_dtor(a) ((php_conv *)a)->dtor((a)) - -/* {{{ php_conv_base64_encode */ -typedef struct _php_conv_base64_encode { - php_conv _super; - - unsigned char erem[3]; - size_t erem_len; - unsigned int line_ccnt; - unsigned int line_len; - const char *lbchars; - int lbchars_dup; - size_t lbchars_len; - int persistent; -} php_conv_base64_encode; - -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); -static void php_conv_base64_encode_dtor(php_conv_base64_encode *inst); - -static unsigned char b64_tbl_enc[256] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' -}; - -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) -{ - inst->_super.convert_op = (php_conv_convert_func) php_conv_base64_encode_convert; - inst->_super.dtor = (php_conv_dtor_func) php_conv_base64_encode_dtor; - inst->erem_len = 0; - inst->line_ccnt = line_len; - inst->line_len = line_len; - if (lbchars != NULL) { - inst->lbchars = (lbchars_dup ? pestrdup(lbchars, persistent) : lbchars); - inst->lbchars_len = lbchars_len; - } else { - inst->lbchars = NULL; - } - inst->lbchars_dup = lbchars_dup; - inst->persistent = persistent; - return SUCCESS; -} - -static void php_conv_base64_encode_dtor(php_conv_base64_encode *inst) -{ - assert(inst != NULL); - if (inst->lbchars_dup && inst->lbchars != NULL) { - pefree((void *)inst->lbchars, inst->persistent); - } -} - -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) -{ - volatile php_conv_err_t err = PHP_CONV_ERR_SUCCESS; - register unsigned char *pd; - register size_t ocnt; - unsigned int line_ccnt; - - pd = (unsigned char *)(*out_pp); - ocnt = *out_left_p; - line_ccnt = inst->line_ccnt; - - switch (inst->erem_len) { - case 0: - /* do nothing */ - break; - - case 1: - if (line_ccnt < 4 && inst->lbchars != NULL) { - if (ocnt < inst->lbchars_len) { - return PHP_CONV_ERR_TOO_BIG; - } - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } - if (ocnt < 4) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)]; - *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4)]; - *(pd++) = '='; - *(pd++) = '='; - inst->erem_len = 0; - ocnt -= 4; - line_ccnt -= 4; - break; - - case 2: - if (line_ccnt < 4 && inst->lbchars != NULL) { - if (ocnt < inst->lbchars_len) { - return PHP_CONV_ERR_TOO_BIG; - } - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } - if (ocnt < 4) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)]; - *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4) | (inst->erem[1] >> 4)]; - *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[1] << 2)]; - *(pd++) = '='; - inst->erem_len = 0; - ocnt -=4; - line_ccnt -= 4; - break; - - default: - /* should not happen... */ - err = PHP_CONV_ERR_UNKNOWN; - break; - } -out: - *out_pp = (char *)pd; - *out_left_p = ocnt; - inst->line_ccnt = line_ccnt; - return err; -} - -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) -{ - volatile php_conv_err_t err = PHP_CONV_ERR_SUCCESS; - register size_t ocnt, icnt; - register unsigned char *ps, *pd; - register unsigned int line_ccnt; - size_t nbytes_written; - - if (in_pp == NULL || in_left_p == NULL) { - return php_conv_base64_encode_flush(inst, in_pp, in_left_p, out_pp, out_left_p); - } - - pd = (unsigned char *)(*out_pp); - ocnt = *out_left_p; - ps = (unsigned char *)(*in_pp); - icnt = *in_left_p; - line_ccnt = inst->line_ccnt; - nbytes_written = 0; - - /* consume the remainder first */ - switch (inst->erem_len) { - case 1: - if (icnt >= 2) { - if (line_ccnt < 4 && inst->lbchars != NULL) { - if (ocnt < inst->lbchars_len) { - return PHP_CONV_ERR_TOO_BIG; - } - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } - if (ocnt < 4) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)]; - *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4) | (ps[0] >> 4)]; - *(pd++) = b64_tbl_enc[(unsigned char)(ps[0] << 2) | (ps[1] >> 6)]; - *(pd++) = b64_tbl_enc[ps[1]]; - ocnt -= 4; - ps += 2; - icnt -= 2; - inst->erem_len = 0; - line_ccnt -= 4; - } - break; - - case 2: - if (icnt >= 1) { - if (inst->line_ccnt < 4 && inst->lbchars != NULL) { - if (ocnt < inst->lbchars_len) { - return PHP_CONV_ERR_TOO_BIG; - } - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } - if (ocnt < 4) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = b64_tbl_enc[(inst->erem[0] >> 2)]; - *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[0] << 4) | (inst->erem[1] >> 4)]; - *(pd++) = b64_tbl_enc[(unsigned char)(inst->erem[1] << 2) | (ps[0] >> 6)]; - *(pd++) = b64_tbl_enc[ps[0]]; - ocnt -= 4; - ps += 1; - icnt -= 1; - inst->erem_len = 0; - line_ccnt -= 4; - } - break; - } - - while (icnt >= 3) { - if (line_ccnt < 4 && inst->lbchars != NULL) { - if (ocnt < inst->lbchars_len) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } - if (ocnt < 4) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = b64_tbl_enc[ps[0] >> 2]; - *(pd++) = b64_tbl_enc[(unsigned char)(ps[0] << 4) | (ps[1] >> 4)]; - *(pd++) = b64_tbl_enc[(unsigned char)(ps[1] << 2) | (ps[2] >> 6)]; - *(pd++) = b64_tbl_enc[ps[2]]; - - ps += 3; - icnt -=3; - ocnt -= 4; - line_ccnt -= 4; - } - for (;icnt > 0; icnt--) { - inst->erem[inst->erem_len++] = *(ps++); - } - -out: - *in_pp = (const char *)ps; - *in_left_p = icnt; - *out_pp = (char *)pd; - *out_left_p = ocnt; - inst->line_ccnt = line_ccnt; - - return err; -} - -/* }}} */ - -/* {{{ php_conv_base64_decode */ -typedef struct _php_conv_base64_decode { - php_conv _super; - - unsigned int urem; - unsigned int urem_nbits; - unsigned int ustat; - int eos; -} php_conv_base64_decode; - -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); -static void php_conv_base64_decode_dtor(php_conv_base64_decode *inst); - -static unsigned int b64_tbl_dec[256] = { - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64,128, 64, 64, - 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, - 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 -}; - -static int php_conv_base64_decode_ctor(php_conv_base64_decode *inst) -{ - inst->_super.convert_op = (php_conv_convert_func) php_conv_base64_decode_convert; - inst->_super.dtor = (php_conv_dtor_func) php_conv_base64_decode_dtor; - - inst->urem = 0; - inst->urem_nbits = 0; - inst->ustat = 0; - inst->eos = 0; - return SUCCESS; -} - -static void php_conv_base64_decode_dtor(php_conv_base64_decode *inst) -{ - /* do nothing */ -} - -#define bmask(a) (0xffff >> (16 - a)) -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) -{ - php_conv_err_t err; - - unsigned int urem, urem_nbits; - unsigned int pack, pack_bcnt; - unsigned char *ps, *pd; - size_t icnt, ocnt; - unsigned int ustat; - - const static unsigned int nbitsof_pack = 8; - - if (in_pp == NULL || in_left_p == NULL) { - if (inst->eos || inst->urem_nbits == 0) { - return SUCCESS; - } - return PHP_CONV_ERR_UNEXPECTED_EOS; - } - - err = PHP_CONV_ERR_SUCCESS; - - ps = (unsigned char *)*in_pp; - pd = (unsigned char *)*out_pp; - icnt = *in_left_p; - ocnt = *out_left_p; - - urem = inst->urem; - urem_nbits = inst->urem_nbits; - ustat = inst->ustat; - - pack = 0; - pack_bcnt = nbitsof_pack; - - for (;;) { - if (pack_bcnt >= urem_nbits) { - pack_bcnt -= urem_nbits; - pack |= (urem << pack_bcnt); - urem_nbits = 0; - } else { - urem_nbits -= pack_bcnt; - pack |= (urem >> urem_nbits); - urem &= bmask(urem_nbits); - pack_bcnt = 0; - } - if (pack_bcnt > 0) { - unsigned int i; - - if (icnt < 1) { - break; - } - - i = b64_tbl_dec[(unsigned int)*(ps++)]; - icnt--; - ustat |= i & 0x80; - - if (!(i & 0xc0)) { - if (ustat) { - err = PHP_CONV_ERR_INVALID_SEQ; - break; - } - if (6 <= pack_bcnt) { - pack_bcnt -= 6; - pack |= (i << pack_bcnt); - urem = 0; - } else { - urem_nbits = 6 - pack_bcnt; - pack |= (i >> urem_nbits); - urem = i & bmask(urem_nbits); - pack_bcnt = 0; - } - } else if (ustat) { - if (pack_bcnt == 8 || pack_bcnt == 2) { - err = PHP_CONV_ERR_INVALID_SEQ; - break; - } - inst->eos = 1; - } - } - if ((pack_bcnt | ustat) == 0) { - if (ocnt < 1) { - err = PHP_CONV_ERR_TOO_BIG; - break; - } - *(pd++) = pack; - ocnt--; - pack = 0; - pack_bcnt = nbitsof_pack; - } - } - - if (urem_nbits >= pack_bcnt) { - urem |= (pack << (urem_nbits - pack_bcnt)); - urem_nbits += (nbitsof_pack - pack_bcnt); - } else { - urem |= (pack >> (pack_bcnt - urem_nbits)); - urem_nbits += (nbitsof_pack - pack_bcnt); - } - - inst->urem = urem; - inst->urem_nbits = urem_nbits; - inst->ustat = ustat; - - *in_pp = (const char *)ps; - *in_left_p = icnt; - *out_pp = (char *)pd; - *out_left_p = ocnt; - - return err; -} -#undef bmask -/* }}} */ - -/* {{{ php_conv_qprint_encode */ -typedef struct _php_conv_qprint_encode { - php_conv _super; - - int opts; - unsigned int line_ccnt; - unsigned int line_len; - const char *lbchars; - int lbchars_dup; - size_t lbchars_len; - int persistent; - unsigned int lb_ptr; - unsigned int lb_cnt; -} php_conv_qprint_encode; - -#define PHP_CONV_QPRINT_OPT_BINARY 0x00000001 -#define PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST 0x00000002 - -static void php_conv_qprint_encode_dtor(php_conv_qprint_encode *inst); -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); - -static void php_conv_qprint_encode_dtor(php_conv_qprint_encode *inst) -{ - assert(inst != NULL); - if (inst->lbchars_dup && inst->lbchars != NULL) { - pefree((void *)inst->lbchars, inst->persistent); - } -} - -#define NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, lbchars) \ - ((lb_ptr) < (lb_cnt) ? (lbchars)[(lb_ptr)] : *(ps)) - -#define CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt) \ - if ((lb_ptr) < (lb_cnt)) { \ - (lb_ptr)++; \ - } else { \ - (lb_cnt) = (lb_ptr) = 0; \ - --(icnt); \ - (ps)++; \ - } - -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) -{ - php_conv_err_t err = PHP_CONV_ERR_SUCCESS; - unsigned char *ps, *pd; - size_t icnt, ocnt; - unsigned int c; - unsigned int line_ccnt; - unsigned int lb_ptr; - unsigned int lb_cnt; - int opts; - static char qp_digits[] = "0123456789ABCDEF"; - - line_ccnt = inst->line_ccnt; - opts = inst->opts; - lb_ptr = inst->lb_ptr; - lb_cnt = inst->lb_cnt; - - if ((in_pp == NULL || in_left_p == NULL) && (lb_ptr >=lb_cnt)) { - return PHP_CONV_ERR_SUCCESS; - } - - ps = (unsigned char *)(*in_pp); - icnt = *in_left_p; - pd = (unsigned char *)(*out_pp); - ocnt = *out_left_p; - - for (;;) { - if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && inst->lbchars != NULL && inst->lbchars_len > 0) { - /* look ahead for the line break chars to make a right decision - * how to consume incoming characters */ - - if (icnt > 0 && *ps == inst->lbchars[lb_cnt]) { - lb_cnt++; - - if (lb_cnt >= inst->lbchars_len) { - unsigned int i; - - if (ocnt < lb_cnt) { - lb_cnt--; - err = PHP_CONV_ERR_TOO_BIG; - break; - } - - for (i = 0; i < lb_cnt; i++) { - *(pd++) = inst->lbchars[i]; - ocnt--; - } - line_ccnt = inst->line_len; - lb_ptr = lb_cnt = 0; - } - ps++, icnt--; - continue; - } - } - - if (lb_ptr >= lb_cnt && icnt <= 0) { - break; - } - - c = NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, inst->lbchars); - - if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && (c == '\t' || c == ' ')) { - if (line_ccnt < 2 && inst->lbchars != NULL) { - if (ocnt < inst->lbchars_len + 1) { - err = PHP_CONV_ERR_TOO_BIG; - break; - } - - *(pd++) = '='; - ocnt--; - line_ccnt--; - - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } else { - if (ocnt < 1) { - err = PHP_CONV_ERR_TOO_BIG; - break; - } - *(pd++) = c; - ocnt--; - line_ccnt--; - CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt); - } - } else if ((!(opts & PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST) || line_ccnt < inst->line_len) && ((c >= 33 && c <= 60) || (c >= 62 && c <= 126))) { - if (line_ccnt < 2) { - if (ocnt < inst->lbchars_len + 1) { - err = PHP_CONV_ERR_TOO_BIG; - break; - } - *(pd++) = '='; - ocnt--; - line_ccnt--; - - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } - if (ocnt < 1) { - err = PHP_CONV_ERR_TOO_BIG; - break; - } - *(pd++) = c; - ocnt--; - line_ccnt--; - CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt); - } else { - if (line_ccnt < 4) { - if (ocnt < inst->lbchars_len + 1) { - err = PHP_CONV_ERR_TOO_BIG; - break; - } - *(pd++) = '='; - ocnt--; - line_ccnt--; - - memcpy(pd, inst->lbchars, inst->lbchars_len); - pd += inst->lbchars_len; - ocnt -= inst->lbchars_len; - line_ccnt = inst->line_len; - } - if (ocnt < 3) { - err = PHP_CONV_ERR_TOO_BIG; - break; - } - *(pd++) = '='; - *(pd++) = qp_digits[(c >> 4)]; - *(pd++) = qp_digits[(c & 0x0f)]; - ocnt -= 3; - line_ccnt -= 3; - CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt); - } - } - - *in_pp = (const char *)ps; - *in_left_p = icnt; - *out_pp = (char *)pd; - *out_left_p = ocnt; - inst->line_ccnt = line_ccnt; - inst->lb_ptr = lb_ptr; - inst->lb_cnt = lb_cnt; - return err; -} -#undef NEXT_CHAR -#undef CONSUME_CHAR - -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) -{ - if (line_len < 4 && lbchars != NULL) { - return PHP_CONV_ERR_TOO_BIG; - } - inst->_super.convert_op = (php_conv_convert_func) php_conv_qprint_encode_convert; - inst->_super.dtor = (php_conv_dtor_func) php_conv_qprint_encode_dtor; - inst->line_ccnt = line_len; - inst->line_len = line_len; - if (lbchars != NULL) { - inst->lbchars = (lbchars_dup ? pestrdup(lbchars, persistent) : lbchars); - inst->lbchars_len = lbchars_len; - } else { - inst->lbchars = NULL; - } - inst->lbchars_dup = lbchars_dup; - inst->persistent = persistent; - inst->opts = opts; - inst->lb_cnt = inst->lb_ptr = 0; - return PHP_CONV_ERR_SUCCESS; -} -/* }}} */ - -/* {{{ php_conv_qprint_decode */ -typedef struct _php_conv_qprint_decode { - php_conv _super; - - int scan_stat; - unsigned int next_char; - const char *lbchars; - int lbchars_dup; - size_t lbchars_len; - int persistent; - unsigned int lb_ptr; - unsigned int lb_cnt; -} php_conv_qprint_decode; - -static void php_conv_qprint_decode_dtor(php_conv_qprint_decode *inst) -{ - assert(inst != NULL); - if (inst->lbchars_dup && inst->lbchars != NULL) { - pefree((void *)inst->lbchars, inst->persistent); - } -} - -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) -{ - php_conv_err_t err = PHP_CONV_ERR_SUCCESS; - size_t icnt, ocnt; - unsigned char *ps, *pd; - unsigned int scan_stat; - unsigned int next_char; - unsigned int lb_ptr, lb_cnt; - - lb_ptr = inst->lb_ptr; - lb_cnt = inst->lb_cnt; - - if ((in_pp == NULL || in_left_p == NULL) && lb_cnt == lb_ptr) { - if (inst->scan_stat != 0) { - return PHP_CONV_ERR_UNEXPECTED_EOS; - } - return PHP_CONV_ERR_SUCCESS; - } - - ps = (unsigned char *)(*in_pp); - icnt = *in_left_p; - pd = (unsigned char *)(*out_pp); - ocnt = *out_left_p; - scan_stat = inst->scan_stat; - next_char = inst->next_char; - - for (;;) { - switch (scan_stat) { - case 0: { - if (icnt <= 0) { - goto out; - } - if (*ps == '=') { - scan_stat = 1; - } else { - if (ocnt < 1) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = *ps; - ocnt--; - } - ps++, icnt--; - } break; - - case 1: { - if (icnt <= 0) { - goto out; - } - if (*ps == ' ' || *ps == '\t') { - scan_stat = 4; - ps++, icnt--; - break; - } else if (lb_cnt < inst->lbchars_len && - *ps == (unsigned char)inst->lbchars[lb_cnt]) { - lb_cnt++; - scan_stat = 5; - ps++, icnt--; - break; - } - } /* break is missing intentionally */ - - case 2: { - unsigned int nbl; - - if (icnt <= 0) { - goto out; - } - nbl = (*ps >= 'A' ? *ps - 0x37 : *ps - 0x30); - - if (nbl > 15) { - err = PHP_CONV_ERR_INVALID_SEQ; - goto out; - } - next_char = (next_char << 4) | nbl; - - scan_stat++; - ps++, icnt--; - if (scan_stat != 3) { - break; - } - } /* break is missing intentionally */ - - case 3: { - if (ocnt < 1) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = next_char; - ocnt--; - scan_stat = 0; - } break; - - case 4: { - if (icnt <= 0) { - goto out; - } - if (lb_cnt < inst->lbchars_len && - *ps == (unsigned char)inst->lbchars[lb_cnt]) { - lb_cnt++; - scan_stat = 5; - } - if (*ps != '\t' && *ps != ' ') { - err = PHP_CONV_ERR_INVALID_SEQ; - goto out; - } - ps++, icnt--; - } break; - - case 5: { - if (lb_cnt >= inst->lbchars_len) { - /* soft line break */ - lb_cnt = lb_ptr = 0; - scan_stat = 0; - } else if (icnt > 0) { - if (*ps == (unsigned char)inst->lbchars[lb_cnt]) { - lb_cnt++; - ps++, icnt--; - } else { - scan_stat = 6; /* no break for short-cut */ - } - } else { - goto out; - } - } break; - - case 6: { - if (lb_ptr < lb_cnt) { - if (ocnt < 1) { - err = PHP_CONV_ERR_TOO_BIG; - goto out; - } - *(pd++) = inst->lbchars[lb_ptr++]; - ocnt--; - } else { - scan_stat = 0; - lb_cnt = lb_ptr = 0; - } - } break; - } - } -out: - *in_pp = (const char *)ps; - *in_left_p = icnt; - *out_pp = (char *)pd; - *out_left_p = ocnt; - inst->scan_stat = scan_stat; - inst->lb_ptr = lb_ptr; - inst->lb_cnt = lb_cnt; - inst->next_char = next_char; - - return err; -} -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) -{ - inst->_super.convert_op = (php_conv_convert_func) php_conv_qprint_decode_convert; - inst->_super.dtor = (php_conv_dtor_func) php_conv_qprint_decode_dtor; - inst->scan_stat = 0; - inst->next_char = 0; - inst->lb_ptr = inst->lb_cnt = 0; - if (lbchars != NULL) { - inst->lbchars = (lbchars_dup ? pestrdup(lbchars, persistent) : lbchars); - inst->lbchars_len = lbchars_len; - } else { - inst->lbchars = NULL; - inst->lbchars_len = 0; - } - inst->lbchars_dup = lbchars_dup; - inst->persistent = persistent; - return PHP_CONV_ERR_SUCCESS; -} -/* }}} */ - -typedef struct _php_convert_filter { - php_conv *cd; - int persistent; - char *filtername; - char stub[128]; - size_t stub_len; -} php_convert_filter; - -#define PHP_CONV_BASE64_ENCODE 1 -#define PHP_CONV_BASE64_DECODE 2 -#define PHP_CONV_QPRINT_ENCODE 3 -#define PHP_CONV_QPRINT_DECODE 4 - -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) -{ - zval **tmpval; - - *pretval = NULL; - *pretval_len = 0; - - if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) { - if (Z_TYPE_PP(tmpval) != IS_STRING) { - zval zt = **tmpval; - - convert_to_string(&zt); - - if (NULL == (*pretval = pemalloc(Z_STRLEN(zt) + 1, persistent))) { - return PHP_CONV_ERR_ALLOC; - } - - *pretval_len = Z_STRLEN(zt); - memcpy(*pretval, Z_STRVAL(zt), Z_STRLEN(zt) + 1); - zval_dtor(&zt); - } else { - if (NULL == (*pretval = pemalloc(Z_STRLEN_PP(tmpval) + 1, persistent))) { - return PHP_CONV_ERR_ALLOC; - } - *pretval_len = Z_STRLEN_PP(tmpval); - memcpy(*pretval, Z_STRVAL_PP(tmpval), Z_STRLEN_PP(tmpval) + 1); - } - } else { - return PHP_CONV_ERR_NOT_FOUND; - } - return PHP_CONV_ERR_SUCCESS; -} - -#if IT_WAS_USED -static php_conv_err_t php_conv_get_long_prop_ex(const HashTable *ht, long *pretval, char *field_name, size_t field_name_len) -{ - zval **tmpval; - - *pretval = 0; - - if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) { - zval tmp, *ztval = *tmpval; - - if (Z_TYPE_PP(tmpval) != IS_LONG) { - tmp = *ztval; - zval_copy_ctor(&tmp); - convert_to_long(&tmp); - ztval = &tmp; - } - *pretval = Z_LVAL_P(ztval); - } else { - return PHP_CONV_ERR_NOT_FOUND; - } - return PHP_CONV_ERR_SUCCESS; -} -#endif - -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) -{ - zval **tmpval; - - *pretval = 0; - - if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) { - zval tmp, *ztval = *tmpval; - - if (Z_TYPE_PP(tmpval) != IS_LONG) { - tmp = *ztval; - zval_copy_ctor(&tmp); - convert_to_long(&tmp); - ztval = &tmp; - } - if (Z_LVAL_P(ztval) < 0) { - *pretval = 0; - } else { - *pretval = Z_LVAL_P(ztval); - } - } else { - return PHP_CONV_ERR_NOT_FOUND; - } - return PHP_CONV_ERR_SUCCESS; -} - -static php_conv_err_t php_conv_get_bool_prop_ex(const HashTable *ht, int *pretval, char *field_name, size_t field_name_len) -{ - zval **tmpval; - - *pretval = 0; - - if (zend_hash_find((HashTable *)ht, field_name, field_name_len, (void **)&tmpval) == SUCCESS) { - zval tmp, *ztval = *tmpval; - - if (Z_TYPE_PP(tmpval) != IS_BOOL) { - tmp = *ztval; - zval_copy_ctor(&tmp); - convert_to_boolean(&tmp); - ztval = &tmp; - } - *pretval = Z_BVAL_P(ztval); - } else { - return PHP_CONV_ERR_NOT_FOUND; - } - return PHP_CONV_ERR_SUCCESS; -} - - -#if IT_WAS_USED -static int php_conv_get_int_prop_ex(const HashTable *ht, int *pretval, char *field_name, size_t field_name_len) -{ - long l; - php_conv_err_t err; - - *pretval = 0; - - if ((err = php_conv_get_long_prop_ex(ht, &l, field_name, field_name_len)) == PHP_CONV_ERR_SUCCESS) { - *pretval = l; - } - return err; -} -#endif - -static int php_conv_get_uint_prop_ex(const HashTable *ht, unsigned int *pretval, char *field_name, size_t field_name_len) -{ - long l; - php_conv_err_t err; - - *pretval = 0; - - if ((err = php_conv_get_ulong_prop_ex(ht, &l, field_name, field_name_len)) == PHP_CONV_ERR_SUCCESS) { - *pretval = l; - } - return err; -} - -#define GET_STR_PROP(ht, var, var_len, fldname, persistent) \ - php_conv_get_string_prop_ex(ht, &var, &var_len, fldname, sizeof(fldname), persistent) - -#define GET_INT_PROP(ht, var, fldname) \ - php_conv_get_int_prop_ex(ht, &var, fldname, sizeof(fldname)) - -#define GET_UINT_PROP(ht, var, fldname) \ - php_conv_get_uint_prop_ex(ht, &var, fldname, sizeof(fldname)) - -#define GET_BOOL_PROP(ht, var, fldname) \ - php_conv_get_bool_prop_ex(ht, &var, fldname, sizeof(fldname)) - -static php_conv *php_conv_open(int conv_mode, const HashTable *options, int persistent) -{ - /* FIXME: I'll have to replace this ugly code by something neat - (factories?) in the near future. */ - php_conv *retval = NULL; - - switch (conv_mode) { - case PHP_CONV_BASE64_ENCODE: { - unsigned int line_len = 0; - char *lbchars = NULL; - size_t lbchars_len; - - if (options != NULL) { - GET_STR_PROP(options, lbchars, lbchars_len, "line-break-chars", 0); - GET_UINT_PROP(options, line_len, "line-length"); - if (line_len < 4) { - if (lbchars != NULL) { - pefree(lbchars, 0); - } - lbchars = NULL; - } else { - if (lbchars == NULL) { - lbchars = pestrdup("\r\n", 0); - lbchars_len = 2; - } - } - } - retval = pemalloc(sizeof(php_conv_base64_encode), persistent); - if (lbchars != NULL) { - if (php_conv_base64_encode_ctor((php_conv_base64_encode *)retval, line_len, lbchars, lbchars_len, 1, persistent)) { - if (lbchars != NULL) { - pefree(lbchars, 0); - } - goto out_failure; - } - pefree(lbchars, 0); - } else { - if (php_conv_base64_encode_ctor((php_conv_base64_encode *)retval, 0, NULL, 0, 0, persistent)) { - goto out_failure; - } - } - } break; - - case PHP_CONV_BASE64_DECODE: - retval = pemalloc(sizeof(php_conv_base64_decode), persistent); - if (php_conv_base64_decode_ctor((php_conv_base64_decode *)retval)) { - goto out_failure; - } - break; - - case PHP_CONV_QPRINT_ENCODE: { - unsigned int line_len = 0; - char *lbchars = NULL; - size_t lbchars_len; - int opts = 0; - - if (options != NULL) { - int opt_binary = 0; - int opt_force_encode_first = 0; - - GET_STR_PROP(options, lbchars, lbchars_len, "line-break-chars", 0); - GET_UINT_PROP(options, line_len, "line-length"); - GET_BOOL_PROP(options, opt_binary, "binary"); - GET_BOOL_PROP(options, opt_force_encode_first, "force-encode-first"); - - if (line_len < 4) { - if (lbchars != NULL) { - pefree(lbchars, 0); - } - lbchars = NULL; - } else { - if (lbchars == NULL) { - lbchars = pestrdup("\r\n", 0); - lbchars_len = 2; - } - } - opts |= (opt_binary ? PHP_CONV_QPRINT_OPT_BINARY : 0); - opts |= (opt_force_encode_first ? PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST : 0); - } - retval = pemalloc(sizeof(php_conv_qprint_encode), persistent); - if (lbchars != NULL) { - if (php_conv_qprint_encode_ctor((php_conv_qprint_encode *)retval, line_len, lbchars, lbchars_len, 1, opts, persistent)) { - pefree(lbchars, 0); - goto out_failure; - } - pefree(lbchars, 0); - } else { - if (php_conv_qprint_encode_ctor((php_conv_qprint_encode *)retval, 0, NULL, 0, 0, opts, persistent)) { - goto out_failure; - } - } - } break; - - case PHP_CONV_QPRINT_DECODE: { - char *lbchars = NULL; - size_t lbchars_len; - - if (options != NULL) { - GET_STR_PROP(options, lbchars, lbchars_len, "line-break-chars", 0); - if (lbchars == NULL) { - lbchars = pestrdup("\r\n", 0); - lbchars_len = 2; - } - } - retval = pemalloc(sizeof(php_conv_qprint_decode), persistent); - if (lbchars != NULL) { - if (php_conv_qprint_decode_ctor((php_conv_qprint_decode *)retval, lbchars, lbchars_len, 1, persistent)) { - pefree(lbchars, 0); - goto out_failure; - } - pefree(lbchars, 0); - } else { - if (php_conv_qprint_decode_ctor((php_conv_qprint_decode *)retval, NULL, 0, 0, persistent)) { - goto out_failure; - } - } - } break; - - default: - retval = NULL; - break; - } - return retval; - -out_failure: - if (retval != NULL) { - pefree(retval, persistent); - } - return NULL; -} - -#undef GET_STR_PROP -#undef GET_INT_PROP -#undef GET_UINT_PROP -#undef GET_BOOL_PROP - -static int php_convert_filter_ctor(php_convert_filter *inst, - int conv_mode, HashTable *conv_opts, - const char *filtername, int persistent) -{ - inst->persistent = persistent; - inst->filtername = pestrdup(filtername, persistent); - inst->stub_len = 0; - - if ((inst->cd = php_conv_open(conv_mode, conv_opts, persistent)) == NULL) { - goto out_failure; - } - - return SUCCESS; - -out_failure: - if (inst->cd != NULL) { - php_conv_dtor(inst->cd); - pefree(inst->cd, persistent); - } - if (inst->filtername != NULL) { - pefree(inst->filtername, persistent); - } - return FAILURE; -} - -static void php_convert_filter_dtor(php_convert_filter *inst) -{ - if (inst->cd != NULL) { - php_conv_dtor(inst->cd); - pefree(inst->cd, inst->persistent); - } - - if (inst->filtername != NULL) { - pefree(inst->filtername, inst->persistent); - } -} - -/* {{{ strfilter_convert_append_bucket */ -static int strfilter_convert_append_bucket( - php_convert_filter *inst, - php_stream *stream, php_stream_filter *filter, - php_stream_bucket_brigade *buckets_out, - const char *ps, size_t buf_len, size_t *consumed, - int persistent TSRMLS_DC) -{ - php_conv_err_t err; - php_stream_bucket *new_bucket; - char *out_buf = NULL; - size_t out_buf_size; - char *pd; - const char *pt; - size_t ocnt, icnt, tcnt; - size_t initial_out_buf_size; - - if (ps == NULL) { - initial_out_buf_size = 64; - icnt = 1; - } else { - initial_out_buf_size = buf_len; - icnt = buf_len; - } - - out_buf_size = ocnt = initial_out_buf_size; - if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) { - return FAILURE; - } - - pd = out_buf; - - if (inst->stub_len > 0) { - pt = inst->stub; - tcnt = inst->stub_len; - - while (tcnt > 0) { - err = php_conv_convert(inst->cd, &pt, &tcnt, &pd, &ocnt); - - switch (err) { - case PHP_CONV_ERR_INVALID_SEQ: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid byte sequence", inst->filtername); - goto out_failure; - - case PHP_CONV_ERR_MORE: - if (ps != NULL) { - if (icnt > 0) { - if (inst->stub_len >= sizeof(inst->stub)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): insufficient buffer", inst->filtername); - goto out_failure; - } - inst->stub[inst->stub_len++] = *(ps++); - icnt--; - pt = inst->stub; - tcnt = inst->stub_len; - } else { - tcnt = 0; - break; - } - } - break; - - case PHP_CONV_ERR_UNEXPECTED_EOS: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected end of stream", inst->filtername); - goto out_failure; - - case PHP_CONV_ERR_TOO_BIG: { - char *new_out_buf; - size_t new_out_buf_size; - - new_out_buf_size = out_buf_size << 1; - - if (new_out_buf_size < out_buf_size) { - /* whoa! no bigger buckets are sold anywhere... */ - if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { - goto out_failure; - } - - php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); - - out_buf_size = ocnt = initial_out_buf_size; - if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) { - return FAILURE; - } - pd = out_buf; - } else { - if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) { - if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { - goto out_failure; - } - - php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); - return FAILURE; - } - - pd = new_out_buf + (pd - out_buf); - ocnt += (new_out_buf_size - out_buf_size); - out_buf = new_out_buf; - out_buf_size = new_out_buf_size; - } - } break; - - case PHP_CONV_ERR_UNKNOWN: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername); - goto out_failure; - - default: - break; - } - } - memmove(inst->stub, pt, tcnt); - inst->stub_len = tcnt; - } - - while (icnt > 0) { - err = ((ps == NULL ? php_conv_convert(inst->cd, NULL, NULL, &pd, &ocnt): - php_conv_convert(inst->cd, &ps, &icnt, &pd, &ocnt))); - switch (err) { - case PHP_CONV_ERR_INVALID_SEQ: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid byte sequence", inst->filtername); - goto out_failure; - - case PHP_CONV_ERR_MORE: - if (ps != NULL) { - if (icnt > sizeof(inst->stub)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): insufficient buffer", inst->filtername); - goto out_failure; - } - memcpy(inst->stub, ps, icnt); - inst->stub_len = icnt; - ps += icnt; - icnt = 0; - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unexpected octet values", inst->filtername); - goto out_failure; - } - break; - - case PHP_CONV_ERR_TOO_BIG: { - char *new_out_buf; - size_t new_out_buf_size; - - new_out_buf_size = out_buf_size << 1; - - if (new_out_buf_size < out_buf_size) { - /* whoa! no bigger buckets are sold anywhere... */ - if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { - goto out_failure; - } - - php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); - - out_buf_size = ocnt = initial_out_buf_size; - if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) { - return FAILURE; - } - pd = out_buf; - } else { - if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) { - if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { - goto out_failure; - } - - php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); - return FAILURE; - } - pd = new_out_buf + (pd - out_buf); - ocnt += (new_out_buf_size - out_buf_size); - out_buf = new_out_buf; - out_buf_size = new_out_buf_size; - } - } break; - - case PHP_CONV_ERR_UNKNOWN: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): unknown error", inst->filtername); - goto out_failure; - - default: - if (ps == NULL) { - icnt = 0; - } - break; - } - } - - if (out_buf_size - ocnt > 0) { - if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent TSRMLS_CC))) { - goto out_failure; - } - php_stream_bucket_append(buckets_out, new_bucket TSRMLS_CC); - } else { - pefree(out_buf, persistent); - } - *consumed += buf_len - icnt; - - return SUCCESS; - -out_failure: - pefree(out_buf, persistent); - return FAILURE; -} -/* }}} */ - -static php_stream_filter_status_t strfilter_convert_filter( - php_stream *stream, - php_stream_filter *thisfilter, - php_stream_bucket_brigade *buckets_in, - php_stream_bucket_brigade *buckets_out, - size_t *bytes_consumed, - int flags - TSRMLS_DC) -{ - php_stream_bucket *bucket = NULL; - size_t consumed = 0; - php_convert_filter *inst = (php_convert_filter *)thisfilter->abstract; - - while (buckets_in->head != NULL) { - bucket = buckets_in->head; - - php_stream_bucket_unlink(bucket TSRMLS_CC); - - if (strfilter_convert_append_bucket(inst, stream, thisfilter, - buckets_out, bucket->buf, bucket->buflen, &consumed, - php_stream_is_persistent(stream) TSRMLS_CC) != SUCCESS) { - goto out_failure; - } - - php_stream_bucket_delref(bucket TSRMLS_CC); - } - - if (flags != PSFS_FLAG_NORMAL) { - if (strfilter_convert_append_bucket(inst, stream, thisfilter, - buckets_out, NULL, 0, &consumed, - php_stream_is_persistent(stream) TSRMLS_CC) != SUCCESS) { - goto out_failure; - } - } - - if (bytes_consumed) { - *bytes_consumed = consumed; - } - - return PSFS_PASS_ON; - -out_failure: - if (bucket != NULL) { - php_stream_bucket_delref(bucket TSRMLS_CC); - } - return PSFS_ERR_FATAL; -} - -static void strfilter_convert_dtor(php_stream_filter *thisfilter TSRMLS_DC) -{ - assert(thisfilter->abstract != NULL); - - php_convert_filter_dtor((php_convert_filter *)thisfilter->abstract); - pefree(thisfilter->abstract, ((php_convert_filter *)thisfilter->abstract)->persistent); -} - -static php_stream_filter_ops strfilter_convert_ops = { - strfilter_convert_filter, - strfilter_convert_dtor, - "convert.*" -}; - -static php_stream_filter *strfilter_convert_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC) -{ - php_convert_filter *inst; - php_stream_filter *retval = NULL; - - char *dot; - int conv_mode = 0; - - if (filterparams != NULL && Z_TYPE_P(filterparams) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream filter (%s): invalid filter parameter", filtername); - return NULL; - } - - if ((dot = strchr(filtername, '.')) == NULL) { - return NULL; - } - ++dot; - - inst = pemalloc(sizeof(php_convert_filter), persistent); - - if (strcasecmp(dot, "base64-encode") == 0) { - conv_mode = PHP_CONV_BASE64_ENCODE; - } else if (strcasecmp(dot, "base64-decode") == 0) { - conv_mode = PHP_CONV_BASE64_DECODE; - } else if (strcasecmp(dot, "quoted-printable-encode") == 0) { - conv_mode = PHP_CONV_QPRINT_ENCODE; - } else if (strcasecmp(dot, "quoted-printable-decode") == 0) { - conv_mode = PHP_CONV_QPRINT_DECODE; - } - - if (php_convert_filter_ctor(inst, conv_mode, - (filterparams != NULL ? Z_ARRVAL_P(filterparams) : NULL), - filtername, persistent) != SUCCESS) { - goto out; - } - - retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); -out: - if (retval == NULL) { - pefree(inst, persistent); - } - - return retval; -} - -static php_stream_filter_factory strfilter_convert_factory = { - strfilter_convert_create -}; -/* }}} */ - -static const struct { - php_stream_filter_ops *ops; - php_stream_filter_factory *factory; -} standard_filters[] = { - { &strfilter_rot13_ops, &strfilter_rot13_factory }, - { &strfilter_toupper_ops, &strfilter_toupper_factory }, - { &strfilter_tolower_ops, &strfilter_tolower_factory }, - { &strfilter_strip_tags_ops, &strfilter_strip_tags_factory }, - { &strfilter_convert_ops, &strfilter_convert_factory }, - /* additional filters to go here */ - { NULL, NULL } -}; - -/* {{{ filter MINIT and MSHUTDOWN */ -PHP_MINIT_FUNCTION(standard_filters) -{ - int i; - - for (i = 0; standard_filters[i].ops; i++) { - if (FAILURE == php_stream_filter_register_factory( - standard_filters[i].ops->label, - standard_filters[i].factory - TSRMLS_CC)) { - return FAILURE; - } - } - return SUCCESS; -} - -PHP_MSHUTDOWN_FUNCTION(standard_filters) -{ - int i; - - for (i = 0; standard_filters[i].ops; i++) { - php_stream_filter_unregister_factory(standard_filters[i].ops->label TSRMLS_CC); - } - return SUCCESS; -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ |