From 459bb4531f92f8663afb6f36aa9be5b789bd591f Mon Sep 17 00:00:00 2001 From: Frédéric Guillot Date: Fri, 6 Jul 2018 21:18:14 -0700 Subject: Update vendor dependencies --- .../appengine/blobstore/blobstore.go | 30 ++++++ .../appengine/blobstore/blobstore_test.go | 106 +++++++++++++++++++++ 2 files changed, 136 insertions(+) (limited to 'vendor/google.golang.org/appengine/blobstore') diff --git a/vendor/google.golang.org/appengine/blobstore/blobstore.go b/vendor/google.golang.org/appengine/blobstore/blobstore.go index 1c8087b..dea25ac 100644 --- a/vendor/google.golang.org/appengine/blobstore/blobstore.go +++ b/vendor/google.golang.org/appengine/blobstore/blobstore.go @@ -8,6 +8,7 @@ package blobstore // import "google.golang.org/appengine/blobstore" import ( "bufio" + "bytes" "encoding/base64" "fmt" "io" @@ -23,6 +24,7 @@ import ( "github.com/golang/protobuf/proto" "golang.org/x/net/context" + "golang.org/x/text/encoding/htmlindex" "google.golang.org/appengine" "google.golang.org/appengine/datastore" @@ -199,12 +201,40 @@ func ParseUpload(req *http.Request) (blobs map[string][]*BlobInfo, other url.Val return nil, nil, err } bi.BlobKey = appengine.BlobKey(params["blob-key"]) + charset := params["charset"] + if ctype != "message/external-body" || bi.BlobKey == "" { if formKey != "" { slurp, serr := ioutil.ReadAll(part) if serr != nil { return nil, nil, errorf("error reading %q MIME part", formKey) } + + // Handle base64 content transfer encoding. multipart.Part transparently + // handles quoted-printable, and no special handling is required for + // 7bit, 8bit, or binary. + ctype, params, err = mime.ParseMediaType(part.Header.Get("Content-Transfer-Encoding")) + if err == nil && ctype == "base64" { + slurp, serr = ioutil.ReadAll(base64.NewDecoder( + base64.StdEncoding, bytes.NewReader(slurp))) + if serr != nil { + return nil, nil, errorf("error %s decoding %q MIME part", ctype, formKey) + } + } + + // Handle charset + if charset != "" { + encoding, err := htmlindex.Get(charset) + if err != nil { + return nil, nil, errorf("error getting decoder for charset %q", charset) + } + + slurp, err = encoding.NewDecoder().Bytes(slurp) + if err != nil { + return nil, nil, errorf("error decoding from charset %q", charset) + } + } + other[formKey] = append(other[formKey], string(slurp)) } continue diff --git a/vendor/google.golang.org/appengine/blobstore/blobstore_test.go b/vendor/google.golang.org/appengine/blobstore/blobstore_test.go index c2be7ef..4616211 100644 --- a/vendor/google.golang.org/appengine/blobstore/blobstore_test.go +++ b/vendor/google.golang.org/appengine/blobstore/blobstore_test.go @@ -5,12 +5,21 @@ package blobstore import ( + "bytes" + "encoding/base64" + "fmt" "io" + "mime/multipart" + "mime/quotedprintable" + "net/http" + "net/textproto" "os" "strconv" "strings" "testing" + "golang.org/x/text/encoding/htmlindex" + "google.golang.org/appengine" "google.golang.org/appengine/internal/aetesting" @@ -19,6 +28,10 @@ import ( const rbs = readBufferSize +const charsetUTF8 = "utf-8" +const charsetISO2022JP = "iso-2022-jp" +const nonASCIIStr = "Hello, 世界" + func min(x, y int) int { if x < y { return x @@ -181,3 +194,96 @@ func TestReader(t *testing.T) { } } } + +// doPlainTextParseUploadTest tests ParseUpload's decoding of non-file form fields. +// It ensures that MIME multipart parts with Content-Type not equal to +// "message/external-body" (i.e. form fields that are not file uploads) are decoded +// correctly according to the value of their Content-Transfer-Encoding header field. +// If charset is not the empty string it will be set in the request's Content-Type +// header field, and if encoding is not the empty string then the Content-Transfer-Encoding +// header field will be set. +func doPlainTextParseUploadTest(t *testing.T, charset string, encoding string, + rawContent string, encodedContent string) { + bodyBuf := &bytes.Buffer{} + w := multipart.NewWriter(bodyBuf) + + fieldName := "foo" + hdr := textproto.MIMEHeader{} + hdr.Set("Content-Disposition", fmt.Sprintf("form-data; name=%q", fieldName)) + + if charset != "" { + hdr.Set("Content-Type", fmt.Sprintf("text/plain; charset=%q", charset)) + } else { + hdr.Set("Content-Type", "text/plain") + } + + if encoding != "" { + hdr.Set("Content-Transfer-Encoding", encoding) + } + + pw, err := w.CreatePart(hdr) + if err != nil { + t.Fatalf("error creating part: %v", err) + } + pw.Write([]byte(encodedContent)) + + if err := w.Close(); err != nil { + t.Fatalf("error closing multipart writer: %v\n", err) + } + + req, err := http.NewRequest("POST", "/upload", bodyBuf) + if err != nil { + t.Fatalf("error creating request: %v", err) + } + + req.Header.Set("Content-Type", w.FormDataContentType()) + _, other, err := ParseUpload(req) + if err != nil { + t.Fatalf("error parsing upload: %v", err) + } + + if other[fieldName][0] != rawContent { + t.Errorf("got %q expected %q", other[fieldName][0], rawContent) + } +} + +func TestParseUploadUTF8Base64Encoding(t *testing.T) { + encoded := base64.StdEncoding.EncodeToString([]byte(nonASCIIStr)) + doPlainTextParseUploadTest(t, charsetUTF8, "base64", nonASCIIStr, encoded) +} + +func TestParseUploadUTF8Base64EncodingMultiline(t *testing.T) { + testStr := "words words words words words words words words words words words words" + encoded := "d29yZHMgd29yZHMgd29yZHMgd29yZHMgd29yZHMgd29yZHMgd29yZHMgd29yZHMgd29yZHMgd29y\r\nZHMgd29yZHMgd29yZHM=" + doPlainTextParseUploadTest(t, charsetUTF8, "base64", testStr, encoded) +} + +func TestParseUploadUTF8QuotedPrintableEncoding(t *testing.T) { + var encoded bytes.Buffer + writer := quotedprintable.NewWriter(&encoded) + writer.Write([]byte(nonASCIIStr)) + writer.Close() + + doPlainTextParseUploadTest(t, charsetUTF8, "quoted-printable", nonASCIIStr, + encoded.String()) +} + +func TestParseUploadISO2022JPBase64Encoding(t *testing.T) { + testStr := "こんにちは" + encoding, err := htmlindex.Get(charsetISO2022JP) + if err != nil { + t.Fatalf("error getting encoding: %v", err) + } + + charsetEncoded, err := encoding.NewEncoder().String(testStr) + if err != nil { + t.Fatalf("error encoding string: %v", err) + } + + base64Encoded := base64.StdEncoding.EncodeToString([]byte(charsetEncoded)) + doPlainTextParseUploadTest(t, charsetISO2022JP, "base64", testStr, base64Encoded) +} + +func TestParseUploadNoEncoding(t *testing.T) { + doPlainTextParseUploadTest(t, "", "", "Hello", "Hello") +} -- cgit v1.2.3