moriyoshi Mon Jan 13 20:23:36 2003 EDT Modified files: /php4/ext/standard filters.c Log: Fixed quoted-printable encoder so that it produces RFC2045 complicant output. As per this specification requirement, the constructor now accepts three options: binary (boolean), line-len (uint), line-break-chars (string).
Index: php4/ext/standard/filters.c diff -u php4/ext/standard/filters.c:1.15 php4/ext/standard/filters.c:1.16 --- php4/ext/standard/filters.c:1.15 Mon Jan 13 06:00:22 2003 +++ php4/ext/standard/filters.c Mon Jan 13 20:23:35 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: filters.c,v 1.15 2003/01/13 11:00:22 moriyoshi Exp $ */ +/* $Id: filters.c,v 1.16 2003/01/14 01:23:35 moriyoshi Exp $ */ #include "php.h" #include "php_globals.h" @@ -653,22 +653,53 @@ /* {{{ 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 + 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) { - /* do nothing */ + 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_cnt) < (lb_ptr) ? (lbchars)[(lb_cnt)] : *(ps)) + +#define CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt) \ + if ((lb_cnt) < (lb_ptr)) { \ + (lb_cnt)++; \ + } 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"; if (in_pp == NULL || in_left_p == NULL) { @@ -679,18 +710,106 @@ icnt = *in_left_p; pd = (unsigned char *)(*out_pp); ocnt = *out_left_p; - - for (; icnt > 0; icnt--, ps++) { - c = *ps; + line_ccnt = inst->line_ccnt; + opts = inst->opts; + lb_ptr = inst->lb_ptr; + lb_cnt = inst->lb_cnt; + + while (icnt > 0) { + 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 (*ps == inst->lbchars[lb_cnt]) { + ps++; + icnt--; + 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; + } + continue; + } + } + + 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--; - if ((c >= 33 && c <= 60) || (c >= 62 && c <= 126)) { + 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 ((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; @@ -699,6 +818,8 @@ *(pd++) = qp_digits[(c >> 4)]; *(pd++) = qp_digits[(c & 0x0f)]; ocnt -= 3; + line_ccnt -= 3; + CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt); } } @@ -706,14 +827,33 @@ *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) +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) { + 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; } /* }}} */ @@ -913,6 +1053,29 @@ 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; +} + + static int php_conv_get_int_prop_ex(const HashTable *ht, int *pretval, char *field_name, size_t field_name_len) { long l; @@ -948,6 +1111,9 @@ #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 @@ -998,12 +1164,45 @@ } break; - case PHP_CONV_QPRINT_ENCODE: + 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; + + 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"); + + 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); + } retval = pemalloc(sizeof(php_conv_qprint_encode), persistent); - if (php_conv_qprint_encode_ctor((php_conv_qprint_encode *)retval)) { - goto out_failure; + 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; + } break; case PHP_CONV_QPRINT_DECODE: retval = pemalloc(sizeof(php_conv_qprint_decode), persistent); @@ -1028,6 +1227,7 @@ #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 write_conv_mode, HashTable *write_conv_opts,
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php