1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 // Strings of content from a trusted source.
14 // CSS encapsulates known safe content that matches any of:
15 // 1. The CSS3 stylesheet production, such as `p { color: purple }`.
16 // 2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
17 // 3. CSS3 declaration productions, such as `color: red; margin: 2px`.
18 // 4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
19 // See http://www.w3.org/TR/css3-syntax/#parsing and
20 // https://web.archive.org/web/20090211114933/http://w3.org/TR/css3-syntax#style
23 // HTML encapsulates a known safe HTML document fragment.
24 // It should not be used for HTML from a third-party, or HTML with
25 // unclosed tags or comments. The outputs of a sound HTML sanitizer
26 // and a template escaped by this package are fine for use with HTML.
29 // HTMLAttr encapsulates an HTML attribute from a trusted source,
30 // for example, ` dir="ltr"`.
33 // JS encapsulates a known safe EcmaScript5 Expression, for example,
35 // Template authors are responsible for ensuring that typed expressions
36 // do not break the intended precedence and that there is no
37 // statement/expression ambiguity as when passing an expression like
38 // "{ foo: bar() }\n['foo']()", which is both a valid Expression and a
39 // valid Program with a very different meaning.
42 // JSStr encapsulates a sequence of characters meant to be embedded
43 // between quotes in a JavaScript expression.
44 // The string must match a series of StringCharacters:
45 // StringCharacter :: SourceCharacter but not `\` or LineTerminator
47 // Note that LineContinuations are not allowed.
48 // JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
51 // URL encapsulates a known safe URL or URL substring (see RFC 3986).
52 // A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
53 // from a trusted source should go in the page, but by default dynamic
54 // `javascript:` URLs are filtered out since they are a frequently
55 // exploited injection vector.
59 type contentType
uint8
62 contentTypePlain contentType
= iota
69 // contentTypeUnsafe is used in attr.go for values that affect how
70 // embedded content and network messages are formed, vetted,
71 // or interpreted; or which credentials network messages carry.
75 // indirect returns the value, after dereferencing as many times
76 // as necessary to reach the base type (or nil).
77 func indirect(a
interface{}) interface{} {
81 if t
:= reflect
.TypeOf(a
); t
.Kind() != reflect
.Ptr
{
82 // Avoid creating a reflect.Value if it's not a pointer.
85 v
:= reflect
.ValueOf(a
)
86 for v
.Kind() == reflect
.Ptr
&& !v
.IsNil() {
93 errorType
= reflect
.TypeOf((*error
)(nil)).Elem()
94 fmtStringerType
= reflect
.TypeOf((*fmt
.Stringer
)(nil)).Elem()
97 // indirectToStringerOrError returns the value, after dereferencing as many times
98 // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
100 func indirectToStringerOrError(a
interface{}) interface{} {
104 v
:= reflect
.ValueOf(a
)
105 for !v
.Type().Implements(fmtStringerType
) && !v
.Type().Implements(errorType
) && v
.Kind() == reflect
.Ptr
&& !v
.IsNil() {
111 // stringify converts its arguments to a string and the type of the content.
112 // All pointers are dereferenced, as in the text/template package.
113 func stringify(args
...interface{}) (string, contentType
) {
115 switch s
:= indirect(args
[0]).(type) {
117 return s
, contentTypePlain
119 return string(s
), contentTypeCSS
121 return string(s
), contentTypeHTML
123 return string(s
), contentTypeHTMLAttr
125 return string(s
), contentTypeJS
127 return string(s
), contentTypeJSStr
129 return string(s
), contentTypeURL
132 for i
, arg
:= range args
{
133 args
[i
] = indirectToStringerOrError(arg
)
135 return fmt
.Sprint(args
...), contentTypePlain