mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 11:28:24 +00:00 
			
		
		
		
	Add warning for BIDI characters in page renders and in diffs (#17562)
Fix #17514 Given the comments I've adjusted this somewhat. The numbers of characters detected are increased and include things like the use of U+300 to make à instead of à and non-breaking spaces. There is a button which can be used to escape the content to show it. Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: Gwyneth Morgan <gwymor@tilde.club> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		| @@ -169,11 +169,11 @@ func getDiffLineSectionInfo(treePath, line string, lastLeftIdx, lastRightIdx int | ||||
| } | ||||
|  | ||||
| // escape a line's content or return <br> needed for copy/paste purposes | ||||
| func getLineContent(content string) string { | ||||
| func getLineContent(content string) DiffInline { | ||||
| 	if len(content) > 0 { | ||||
| 		return html.EscapeString(content) | ||||
| 		return DiffInlineWithUnicodeEscape(template.HTML(html.EscapeString(content))) | ||||
| 	} | ||||
| 	return "<br>" | ||||
| 	return DiffInline{Content: "<br>"} | ||||
| } | ||||
|  | ||||
| // DiffSection represents a section of a DiffFile. | ||||
| @@ -411,7 +411,7 @@ func fixupBrokenSpans(diffs []diffmatchpatch.Diff) []diffmatchpatch.Diff { | ||||
| 	return fixedup | ||||
| } | ||||
|  | ||||
| func diffToHTML(fileName string, diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML { | ||||
| func diffToHTML(fileName string, diffs []diffmatchpatch.Diff, lineType DiffLineType) DiffInline { | ||||
| 	buf := bytes.NewBuffer(nil) | ||||
| 	match := "" | ||||
|  | ||||
| @@ -483,7 +483,7 @@ func diffToHTML(fileName string, diffs []diffmatchpatch.Diff, lineType DiffLineT | ||||
| 			buf.Write(codeTagSuffix) | ||||
| 		} | ||||
| 	} | ||||
| 	return template.HTML(buf.Bytes()) | ||||
| 	return DiffInlineWithUnicodeEscape(template.HTML(buf.String())) | ||||
| } | ||||
|  | ||||
| // GetLine gets a specific line by type (add or del) and file line number | ||||
| @@ -535,10 +535,28 @@ func init() { | ||||
| 	diffMatchPatch.DiffEditCost = 100 | ||||
| } | ||||
|  | ||||
| // DiffInline is a struct that has a content and escape status | ||||
| type DiffInline struct { | ||||
| 	EscapeStatus charset.EscapeStatus | ||||
| 	Content      template.HTML | ||||
| } | ||||
|  | ||||
| // DiffInlineWithUnicodeEscape makes a DiffInline with hidden unicode characters escaped | ||||
| func DiffInlineWithUnicodeEscape(s template.HTML) DiffInline { | ||||
| 	status, content := charset.EscapeControlString(string(s)) | ||||
| 	return DiffInline{EscapeStatus: status, Content: template.HTML(content)} | ||||
| } | ||||
|  | ||||
| // DiffInlineWithHighlightCode makes a DiffInline with code highlight and hidden unicode characters escaped | ||||
| func DiffInlineWithHighlightCode(fileName, language, code string) DiffInline { | ||||
| 	status, content := charset.EscapeControlString(highlight.Code(fileName, language, code)) | ||||
| 	return DiffInline{EscapeStatus: status, Content: template.HTML(content)} | ||||
| } | ||||
|  | ||||
| // GetComputedInlineDiffFor computes inline diff for the given line. | ||||
| func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) template.HTML { | ||||
| func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) DiffInline { | ||||
| 	if setting.Git.DisableDiffHighlight { | ||||
| 		return template.HTML(getLineContent(diffLine.Content[1:])) | ||||
| 		return getLineContent(diffLine.Content[1:]) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| @@ -555,26 +573,26 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) tem | ||||
| 	// try to find equivalent diff line. ignore, otherwise | ||||
| 	switch diffLine.Type { | ||||
| 	case DiffLineSection: | ||||
| 		return template.HTML(getLineContent(diffLine.Content[1:])) | ||||
| 		return getLineContent(diffLine.Content[1:]) | ||||
| 	case DiffLineAdd: | ||||
| 		compareDiffLine = diffSection.GetLine(DiffLineDel, diffLine.RightIdx) | ||||
| 		if compareDiffLine == nil { | ||||
| 			return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content[1:])) | ||||
| 			return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:]) | ||||
| 		} | ||||
| 		diff1 = compareDiffLine.Content | ||||
| 		diff2 = diffLine.Content | ||||
| 	case DiffLineDel: | ||||
| 		compareDiffLine = diffSection.GetLine(DiffLineAdd, diffLine.LeftIdx) | ||||
| 		if compareDiffLine == nil { | ||||
| 			return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content[1:])) | ||||
| 			return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:]) | ||||
| 		} | ||||
| 		diff1 = diffLine.Content | ||||
| 		diff2 = compareDiffLine.Content | ||||
| 	default: | ||||
| 		if strings.IndexByte(" +-", diffLine.Content[0]) > -1 { | ||||
| 			return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content[1:])) | ||||
| 			return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:]) | ||||
| 		} | ||||
| 		return template.HTML(highlight.Code(diffSection.FileName, language, diffLine.Content)) | ||||
| 		return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content) | ||||
| 	} | ||||
|  | ||||
| 	diffRecord := diffMatchPatch.DiffMain(highlight.Code(diffSection.FileName, language, diff1[1:]), highlight.Code(diffSection.FileName, language, diff2[1:]), true) | ||||
|   | ||||
| @@ -38,14 +38,14 @@ func TestDiffToHTML(t *testing.T) { | ||||
| 		{Type: dmp.DiffInsert, Text: "bar"}, | ||||
| 		{Type: dmp.DiffDelete, Text: " baz"}, | ||||
| 		{Type: dmp.DiffEqual, Text: " biz"}, | ||||
| 	}, DiffLineAdd)) | ||||
| 	}, DiffLineAdd).Content) | ||||
|  | ||||
| 	assertEqual(t, "foo <span class=\"removed-code\">bar</span> biz", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffEqual, Text: "foo "}, | ||||
| 		{Type: dmp.DiffDelete, Text: "bar"}, | ||||
| 		{Type: dmp.DiffInsert, Text: " baz"}, | ||||
| 		{Type: dmp.DiffEqual, Text: " biz"}, | ||||
| 	}, DiffLineDel)) | ||||
| 	}, DiffLineDel).Content) | ||||
|  | ||||
| 	assertEqual(t, "<span class=\"k\">if</span> <span class=\"p\">!</span><span class=\"nx\">nohl</span> <span class=\"o\">&&</span> <span class=\"added-code\"><span class=\"p\">(</span></span><span class=\"nx\">lexer</span> <span class=\"o\">!=</span> <span class=\"kc\">nil</span><span class=\"added-code\"> <span class=\"o\">||</span> <span class=\"nx\">r</span><span class=\"p\">.</span><span class=\"nx\">GuessLanguage</span><span class=\"p\">)</span></span> <span class=\"p\">{</span>", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffEqual, Text: "<span class=\"k\">if</span> <span class=\"p\">!</span><span class=\"nx\">nohl</span> <span class=\"o\">&&</span> <span class=\""}, | ||||
| @@ -53,7 +53,7 @@ func TestDiffToHTML(t *testing.T) { | ||||
| 		{Type: dmp.DiffEqual, Text: "nx\">lexer</span> <span class=\"o\">!=</span> <span class=\"kc\">nil"}, | ||||
| 		{Type: dmp.DiffInsert, Text: "</span> <span class=\"o\">||</span> <span class=\"nx\">r</span><span class=\"p\">.</span><span class=\"nx\">GuessLanguage</span><span class=\"p\">)"}, | ||||
| 		{Type: dmp.DiffEqual, Text: "</span> <span class=\"p\">{</span>"}, | ||||
| 	}, DiffLineAdd)) | ||||
| 	}, DiffLineAdd).Content) | ||||
|  | ||||
| 	assertEqual(t, "<span class=\"nx\">tagURL</span> <span class=\"o\">:=</span> <span class=\"removed-code\"><span class=\"nx\">fmt</span><span class=\"p\">.</span><span class=\"nf\">Sprintf</span><span class=\"p\">(</span><span class=\"s\">"## [%s](%s/%s/%s/%s?q=&type=all&state=closed&milestone=%d) - %s"</span><span class=\"p\">,</span> <span class=\"nx\">ge</span><span class=\"p\">.</span><span class=\"nx\">Milestone\"</span></span><span class=\"p\">,</span> <span class=\"nx\">ge</span><span class=\"p\">.</span><span class=\"nx\">BaseURL</span><span class=\"p\">,</span> <span class=\"nx\">ge</span><span class=\"p\">.</span><span class=\"nx\">Owner</span><span class=\"p\">,</span> <span class=\"nx\">ge</span><span class=\"p\">.</span><span class=\"nx\">Repo</span><span class=\"p\">,</span> <span class=\"removed-code\"><span class=\"nx\">from</span><span class=\"p\">,</span> <span class=\"nx\">milestoneID</span><span class=\"p\">,</span> <span class=\"nx\">time</span><span class=\"p\">.</span><span class=\"nf\">Now</span><span class=\"p\">(</span><span class=\"p\">)</span><span class=\"p\">.</span><span class=\"nf\">Format</span><span class=\"p\">(</span><span class=\"s\">"2006-01-02"</span><span class=\"p\">)</span></span><span class=\"p\">)</span>", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffEqual, Text: "<span class=\"nx\">tagURL</span> <span class=\"o\">:=</span> <span class=\"n"}, | ||||
| @@ -63,7 +63,7 @@ func TestDiffToHTML(t *testing.T) { | ||||
| 		{Type: dmp.DiffDelete, Text: "from</span><span class=\"p\">,</span> <span class=\"nx\">milestoneID</span><span class=\"p\">,</span> <span class=\"nx\">time</span><span class=\"p\">.</span><span class=\"nf\">Now</span><span class=\"p\">(</span><span class=\"p\">)</span><span class=\"p\">.</span><span class=\"nf\">Format</span><span class=\"p\">(</span><span class=\"s\">"2006-01-02"</span><span class=\"p\">)"}, | ||||
| 		{Type: dmp.DiffInsert, Text: "ge</span><span class=\"p\">.</span><span class=\"nx\">Milestone</span><span class=\"p\">,</span> <span class=\"nx\">from</span><span class=\"p\">,</span> <span class=\"nx\">milestoneID"}, | ||||
| 		{Type: dmp.DiffEqual, Text: "</span><span class=\"p\">)</span>"}, | ||||
| 	}, DiffLineDel)) | ||||
| 	}, DiffLineDel).Content) | ||||
|  | ||||
| 	assertEqual(t, "<span class=\"nx\">r</span><span class=\"p\">.</span><span class=\"nf\">WrapperRenderer</span><span class=\"p\">(</span><span class=\"nx\">w</span><span class=\"p\">,</span> <span class=\"removed-code\"><span class=\"nx\">language</span><span class=\"p\">,</span> <span class=\"kc\">true</span><span class=\"p\">,</span> <span class=\"nx\">attrs</span></span><span class=\"p\">,</span> <span class=\"kc\">false</span><span class=\"p\">)</span>", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffEqual, Text: "<span class=\"nx\">r</span><span class=\"p\">.</span><span class=\"nf\">WrapperRenderer</span><span class=\"p\">(</span><span class=\"nx\">w</span><span class=\"p\">,</span> <span class=\"nx\">"}, | ||||
| @@ -71,14 +71,14 @@ func TestDiffToHTML(t *testing.T) { | ||||
| 		{Type: dmp.DiffEqual, Text: "c"}, | ||||
| 		{Type: dmp.DiffDelete, Text: "lass=\"p\">,</span> <span class=\"kc\">true</span><span class=\"p\">,</span> <span class=\"nx\">attrs"}, | ||||
| 		{Type: dmp.DiffEqual, Text: "</span><span class=\"p\">,</span> <span class=\"kc\">false</span><span class=\"p\">)</span>"}, | ||||
| 	}, DiffLineDel)) | ||||
| 	}, DiffLineDel).Content) | ||||
|  | ||||
| 	assertEqual(t, "<span class=\"added-code\">language</span><span class=\"p\">,</span> <span class=\"kc\">true</span><span class=\"p\">,</span> <span class=\"nx\">attrs</span></span><span class=\"p\">,</span> <span class=\"kc\">false</span><span class=\"p\">)</span>", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffInsert, Text: "language</span><span "}, | ||||
| 		{Type: dmp.DiffEqual, Text: "c"}, | ||||
| 		{Type: dmp.DiffInsert, Text: "lass=\"p\">,</span> <span class=\"kc\">true</span><span class=\"p\">,</span> <span class=\"nx\">attrs"}, | ||||
| 		{Type: dmp.DiffEqual, Text: "</span><span class=\"p\">,</span> <span class=\"kc\">false</span><span class=\"p\">)</span>"}, | ||||
| 	}, DiffLineAdd)) | ||||
| 	}, DiffLineAdd).Content) | ||||
|  | ||||
| 	assertEqual(t, "<span class=\"k\">print</span><span class=\"added-code\"><span class=\"p\">(</span></span><span class=\"sa\"></span><span class=\"s2\">"</span><span class=\"s2\">// </span><span class=\"s2\">"</span><span class=\"p\">,</span> <span class=\"n\">sys</span><span class=\"o\">.</span><span class=\"n\">argv</span><span class=\"added-code\"><span class=\"p\">)</span></span>", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffEqual, Text: "<span class=\"k\">print</span>"}, | ||||
| @@ -87,14 +87,14 @@ func TestDiffToHTML(t *testing.T) { | ||||
| 		{Type: dmp.DiffInsert, Text: "class=\"p\">(</span>"}, | ||||
| 		{Type: dmp.DiffEqual, Text: "<span class=\"sa\"></span><span class=\"s2\">"</span><span class=\"s2\">// </span><span class=\"s2\">"</span><span class=\"p\">,</span> <span class=\"n\">sys</span><span class=\"o\">.</span><span class=\"n\">argv</span>"}, | ||||
| 		{Type: dmp.DiffInsert, Text: "<span class=\"p\">)</span>"}, | ||||
| 	}, DiffLineAdd)) | ||||
| 	}, DiffLineAdd).Content) | ||||
|  | ||||
| 	assertEqual(t, "sh <span class=\"added-code\">'useradd -u $(stat -c "%u" .gitignore) jenkins'</span>", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffEqual, Text: "sh "}, | ||||
| 		{Type: dmp.DiffDelete, Text: "4;useradd -u 111 jenkins""}, | ||||
| 		{Type: dmp.DiffInsert, Text: "9;useradd -u $(stat -c "%u" .gitignore) jenkins'"}, | ||||
| 		{Type: dmp.DiffEqual, Text: ";"}, | ||||
| 	}, DiffLineAdd)) | ||||
| 	}, DiffLineAdd).Content) | ||||
|  | ||||
| 	assertEqual(t, "<span class=\"x\">							<h<span class=\"added-code\">4 class="release-list-title df ac"</span>></span>", diffToHTML("", []dmp.Diff{ | ||||
| 		{Type: dmp.DiffEqual, Text: "<span class=\"x\">							<h"}, | ||||
| @@ -102,7 +102,7 @@ func TestDiffToHTML(t *testing.T) { | ||||
| 		{Type: dmp.DiffEqual, Text: "3"}, | ||||
| 		{Type: dmp.DiffInsert, Text: "4;release-list-title df ac""}, | ||||
| 		{Type: dmp.DiffEqual, Text: "></span>"}, | ||||
| 	}, DiffLineAdd)) | ||||
| 	}, DiffLineAdd).Content) | ||||
| } | ||||
|  | ||||
| func TestParsePatch_skipTo(t *testing.T) { | ||||
| @@ -718,7 +718,7 @@ func TestDiffToHTML_14231(t *testing.T) { | ||||
| 	expected := `		<span class="n">run</span><span class="added-code"><span class="o">(</span><span class="n">db</span></span><span class="o">)</span>` | ||||
| 	output := diffToHTML("main.v", diffRecord, DiffLineAdd) | ||||
|  | ||||
| 	assertEqual(t, expected, output) | ||||
| 	assertEqual(t, expected, output.Content) | ||||
| } | ||||
|  | ||||
| func TestNoCrashes(t *testing.T) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user