summaryrefslogtreecommitdiff
path: root/libgo/go/mime
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-09-24 21:46:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-24 21:46:21 +0000
commitdd931d9b48647e898dc80927c532ae93cc09e192 (patch)
tree71be2295cd79b8a182f6130611658db8628772d5 /libgo/go/mime
parent779d8a5ad09b01428726ea5a0e6c87bd9ac3c0e4 (diff)
libgo: update to Go 1.11
Reviewed-on: https://go-review.googlesource.com/136435 gotools/: * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to make sure it is writable. (check-go-tools): Likewise. (check-vet): Copy internal/objabi to check-vet-dir. * Makefile.in: Rebuild. From-SVN: r264546
Diffstat (limited to 'libgo/go/mime')
-rw-r--r--libgo/go/mime/encodedword.go60
-rw-r--r--libgo/go/mime/mediatype.go7
-rw-r--r--libgo/go/mime/multipart/formdata.go3
-rw-r--r--libgo/go/mime/multipart/formdata_test.go29
-rw-r--r--libgo/go/mime/multipart/multipart.go8
-rw-r--r--libgo/go/mime/multipart/multipart_test.go8
-rw-r--r--libgo/go/mime/quotedprintable/reader.go4
-rw-r--r--libgo/go/mime/quotedprintable/reader_test.go4
-rw-r--r--libgo/go/mime/quotedprintable/writer_test.go2
-rw-r--r--libgo/go/mime/type.go3
-rw-r--r--libgo/go/mime/type_unix.go2
11 files changed, 74 insertions, 56 deletions
diff --git a/libgo/go/mime/encodedword.go b/libgo/go/mime/encodedword.go
index 99eb432f54e..58f60daec43 100644
--- a/libgo/go/mime/encodedword.go
+++ b/libgo/go/mime/encodedword.go
@@ -11,7 +11,6 @@ import (
"fmt"
"io"
"strings"
- "sync"
"unicode"
"unicode/utf8"
)
@@ -51,16 +50,19 @@ func needsEncoding(s string) bool {
// encodeWord encodes a string into an encoded-word.
func (e WordEncoder) encodeWord(charset, s string) string {
- buf := getBuffer()
- defer putBuffer(buf)
+ var buf strings.Builder
+ // Could use a hint like len(s)*3, but that's not enough for cases
+ // with word splits and too much for simpler inputs.
+ // 48 is close to maxEncodedWordLen/2, but adjusted to allocator size class.
+ buf.Grow(48)
- e.openWord(buf, charset)
+ e.openWord(&buf, charset)
if e == BEncoding {
- e.bEncode(buf, charset, s)
+ e.bEncode(&buf, charset, s)
} else {
- e.qEncode(buf, charset, s)
+ e.qEncode(&buf, charset, s)
}
- closeWord(buf)
+ closeWord(&buf)
return buf.String()
}
@@ -77,7 +79,7 @@ const (
var maxBase64Len = base64.StdEncoding.DecodedLen(maxContentLen)
// bEncode encodes s using base64 encoding and writes it to buf.
-func (e WordEncoder) bEncode(buf *bytes.Buffer, charset, s string) {
+func (e WordEncoder) bEncode(buf *strings.Builder, charset, s string) {
w := base64.NewEncoder(base64.StdEncoding, buf)
// If the charset is not UTF-8 or if the content is short, do not bother
// splitting the encoded-word.
@@ -109,7 +111,7 @@ func (e WordEncoder) bEncode(buf *bytes.Buffer, charset, s string) {
// qEncode encodes s using Q encoding and writes it to buf. It splits the
// encoded-words when necessary.
-func (e WordEncoder) qEncode(buf *bytes.Buffer, charset, s string) {
+func (e WordEncoder) qEncode(buf *strings.Builder, charset, s string) {
// We only split encoded-words when the charset is UTF-8.
if !isUTF8(charset) {
writeQString(buf, s)
@@ -139,7 +141,7 @@ func (e WordEncoder) qEncode(buf *bytes.Buffer, charset, s string) {
}
// writeQString encodes s using Q encoding and writes it to buf.
-func writeQString(buf *bytes.Buffer, s string) {
+func writeQString(buf *strings.Builder, s string) {
for i := 0; i < len(s); i++ {
switch b := s[i]; {
case b == ' ':
@@ -155,7 +157,7 @@ func writeQString(buf *bytes.Buffer, s string) {
}
// openWord writes the beginning of an encoded-word into buf.
-func (e WordEncoder) openWord(buf *bytes.Buffer, charset string) {
+func (e WordEncoder) openWord(buf *strings.Builder, charset string) {
buf.WriteString("=?")
buf.WriteString(charset)
buf.WriteByte('?')
@@ -164,12 +166,12 @@ func (e WordEncoder) openWord(buf *bytes.Buffer, charset string) {
}
// closeWord writes the end of an encoded-word into buf.
-func closeWord(buf *bytes.Buffer) {
+func closeWord(buf *strings.Builder) {
buf.WriteString("?=")
}
// splitWord closes the current encoded-word and opens a new one.
-func (e WordEncoder) splitWord(buf *bytes.Buffer, charset string) {
+func (e WordEncoder) splitWord(buf *strings.Builder, charset string) {
closeWord(buf)
buf.WriteByte(' ')
e.openWord(buf, charset)
@@ -224,10 +226,9 @@ func (d *WordDecoder) Decode(word string) (string, error) {
return "", err
}
- buf := getBuffer()
- defer putBuffer(buf)
+ var buf strings.Builder
- if err := d.convert(buf, charset, content); err != nil {
+ if err := d.convert(&buf, charset, content); err != nil {
return "", err
}
@@ -243,8 +244,7 @@ func (d *WordDecoder) DecodeHeader(header string) (string, error) {
return header, nil
}
- buf := getBuffer()
- defer putBuffer(buf)
+ var buf strings.Builder
buf.WriteString(header[:i])
header = header[i:]
@@ -296,7 +296,7 @@ func (d *WordDecoder) DecodeHeader(header string) (string, error) {
buf.WriteString(header[:start])
}
- if err := d.convert(buf, charset, content); err != nil {
+ if err := d.convert(&buf, charset, content); err != nil {
return "", err
}
@@ -322,7 +322,7 @@ func decode(encoding byte, text string) ([]byte, error) {
}
}
-func (d *WordDecoder) convert(buf *bytes.Buffer, charset string, content []byte) error {
+func (d *WordDecoder) convert(buf *strings.Builder, charset string, content []byte) error {
switch {
case strings.EqualFold("utf-8", charset):
buf.Write(content)
@@ -346,7 +346,7 @@ func (d *WordDecoder) convert(buf *bytes.Buffer, charset string, content []byte)
if err != nil {
return err
}
- if _, err = buf.ReadFrom(r); err != nil {
+ if _, err = io.Copy(buf, r); err != nil {
return err
}
}
@@ -422,21 +422,3 @@ func fromHex(b byte) (byte, error) {
}
return 0, fmt.Errorf("mime: invalid hex byte %#02x", b)
}
-
-var bufPool = sync.Pool{
- New: func() interface{} {
- return new(bytes.Buffer)
- },
-}
-
-func getBuffer() *bytes.Buffer {
- return bufPool.Get().(*bytes.Buffer)
-}
-
-func putBuffer(buf *bytes.Buffer) {
- if buf.Len() > 1024 {
- return
- }
- buf.Reset()
- bufPool.Put(buf)
-}
diff --git a/libgo/go/mime/mediatype.go b/libgo/go/mime/mediatype.go
index 426d417da23..ea2bbac1891 100644
--- a/libgo/go/mime/mediatype.go
+++ b/libgo/go/mime/mediatype.go
@@ -5,7 +5,6 @@
package mime
import (
- "bytes"
"errors"
"fmt"
"sort"
@@ -19,7 +18,7 @@ import (
// When any of the arguments result in a standard violation then
// FormatMediaType returns the empty string.
func FormatMediaType(t string, param map[string]string) string {
- var b bytes.Buffer
+ var b strings.Builder
if slash := strings.Index(t, "/"); slash == -1 {
if !isToken(t) {
return ""
@@ -167,7 +166,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err e
// Stitch together any continuations or things with stars
// (i.e. RFC 2231 things with stars: "foo*0" or "foo*")
- var buf bytes.Buffer
+ var buf strings.Builder
for key, pieceMap := range continuation {
singlePartKey := key + "*"
if v, ok := pieceMap[singlePartKey]; ok {
@@ -265,7 +264,7 @@ func consumeValue(v string) (value, rest string) {
}
// parse a quoted-string
- buffer := new(bytes.Buffer)
+ buffer := new(strings.Builder)
for i := 1; i < len(v); i++ {
r := v[i]
if r == '"' {
diff --git a/libgo/go/mime/multipart/formdata.go b/libgo/go/mime/multipart/formdata.go
index 2a4ebdd4a06..832d0ad6936 100644
--- a/libgo/go/mime/multipart/formdata.go
+++ b/libgo/go/mime/multipart/formdata.go
@@ -58,8 +58,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
var b bytes.Buffer
- _, hasContentTypeHeader := p.Header["Content-Type"]
- if !hasContentTypeHeader && filename == "" {
+ if filename == "" {
// value, store as string in memory
n, err := io.CopyN(&b, p, maxValueBytes+1)
if err != nil && err != io.EOF {
diff --git a/libgo/go/mime/multipart/formdata_test.go b/libgo/go/mime/multipart/formdata_test.go
index 69333d3d0de..2d6a830cb66 100644
--- a/libgo/go/mime/multipart/formdata_test.go
+++ b/libgo/go/mime/multipart/formdata_test.go
@@ -47,12 +47,24 @@ func TestReadFormWithNamelessFile(t *testing.T) {
}
defer f.RemoveAll()
- fd := testFile(t, f.File["hiddenfile"][0], "", filebContents)
- if _, ok := fd.(sectionReadCloser); !ok {
- t.Errorf("file has unexpected underlying type %T", fd)
+ if g, e := f.Value["hiddenfile"][0], filebContents; g != e {
+ t.Errorf("hiddenfile value = %q, want %q", g, e)
}
- fd.Close()
+}
+func TestReadFormWithTextContentType(t *testing.T) {
+ // From https://github.com/golang/go/issues/24041
+ b := strings.NewReader(strings.Replace(messageWithTextContentType, "\n", "\r\n", -1))
+ r := NewReader(b, boundary)
+ f, err := r.ReadForm(25)
+ if err != nil {
+ t.Fatal("ReadForm:", err)
+ }
+ defer f.RemoveAll()
+
+ if g, e := f.Value["texta"][0], textaValue; g != e {
+ t.Errorf("texta value = %q, want %q", g, e)
+ }
}
func testFile(t *testing.T, fh *FileHeader, efn, econtent string) File {
@@ -94,6 +106,15 @@ Content-Type: text/plain
--MyBoundary--
`
+const messageWithTextContentType = `
+--MyBoundary
+Content-Disposition: form-data; name="texta"
+Content-Type: text/plain
+
+` + textaValue + `
+--MyBoundary
+`
+
const message = `
--MyBoundary
Content-Disposition: form-data; name="filea"; filename="filea.txt"
diff --git a/libgo/go/mime/multipart/multipart.go b/libgo/go/mime/multipart/multipart.go
index 19548081769..0993fb7e91d 100644
--- a/libgo/go/mime/multipart/multipart.go
+++ b/libgo/go/mime/multipart/multipart.go
@@ -61,7 +61,7 @@ type Part struct {
// FormName returns the name parameter if p has a Content-Disposition
// of type "form-data". Otherwise it returns the empty string.
func (p *Part) FormName() string {
- // See http://tools.ietf.org/html/rfc2183 section 2 for EBNF
+ // See https://tools.ietf.org/html/rfc2183 section 2 for EBNF
// of Content-Disposition value format.
if p.dispositionParams == nil {
p.parseContentDisposition()
@@ -303,7 +303,9 @@ func (r *Reader) NextPart() (*Part, error) {
if r.currentPart != nil {
r.currentPart.Close()
}
-
+ if string(r.dashBoundary) == "--" {
+ return nil, fmt.Errorf("multipart: boundary is empty")
+ }
expectNewPart := false
for {
line, err := r.bufReader.ReadSlice('\n')
@@ -370,7 +372,7 @@ func (mr *Reader) isFinalBoundary(line []byte) bool {
}
func (mr *Reader) isBoundaryDelimiterLine(line []byte) (ret bool) {
- // http://tools.ietf.org/html/rfc2046#section-5.1
+ // https://tools.ietf.org/html/rfc2046#section-5.1
// The boundary delimiter line is then defined as a line
// consisting entirely of two hyphen characters ("-",
// decimal value 45) followed by the boundary parameter
diff --git a/libgo/go/mime/multipart/multipart_test.go b/libgo/go/mime/multipart/multipart_test.go
index 7fbee90ac38..abe1cc8e77c 100644
--- a/libgo/go/mime/multipart/multipart_test.go
+++ b/libgo/go/mime/multipart/multipart_test.go
@@ -880,3 +880,11 @@ func roundTripParseTest() parseTest {
t.sep = w.Boundary()
return t
}
+
+func TestNoBoundary(t *testing.T) {
+ mr := NewReader(strings.NewReader(""), "")
+ _, err := mr.NextPart()
+ if got, want := fmt.Sprint(err), "multipart: boundary is empty"; got != want {
+ t.Errorf("NextPart error = %v; want %v", got, want)
+ }
+}
diff --git a/libgo/go/mime/quotedprintable/reader.go b/libgo/go/mime/quotedprintable/reader.go
index b1422403430..4239625402a 100644
--- a/libgo/go/mime/quotedprintable/reader.go
+++ b/libgo/go/mime/quotedprintable/reader.go
@@ -123,6 +123,10 @@ func (r *Reader) Read(p []byte) (n int, err error) {
r.line = r.line[2:] // 2 of the 3; other 1 is done below
case b == '\t' || b == '\r' || b == '\n':
break
+ case b >= 0x80:
+ // As an extension to RFC 2045, we accept
+ // values >= 0x80 without complaint. Issue 22597.
+ break
case b < ' ' || b > '~':
return n, fmt.Errorf("quotedprintable: invalid unescaped byte 0x%02x in body", b)
}
diff --git a/libgo/go/mime/quotedprintable/reader_test.go b/libgo/go/mime/quotedprintable/reader_test.go
index ca016f969a4..f870bdaa8df 100644
--- a/libgo/go/mime/quotedprintable/reader_test.go
+++ b/libgo/go/mime/quotedprintable/reader_test.go
@@ -37,7 +37,7 @@ func TestReader(t *testing.T) {
{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: "quotedprintable: invalid unescaped byte 0x00 in body"},
- {in: "foo bar\xff", want: "foo bar", err: "quotedprintable: invalid unescaped byte 0xff in body"},
+ {in: "foo bar\xff", want: "foo bar\xff"},
// Equal sign.
{in: "=3D30\n", want: "=30\n"},
@@ -65,6 +65,8 @@ func TestReader(t *testing.T) {
// 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."},
+ {in: "accept UTF-8 right quotation mark: ’",
+ want: "accept UTF-8 right quotation mark: ’"},
}
for _, tt := range tests {
var buf bytes.Buffer
diff --git a/libgo/go/mime/quotedprintable/writer_test.go b/libgo/go/mime/quotedprintable/writer_test.go
index a9b77b3f989..d494c1e3dc3 100644
--- a/libgo/go/mime/quotedprintable/writer_test.go
+++ b/libgo/go/mime/quotedprintable/writer_test.go
@@ -138,7 +138,7 @@ func TestRoundTrip(t *testing.T) {
}
}
-// From http://fr.wikipedia.org/wiki/Quoted-Printable
+// From https://fr.wikipedia.org/wiki/Quoted-Printable
var testMsg = []byte("Quoted-Printable (QP) est un format d'encodage de données codées sur 8 bits, qui utilise exclusivement les caractères alphanumériques imprimables du code ASCII (7 bits).\r\n" +
"\r\n" +
"En effet, les différents codages comprennent de nombreux caractères qui ne sont pas représentables en ASCII (par exemple les caractères accentués), ainsi que des caractères dits « non-imprimables ».\r\n" +
diff --git a/libgo/go/mime/type.go b/libgo/go/mime/type.go
index 78fc6b6714e..64e26ffb7cc 100644
--- a/libgo/go/mime/type.go
+++ b/libgo/go/mime/type.go
@@ -62,7 +62,8 @@ var builtinTypesLower = map[string]string{
".htm": "text/html; charset=utf-8",
".html": "text/html; charset=utf-8",
".jpg": "image/jpeg",
- ".js": "application/x-javascript",
+ ".js": "application/javascript",
+ ".wasm": "application/wasm",
".pdf": "application/pdf",
".png": "image/png",
".svg": "image/svg+xml",
diff --git a/libgo/go/mime/type_unix.go b/libgo/go/mime/type_unix.go
index 8e177ca14ee..dfc1f88b2ae 100644
--- a/libgo/go/mime/type_unix.go
+++ b/libgo/go/mime/type_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package mime