mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Refactor markup render system (#32533)
Remove unmaintainable sanitizer rules. No need to add special "class" regexp rules anymore, use RenderInternal.SafeAttr instead, more details (and examples) are in the tests
This commit is contained in:
@@ -10,12 +10,12 @@ import (
|
||||
"html/template"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/htmlutil"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/svg"
|
||||
@@ -39,7 +39,7 @@ func NewFuncMap() template.FuncMap {
|
||||
"Iif": iif,
|
||||
"Eval": evalTokens,
|
||||
"SafeHTML": safeHTML,
|
||||
"HTMLFormat": HTMLFormat,
|
||||
"HTMLFormat": htmlutil.HTMLFormat,
|
||||
"HTMLEscape": htmlEscape,
|
||||
"QueryEscape": queryEscape,
|
||||
"JSEscape": jsEscapeSafe,
|
||||
@@ -184,23 +184,6 @@ func NewFuncMap() template.FuncMap {
|
||||
}
|
||||
}
|
||||
|
||||
func HTMLFormat(s string, rawArgs ...any) template.HTML {
|
||||
args := slices.Clone(rawArgs)
|
||||
for i, v := range args {
|
||||
switch v := v.(type) {
|
||||
case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, template.HTML:
|
||||
// for most basic types (including template.HTML which is safe), just do nothing and use it
|
||||
case string:
|
||||
args[i] = template.HTMLEscapeString(v)
|
||||
case fmt.Stringer:
|
||||
args[i] = template.HTMLEscapeString(v.String())
|
||||
default:
|
||||
args[i] = template.HTMLEscapeString(fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
return template.HTML(fmt.Sprintf(s, args...))
|
||||
}
|
||||
|
||||
// safeHTML render raw as HTML
|
||||
func safeHTML(s any) template.HTML {
|
||||
switch v := s.(type) {
|
||||
|
@@ -61,10 +61,6 @@ func TestJSEscapeSafe(t *testing.T) {
|
||||
assert.EqualValues(t, `\u0026\u003C\u003E\'\"`, jsEscapeSafe(`&<>'"`))
|
||||
}
|
||||
|
||||
func TestHTMLFormat(t *testing.T) {
|
||||
assert.Equal(t, template.HTML("<a>< < 1</a>"), HTMLFormat("<a>%s %s %d</a>", "<", template.HTML("<"), 1))
|
||||
}
|
||||
|
||||
func TestSanitizeHTML(t *testing.T) {
|
||||
assert.Equal(t, template.HTML(`<a href="/" rel="nofollow">link</a> xss <div>inline</div>`), SanitizeHTML(`<a href="/">link</a> <a href="javascript:">xss</a> <div style="dangerous">inline</div>`))
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@ import (
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
gitea_html "code.gitea.io/gitea/modules/html"
|
||||
gitea_html "code.gitea.io/gitea/modules/htmlutil"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
|
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/modules/emoji"
|
||||
"code.gitea.io/gitea/modules/htmlutil"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/markdown"
|
||||
@@ -140,7 +141,7 @@ func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML {
|
||||
|
||||
if labelScope == "" {
|
||||
// Regular label
|
||||
return HTMLFormat(`<div class="ui label %s" style="color: %s !important; background-color: %s !important;" data-tooltip-content title="%s">%s</div>`,
|
||||
return htmlutil.HTMLFormat(`<div class="ui label %s" style="color: %s !important; background-color: %s !important;" data-tooltip-content title="%s">%s</div>`,
|
||||
extraCSSClasses, textColor, label.Color, descriptionText, ut.RenderEmoji(label.Name))
|
||||
}
|
||||
|
||||
@@ -174,7 +175,7 @@ func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML {
|
||||
itemColor := "#" + hex.EncodeToString(itemBytes)
|
||||
scopeColor := "#" + hex.EncodeToString(scopeBytes)
|
||||
|
||||
return HTMLFormat(`<span class="ui label %s scope-parent" data-tooltip-content title="%s">`+
|
||||
return htmlutil.HTMLFormat(`<span class="ui label %s scope-parent" data-tooltip-content title="%s">`+
|
||||
`<div class="ui label scope-left" style="color: %s !important; background-color: %s !important">%s</div>`+
|
||||
`<div class="ui label scope-right" style="color: %s !important; background-color: %s !important">%s</div>`+
|
||||
`</span>`,
|
||||
|
@@ -113,34 +113,34 @@ func TestRenderCommitBody(t *testing.T) {
|
||||
}
|
||||
|
||||
expected := `/just/a/path.bin
|
||||
<a href="https://example.com/file.bin" class="link">https://example.com/file.bin</a>
|
||||
<a href="https://example.com/file.bin">https://example.com/file.bin</a>
|
||||
[local link](file.bin)
|
||||
[remote link](<a href="https://example.com" class="link">https://example.com</a>)
|
||||
[remote link](<a href="https://example.com">https://example.com</a>)
|
||||
[[local link|file.bin]]
|
||||
[[remote link|<a href="https://example.com" class="link">https://example.com</a>]]
|
||||
[[remote link|<a href="https://example.com">https://example.com</a>]]
|
||||

|
||||

|
||||

|
||||
[[local image|image.jpg]]
|
||||
[[remote link|<a href="https://example.com/image.jpg" class="link">https://example.com/image.jpg</a>]]
|
||||
[[remote link|<a href="https://example.com/image.jpg">https://example.com/image.jpg</a>]]
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" class="compare"><code class="nohighlight">88fc37a3c0...12fc37a3c0 (hash)</code></a>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" class="commit"><code class="nohighlight">88fc37a3c0</code></a>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
|
||||
<span class="emoji" aria-label="thumbs up">👍</span>
|
||||
<a href="mailto:mail@domain.com" class="mailto">mail@domain.com</a>
|
||||
<a href="/mention-user" class="mention">@mention-user</a> test
|
||||
<a href="mailto:mail@domain.com">mail@domain.com</a>
|
||||
<a href="/mention-user">@mention-user</a> test
|
||||
<a href="/user13/repo11/issues/123" class="ref-issue">#123</a>
|
||||
space`
|
||||
assert.EqualValues(t, expected, string(newTestRenderUtils().RenderCommitBody(testInput(), testMetas)))
|
||||
}
|
||||
|
||||
func TestRenderCommitMessage(t *testing.T) {
|
||||
expected := `space <a href="/mention-user" data-markdown-generated-content="" class="mention">@mention-user</a> `
|
||||
expected := `space <a href="/mention-user" data-markdown-generated-content="">@mention-user</a> `
|
||||
assert.EqualValues(t, expected, newTestRenderUtils().RenderCommitMessage(testInput(), testMetas))
|
||||
}
|
||||
|
||||
func TestRenderCommitMessageLinkSubject(t *testing.T) {
|
||||
expected := `<a href="https://example.com/link" class="muted">space </a><a href="/mention-user" data-markdown-generated-content="" class="mention">@mention-user</a>`
|
||||
expected := `<a href="https://example.com/link" class="muted">space </a><a href="/mention-user" data-markdown-generated-content="">@mention-user</a>`
|
||||
assert.EqualValues(t, expected, newTestRenderUtils().RenderCommitMessageLinkSubject(testInput(), "https://example.com/link", testMetas))
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user