Source file src/pkg/html/template/attr.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 "strings"
9 )
10
11 // attrTypeMap[n] describes the value of the given attribute.
12 // If an attribute affects (or can mask) the encoding or interpretation of
13 // other content, or affects the contents, idempotency, or credentials of a
14 // network message, then the value in this map is contentTypeUnsafe.
15 // This map is derived from HTML5, specifically
16 // http://www.w3.org/TR/html5/Overview.html#attributes-1
17 // as well as "%URI"-typed attributes from
18 // http://www.w3.org/TR/html4/index/attributes.html
19 var attrTypeMap = map[string]contentType{
20 "accept": contentTypePlain,
21 "accept-charset": contentTypeUnsafe,
22 "action": contentTypeURL,
23 "alt": contentTypePlain,
24 "archive": contentTypeURL,
25 "async": contentTypeUnsafe,
26 "autocomplete": contentTypePlain,
27 "autofocus": contentTypePlain,
28 "autoplay": contentTypePlain,
29 "background": contentTypeURL,
30 "border": contentTypePlain,
31 "checked": contentTypePlain,
32 "cite": contentTypeURL,
33 "challenge": contentTypeUnsafe,
34 "charset": contentTypeUnsafe,
35 "class": contentTypePlain,
36 "classid": contentTypeURL,
37 "codebase": contentTypeURL,
38 "cols": contentTypePlain,
39 "colspan": contentTypePlain,
40 "content": contentTypeUnsafe,
41 "contenteditable": contentTypePlain,
42 "contextmenu": contentTypePlain,
43 "controls": contentTypePlain,
44 "coords": contentTypePlain,
45 "crossorigin": contentTypeUnsafe,
46 "data": contentTypeURL,
47 "datetime": contentTypePlain,
48 "default": contentTypePlain,
49 "defer": contentTypeUnsafe,
50 "dir": contentTypePlain,
51 "dirname": contentTypePlain,
52 "disabled": contentTypePlain,
53 "draggable": contentTypePlain,
54 "dropzone": contentTypePlain,
55 "enctype": contentTypeUnsafe,
56 "for": contentTypePlain,
57 "form": contentTypeUnsafe,
58 "formaction": contentTypeURL,
59 "formenctype": contentTypeUnsafe,
60 "formmethod": contentTypeUnsafe,
61 "formnovalidate": contentTypeUnsafe,
62 "formtarget": contentTypePlain,
63 "headers": contentTypePlain,
64 "height": contentTypePlain,
65 "hidden": contentTypePlain,
66 "high": contentTypePlain,
67 "href": contentTypeURL,
68 "hreflang": contentTypePlain,
69 "http-equiv": contentTypeUnsafe,
70 "icon": contentTypeURL,
71 "id": contentTypePlain,
72 "ismap": contentTypePlain,
73 "keytype": contentTypeUnsafe,
74 "kind": contentTypePlain,
75 "label": contentTypePlain,
76 "lang": contentTypePlain,
77 "language": contentTypeUnsafe,
78 "list": contentTypePlain,
79 "longdesc": contentTypeURL,
80 "loop": contentTypePlain,
81 "low": contentTypePlain,
82 "manifest": contentTypeURL,
83 "max": contentTypePlain,
84 "maxlength": contentTypePlain,
85 "media": contentTypePlain,
86 "mediagroup": contentTypePlain,
87 "method": contentTypeUnsafe,
88 "min": contentTypePlain,
89 "multiple": contentTypePlain,
90 "name": contentTypePlain,
91 "novalidate": contentTypeUnsafe,
92 // Skip handler names from
93 // http://www.w3.org/TR/html5/Overview.html#event-handlers-on-elements-document-objects-and-window-objects
94 // since we have special handling in attrType.
95 "open": contentTypePlain,
96 "optimum": contentTypePlain,
97 "pattern": contentTypeUnsafe,
98 "placeholder": contentTypePlain,
99 "poster": contentTypeURL,
100 "profile": contentTypeURL,
101 "preload": contentTypePlain,
102 "pubdate": contentTypePlain,
103 "radiogroup": contentTypePlain,
104 "readonly": contentTypePlain,
105 "rel": contentTypeUnsafe,
106 "required": contentTypePlain,
107 "reversed": contentTypePlain,
108 "rows": contentTypePlain,
109 "rowspan": contentTypePlain,
110 "sandbox": contentTypeUnsafe,
111 "spellcheck": contentTypePlain,
112 "scope": contentTypePlain,
113 "scoped": contentTypePlain,
114 "seamless": contentTypePlain,
115 "selected": contentTypePlain,
116 "shape": contentTypePlain,
117 "size": contentTypePlain,
118 "sizes": contentTypePlain,
119 "span": contentTypePlain,
120 "src": contentTypeURL,
121 "srcdoc": contentTypeHTML,
122 "srclang": contentTypePlain,
123 "start": contentTypePlain,
124 "step": contentTypePlain,
125 "style": contentTypeCSS,
126 "tabindex": contentTypePlain,
127 "target": contentTypePlain,
128 "title": contentTypePlain,
129 "type": contentTypeUnsafe,
130 "usemap": contentTypeURL,
131 "value": contentTypeUnsafe,
132 "width": contentTypePlain,
133 "wrap": contentTypePlain,
134 "xmlns": contentTypeURL,
135 }
136
137 // attrType returns a conservative (upper-bound on authority) guess at the
138 // type of the named attribute.
139 func attrType(name string) contentType {
140 name = strings.ToLower(name)
141 if strings.HasPrefix(name, "data-") {
142 // Strip data- so that custom attribute heuristics below are
143 // widely applied.
144 // Treat data-action as URL below.
145 name = name[5:]
146 } else if colon := strings.IndexRune(name, ':'); colon != -1 {
147 if name[:colon] == "xmlns" {
148 return contentTypeURL
149 }
150 // Treat svg:href and xlink:href as href below.
151 name = name[colon+1:]
152 }
153 if t, ok := attrTypeMap[name]; ok {
154 return t
155 }
156 // Treat partial event handler names as script.
157 if strings.HasPrefix(name, "on") {
158 return contentTypeJS
159 }
160
161 // Heuristics to prevent "javascript:..." injection in custom
162 // data attributes and custom attributes like g:tweetUrl.
163 // http://www.w3.org/TR/html5/elements.html#embedding-custom-non-visible-data-with-the-data-attributes:
164 // "Custom data attributes are intended to store custom data
165 // private to the page or application, for which there are no
166 // more appropriate attributes or elements."
167 // Developers seem to store URL content in data URLs that start
168 // or end with "URI" or "URL".
169 if strings.Contains(name, "src") ||
170 strings.Contains(name, "uri") ||
171 strings.Contains(name, "url") {
172 return contentTypeURL
173 }
174 return contentTypePlain
175 }