Home | History | Annotate | Download | only in template
      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/webappapis.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/dom.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 }
    176