mirror of
https://github.com/golang/go
synced 2024-11-21 20:54:45 -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 field", `{{printf "%s" .U.V}}`, "v", tVal, true},
|
||||||
{"printf method", `{{printf "%s" .Method0}}`, "resultOfMethod0", 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},
|
{"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.
|
||||||
{"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
|
{"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
|
||||||
{"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true},
|
{"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true},
|
||||||
|
@ -5,8 +5,11 @@
|
|||||||
package template
|
package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FuncMap is the type of the map defining the mapping from names to functions.
|
// 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{
|
var funcs = map[string]reflect.Value{
|
||||||
"printf": reflect.ValueOf(fmt.Sprintf),
|
"printf": reflect.ValueOf(fmt.Sprintf),
|
||||||
|
"html": reflect.ValueOf(HTMLEscaper),
|
||||||
}
|
}
|
||||||
|
|
||||||
// addFuncs adds to values the functions in funcs, converting them to reflect.Values.
|
// 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
|
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