]> granicus.if.org Git - php/commitdiff
Fix #64166: quoted-printable-encode stream filter incorrectly discarding whitespace
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 7 Feb 2013 19:37:52 +0000 (12:37 -0700)
committerStanislav Malyshev <stas@php.net>
Sun, 16 Jun 2013 23:04:14 +0000 (16:04 -0700)
If trailing whitespace on a line is detected, mark the linebreak as a
soft linebreak.

ext/standard/filters.c
ext/standard/tests/streams/bug64166.phpt [new file with mode: 0644]

index 084860c76b43353ea0f93957fe9c2c62d79c644f..21e165b6c279e3d7da63fb072978cdb1b1833969 100644 (file)
@@ -791,6 +791,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
        unsigned int line_ccnt;
        unsigned int lb_ptr;
        unsigned int lb_cnt;
+       unsigned int prev_ws;
        int opts;
        static char qp_digits[] = "0123456789ABCDEF";
 
@@ -807,6 +808,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
        icnt = *in_left_p;
        pd = (unsigned char *)(*out_pp);
        ocnt = *out_left_p;
+       prev_ws = 0;
 
        for (;;) {
                if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && inst->lbchars != NULL && inst->lbchars_len > 0) {
@@ -825,6 +827,14 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
                                                break;
                                        }
 
+                                       /* If the character(s) immediately before the line break
+                                        * is whitespace, need to convert to soft linebreak to
+                                        * preserve that data. */
+                                       if (prev_ws > 0) {
+                                               *(pd++) = '=';
+                                               ocnt--;
+                                       }
+
                                        for (i = 0; i < lb_cnt; i++) {
                                                *(pd++) = inst->lbchars[i];
                                                ocnt--;
@@ -842,6 +852,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
                } 
 
                c = NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, inst->lbchars);
+               prev_ws = 0;
 
                if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && (c == '\t' || c == ' ')) {
                        if (line_ccnt < 2 && inst->lbchars != NULL) {
@@ -866,6 +877,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
                                *(pd++) = c;
                                ocnt--;
                                line_ccnt--;
+                               prev_ws = 1;
                                CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
                        }
                } else if ((!(opts & PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST) || line_ccnt < inst->line_len) && ((c >= 33 && c <= 60) || (c >= 62 && c <= 126))) { 
diff --git a/ext/standard/tests/streams/bug64166.phpt b/ext/standard/tests/streams/bug64166.phpt
new file mode 100644 (file)
index 0000000..b9a7a05
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Bug #64166: quoted-printable-encode stream filter incorrectly discarding whitespace
+--FILE--
+<?php
+$data = "FIRST \nSECOND";
+
+$fd = fopen('php://temp', 'w+');
+fwrite($fd, $data);
+rewind($fd);
+
+$res = stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array(
+       'line-break-chars' => "\n",
+       'line-length' => 7
+));
+var_dump(stream_get_contents($fd, -1, 0));
+
+stream_filter_remove($res);
+
+rewind($fd);
+stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array(
+       'line-break-chars' => "\n",
+       'line-length' => 6
+));
+var_dump(stream_get_contents($fd, -1, 0));
+?>
+--EXPECT--
+string(14) "FIRST =
+SECOND"
+string(18) "FIRST=
+ =
+SECON=
+D"