]> Cypherpunks repositories - gostls13.git/commitdiff
net/textproto: accept bad MIME headers as browsers do
authorBrad Fitzpatrick <bradfitz@golang.org>
Wed, 22 Feb 2012 00:13:59 +0000 (11:13 +1100)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 22 Feb 2012 00:13:59 +0000 (11:13 +1100)
Accept certain non-compliant response headers
(in particular, when spaces preceed the colon).
All major browser and curl seem to support this,
and at least one webserver seems to send these.

*shrug*

R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/5690059

src/pkg/net/textproto/reader.go
src/pkg/net/textproto/reader_test.go

index 862cd536c467e237ec6f56d56195ea5fa255444c..125feb3e885c39a986dda30e6a0450a5e845ba3c 100644 (file)
@@ -454,10 +454,14 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
 
                // Key ends at first colon; must not have spaces.
                i := bytes.IndexByte(kv, ':')
-               if i < 0 || bytes.IndexByte(kv[0:i], ' ') >= 0 {
+               if i < 0 {
                        return m, ProtocolError("malformed MIME header line: " + string(kv))
                }
-               key := CanonicalMIMEHeaderKey(string(kv[0:i]))
+               key := string(kv[0:i])
+               if strings.Index(key, " ") >= 0 {
+                       key = strings.TrimRight(key, " ")
+               }
+               key = CanonicalMIMEHeaderKey(key)
 
                // Skip initial spaces in value.
                i++ // skip colon
@@ -503,6 +507,11 @@ MustRewrite:
        a := []byte(s)
        upper := true
        for i, v := range a {
+               if v == ' ' {
+                       a[i] = '-'
+                       upper = true
+                       continue
+               }
                if upper && 'a' <= v && v <= 'z' {
                        a[i] = v + 'A' - 'a'
                }
index 4d036914801f9b8fb30fe51fa16be01fead1dbaa..7c5d16227ff95559362a91660852c2ae0e3f1d2f 100644 (file)
@@ -164,6 +164,29 @@ func TestLargeReadMIMEHeader(t *testing.T) {
        }
 }
 
+// Test that we read slightly-bogus MIME headers seen in the wild,
+// with spaces before colons, and spaces in keys.
+func TestReadMIMEHeaderNonCompliant(t *testing.T) {
+       // Invalid HTTP response header as sent by an Axis security
+       // camera: (this is handled by IE, Firefox, Chrome, curl, etc.)
+       r := reader("Foo: bar\r\n" +
+               "Content-Language: en\r\n" +
+               "SID : 0\r\n" +
+               "Audio Mode : None\r\n" +
+               "Privilege : 127\r\n\r\n")
+       m, err := r.ReadMIMEHeader()
+       want := MIMEHeader{
+               "Foo":              {"bar"},
+               "Content-Language": {"en"},
+               "Sid":              {"0"},
+               "Audio-Mode":       {"None"},
+               "Privilege":        {"127"},
+       }
+       if !reflect.DeepEqual(m, want) || err != nil {
+               t.Fatalf("ReadMIMEHeader =\n%v, %v; want:\n%v", m, err, want)
+       }
+}
+
 type readResponseTest struct {
        in       string
        inCode   int