escape Text input, rename Raw to UnsafeRaw
This commit is contained in:
parent
4d95e21316
commit
2d333a6e0a
5 changed files with 23 additions and 13 deletions
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
"github.com/maddalax/htmgo/framework/hx"
|
"github.com/maddalax/htmgo/framework/hx"
|
||||||
"github.com/microcosm-cc/bluemonday"
|
|
||||||
"todolist/ent"
|
"todolist/ent"
|
||||||
"todolist/internal/tasks"
|
"todolist/internal/tasks"
|
||||||
)
|
)
|
||||||
|
|
@ -18,8 +17,6 @@ const (
|
||||||
TabComplete Tab = "Complete"
|
TabComplete Tab = "Complete"
|
||||||
)
|
)
|
||||||
|
|
||||||
var policy = bluemonday.UGCPolicy()
|
|
||||||
|
|
||||||
func getActiveTab(ctx *h.RequestContext) Tab {
|
func getActiveTab(ctx *h.RequestContext) Tab {
|
||||||
if tab := h.GetQueryParam(ctx, "tab"); tab != "" {
|
if tab := h.GetQueryParam(ctx, "tab"); tab != "" {
|
||||||
return tab
|
return tab
|
||||||
|
|
@ -185,7 +182,7 @@ func CompleteIcon(task *ent.Task) *h.Element {
|
||||||
"border-green-500": task.CompletedAt != nil,
|
"border-green-500": task.CompletedAt != nil,
|
||||||
"border-slate-400": task.CompletedAt == nil,
|
"border-slate-400": task.CompletedAt == nil,
|
||||||
}),
|
}),
|
||||||
h.If(task.CompletedAt != nil, h.Raw(`
|
h.If(task.CompletedAt != nil, h.UnsafeRaw(`
|
||||||
<svg class="w-6 h-6 text-green-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-6 h-6 text-green-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
@ -290,7 +287,6 @@ func ClearCompleted(ctx *h.RequestContext) *h.Partial {
|
||||||
|
|
||||||
func Create(ctx *h.RequestContext) *h.Partial {
|
func Create(ctx *h.RequestContext) *h.Partial {
|
||||||
name := ctx.FormValue("name")
|
name := ctx.FormValue("name")
|
||||||
name = policy.Sanitize(name)
|
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return h.NewPartial(h.Div(h.Text("name is required")))
|
return h.NewPartial(h.Div(h.Text("name is required")))
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ func TestRender(t *testing.T) {
|
||||||
func TestRawContent(t *testing.T) {
|
func TestRawContent(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
str := "<div>hello, world</div>"
|
str := "<div>hello, world</div>"
|
||||||
raw := Raw(str)
|
raw := UnsafeRaw(str)
|
||||||
assert.Equal(t, str, Render(raw))
|
assert.Equal(t, str, Render(raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,6 +526,13 @@ func TestBackgroundCleaner(t *testing.T) {
|
||||||
assert.Equal(t, 0, len(node.byKeyCache))
|
assert.Equal(t, 0, len(node.byKeyCache))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEscapeHtml(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert.Equal(t, "<script>alert(1)</script>", Render(Text("<script>alert(1)</script>")))
|
||||||
|
assert.Equal(t, "<p ><script>alert(1)</script></p>", Render(Pf("<script>alert(1)</script>")))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkCacheByKey(b *testing.B) {
|
func BenchmarkCacheByKey(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
page := CachedPerKeyT(time.Second*3, func(userId string) (any, GetElementFunc) {
|
page := CachedPerKeyT(time.Second*3, func(userId string) (any, GetElementFunc) {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/maddalax/htmgo/framework/hx"
|
"github.com/maddalax/htmgo/framework/hx"
|
||||||
"golang.org/x/net/html"
|
"golang.org/x/net/html"
|
||||||
|
"html/template"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -167,7 +168,7 @@ func (a *AttributeR) Render(context *RenderContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TextContent) Render(context *RenderContext) {
|
func (t *TextContent) Render(context *RenderContext) {
|
||||||
context.builder.WriteString(t.Content)
|
context.builder.WriteString(template.HTMLEscapeString(t.Content))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RawContent) Render(context *RenderContext) {
|
func (r *RawContent) Render(context *RenderContext) {
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,9 @@ func Script(url string) *Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Raw(text string) *RawContent {
|
// UnsafeRaw is a helper function to create a raw content with the given text
|
||||||
|
// The text is not escaped, do not use this function with user input
|
||||||
|
func UnsafeRaw(text string) *RawContent {
|
||||||
return NewRawContent(text)
|
return NewRawContent(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,12 +137,16 @@ func MultiLineQuotes(text string) string {
|
||||||
return "`" + text + "`"
|
return "`" + text + "`"
|
||||||
}
|
}
|
||||||
|
|
||||||
func RawF(text string, args any) *RawContent {
|
// UnsafeRawF is a helper function to create a raw content with the given text
|
||||||
return Raw(fmt.Sprintf(text, args))
|
// The text is not escaped, do not use this function with user input
|
||||||
|
func UnsafeRawF(text string, args any) *RawContent {
|
||||||
|
return UnsafeRaw(fmt.Sprintf(text, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
func RawScript(text string) *RawContent {
|
// UnsafeRawScript is a helper function to create a script tag with the given text
|
||||||
return Raw("<script>" + text + "</script>")
|
// The text is not escaped, do not use this function with user input
|
||||||
|
func UnsafeRawScript(text string) *RawContent {
|
||||||
|
return UnsafeRaw("<script>" + text + "</script>")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pre(children ...Ren) *Element {
|
func Pre(children ...Ren) *Element {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ func MarkdownContent(ctx *h.RequestContext, path string, id string) *h.Element {
|
||||||
h.If(id != "", h.Id(id)),
|
h.If(id != "", h.Id(id)),
|
||||||
h.Div(
|
h.Div(
|
||||||
h.Class("w-full flex flex-col prose max-w-[95vw] md:max-w-3xl prose-code:text-black prose-p:my-1 prose:p-0 prose-li:m-0 prose-ul:m-0 prose-ol:m-0"),
|
h.Class("w-full flex flex-col prose max-w-[95vw] md:max-w-3xl prose-code:text-black prose-p:my-1 prose:p-0 prose-li:m-0 prose-ul:m-0 prose-ol:m-0"),
|
||||||
h.Raw(renderer.RenderFile(path, embeddedMd)),
|
h.UnsafeRaw(renderer.RenderFile(path, embeddedMd)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue