From fbdbb595b6e7e30e31f83777c63c69336b6dd2d6 Mon Sep 17 00:00:00 2001 From: "Pascal S. de Kloe" Date: Fri, 26 Aug 2011 16:55:18 -0400 Subject: [PATCH] mime: media type formatter R=bradfitz, rsc CC=golang-dev https://golang.org/cl/4654069 --- src/pkg/mime/grammar.go | 9 ++++++++ src/pkg/mime/mediatype.go | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/pkg/mime/grammar.go b/src/pkg/mime/grammar.go index 6e319ff8be..70a94cd807 100644 --- a/src/pkg/mime/grammar.go +++ b/src/pkg/mime/grammar.go @@ -22,6 +22,15 @@ func IsTokenChar(rune int) bool { return rune > 0x20 && rune < 0x7f && !isTSpecial(rune) } +// IsToken returns true if s is a 'token' as as defined by RFC 1521 +// and RFC 2045. +func IsToken(s string) bool { + if s == "" { + return false + } + return strings.IndexFunc(s, isNotTokenChar) < 0 +} + // IsQText returns true if rune is in 'qtext' as defined by RFC 822. func IsQText(rune int) bool { // CHAR = ; ( 0-177, 0.-127.) diff --git a/src/pkg/mime/mediatype.go b/src/pkg/mime/mediatype.go index 9c25b9eff4..35cac13458 100644 --- a/src/pkg/mime/mediatype.go +++ b/src/pkg/mime/mediatype.go @@ -12,6 +12,50 @@ import ( "unicode" ) +// FormatMediaType serializes type t, subtype sub and the paramaters +// param as a media type conform RFC 2045 and RFC 2616. +// The type, subtype, and parameter names are written in lower-case. +// When any of the arguments result in a standard violation then +// FormatMediaType returns the empty string. +func FormatMediaType(t, sub string, param map[string]string) string { + if !(IsToken(t) && IsToken(sub)) { + return "" + } + var buffer bytes.Buffer + buffer.WriteString(strings.ToLower(t)) + buffer.WriteByte('/') + buffer.WriteString(strings.ToLower(sub)) + + for attribute, value := range param { + buffer.WriteByte(';') + if !IsToken(attribute) { + return "" + } + buffer.WriteString(strings.ToLower(attribute)) + buffer.WriteByte('=') + if IsToken(value) { + buffer.WriteString(value) + continue + } + + buffer.WriteByte('"') + offset := 0 + for index, character := range value { + if character == '"' || character == '\r' { + buffer.WriteString(value[offset:index]) + offset = index + buffer.WriteByte('\\') + } + if character&0x80 != 0 { + return "" + } + } + buffer.WriteString(value[offset:]) + buffer.WriteByte('"') + } + return buffer.String() +} + func checkMediaTypeDisposition(s string) os.Error { typ, rest := consumeToken(s) if typ == "" { -- 2.50.0