mirror of
https://github.com/golang/go
synced 2024-11-18 01:54:45 -07:00
mime/quotedprintable: accept = not followed by 2 hex digits as literal equals
This lets quotedprintable handle some inputs found in the wild, most notably generated by "Microsoft CDO for Exchange 2000", and it also matches how Python's quopri package handles these inputs. Fixes #13219. Change-Id: I69d400659d01b6ea0f707b7053d61803a85b4799 Reviewed-on: https://go-review.googlesource.com/32174 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
864859d209
commit
a8e86d99f1
@ -15,7 +15,7 @@ import (
|
||||
func ExampleNewReader() {
|
||||
for _, s := range []string{
|
||||
`=48=65=6C=6C=6F=2C=20=47=6F=70=68=65=72=73=21`,
|
||||
`invalid escape: =B`,
|
||||
`invalid escape: <b style="font-size: 200%">hello</b>`,
|
||||
"Hello, Gophers! This symbol will be unescaped: =3D and this will be written in =\r\none line.",
|
||||
} {
|
||||
b, err := ioutil.ReadAll(quotedprintable.NewReader(strings.NewReader(s)))
|
||||
@ -23,7 +23,7 @@ func ExampleNewReader() {
|
||||
}
|
||||
// Output:
|
||||
// Hello, Gophers! <nil>
|
||||
// invalid escape: unexpected EOF
|
||||
// invalid escape: <b style="font-size: 200%">hello</b> <nil>
|
||||
// Hello, Gophers! This symbol will be unescaped: = and this will be written in one line. <nil>
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,8 @@ func (r *Reader) Read(p []byte) (n int, err error) {
|
||||
// 3. it accepts soft line-break (=) at end of message (issue 15486); i.e.
|
||||
// the final byte read from the underlying reader is allowed to be '=',
|
||||
// and it will be silently ignored.
|
||||
// 4. it takes = as literal = if not followed by two hex digits
|
||||
// but not at end of line (issue 13219).
|
||||
for len(p) > 0 {
|
||||
if len(r.line) == 0 {
|
||||
if r.rerr != nil {
|
||||
@ -111,6 +113,11 @@ func (r *Reader) Read(p []byte) (n int, err error) {
|
||||
case b == '=':
|
||||
b, err = readHexByte(r.line[1:])
|
||||
if err != nil {
|
||||
if len(r.line) >= 2 && r.line[1] != '\r' && r.line[1] != '\n' {
|
||||
// Take the = as a literal =.
|
||||
b = '='
|
||||
break
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
r.line = r.line[2:] // 2 of the 3; other 1 is done below
|
||||
|
@ -30,7 +30,7 @@ func TestReader(t *testing.T) {
|
||||
{in: "foo bar=3d", want: "foo bar="}, // lax.
|
||||
{in: "foo bar=\n", want: "foo bar"},
|
||||
{in: "foo bar\n", want: "foo bar\n"}, // somewhat lax.
|
||||
{in: "foo bar=0", want: "foo bar", err: io.ErrUnexpectedEOF},
|
||||
{in: "foo bar=0", want: "foo bar=0"}, // lax
|
||||
{in: "foo bar=0D=0A", want: "foo bar\r\n"},
|
||||
{in: " A B \r\n C ", want: " A B\r\n C"},
|
||||
{in: " A B =\r\n C ", want: " A B C"},
|
||||
@ -194,13 +194,10 @@ func TestExhaustive(t *testing.T) {
|
||||
}
|
||||
sort.Strings(outcomes)
|
||||
got := strings.Join(outcomes, "\n")
|
||||
want := `OK: 21576
|
||||
invalid bytes after =: 3397
|
||||
quotedprintable: invalid hex byte 0x0a: 1400
|
||||
quotedprintable: invalid hex byte 0x0d: 2700
|
||||
quotedprintable: invalid hex byte 0x20: 2490
|
||||
quotedprintable: invalid hex byte 0x3d: 440
|
||||
unexpected EOF: 3122`
|
||||
want := `OK: 28934
|
||||
invalid bytes after =: 3949
|
||||
quotedprintable: invalid hex byte 0x0d: 2048
|
||||
unexpected EOF: 194`
|
||||
if got != want {
|
||||
t.Errorf("Got:\n%s\nWant:\n%s", got, want)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user