Support inline rendering of CUSTOM_URL_SCHEMES (#8496)
* Support inline rendering of CUSTOM_URL_SCHEMES * Fix lint * Add tests * Fix lint
This commit is contained in:
		
							parent
							
								
									8ad2697611
								
							
						
					
					
						commit
						cea8ea5ae6
					
				| @ -92,6 +92,32 @@ func getIssueFullPattern() *regexp.Regexp { | ||||
| 	return issueFullPattern | ||||
| } | ||||
| 
 | ||||
| // CustomLinkURLSchemes allows for additional schemes to be detected when parsing links within text
 | ||||
| func CustomLinkURLSchemes(schemes []string) { | ||||
| 	schemes = append(schemes, "http", "https") | ||||
| 	withAuth := make([]string, 0, len(schemes)) | ||||
| 	validScheme := regexp.MustCompile(`^[a-z]+$`) | ||||
| 	for _, s := range schemes { | ||||
| 		if !validScheme.MatchString(s) { | ||||
| 			continue | ||||
| 		} | ||||
| 		without := false | ||||
| 		for _, sna := range xurls.SchemesNoAuthority { | ||||
| 			if s == sna { | ||||
| 				without = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		if without { | ||||
| 			s += ":" | ||||
| 		} else { | ||||
| 			s += "://" | ||||
| 		} | ||||
| 		withAuth = append(withAuth, s) | ||||
| 	} | ||||
| 	linkRegex, _ = xurls.StrictMatchingScheme(strings.Join(withAuth, "|")) | ||||
| } | ||||
| 
 | ||||
| // IsSameDomain checks if given url string has the same hostname as current Gitea instance
 | ||||
| func IsSameDomain(s string) bool { | ||||
| 	if strings.HasPrefix(s, "/") { | ||||
|  | ||||
| @ -89,6 +89,11 @@ func TestRender_links(t *testing.T) { | ||||
| 	} | ||||
| 	// Text that should be turned into URL
 | ||||
| 
 | ||||
| 	defaultCustom := setting.Markdown.CustomURLSchemes | ||||
| 	setting.Markdown.CustomURLSchemes = []string{"ftp", "magnet"} | ||||
| 	ReplaceSanitizer() | ||||
| 	CustomLinkURLSchemes(setting.Markdown.CustomURLSchemes) | ||||
| 
 | ||||
| 	test( | ||||
| 		"https://www.example.com", | ||||
| 		`<p><a href="https://www.example.com" rel="nofollow">https://www.example.com</a></p>`) | ||||
| @ -131,6 +136,12 @@ func TestRender_links(t *testing.T) { | ||||
| 	test( | ||||
| 		"https://username:password@gitea.com", | ||||
| 		`<p><a href="https://username:password@gitea.com" rel="nofollow">https://username:password@gitea.com</a></p>`) | ||||
| 	test( | ||||
| 		"ftp://gitea.com/file.txt", | ||||
| 		`<p><a href="ftp://gitea.com/file.txt" rel="nofollow">ftp://gitea.com/file.txt</a></p>`) | ||||
| 	test( | ||||
| 		"magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download", | ||||
| 		`<p><a href="magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download" rel="nofollow">magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download</a></p>`) | ||||
| 
 | ||||
| 	// Test that should *not* be turned into URL
 | ||||
| 	test( | ||||
| @ -154,6 +165,14 @@ func TestRender_links(t *testing.T) { | ||||
| 	test( | ||||
| 		"www", | ||||
| 		`<p>www</p>`) | ||||
| 	test( | ||||
| 		"ftps://gitea.com", | ||||
| 		`<p>ftps://gitea.com</p>`) | ||||
| 
 | ||||
| 	// Restore previous settings
 | ||||
| 	setting.Markdown.CustomURLSchemes = defaultCustom | ||||
| 	ReplaceSanitizer() | ||||
| 	CustomLinkURLSchemes(setting.Markdown.CustomURLSchemes) | ||||
| } | ||||
| 
 | ||||
| func TestRender_email(t *testing.T) { | ||||
|  | ||||
| @ -9,12 +9,16 @@ import ( | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| ) | ||||
| 
 | ||||
| // Init initialize regexps for markdown parsing
 | ||||
| func Init() { | ||||
| 	getIssueFullPattern() | ||||
| 	NewSanitizer() | ||||
| 	if len(setting.Markdown.CustomURLSchemes) > 0 { | ||||
| 		CustomLinkURLSchemes(setting.Markdown.CustomURLSchemes) | ||||
| 	} | ||||
| 
 | ||||
| 	// since setting maybe changed extensions, this will reload all parser extensions mapping
 | ||||
| 	extParsers = make(map[string]Parser) | ||||
|  | ||||
| @ -28,6 +28,13 @@ var sanitizer = &Sanitizer{} | ||||
| // entire application lifecycle.
 | ||||
| func NewSanitizer() { | ||||
| 	sanitizer.init.Do(func() { | ||||
| 		ReplaceSanitizer() | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // ReplaceSanitizer replaces the current sanitizer to account for changes in settings
 | ||||
| func ReplaceSanitizer() { | ||||
| 	sanitizer = &Sanitizer{} | ||||
| 	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") | ||||
| @ -41,7 +48,6 @@ func NewSanitizer() { | ||||
| 
 | ||||
| 	// Allow keyword markup
 | ||||
| 	sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^` + keywordClass + `$`)).OnElements("span") | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // Sanitize takes a string that contains a HTML fragment or document and applies policy whitelist.
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user