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:
zeripath 2022-01-07 01:18:52 +00:00 committed by GitHub
parent ee60f27aec
commit 21ed4fd8da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 809 additions and 87 deletions

View file

@ -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)