summaryrefslogtreecommitdiff
path: root/libgo/go/mime/multipart/multipart.go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
commitadb0401dac41c81571722312d4586b2693f95aa6 (patch)
treeea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/mime/multipart/multipart.go
parent5548ca3540bccbc908a45942896d635ea5f1c23f (diff)
downloadgcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.gz
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/mime/multipart/multipart.go')
-rw-r--r--libgo/go/mime/multipart/multipart.go90
1 files changed, 37 insertions, 53 deletions
diff --git a/libgo/go/mime/multipart/multipart.go b/libgo/go/mime/multipart/multipart.go
index 9affa112611..2533bd337dc 100644
--- a/libgo/go/mime/multipart/multipart.go
+++ b/libgo/go/mime/multipart/multipart.go
@@ -21,28 +21,15 @@ import (
"mime"
"net/textproto"
"os"
- "regexp"
)
-var headerRegexp *regexp.Regexp = regexp.MustCompile("^([a-zA-Z0-9\\-]+): *([^\r\n]+)")
+// TODO(bradfitz): inline these once the compiler can inline them in
+// read-only situation (such as bytes.HasSuffix)
+var lf = []byte("\n")
+var crlf = []byte("\r\n")
var emptyParams = make(map[string]string)
-// Reader is an iterator over parts in a MIME multipart body.
-// Reader's underlying parser consumes its input as needed. Seeking
-// isn't supported.
-type Reader interface {
- // NextPart returns the next part in the multipart or an error.
- // When there are no more parts, the error os.EOF is returned.
- NextPart() (*Part, os.Error)
-
- // ReadForm parses an entire multipart message whose parts have
- // a Content-Disposition of "form-data".
- // It stores up to maxMemory bytes of the file parts in memory
- // and the remainder on disk in temporary files.
- ReadForm(maxMemory int64) (*Form, os.Error)
-}
-
// A Part represents a single part in a multipart body.
type Part struct {
// The headers of the body, if any, with the keys canonicalized
@@ -51,7 +38,7 @@ type Part struct {
Header textproto.MIMEHeader
buffer *bytes.Buffer
- mr *multiReader
+ mr *Reader
disposition string
dispositionParams map[string]string
@@ -71,7 +58,6 @@ func (p *Part) FormName() string {
return p.dispositionParams["name"]
}
-
// FileName returns the filename parameter of the Part's
// Content-Disposition header.
func (p *Part) FileName() string {
@@ -91,20 +77,19 @@ func (p *Part) parseContentDisposition() {
// NewReader creates a new multipart Reader reading from r using the
// given MIME boundary.
-func NewReader(reader io.Reader, boundary string) Reader {
+func NewReader(reader io.Reader, boundary string) *Reader {
b := []byte("\r\n--" + boundary + "--")
- return &multiReader{
+ return &Reader{
bufReader: bufio.NewReader(reader),
+ nl: b[:2],
nlDashBoundary: b[:len(b)-2],
dashBoundaryDash: b[2:],
dashBoundary: b[2 : len(b)-2],
}
}
-// Implementation ....
-
-func newPart(mr *multiReader) (*Part, os.Error) {
+func newPart(mr *Reader) (*Part, os.Error) {
bp := &Part{
Header: make(map[string][]string),
mr: mr,
@@ -117,22 +102,12 @@ func newPart(mr *multiReader) (*Part, os.Error) {
}
func (bp *Part) populateHeaders() os.Error {
- for {
- lineBytes, err := bp.mr.bufReader.ReadSlice('\n')
- if err != nil {
- return err
- }
- line := string(lineBytes)
- if line == "\n" || line == "\r\n" {
- return nil
- }
- if matches := headerRegexp.FindStringSubmatch(line); len(matches) == 3 {
- bp.Header.Add(matches[1], matches[2])
- continue
- }
- return os.NewError("Unexpected header line found parsing multipart body")
+ r := textproto.NewReader(bp.mr.bufReader)
+ header, err := r.ReadMIMEHeader()
+ if err == nil {
+ bp.Header = header
}
- panic("unreachable")
+ return err
}
// Read reads the body of a part, after its headers and before the
@@ -188,16 +163,21 @@ func (bp *Part) Close() os.Error {
return nil
}
-type multiReader struct {
+// Reader is an iterator over parts in a MIME multipart body.
+// Reader's underlying parser consumes its input as needed. Seeking
+// isn't supported.
+type Reader struct {
bufReader *bufio.Reader
currentPart *Part
partsRead int
- nlDashBoundary, dashBoundaryDash, dashBoundary []byte
+ nl, nlDashBoundary, dashBoundaryDash, dashBoundary []byte
}
-func (mr *multiReader) NextPart() (*Part, os.Error) {
+// NextPart returns the next part in the multipart or an error.
+// When there are no more parts, the error os.EOF is returned.
+func (mr *Reader) NextPart() (*Part, os.Error) {
if mr.currentPart != nil {
mr.currentPart.Close()
}
@@ -233,11 +213,11 @@ func (mr *multiReader) NextPart() (*Part, os.Error) {
continue
}
- if bytes.Equal(line, []byte("\r\n")) {
- // Consume the "\r\n" separator between the
- // body of the previous part and the boundary
- // line we now expect will follow. (either a
- // new part or the end boundary)
+ // Consume the "\n" or "\r\n" separator between the
+ // body of the previous part and the boundary line we
+ // now expect will follow. (either a new part or the
+ // end boundary)
+ if bytes.Equal(line, mr.nl) {
expectNewPart = true
continue
}
@@ -247,7 +227,7 @@ func (mr *multiReader) NextPart() (*Part, os.Error) {
panic("unreachable")
}
-func (mr *multiReader) isBoundaryDelimiterLine(line []byte) bool {
+func (mr *Reader) isBoundaryDelimiterLine(line []byte) bool {
// http://tools.ietf.org/html/rfc2046#section-5.1
// The boundary delimiter line is then defined as a line
// consisting entirely of two hyphen characters ("-",
@@ -257,13 +237,17 @@ func (mr *multiReader) isBoundaryDelimiterLine(line []byte) bool {
if !bytes.HasPrefix(line, mr.dashBoundary) {
return false
}
- if bytes.HasSuffix(line, []byte("\r\n")) {
- return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-2])
+ if bytes.HasSuffix(line, mr.nl) {
+ return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-len(mr.nl)])
}
// Violate the spec and also support newlines without the
// carriage return...
- if bytes.HasSuffix(line, []byte("\n")) {
- return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-1])
+ if mr.partsRead == 0 && bytes.HasSuffix(line, lf) {
+ if onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-1]) {
+ mr.nl = mr.nl[1:]
+ mr.nlDashBoundary = mr.nlDashBoundary[1:]
+ return true
+ }
}
return false
}
@@ -280,5 +264,5 @@ func onlyHorizontalWhitespace(s []byte) bool {
func hasPrefixThenNewline(s, prefix []byte) bool {
return bytes.HasPrefix(s, prefix) &&
(len(s) == len(prefix)+1 && s[len(s)-1] == '\n' ||
- len(s) == len(prefix)+2 && bytes.HasSuffix(s, []byte("\r\n")))
+ len(s) == len(prefix)+2 && bytes.HasSuffix(s, crlf))
}