Commit:    b5b0a53b09776f74ab4ddf6b9468ab1b41267ab5
Author:    Michael M Slusarz <slus...@curecanti.org>         Sun, 24 Feb 2013 
18:34:35 -0700
Committer: Stanislav Malyshev <s...@php.net>      Sun, 16 Jun 2013 16:04:19 
-0700
Parents:   600d6deef9c8983eb8023171c6c5ae90ca60b6c1
Branches:  PHP-5.4 PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=b5b0a53b09776f74ab4ddf6b9468ab1b41267ab5

Log:
Fix #64166: quoted-printable-encode stream filter incorrectly discarding 
whitespace

Second attempt: need to use lookaheadto determine whether to encode ws

Bugs:
https://bugs.php.net/64166

Changed paths:
  M  ext/standard/filters.c
  M  ext/standard/tests/streams/bug64166.phpt


Diff:
diff --git a/ext/standard/filters.c b/ext/standard/filters.c
index 21e165b..99a39be 100644
--- a/ext/standard/filters.c
+++ b/ext/standard/filters.c
@@ -791,7 +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;
+       unsigned int trail_ws;
        int opts;
        static char qp_digits[] = "0123456789ABCDEF";
 
@@ -808,7 +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;
+       trail_ws = 0;
 
        for (;;) {
                if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && inst->lbchars != 
NULL && inst->lbchars_len > 0) {
@@ -827,14 +827,6 @@ 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--;
@@ -852,9 +844,10 @@ 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 (!(opts & PHP_CONV_QPRINT_OPT_BINARY) &&
+                       (trail_ws == 0) &&
+                       (c == '\t' || c == ' ')) {
                        if (line_ccnt < 2 && inst->lbchars != NULL) {
                                if (ocnt < inst->lbchars_len + 1) {
                                        err = PHP_CONV_ERR_TOO_BIG;
@@ -874,11 +867,41 @@ static php_conv_err_t 
php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
                                        err = PHP_CONV_ERR_TOO_BIG;
                                        break;
                                }
-                               *(pd++) = c;
-                               ocnt--;
-                               line_ccnt--;
-                               prev_ws = 1;
-                               CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
+
+                               /* Check to see if this is EOL whitespace. */
+                               if (inst->lbchars != NULL) {
+                                       unsigned int j, lb_cnt2;
+                                       lb_cnt2 = 0;
+                                       unsigned char *ps2;
+                                       ps2 = ps;
+                                       trail_ws = 1;
+
+                                       for (j = icnt - 1; j > 0; j--, ps2++) {
+                                               if (*ps2 == 
inst->lbchars[lb_cnt2]) {
+                                                       lb_cnt2++;
+                                                       if (lb_cnt2 >= 
inst->lbchars_len) {
+                                                               /* Found 
trailing ws. Reset to top of main
+                                                                * for loop to 
allow for code to do necessary
+                                                                * 
wrapping/encoding. */
+                                                               break;
+                                                       }
+                                               } else if (lb_cnt2 != 0 || 
(*ps2 != '\t' && *ps2 != ' ')) {
+                                                       /* At least one non-EOL 
character following, so
+                                                        * don't need to encode 
ws. */
+                                                       trail_ws = 0;
+                                                       break;
+                                               } else {
+                                                       trail_ws++;
+                                               }
+                                       }
+                               }
+
+                               if (trail_ws == 0) {
+                                       *(pd++) = c;
+                                       ocnt--;
+                                       line_ccnt--;
+                                       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))) 
{ 
                        if (line_ccnt < 2 && inst->lbchars != NULL) {
@@ -927,6 +950,7 @@ static php_conv_err_t 
php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
                        *(pd++) = qp_digits[(c & 0x0f)]; 
                        ocnt -= 3;
                        line_ccnt -= 3;
+                       trail_ws--;
                        CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
                }
        }
diff --git a/ext/standard/tests/streams/bug64166.phpt 
b/ext/standard/tests/streams/bug64166.phpt
index b9a7a05..e725a4b 100644
--- a/ext/standard/tests/streams/bug64166.phpt
+++ b/ext/standard/tests/streams/bug64166.phpt
@@ -2,31 +2,45 @@
 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);
+function test_64166($data) {
+    $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));
+    $res = stream_filter_append($fd, 'convert.quoted-printable-encode', 
STREAM_FILTER_READ, array(
+               'line-break-chars' => "\n",
+               'line-length' => 74
+    ));
+    var_dump(stream_get_contents($fd, -1, 0));
 
-stream_filter_remove($res);
+    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));
+
+    fclose($fd);
+}
+
+test_64166("FIRST \nSECOND");
+test_64166("FIRST  \nSECOND");
 
-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 =
+string(15) "FIRST=20
+SECOND"
+string(19) "FIRST=
+=20
+SECON=
+D"
+string(18) "FIRST=20=20
 SECOND"
-string(18) "FIRST=
- =
+string(24) "FIRST=
+=20=
+=20
 SECON=
 D"


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to