summaryrefslogtreecommitdiff
path: root/libgo/go/html
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/html')
-rw-r--r--libgo/go/html/template/clone_test.go33
-rw-r--r--libgo/go/html/template/content.go4
-rw-r--r--libgo/go/html/template/doc.go2
-rw-r--r--libgo/go/html/template/escape.go42
-rw-r--r--libgo/go/html/template/escape_test.go9
-rw-r--r--libgo/go/html/template/template.go34
6 files changed, 115 insertions, 9 deletions
diff --git a/libgo/go/html/template/clone_test.go b/libgo/go/html/template/clone_test.go
index c612775d4f0..2663cddc24b 100644
--- a/libgo/go/html/template/clone_test.go
+++ b/libgo/go/html/template/clone_test.go
@@ -113,3 +113,36 @@ func TestClone(t *testing.T) {
t.Errorf("t3: got %q want %q", got, want)
}
}
+
+func TestTemplates(t *testing.T) {
+ names := []string{"t0", "a", "lhs", "rhs"}
+ // Some template definitions borrowed from TestClone.
+ const tmpl = `
+ {{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}
+ {{define "lhs"}} <a href=" {{end}}
+ {{define "rhs"}} "></a> {{end}}`
+ t0 := Must(New("t0").Parse(tmpl))
+ templates := t0.Templates()
+ if len(templates) != len(names) {
+ t.Errorf("expected %d templates; got %d", len(names), len(templates))
+ }
+ for _, name := range names {
+ found := false
+ for _, tmpl := range templates {
+ if name == tmpl.text.Name() {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Error("could not find template", name)
+ }
+ }
+}
+
+// This used to crash; http://golang.org/issue/3281
+func TestCloneCrash(t *testing.T) {
+ t1 := New("all")
+ Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`))
+ t1.Clone()
+}
diff --git a/libgo/go/html/template/content.go b/libgo/go/html/template/content.go
index 539664f9729..c1bd2e4949b 100644
--- a/libgo/go/html/template/content.go
+++ b/libgo/go/html/template/content.go
@@ -26,10 +26,10 @@ type (
HTML string
// HTMLAttr encapsulates an HTML attribute from a trusted source,
- // for example: ` dir="ltr"`.
+ // for example, ` dir="ltr"`.
HTMLAttr string
- // JS encapsulates a known safe EcmaScript5 Expression, or example,
+ // JS encapsulates a known safe EcmaScript5 Expression, for example,
// `(x + y * z())`.
// Template authors are responsible for ensuring that typed expressions
// do not break the intended precedence and that there is no
diff --git a/libgo/go/html/template/doc.go b/libgo/go/html/template/doc.go
index 3699ea1a91c..f470facfd0c 100644
--- a/libgo/go/html/template/doc.go
+++ b/libgo/go/html/template/doc.go
@@ -29,7 +29,7 @@ can be safely embedded in an HTML document. The escaping is contextual, so
actions can appear within JavaScript, CSS, and URI contexts.
The security model used by this package assumes that template authors are
-trusted, while text/template Execute's data parameter is not. More details are
+trusted, while Execute's data parameter is not. More details are
provided below.
Example
diff --git a/libgo/go/html/template/escape.go b/libgo/go/html/template/escape.go
index a058e20d7b3..5f0e28e8c1c 100644
--- a/libgo/go/html/template/escape.go
+++ b/libgo/go/html/template/escape.go
@@ -8,6 +8,7 @@ import (
"bytes"
"fmt"
"html"
+ "io"
"text/template"
"text/template/parse"
)
@@ -751,3 +752,44 @@ func (e *escaper) template(name string) *template.Template {
}
return t
}
+
+// Forwarding functions so that clients need only import this package
+// to reach the general escaping functions of text/template.
+
+// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
+func HTMLEscape(w io.Writer, b []byte) {
+ template.HTMLEscape(w, b)
+}
+
+// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
+func HTMLEscapeString(s string) string {
+ return template.HTMLEscapeString(s)
+}
+
+// HTMLEscaper returns the escaped HTML equivalent of the textual
+// representation of its arguments.
+func HTMLEscaper(args ...interface{}) string {
+ return template.HTMLEscaper(args...)
+}
+
+// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
+func JSEscape(w io.Writer, b []byte) {
+ template.JSEscape(w, b)
+}
+
+// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
+func JSEscapeString(s string) string {
+ return template.JSEscapeString(s)
+}
+
+// JSEscaper returns the escaped JavaScript equivalent of the textual
+// representation of its arguments.
+func JSEscaper(args ...interface{}) string {
+ return template.JSEscaper(args...)
+}
+
+// URLQueryEscaper returns the escaped value of the textual representation of
+// its arguments in a form suitable for embedding in a URL query.
+func URLQueryEscaper(args ...interface{}) string {
+ return template.URLQueryEscaper(args...)
+}
diff --git a/libgo/go/html/template/escape_test.go b/libgo/go/html/template/escape_test.go
index 2bbb1b1bc94..ce12c1795c2 100644
--- a/libgo/go/html/template/escape_test.go
+++ b/libgo/go/html/template/escape_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"encoding/json"
"fmt"
+ "os"
"strings"
"testing"
"text/template"
@@ -1637,6 +1638,14 @@ func TestIndirectPrint(t *testing.T) {
}
}
+// This is a test for issue 3272.
+func TestEmptyTemplate(t *testing.T) {
+ page := Must(New("page").ParseFiles(os.DevNull))
+ if err := page.ExecuteTemplate(os.Stdout, "page", "nothing"); err == nil {
+ t.Fatal("expected error")
+ }
+}
+
func BenchmarkEscapedExecute(b *testing.B) {
tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))
var buf bytes.Buffer
diff --git a/libgo/go/html/template/template.go b/libgo/go/html/template/template.go
index b0bae7a54fb..edac7335cfd 100644
--- a/libgo/go/html/template/template.go
+++ b/libgo/go/html/template/template.go
@@ -31,6 +31,20 @@ type nameSpace struct {
set map[string]*Template
}
+// Templates returns a slice of the templates associated with t, including t
+// itself.
+func (t *Template) Templates() []*Template {
+ ns := t.nameSpace
+ ns.mu.Lock()
+ defer ns.mu.Unlock()
+ // Return a slice so we don't expose the map.
+ m := make([]*Template, 0, len(ns.set))
+ for _, v := range ns.set {
+ m = append(m, v)
+ }
+ return m
+}
+
// Execute applies a parsed template to the specified data object,
// writing the output to wr.
func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
@@ -64,7 +78,13 @@ func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err err
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
tmpl = t.set[name]
- if (tmpl == nil) != (t.text.Lookup(name) == nil) {
+ if tmpl == nil {
+ return nil, fmt.Errorf("html/template: %q is undefined", name)
+ }
+ if tmpl.text.Tree == nil || tmpl.text.Root == nil {
+ return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
+ }
+ if t.text.Lookup(name) == nil {
panic("html/template internal error: template escaping out of sync")
}
if tmpl != nil && !tmpl.escaped {
@@ -160,9 +180,11 @@ func (t *Template) Clone() (*Template, error) {
if src == nil || src.escaped {
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
}
- x.Tree = &parse.Tree{
- Name: x.Tree.Name,
- Root: x.Tree.Root.CopyList(),
+ if x.Tree != nil {
+ x.Tree = &parse.Tree{
+ Name: x.Tree.Name,
+ Root: x.Tree.Root.CopyList(),
+ }
}
ret.set[name] = &Template{
false,
@@ -274,7 +296,7 @@ func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
func parseFiles(t *Template, filenames ...string) (*Template, error) {
if len(filenames) == 0 {
// Not really a problem, but be consistent.
- return nil, fmt.Errorf("template: no files named in call to ParseFiles")
+ return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
}
for _, filename := range filenames {
b, err := ioutil.ReadFile(filename)
@@ -331,7 +353,7 @@ func parseGlob(t *Template, pattern string) (*Template, error) {
return nil, err
}
if len(filenames) == 0 {
- return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
+ return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
}
return parseFiles(t, filenames...)
}