mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-01 05:36:19 +01:00
27757714d0
* Move to goldmark Markdown rendering moved from blackfriday to the goldmark. Multiple subtle changes required to the goldmark extensions to keep current rendering and defaults. Can go further with goldmark linkify and have this work within markdown rendering making the link processor unnecessary. Need to think about how to go about allowing extensions - at present it seems that these would be hard to do without recompilation. * linter fixes Co-authored-by: Lauris BH <lauris@nix.lv>
86 lines
2.6 KiB
Go
86 lines
2.6 KiB
Go
// Copyright 2017 The Gitea Authors. All rights reserved.
|
|
// Copyright 2017 The Gogs Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package markup
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"regexp"
|
|
"sync"
|
|
|
|
"code.gitea.io/gitea/modules/setting"
|
|
|
|
"github.com/microcosm-cc/bluemonday"
|
|
)
|
|
|
|
// Sanitizer is a protection wrapper of *bluemonday.Policy which does not allow
|
|
// any modification to the underlying policies once it's been created.
|
|
type Sanitizer struct {
|
|
policy *bluemonday.Policy
|
|
init sync.Once
|
|
}
|
|
|
|
var sanitizer = &Sanitizer{}
|
|
|
|
// NewSanitizer initializes sanitizer with allowed attributes based on settings.
|
|
// Multiple calls to this function will only create one instance of Sanitizer during
|
|
// entire application lifecycle.
|
|
func NewSanitizer() {
|
|
sanitizer.init.Do(func() {
|
|
ReplaceSanitizer()
|
|
})
|
|
}
|
|
|
|
// ReplaceSanitizer replaces the current sanitizer to account for changes in settings
|
|
func ReplaceSanitizer() {
|
|
sanitizer.policy = bluemonday.UGCPolicy()
|
|
// We only want to allow HighlightJS specific classes for code blocks
|
|
sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^language-\w+$`)).OnElements("code")
|
|
|
|
// Checkboxes
|
|
sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
|
|
sanitizer.policy.AllowAttrs("checked", "disabled").OnElements("input")
|
|
|
|
// Custom URL-Schemes
|
|
sanitizer.policy.AllowURLSchemes(setting.Markdown.CustomURLSchemes...)
|
|
|
|
// Allow keyword markup
|
|
sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^` + keywordClass + `$`)).OnElements("span")
|
|
|
|
// Allow <kbd> tags for keyboard shortcut styling
|
|
sanitizer.policy.AllowElements("kbd")
|
|
|
|
// Custom keyword markup
|
|
for _, rule := range setting.ExternalSanitizerRules {
|
|
if rule.Regexp != nil {
|
|
sanitizer.policy.AllowAttrs(rule.AllowAttr).Matching(rule.Regexp).OnElements(rule.Element)
|
|
} else {
|
|
sanitizer.policy.AllowAttrs(rule.AllowAttr).OnElements(rule.Element)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sanitize takes a string that contains a HTML fragment or document and applies policy whitelist.
|
|
func Sanitize(s string) string {
|
|
NewSanitizer()
|
|
return sanitizer.policy.Sanitize(s)
|
|
}
|
|
|
|
// SanitizeReader sanitizes a Reader
|
|
func SanitizeReader(r io.Reader) *bytes.Buffer {
|
|
NewSanitizer()
|
|
return sanitizer.policy.SanitizeReader(r)
|
|
}
|
|
|
|
// SanitizeBytes takes a []byte slice that contains a HTML fragment or document and applies policy whitelist.
|
|
func SanitizeBytes(b []byte) []byte {
|
|
if len(b) == 0 {
|
|
// nothing to sanitize
|
|
return b
|
|
}
|
|
NewSanitizer()
|
|
return sanitizer.policy.SanitizeBytes(b)
|
|
}
|