Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / html / template / content.go
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.
4
5 package template
6
7 import (
8         "fmt"
9         "reflect"
10 )
11
12 // Strings of content from a trusted source.
13 type (
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
20         CSS string
21
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.
26         HTML string
27
28         // HTMLAttr encapsulates an HTML attribute from a trusted source,
29         // for example, ` dir="ltr"`.
30         HTMLAttr string
31
32         // JS encapsulates a known safe EcmaScript5 Expression, for example,
33         // `(x + y * z())`.
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.
39         JS string
40
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
45         //                    | EscapeSequence
46         // Note that LineContinuations are not allowed.
47         // JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
48         JSStr string
49
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.
55         URL string
56 )
57
58 type contentType uint8
59
60 const (
61         contentTypePlain contentType = iota
62         contentTypeCSS
63         contentTypeHTML
64         contentTypeHTMLAttr
65         contentTypeJS
66         contentTypeJSStr
67         contentTypeURL
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.
71         contentTypeUnsafe
72 )
73
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.
79                 return a
80         }
81         v := reflect.ValueOf(a)
82         for v.Kind() == reflect.Ptr && !v.IsNil() {
83                 v = v.Elem()
84         }
85         return v.Interface()
86 }
87
88 var (
89         errorType       = reflect.TypeOf((*error)(nil)).Elem()
90         fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
91 )
92
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
95 // or error,
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() {
99                 v = v.Elem()
100         }
101         return v.Interface()
102 }
103
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) {
107         if len(args) == 1 {
108                 switch s := indirect(args[0]).(type) {
109                 case string:
110                         return s, contentTypePlain
111                 case CSS:
112                         return string(s), contentTypeCSS
113                 case HTML:
114                         return string(s), contentTypeHTML
115                 case HTMLAttr:
116                         return string(s), contentTypeHTMLAttr
117                 case JS:
118                         return string(s), contentTypeJS
119                 case JSStr:
120                         return string(s), contentTypeJSStr
121                 case URL:
122                         return string(s), contentTypeURL
123                 }
124         }
125         for i, arg := range args {
126                 args[i] = indirectToStringerOrError(arg)
127         }
128         return fmt.Sprint(args...), contentTypePlain
129 }