Browse Source

Implemented quoted-printable stream filter

PHP-5
Moriyoshi Koizumi 24 years ago
parent
commit
eed5a6bed0
  1. 107
      ext/standard/filters.c

107
ext/standard/filters.c

@ -480,6 +480,112 @@ static php_stream_filter_factory strfilter_base64_factory = {
};
/* }}} */
/* {{{ 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 @@ static const struct {
{ &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 }
};

Loading…
Cancel
Save