}
// parse a quoted-string
- rest = v[1:] // consume the leading quote
buffer := new(bytes.Buffer)
- var nextIsLiteral bool
- for idx, r := range rest {
- switch {
- case nextIsLiteral:
- buffer.WriteRune(r)
- nextIsLiteral = false
- case r == '"':
- return buffer.String(), rest[idx+1:]
- case r == '\\':
- nextIsLiteral = true
- case r != '\r' && r != '\n':
- buffer.WriteRune(r)
- default:
+ for i := 1; i < len(v); i++ {
+ r := v[i]
+ if r == '"' {
+ return buffer.String(), v[i+1:]
+ }
+ // When MSIE sends a full file path (in "intranet mode"), it does not
+ // escape backslashes: "C:\dev\go\foo.txt", not "C:\\dev\\go\\foo.txt".
+ //
+ // No known MIME generators emit unnecessary backslash escapes
+ // for simple token characters like numbers and letters.
+ //
+ // If we see an unnecessary backslash escape, assume it is from MSIE
+ // and intended as a literal backslash. This makes Go servers deal better
+ // with MSIE without affecting the way they handle conforming MIME
+ // generators.
+ if r == '\\' && i+1 < len(v) && !isTokenChar(rune(v[i+1])) {
+ buffer.WriteByte(v[i+1])
+ i++
+ continue
+ }
+ if r == '\r' || r == '\n' {
return "", v
}
+ buffer.WriteByte(v[i])
}
+ // Did not find end quote.
return "", v
}
m("title", "This is even more ***fun*** isn't it!")},
// Tests from http://greenbytes.de/tech/tc2231/
+ // Note: Backslash escape handling is a bit loose, like MSIE.
// TODO(bradfitz): add the rest of the tests from that site.
{`attachment; filename="f\oo.html"`,
"attachment",
- m("filename", "foo.html")},
+ m("filename", "f\\oo.html")},
{`attachment; filename="\"quoting\" tested.html"`,
"attachment",
m("filename", `"quoting" tested.html`)},
m("filename", "foo-%41.html")},
{`attachment; filename="foo-%\41.html"`,
"attachment",
- m("filename", "foo-%41.html")},
+ m("filename", "foo-%\\41.html")},
{`filename=foo.html`,
"", m()},
{`x=y; filename=foo.html`,
// Empty string used to be mishandled.
{`foo; bar=""`, "foo", m("bar", "")},
+
+ // Microsoft browers in intranet mode do not think they need to escape \ in file name.
+ {`form-data; name="file"; filename="C:\dev\go\robots.txt"`, "form-data", m("name", "file", "filename", `C:\dev\go\robots.txt`)},
}
for _, test := range tests {
mt, params, err := ParseMediaType(test.in)
if err != nil {
if test.t != "" {
- t.Errorf("for input %q, unexpected error: %v", test.in, err)
+ t.Errorf("for input %#q, unexpected error: %v", test.in, err)
continue
}
continue
}
if g, e := mt, test.t; g != e {
- t.Errorf("for input %q, expected type %q, got %q",
+ t.Errorf("for input %#q, expected type %q, got %q",
test.in, e, g)
continue
}
continue
}
if !reflect.DeepEqual(params, test.p) {
- t.Errorf("for input %q, wrong params.\n"+
+ t.Errorf("for input %#q, wrong params.\n"+
"expected: %#v\n"+
" got: %#v",
test.in, test.p, params)