moriyoshi Mon Jan 6 20:41:18 2003 EDT Modified files: /php4/ext/standard filters.c Log: Implemented quoted-printable stream filter Index: php4/ext/standard/filters.c diff -u php4/ext/standard/filters.c:1.5 php4/ext/standard/filters.c:1.6 --- php4/ext/standard/filters.c:1.5 Mon Jan 6 19:03:25 2003 +++ php4/ext/standard/filters.c Mon Jan 6 20:41:18 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: filters.c,v 1.5 2003/01/07 00:03:25 moriyoshi Exp $ */ +/* $Id: filters.c,v 1.6 2003/01/07 01:41:18 moriyoshi Exp $ */ #include "php.h" #include "php_globals.h" @@ -480,6 +480,112 @@ }; /* }}} */ +/* {{{ quoted-printable stream filter implementation */ + +static size_t strfilter_quoted_printable_write(php_stream *stream, php_stream_filter +*thisfilter, + const char *buf, size_t count TSRMLS_DC) +{ + char chunk[4096]; + size_t chunk_len; + unsigned char *ps; + unsigned int bcnt; + static char qp_digits[] = "0123456789ABCDEF"; + + chunk_len = 0; + + ps = (unsigned char *)buf; + for (bcnt = count; bcnt > 0; bcnt--) { + unsigned int c = *(ps++); + + if ((c >= 33 && c <= 60) || (c >= 62 && c <= 126)) { + if (chunk_len >= sizeof(chunk)) { + php_stream_filter_write_next(stream, thisfilter, +chunk, chunk_len); + chunk_len = 0; + } + chunk[chunk_len++] = c; + } else { + if (chunk_len > sizeof(chunk) - 3) { + php_stream_filter_write_next(stream, thisfilter, +chunk, chunk_len); + chunk_len = 0; + } + chunk[chunk_len++] = '='; + chunk[chunk_len++] = qp_digits[(c >> 4)]; + chunk[chunk_len++] = qp_digits[(c & 0x0f)]; + } + } + php_stream_filter_write_next(stream, thisfilter, chunk, chunk_len); + + return count; +} + +static size_t strfilter_quoted_printable_read(php_stream *stream, php_stream_filter +*thisfilter, + char *buf, size_t count TSRMLS_DC) +{ + size_t nbytes_decoded; + size_t bcnt; + unsigned char *ps, *pd; + unsigned int scan_stat = (unsigned int)thisfilter->abstract; + unsigned int v; + + bcnt = php_stream_filter_read_next(stream, thisfilter, buf, count); + nbytes_decoded = 0; + ps = pd = (unsigned char *)buf; + v = 0; + + for (;bcnt > 0; bcnt--) { + switch (scan_stat) { + case 0: + if (*ps == '=') { + scan_stat = 1; + } else { + *(pd++) = *ps; + nbytes_decoded++; + } + break; + + case 1: case 2: { + unsigned int nbl = (*ps >= 'A' ? *ps - 0x37 : *ps - +0x30); + + if (nbl > 15) { + php_error(E_WARNING, "stream +filter(stream.quoted-printable): invalid character sequence"); + return 0; + } + v = (v << 4) | nbl; + + scan_stat++; + if (scan_stat == 3) { + *(pd++) = v; + nbytes_decoded++; + scan_stat = 0; + } + } + } + ps++; + } + (unsigned int)thisfilter->abstract = scan_stat; + return nbytes_decoded; +} + +static php_stream_filter_ops strfilter_quoted_printable_ops = { + strfilter_quoted_printable_write, + strfilter_quoted_printable_read, + commonfilter_nop_flush, + commonfilter_nop_eof, + NULL, + "string.quoted-printable" +}; + +static php_stream_filter *strfilter_quoted_printable_create(const char *filtername, +const char *filterparams, + int filterparamslen, int persistent TSRMLS_DC) +{ + return php_stream_filter_alloc(&strfilter_quoted_printable_ops, 0, persistent); +} + +static php_stream_filter_factory strfilter_quoted_printable_factory = { + strfilter_quoted_printable_create +}; +/* }}} */ + static const struct { php_stream_filter_ops *ops; php_stream_filter_factory *factory; @@ -488,6 +594,7 @@ { &strfilter_toupper_ops, &strfilter_toupper_factory }, { &strfilter_tolower_ops, &strfilter_tolower_factory }, { &strfilter_base64_ops, &strfilter_base64_factory }, + { &strfilter_quoted_printable_ops, &strfilter_quoted_printable_factory }, /* additional filters to go here */ { NULL, NULL } };
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php