moriyoshi Mon Jan 13 05:21:41 2003 EDT Modified files: /php4/ext/standard filters.c Log: . Implemented a common filter parameter parsing function. # For example "base64-encode.line-break-chars=--,base64-decode.blah=foobar" # will be parsed and splitted into a zval array as # array(2) { # ["base64-encode"]=> # array(1) { # ["line-break-chars"]=> # string(2) "--" # } # ["base64-decode"]=> # array(1) { # ["blah"] => # string(6) "foobar" # } # } . Added automatic line-breaking feature for base64 encode filter. This can be turned on by putting a option entry "base64-encode.line-length" to the filter parameters.
Index: php4/ext/standard/filters.c diff -u php4/ext/standard/filters.c:1.13 php4/ext/standard/filters.c:1.14 --- php4/ext/standard/filters.c:1.13 Sun Jan 12 16:05:22 2003 +++ php4/ext/standard/filters.c Mon Jan 13 05:21:40 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: filters.c,v 1.13 2003/01/12 21:05:22 moriyoshi Exp $ */ +/* $Id: filters.c,v 1.14 2003/01/13 10:21:40 moriyoshi Exp $ */ #include "php.h" #include "php_globals.h" @@ -213,7 +213,9 @@ PHP_CONV_ERR_UNKNOWN, PHP_CONV_ERR_TOO_BIG, PHP_CONV_ERR_INVALID_SEQ, - PHP_CONV_ERR_UNEXPECTED_EOS + PHP_CONV_ERR_UNEXPECTED_EOS, + PHP_CONV_ERR_EXISTS, + PHP_CONV_ERR_NOT_FOUND } php_conv_err_t; typedef struct _php_conv php_conv; @@ -235,6 +237,12 @@ 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); @@ -259,134 +267,219 @@ '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) +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) { - /* do nothing */ + 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_convert(php_conv_base64_encode *inst, const char **in_pp, size_t *in_left_p, char **out_pp, size_t *out_left_p) +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) { - register size_t ocnt, icnt; - register unsigned char *ps, *pd; - size_t nbytes_written; + 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; - nbytes_written = 0; + line_ccnt = inst->line_ccnt; - if (in_pp != NULL && in_left_p != NULL) { - ps = (unsigned char *)(*in_pp); - icnt = *in_left_p; - - /* consume the remainder first */ - switch (inst->erem_len) { - case 1: - if (icnt >= 2) { - if (ocnt < 4) { - return PHP_CONV_ERR_TOO_BIG; - } - *(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; - } - break; + switch (inst->erem_len) { + case 0: + /* do nothing */ + break; - case 2: - if (icnt >= 1) { - if (ocnt < 4) { - return PHP_CONV_ERR_TOO_BIG; - } - *(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; + case 1: + if (line_ccnt < 4 && inst->lbchars != NULL) { + if (ocnt < inst->lbchars_len) { + return PHP_CONV_ERR_TOO_BIG; } - break; - } + 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; - while (icnt >= 3) { + 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) { - *in_pp = (const char *)ps; - *in_left_p = icnt; - *out_pp = (char *)pd; - *out_left_p = ocnt; - - return PHP_CONV_ERR_TOO_BIG; - } - *(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]]; + 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; - ps += 3; - icnt -=3; - ocnt -= 4; - } + 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; +} - for (;icnt > 0; icnt--) { - inst->erem[inst->erem_len++] = *(ps++); - } +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; - *in_pp = (const char *)ps; - *in_left_p = icnt; - *out_pp = (char *)pd; - *out_left_p = ocnt; - } else { - switch (inst->erem_len) { - case 0: - /* do nothing */ - break; + 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); + } - case 1: + 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) { - return PHP_CONV_ERR_TOO_BIG; + 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; + *(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; - break; + ps += 2; + icnt -= 2; + inst->erem_len = 0; + line_ccnt -= 4; + } + break; - case 2: + 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) { - return PHP_CONV_ERR_TOO_BIG; + 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++) = '='; + *(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; - ocnt -=4; - break; + line_ccnt -= 4; + } + break; + } - default: - /* should not happen... */ - return PHP_CONV_ERR_UNKNOWN; + 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; } - *out_pp = (char *)pd; - *out_left_p = ocnt; + *(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++); } - return PHP_CONV_ERR_SUCCESS; +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; } /* }}} */ @@ -746,19 +839,157 @@ #define PHP_CONV_QPRINT_ENCODE 3 #define PHP_CONV_QPRINT_DECODE 4 -static php_conv *php_conv_open(int conv_mode, int persistent) +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); + *pretval = pemalloc(Z_STRLEN(zt) + 1, persistent); + *pretval_len = Z_STRLEN(zt); + memcpy(*pretval, Z_STRVAL(zt), Z_STRLEN(zt) + 1); + zval_dtor(&zt); + } else { + *pretval = pemalloc(Z_STRLEN_PP(tmpval) + 1, persistent); + *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; +} + +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; +} + +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 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; +} + +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)) + +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: + 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 (php_conv_base64_encode_ctor((php_conv_base64_encode *)retval)) { - goto out_failure; + 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; + } break; case PHP_CONV_BASE64_DECODE: retval = pemalloc(sizeof(php_conv_base64_decode), persistent); @@ -794,7 +1025,14 @@ return NULL; } -static int php_convert_filter_ctor(php_convert_filter *inst, int write_conv_mode, int read_conv_mode, const char *filtername, int persistent) +#undef GET_STR_PROP +#undef GET_INT_PROP +#undef GET_UINT_PROP + +static int php_convert_filter_ctor(php_convert_filter *inst, + int write_conv_mode, HashTable *write_conv_opts, + int read_conv_mode, HashTable *read_conv_opts, + const char *filtername, int persistent) { php_conv *write_cd = NULL; php_conv *read_cd = NULL; @@ -803,11 +1041,11 @@ inst->filtername = pestrdup(filtername, persistent); - if ((write_cd = php_conv_open(write_conv_mode, persistent)) == NULL) { + if ((write_cd = php_conv_open(write_conv_mode, write_conv_opts, persistent)) +== NULL) { goto out_failure; } - if ((read_cd = php_conv_open(read_conv_mode, persistent)) == NULL) { + if ((read_cd = php_conv_open(read_conv_mode, read_conv_opts, persistent)) == +NULL) { goto out_failure; } @@ -1007,12 +1245,199 @@ "convert.*" }; +static zval *strfilter_convert_parse_parameters(const char *param_str) +{ + zval *retval, *node; + const unsigned char *p; + char *node_name; + char *value; + size_t node_name_len, value_len; + int scan_stat; + char *buf; + size_t buf_size; + + static int scancode_tbl[256] = { + -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + + + MAKE_STD_ZVAL(retval); + array_init(retval); + + node = retval; + node_name = NULL; + node_name_len = 0; + value = NULL; + buf = NULL; + buf_size = 0; + + scan_stat = 0; + p = (const unsigned char *)param_str; + for (;;) { + int m = scancode_tbl[(unsigned int)*p]; + switch (m) { + case 2: /* '=' */ + switch (scan_stat) { + case 2: + node_name_len = (size_t)((char *)p - +node_name); + scan_stat = 3; + break; + + case 3: + goto out_failure; + } + break; + + case 5: /* ',' */ + case -1: /* EOS */ + if (value == NULL) { + value = empty_string; + value_len = 0; + } else { + value_len = (size_t)((char *)p - value); + } + if (node_name != NULL) { + zval *new_val; + + if (buf_size <= node_name_len) { + char *new_buf; + + buf_size = node_name_len + 1; + new_buf = erealloc(buf, buf_size); + assert(new_buf != NULL); + buf = new_buf; + } + memcpy(buf, node_name, node_name_len); + buf[node_name_len] = '\0'; + + MAKE_STD_ZVAL(new_val); + ZVAL_STRINGL(new_val, value, (int)value_len, +1); + zend_hash_update(Z_ARRVAL_P(node), buf, +node_name_len + 1, &new_val, sizeof(zval *), NULL); + node_name = NULL; + } + value = NULL; + node = retval; + scan_stat = 0; + if (m == -1) { + goto end_scan; + } + break; + + case 3: /* '.' */ + switch (scan_stat) { + case 0: case 1: + node_name = (char *)p; + case 2: { + zval **z_tmp; + + node_name_len = (size_t)((char *)p - +node_name); + + if (buf_size <= node_name_len) { + char *new_buf; + + buf_size = node_name_len + 1; + new_buf = erealloc(buf, +buf_size); + assert(new_buf != NULL); + buf = new_buf; + } + memcpy(buf, node_name, node_name_len); + buf[node_name_len] = '\0'; + + if (zend_hash_find(Z_ARRVAL_P(node), +buf, node_name_len + 1, (void **)&z_tmp) != SUCCESS) { + zval *new_node; + + MAKE_STD_ZVAL(new_node); + array_init(new_node); + +zend_hash_update(Z_ARRVAL_P(node), buf, node_name_len + 1, &new_node, sizeof(zval *), +NULL); + node = new_node; + } else { + node = *z_tmp; + } + scan_stat = 1; + } break; + + case 3: + value = (char *)p; + scan_stat = 4; + case 4: + break; + } + break; + + case 4: /* ' ' */ + switch (scan_stat) { + default: + goto out_failure; + + case 0: + scan_stat = 1; + break; + + case 1: + break; + + case 3: + value = (char *)p; + scan_stat = 4; + case 4: + break; + } + break; + + case 1: + switch (scan_stat) { + case 0: case 1: + node_name = (char *)p; + scan_stat = 2; + break; + + case 3: + value = (char *)p; + scan_stat = 4; + break; + } + break; + } + p++; + } +end_scan: + if (buf != NULL) { + efree(buf); + } + return retval; + +out_failure: + if (buf != NULL) { + efree(buf); + } + zval_dtor(retval); + FREE_ZVAL(retval); + return NULL; +} + static php_stream_filter *strfilter_convert_create(const char *filtername, const char *filterparams, int filterparamslen, int persistent TSRMLS_DC) { php_convert_filter *inst; php_stream_filter *retval = NULL; char *dot; + zval *options = NULL, **tmp_zval_pp; + HashTable *write_conv_opts, *read_conv_opts; if ((dot = strchr(filtername, '.')) == NULL) { return NULL; @@ -1020,46 +1445,81 @@ ++dot; inst = pemalloc(sizeof(php_convert_filter), persistent); - assert(inst != NULL); + + if (filterparams != NULL) { + options = strfilter_convert_parse_parameters(filterparams); + if (options == NULL) { + php_error(E_WARNING, "stream filter (%s): invalid filter +parameter \"%s\"", filtername, filterparams); + } + } + + write_conv_opts = read_conv_opts = NULL; if (strcasecmp(dot, "base64-encode") == 0) { + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"base64-encode", sizeof("base64-encode"), (void **)&tmp_zval_pp) == SUCCESS) { + write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"base64-decode", sizeof("base64-decode"), (void **)&tmp_zval_pp) == SUCCESS) { + read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } if (php_convert_filter_ctor(inst, - PHP_CONV_BASE64_ENCODE, PHP_CONV_BASE64_DECODE, + PHP_CONV_BASE64_ENCODE, write_conv_opts, + PHP_CONV_BASE64_DECODE, read_conv_opts, filtername, persistent) != SUCCESS) { - pefree(inst, persistent); - return NULL; + goto out; } retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); } else if (strcasecmp(dot, "base64-decode") == 0) { + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"base64-decode", sizeof("base64-decode"), (void **)&tmp_zval_pp) == SUCCESS) { + write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"base64-encode", sizeof("base64-encode"), (void **)&tmp_zval_pp) == SUCCESS) { + read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } if (php_convert_filter_ctor(inst, - PHP_CONV_BASE64_DECODE, PHP_CONV_BASE64_ENCODE, + PHP_CONV_BASE64_DECODE, write_conv_opts, + PHP_CONV_BASE64_ENCODE, read_conv_opts, filtername, persistent) != SUCCESS) { - pefree(inst, persistent); - return NULL; + goto out; } retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); } else if (strcasecmp(dot, "quoted-printable-encode") == 0) { + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"quoted-printable-encode", sizeof("quoted-printable-encode"), (void **)&tmp_zval_pp) +== SUCCESS) { + write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"quoted-printable-decode", sizeof("quoted-printable-decode"), (void **)&tmp_zval_pp) +== SUCCESS) { + read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } if (php_convert_filter_ctor(inst, - PHP_CONV_QPRINT_ENCODE, PHP_CONV_QPRINT_DECODE, + PHP_CONV_QPRINT_ENCODE, write_conv_opts, + PHP_CONV_QPRINT_DECODE, read_conv_opts, filtername, persistent) != SUCCESS) { - pefree(inst, persistent); - return NULL; + goto out; } retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); } else if (strcasecmp(dot, "quoted-printable-decode") == 0) { + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"quoted-printable-decode", sizeof("quoted-printable-decode"), (void **)&tmp_zval_pp) +== SUCCESS) { + write_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } + if (options != NULL && zend_hash_find(Z_ARRVAL_P(options), +"quoted-printable-encode", sizeof("quoted-printable-encode"), (void **)&tmp_zval_pp) +== SUCCESS) { + read_conv_opts = Z_ARRVAL_PP(tmp_zval_pp); + } if (php_convert_filter_ctor(inst, - PHP_CONV_QPRINT_DECODE, PHP_CONV_QPRINT_ENCODE, + PHP_CONV_QPRINT_DECODE, write_conv_opts, + PHP_CONV_QPRINT_ENCODE, read_conv_opts, filtername, persistent) != SUCCESS) { - pefree(inst, persistent); - return NULL; + goto out; } retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); } - +out: if (retval == NULL) { pefree(inst, persistent); } - + + if (options != NULL) { + zval_ptr_dtor(&options); + } return retval; }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php