mirror of
https://github.com/golang/go
synced 2024-11-21 20:04:44 -07:00
exp/template: add an html escaping function.
R=golang-dev, dsymonds, adg CC=golang-dev https://golang.org/cl/4626092
This commit is contained in:
parent
104f57ad39
commit
cc9fed7c1a
@ -150,6 +150,10 @@ var execTests = []execTest{
|
||||
{"printf field", `{{printf "%s" .U.V}}`, "v", tVal, true},
|
||||
{"printf method", `{{printf "%s" .Method0}}`, "resultOfMethod0", tVal, true},
|
||||
{"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) resultOfMethod0", tVal, true},
|
||||
{"html", `{{html "<script>alert(\"XSS\");</script>"}}`,
|
||||
"<script>alert("XSS");</script>", tVal, true},
|
||||
{"html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`,
|
||||
"<script>alert("XSS");</script>", tVal, true},
|
||||
// With.
|
||||
{"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
|
||||
{"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true},
|
||||
|
@ -5,8 +5,11 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FuncMap is the type of the map defining the mapping from names to functions.
|
||||
@ -16,6 +19,7 @@ type FuncMap map[string]interface{}
|
||||
|
||||
var funcs = map[string]reflect.Value{
|
||||
"printf": reflect.ValueOf(fmt.Sprintf),
|
||||
"html": reflect.ValueOf(HTMLEscaper),
|
||||
}
|
||||
|
||||
// addFuncs adds to values the functions in funcs, converting them to reflect.Values.
|
||||
@ -61,3 +65,64 @@ func findFunction(name string, tmpl *Template, set *Set) (reflect.Value, bool) {
|
||||
}
|
||||
return reflect.Value{}, false
|
||||
}
|
||||
|
||||
// HTML escaping
|
||||
|
||||
var (
|
||||
escQuot = []byte(""") // shorter than """
|
||||
escApos = []byte("'") // shorter than "'"
|
||||
escAmp = []byte("&")
|
||||
escLt = []byte("<")
|
||||
escGt = []byte(">")
|
||||
)
|
||||
|
||||
// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
|
||||
func HTMLEscape(w io.Writer, b []byte) {
|
||||
last := 0
|
||||
for i, c := range b {
|
||||
var esc []byte
|
||||
switch c {
|
||||
case '"':
|
||||
esc = escQuot
|
||||
case '\'':
|
||||
esc = escApos
|
||||
case '&':
|
||||
esc = escAmp
|
||||
case '<':
|
||||
esc = escLt
|
||||
case '>':
|
||||
esc = escGt
|
||||
default:
|
||||
continue
|
||||
}
|
||||
w.Write(b[last:i])
|
||||
w.Write(esc)
|
||||
last = i + 1
|
||||
}
|
||||
w.Write(b[last:])
|
||||
}
|
||||
|
||||
// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
|
||||
func HTMLEscapeString(s string) string {
|
||||
// Avoid allocation if we can.
|
||||
if strings.IndexAny(s, `'"&<>`) < 0 {
|
||||
return s
|
||||
}
|
||||
var b bytes.Buffer
|
||||
HTMLEscape(&b, []byte(s))
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// HTMLEscaper returns the escaped HTML equivalent of the textual
|
||||
// representation of its arguments.
|
||||
func HTMLEscaper(args ...interface{}) string {
|
||||
ok := false
|
||||
var s string
|
||||
if len(args) == 1 {
|
||||
s, ok = args[0].(string)
|
||||
}
|
||||
if !ok {
|
||||
s = fmt.Sprint(args...)
|
||||
}
|
||||
return HTMLEscapeString(s)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user