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