Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fix #64166: quoted-printable-encode stream filter incorrectly discarding... #272

Closed
wants to merge 4 commits into from

4 participants

Michael M Slusarz Stanislav Malyshev Account for PHP Pull Requests Anatol Belski
Michael M Slusarz

... whitespace

If trailing whitespace on a line is detected, mark the linebreak as a
soft linebreak.

Michael M Slusarz slusarz Fix #64166: quoted-printable-encode stream filter incorrectly discard…
…ing whitespace

If trailing whitespace on a line is detected, mark the linebreak as a
soft linebreak.
bfffa7d
ext/standard/tests/streams/bug64166.phpt
((12 lines not shown))
+ '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 =
Stanislav Malyshev Owner

Why this produces "FIRST{SPACE}" when quoted_printable_encode in this situation produces "FIRST=20"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Stanislav Malyshev
Owner

This patch seems to work differently with join and split writes:

<?php
$data1 = "FIRST ";
$data2 = "\nSECOND";

$fd = fopen('t', 'w+');

$res = stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_WRITE, array(
        'line-break-chars' => "\n",
        'line-length' => 7
));
fwrite($fd, $data1);
fwrite($fd, $data2);
//fwrite($fd, $data1.$data2);
fclose($fd);
var_dump(file_get_contents('t'));

If I do split write, I get this:
string(13) "FIRST
SECOND"
If I do joint write, I get this:
string(14) "FIRST =
SECOND"

I don't think this is a right behavior.

Michael M Slusarz slusarz Fix #64166: quoted-printable-encode stream filter incorrectly discard…
…ing whitespace

Second attempt: need to use lookaheadto determine whether to encode ws
f4d8330
Michael M Slusarz

Things should be fixed now.

Anatol Belski

declarations should be at the top of the nearest block

Account for PHP Pull Requests
Collaborator

Comment on behalf of stas at php.net:

merged

Account for PHP Pull Requests php-pulls closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 7, 2013
  1. Michael M Slusarz

    Fix #64166: quoted-printable-encode stream filter incorrectly discard…

    slusarz authored
    …ing whitespace
    
    If trailing whitespace on a line is detected, mark the linebreak as a
    soft linebreak.
Commits on Feb 25, 2013
  1. Michael M Slusarz

    Fix #64166: quoted-printable-encode stream filter incorrectly discard…

    slusarz authored
    …ing whitespace
    
    Second attempt: need to use lookaheadto determine whether to encode ws
Commits on Mar 18, 2013
  1. Michael M Slusarz

    trailing ws

    slusarz authored
  2. Michael M Slusarz
This page is out of date. Refresh to see the latest.
Showing with 93 additions and 10 deletions.
  1. +47 −10 ext/standard/filters.c
  2. +46 −0 ext/standard/tests/streams/bug64166.phpt
57 ext/standard/filters.c
View
@@ -771,7 +771,7 @@ static void php_conv_qprint_encode_dtor(php_conv_qprint_encode *inst)
}
#define NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, lbchars) \
- ((lb_ptr) < (lb_cnt) ? (lbchars)[(lb_ptr)] : *(ps))
+ ((lb_ptr) < (lb_cnt) ? (lbchars)[(lb_ptr)] : *(ps))
#define CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt) \
if ((lb_ptr) < (lb_cnt)) { \
@@ -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 trail_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;
+ trail_ws = 0;
for (;;) {
if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && inst->lbchars != NULL && inst->lbchars_len > 0) {
@@ -839,11 +841,13 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
if (lb_ptr >= lb_cnt && icnt <= 0) {
break;
- }
+ }
c = NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, inst->lbchars);
- 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;
@@ -863,12 +867,44 @@ 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--;
- CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
+
+ /* Check to see if this is EOL whitespace. */
+ if (inst->lbchars != NULL) {
+ unsigned char *ps2;
+ unsigned int j, lb_cnt2;
+
+ lb_cnt2 = 0;
+ 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))) {
+ } 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) {
if (ocnt < inst->lbchars_len + 1) {
err = PHP_CONV_ERR_TOO_BIG;
@@ -912,9 +948,10 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
}
*(pd++) = '=';
*(pd++) = qp_digits[(c >> 4)];
- *(pd++) = qp_digits[(c & 0x0f)];
+ *(pd++) = qp_digits[(c & 0x0f)];
ocnt -= 3;
line_ccnt -= 3;
+ trail_ws--;
CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
}
}
@@ -922,7 +959,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
*in_pp = (const char *)ps;
*in_left_p = icnt;
*out_pp = (char *)pd;
- *out_left_p = ocnt;
+ *out_left_p = ocnt;
inst->line_ccnt = line_ccnt;
inst->lb_ptr = lb_ptr;
inst->lb_cnt = lb_cnt;
46 ext/standard/tests/streams/bug64166.phpt
View
@@ -0,0 +1,46 @@
+--TEST--
+Bug #64166: quoted-printable-encode stream filter incorrectly discarding whitespace
+--FILE--
+<?php
+
+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' => 74
+ ));
+ 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));
+
+ fclose($fd);
+}
+
+test_64166("FIRST \nSECOND");
+test_64166("FIRST \nSECOND");
+
+?>
+--EXPECT--
+string(15) "FIRST=20
+SECOND"
+string(19) "FIRST=
+=20
+SECON=
+D"
+string(18) "FIRST=20=20
+SECOND"
+string(24) "FIRST=
+=20=
+=20
+SECON=
+D"
Something went wrong with that request. Please try again.