summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael M Slusarz <slusarz@curecanti.org>2013-02-07 12:37:52 -0700
committerStanislav Malyshev <stas@php.net>2013-06-16 16:04:14 -0700
commit600d6deef9c8983eb8023171c6c5ae90ca60b6c1 (patch)
tree3314c42afd88dc2eeb4486e7befad281d57342e8
parent2208447d428542960c73cfeceaf52e95ff0ca2d0 (diff)
downloadphp-git-600d6deef9c8983eb8023171c6c5ae90ca60b6c1.tar.gz
Fix #64166: quoted-printable-encode stream filter incorrectly discarding whitespace
If trailing whitespace on a line is detected, mark the linebreak as a soft linebreak.
-rw-r--r--ext/standard/filters.c12
-rw-r--r--ext/standard/tests/streams/bug64166.phpt32
2 files changed, 44 insertions, 0 deletions
diff --git a/ext/standard/filters.c b/ext/standard/filters.c
index 084860c76b..21e165b6c2 100644
--- a/ext/standard/filters.c
+++ b/ext/standard/filters.c
@@ -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
index 0000000000..b9a7a052a4
--- /dev/null
+++ b/ext/standard/tests/streams/bug64166.phpt
@@ -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"