]> granicus.if.org Git - php/commitdiff
Implemented quoted-printable stream filter
authorMoriyoshi Koizumi <moriyoshi@php.net>
Tue, 7 Jan 2003 01:41:18 +0000 (01:41 +0000)
committerMoriyoshi Koizumi <moriyoshi@php.net>
Tue, 7 Jan 2003 01:41:18 +0000 (01:41 +0000)
ext/standard/filters.c

index f1fdde8ec4fdad029f54a7c156f9158db1f3ced8..3378384583f0772580f061d32ee5bd81e3d96dbc 100644 (file)
@@ -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 }
 };