diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 15:47:21 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 15:47:21 +0000 |
commit | adb0401dac41c81571722312d4586b2693f95aa6 (patch) | |
tree | ea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/mime/multipart/multipart.go | |
parent | 5548ca3540bccbc908a45942896d635ea5f1c23f (diff) | |
download | gcc-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.go | 90 |
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)) } |