]> Cypherpunks repositories - gostls13.git/commitdiff
mime/multipart: don't strip leading space/tab in quoted-printable decoding
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 18 Apr 2013 03:04:58 +0000 (20:04 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 18 Apr 2013 03:04:58 +0000 (20:04 -0700)
Late bug fix, but this is arguably a regression from Go 1.0,
since we added this transparent decoding since then. Without
this fix, Go 1.0 users could decode this correctly, but Go 1.1
users would not be able to.

The newly added test is from the RFC itself.

The updated tests had the wrong "want" values before. They
were there to test \r\n vs \n equivalence (which is
unchanged), not leading whitespace.

The skipWhite decoder struct field was added in the battles of
Issue 4771 in revision b3bb265bfecf. It was just a wrong
strategy, from an earlier round of attempts in
https://golang.org/cl/7300092/

Update #4771
Fixes #5295

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/8536045

src/pkg/mime/multipart/quotedprintable.go
src/pkg/mime/multipart/quotedprintable_test.go

index 9e18e1ea1230941a2e7b886e94ab7a8701895b7d..9ff4ee703ee1d952231ba76441d67cf0a51f1908 100644 (file)
@@ -18,16 +18,14 @@ import (
 )
 
 type qpReader struct {
-       br        *bufio.Reader
-       skipWhite bool
-       rerr      error  // last read error
-       line      []byte // to be consumed before more of br
+       br   *bufio.Reader
+       rerr error  // last read error
+       line []byte // to be consumed before more of br
 }
 
 func newQuotedPrintableReader(r io.Reader) io.Reader {
        return &qpReader{
-               br:        bufio.NewReader(r),
-               skipWhite: true,
+               br: bufio.NewReader(r),
        }
 }
 
@@ -55,10 +53,6 @@ func (q *qpReader) readHexByte(v []byte) (b byte, err error) {
        return hb<<4 | lb, nil
 }
 
-func isQPSkipWhiteByte(b byte) bool {
-       return b == ' ' || b == '\t'
-}
-
 func isQPDiscardWhitespace(r rune) bool {
        switch r {
        case '\n', '\r', ' ', '\t':
@@ -79,7 +73,6 @@ func (q *qpReader) Read(p []byte) (n int, err error) {
                        if q.rerr != nil {
                                return n, q.rerr
                        }
-                       q.skipWhite = true
                        q.line, q.rerr = q.br.ReadSlice('\n')
 
                        // Does the line end in CRLF instead of just LF?
@@ -103,11 +96,6 @@ func (q *qpReader) Read(p []byte) (n int, err error) {
                        continue
                }
                b := q.line[0]
-               if q.skipWhite && isQPSkipWhiteByte(b) {
-                       q.line = q.line[1:]
-                       continue
-               }
-               q.skipWhite = false
 
                switch {
                case b == '=':
index 7bcf5767beed59dda055b8a9de3d94be9db56b2f..8a95f7f037b65291215f6d63f6e6f27dc898ea31 100644 (file)
@@ -32,8 +32,9 @@ func TestQuotedPrintable(t *testing.T) {
                {in: "foo bar=0", want: "foo bar", err: io.ErrUnexpectedEOF},
                {in: "foo bar=ab", want: "foo bar", err: "multipart: invalid quoted-printable hex byte 0x61"},
                {in: "foo bar=0D=0A", want: "foo bar\r\n"},
-               {in: " A B =\r\n C ", want: "A B C"},
-               {in: " A B =\n C ", want: "A B C"}, // lax. treating LF as CRLF
+               {in: " A B        \r\n C ", want: " A B\r\n C"},
+               {in: " A B =\r\n C ", want: " A B  C"},
+               {in: " A B =\n C ", want: " A B  C"}, // lax. treating LF as CRLF
                {in: "foo=\nbar", want: "foobar"},
                {in: "foo\x00bar", want: "foo", err: "multipart: invalid unescaped byte 0x00 in quoted-printable body"},
                {in: "foo bar\xff", want: "foo bar", err: "multipart: invalid unescaped byte 0xff in quoted-printable body"},
@@ -57,6 +58,10 @@ func TestQuotedPrintable(t *testing.T) {
                {in: "foo=\nbar", want: "foobar"},
                {in: "foo=\rbar", want: "foo", err: "multipart: invalid quoted-printable hex byte 0x0d"},
                {in: "foo=\r\r\r \nbar", want: "foo", err: `multipart: invalid bytes after =: "\r\r\r \n"`},
+
+               // Example from RFC 2045:
+               {in: "Now's the time =\n" + "for all folk to come=\n" + " to the aid of their country.",
+                       want: "Now's the time for all folk to come to the aid of their country."},
        }
        for _, tt := range tests {
                var buf bytes.Buffer