Html/templates - Replacing Newlines With
Solution 1:
It seems you could run template.HTMLEscape() on your text first to sanitize it, then do the \n to substitution that you trust, then use that as pre-escaped and trusted template data.
Update: Expanding on Kocka's example, this is what I had in mind:
package main
import (
"html/template"
"os"
"strings"
)
const page = `<!DOCTYPE html><html><head></head><body><p>{{.}}</p></body></html>`
const text = `first line
<script>dangerous</script>
last line`
func main() {
t := template.Must(template.New("page").Parse(page))
safe := template.HTMLEscapeString(text)
safe = strings.Replace(safe, "\n", "<br>", -1)
t.Execute(os.Stdout, template.HTML(safe)) // template.HTML encapsulates a known safe HTML document fragment.
}
http://play.golang.org/p/JiH0uD5Zh2
Output is
<!DOCTYPE html><html><head></head><body><p>first line<br><script>dangerous</script><br>last line</p></body></html>
And text rendered in the browser is
first line
<script>dangerous</script>
last line
Solution 2:
Not sure where you're substituting \n
for <br>
but if it's in go, you can cast the string as template.HTML
so it's not escaped.
See: http://golang.org/pkg/html/template/#HTML
If it's in a template, there should be a pipeline available, {{. | html}}
Solution 3:
You can do it like this:
package main
import (
"html/template"
"os"
)
const page = `<!DOCTYPE html><html><head></head><body><p>{{.}}</p></body></html>`
func main() {
t := template.Must(template.New("page").Parse(page))
t.Execute(os.Stdout, template.HTML("<br>"))
}
Solution 4:
The accepted answer can easily be turned into a custom template function:
funcreplaceNewline(s string) template.HTML {
return template.HTML(strings.Replace(template.HTMLEscapeString(s), "\n", "<br>", -1))
}
Add it with func (*Template) Funcs
Example
package main
import (
"html/template""os""strings"
)
const page = `<!DOCTYPE html>
<html>
<body>
<p>{{. | replaceNewline}}</p>
</body>
</html>`const text = `first line
<script>dangerous</script>
last line`funcmain() {
t := template.Must(template.New("page").Funcs(template.FuncMap{
"replaceNewline": func(s string) template.HTML {
return template.HTML(strings.Replace(template.HTMLEscapeString(s), "\n", "<br>", -1))
},
}).Parse(page))
t.Execute(os.Stdout, text)
}
Output
<!DOCTYPE html><html><body><p>first line<br><script>dangerous</script><br>last line</p></body></html>
Solution 5:
It is unnecessary to pass your entire template as an unsafe template (and this is bad practice).
You should pass a map to your template, and only explicitly 'unsafe' the elements you want to use as such, eg.
package main
import"bytes"import"fmt"import"html/template"import"strings"var input = `
{{ define "LAYOUT" }}
<html>
<body>
{{ template "CONTENT" . }}
</body>
</html>
{{ end }}
{{ define "CONTENT" }}
Unsafe content: {{ .Unsafe }}
Newlines converted to <br/> follow:
{{ .Normal }}
{{ end }}
{{ template "LAYOUT" . }}
`var other = `
Hello
World
Again
`var other2 = `
<script>alert("Owned!");</script>
`funcmain() {
var t, err = template.New("sample").Parse(input)
if err != nil {
panic(err)
}
var fixed = strings.Replace(other, "\n", "\n<br/>", -1)
var model = map[string]interface{}{
"Normal": template.HTML(fixed),
"Unsafe": other2,
}
var out bytes.Buffer
t.Execute(&out, model) # <--- !! Notice the model is NOT an HTML type.
var raw = out.String()
fmt.Printf("%s", raw)
}
Yields:
Unsafe content: <script>alert("Owned!");</script>
Newlines converted to <br/> follow:
<br/> Hello
<br/> World
<br/> Again
<br/></body></html>
Post a Comment for "Html/templates - Replacing Newlines With
"