]> Cypherpunks repositories - gostls13.git/commitdiff
multipart: use textproto to handle multiline header
authorEvan Martin <evan.martin@gmail.com>
Sat, 9 Jul 2011 22:18:31 +0000 (15:18 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sat, 9 Jul 2011 22:18:31 +0000 (15:18 -0700)
R=bradfitz
CC=golang-dev
https://golang.org/cl/4686044

src/pkg/mime/multipart/multipart.go
src/pkg/mime/multipart/multipart_test.go

index 4711fd78ba4a4536992dcfe914faec4b5291d6ee..630aaf5ed2d39e70391dd4b827f0676ae3e86c4f 100644 (file)
@@ -21,7 +21,6 @@ import (
        "mime"
        "net/textproto"
        "os"
-       "regexp"
 )
 
 // TODO(bradfitz): inline these once the compiler can inline them in
@@ -29,8 +28,6 @@ import (
 var lf = []byte("\n")
 var crlf = []byte("\r\n")
 
-var headerRegexp *regexp.Regexp = regexp.MustCompile("^([a-zA-Z0-9\\-]+): *([^\r\n]+)")
-
 var emptyParams = make(map[string]string)
 
 // A Part represents a single part in a multipart body.
@@ -106,22 +103,12 @@ func newPart(mr *Reader) (*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
index 1357466acd0b94be77fb7c19a41e724870c425ad..3f3b8b1a0e7fface1ca878312c2a22348f73711a 100644 (file)
@@ -352,3 +352,29 @@ func (s *slowReader) Read(p []byte) (int, os.Error) {
        }
        return s.r.Read(p[:1])
 }
+
+func TestLineContinuation(t *testing.T) {
+       // This body, extracted from an email, contains headers that span multiple
+       // lines.
+
+       // TODO: The original mail ended with a double-newline before the
+       // final delimiter; this was manually edited to use a CRLF.
+       testBody :=
+               "\n--Apple-Mail-2-292336769\nContent-Transfer-Encoding: 7bit\nContent-Type: text/plain;\n\tcharset=US-ASCII;\n\tdelsp=yes;\n\tformat=flowed\n\nI'm finding the same thing happening on my system (10.4.1).\n\n\n--Apple-Mail-2-292336769\nContent-Transfer-Encoding: quoted-printable\nContent-Type: text/html;\n\tcharset=ISO-8859-1\n\n<HTML><BODY>I'm finding the same thing =\nhappening on my system (10.4.1).=A0 But I built it with XCode =\n2.0.</BODY></=\nHTML>=\n\r\n--Apple-Mail-2-292336769--\n"
+
+       r := NewReader(strings.NewReader(testBody), "Apple-Mail-2-292336769")
+
+       for i := 0; i < 2; i++ {
+               part, err := r.NextPart()
+               if err != nil {
+                       t.Fatalf("didn't get a part")
+               }
+               n, err := io.Copy(ioutil.Discard, part)
+               if err != nil {
+                       t.Errorf("error reading part: %v", err)
+               }
+               if n <= 0 {
+                       t.Errorf("read %d bytes; expected >0", n)
+               }
+       }
+}