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/#style
22 // HTML encapsulates a known safe HTML document fragment.
23 // It should not be used for HTML from a third-party, or HTML with
24 // unclosed tags or comments. The outputs of a sound HTML sanitizer
25 // and a template escaped by this package are fine for use with HTML.
28 // HTMLAttr encapsulates an HTML attribute from a trusted source,
29 // for example, ` dir="ltr"`.
32 // JS encapsulates a known safe EcmaScript5 Expression, for example,
34 // Template authors are responsible for ensuring that typed expressions
35 // do not break the intended precedence and that there is no
36 // statement/expression ambiguity as when passing an expression like
37 // "{ foo: bar() }\n['foo']()", which is both a valid Expression and a
38 // valid Program with a very different meaning.
41 // JSStr encapsulates a sequence of characters meant to be embedded
42 // between quotes in a JavaScript expression.
43 // The string must match a series of StringCharacters:
44 // StringCharacter :: SourceCharacter but not `\` or LineTerminator
46 // Note that LineContinuations are not allowed.
47 // JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
50 // URL encapsulates a known safe URL or URL substring (see RFC 3986).
51 // A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
52 // from a trusted source should go in the page, but by default dynamic
53 // `javascript:` URLs are filtered out since they are a frequently
54 // exploited injection vector.
58 type contentType uint8
61 contentTypePlain contentType = iota
68 // contentTypeUnsafe is used in attr.go for values that affect how
69 // embedded content and network messages are formed, vetted,
70 // or interpreted; or which credentials network messages carry.
74 // indirect returns the value, after dereferencing as many times
75 // as necessary to reach the base type (or nil).
76 func indirect(a interface{}) interface{} {
77 if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
78 // Avoid creating a reflect.Value if it's not a pointer.
81 v := reflect.ValueOf(a)
82 for v.Kind() == reflect.Ptr && !v.IsNil() {
89 errorType = reflect.TypeOf((*error)(nil)).Elem()
90 fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
93 // indirectToStringerOrError returns the value, after dereferencing as many times
94 // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
96 func indirectToStringerOrError(a interface{}) interface{} {
97 v := reflect.ValueOf(a)
98 for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
104 // stringify converts its arguments to a string and the type of the content.
105 // All pointers are dereferenced, as in the text/template package.
106 func stringify(args ...interface{}) (string, contentType) {
108 switch s := indirect(args[0]).(type) {
110 return s, contentTypePlain
112 return string(s), contentTypeCSS
114 return string(s), contentTypeHTML
116 return string(s), contentTypeHTMLAttr
118 return string(s), contentTypeJS
120 return string(s), contentTypeJSStr
122 return string(s), contentTypeURL
125 for i, arg := range args {
126 args[i] = indirectToStringerOrError(arg)
128 return fmt.Sprint(args...), contentTypePlain