diff options
author | KN4CK3R <admin@oldschoolhack.me> | 2024-01-16 03:13:29 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-16 02:13:29 +0000 |
commit | 022552d5b6adc792d3cd16df7de6e52cb7b41a72 (patch) | |
tree | 4c709003d9d529475f563ff3997b7be874448052 /routers/web/repo | |
parent | 376fa0d8c49ca8a290ebb328281a56af346f5785 (diff) | |
download | gitea-022552d5b6adc792d3cd16df7de6e52cb7b41a72.tar.gz gitea-022552d5b6adc792d3cd16df7de6e52cb7b41a72.zip |
Rework markup link rendering (#26745) (#28803)
Backport #26745
Fixes #26548
This PR refactors the rendering of markup links. The old code uses
`strings.Replace` to change some urls while the new code uses more
context to decide which link should be generated.
The added tests should ensure the same output for the old and new
behaviour (besides the bug).
We may need to refactor the rendering a bit more to make it clear how
the different helper methods render the input string. There are lots of
options (resolve links / images / mentions / git hashes / emojis / ...)
but you don't really know what helper uses which options. For example,
we currently support images in the user description which should not be
allowed I think:
<details>
<summary>Profile</summary>
https://try.gitea.io/KN4CK3R

</details>
Diffstat (limited to 'routers/web/repo')
-rw-r--r-- | routers/web/repo/commit.go | 18 | ||||
-rw-r--r-- | routers/web/repo/issue.go | 51 | ||||
-rw-r--r-- | routers/web/repo/milestone.go | 20 | ||||
-rw-r--r-- | routers/web/repo/projects.go | 20 | ||||
-rw-r--r-- | routers/web/repo/release.go | 20 | ||||
-rw-r--r-- | routers/web/repo/render.go | 15 | ||||
-rw-r--r-- | routers/web/repo/view.go | 58 | ||||
-rw-r--r-- | routers/web/repo/wiki.go | 10 |
8 files changed, 130 insertions, 82 deletions
diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index a6eb7efeb0..7c8dcbbe7b 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -7,7 +7,9 @@ package repo import ( "errors" "fmt" + "html/template" "net/http" + "path" "strings" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -21,7 +23,9 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitgraph" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" git_service "code.gitea.io/gitea/services/repository" ) @@ -370,9 +374,21 @@ func Diff(ctx *context.Context) { note := &git.Note{} err = git.GetNote(ctx, ctx.Repo.GitRepo, commitID, note) if err == nil { - ctx.Data["Note"] = string(charset.ToUTF8WithFallback(note.Message)) ctx.Data["NoteCommit"] = note.Commit ctx.Data["NoteAuthor"] = user_model.ValidateCommitWithEmail(ctx, note.Commit) + ctx.Data["NoteRendered"], err = markup.RenderCommitMessage(&markup.RenderContext{ + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + BranchPath: path.Join("commit", util.PathEscapeSegments(commitID)), + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, + }, template.HTMLEscapeString(string(charset.ToUTF8WithFallback(note.Message)))) + if err != nil { + ctx.ServerError("RenderCommitMessage", err) + return + } } ctx.Data["BranchName"], err = commit.GetBranchName() diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 87493dd8ad..fe42e86345 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1424,12 +1424,13 @@ func ViewIssue(ctx *context.Context) { } } ctx.Data["IssueWatch"] = iw - issue.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, issue.Content) if err != nil { ctx.ServerError("RenderString", err) @@ -1589,10 +1590,12 @@ func ViewIssue(ctx *context.Context) { } comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, comment.Content) if err != nil { ctx.ServerError("RenderString", err) @@ -1666,10 +1669,12 @@ func ViewIssue(ctx *context.Context) { } } else if comment.Type.HasContentSupport() { comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, comment.Content) if err != nil { ctx.ServerError("RenderString", err) @@ -2220,10 +2225,12 @@ func UpdateIssueContent(ctx *context.Context) { } content, err := markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.FormString("context"), // FIXME: <- IS THIS SAFE ? - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.FormString("context"), // FIXME: <- IS THIS SAFE ? + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, issue.Content) if err != nil { ctx.ServerError("RenderString", err) @@ -3129,10 +3136,12 @@ func UpdateCommentContent(ctx *context.Context) { } content, err := markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.FormString("context"), // FIXME: <- IS THIS SAFE ? - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.FormString("context"), // FIXME: <- IS THIS SAFE ? + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, comment.Content) if err != nil { ctx.ServerError("RenderString", err) diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go index eb27c4b00f..a9fcba4bae 100644 --- a/routers/web/repo/milestone.go +++ b/routers/web/repo/milestone.go @@ -81,10 +81,12 @@ func Milestones(ctx *context.Context) { } for _, m := range miles { m.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, m.Content) if err != nil { ctx.ServerError("RenderString", err) @@ -275,10 +277,12 @@ func MilestoneIssuesAndPulls(ctx *context.Context) { } milestone.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, milestone.Content) if err != nil { ctx.ServerError("RenderString", err) diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 541f24c7f4..09d9c1148d 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -86,10 +86,12 @@ func Projects(ctx *context.Context) { for i := range projects { projects[i].RenderedContent, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, projects[i].Description) if err != nil { ctx.ServerError("RenderString", err) @@ -353,10 +355,12 @@ func ViewProject(ctx *context.Context) { ctx.Data["LinkedPRs"] = linkedPrsMap project.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, project.Description) if err != nil { ctx.ServerError("RenderString", err) diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 338dc34cf4..0264242219 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -175,10 +175,12 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { } r.Note, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, r.Note) if err != nil { ctx.ServerError("RenderString", err) @@ -281,10 +283,12 @@ func SingleRelease(ctx *context.Context) { } } release.Note, err = markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeMetas(), - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + Metas: ctx.Repo.Repository.ComposeMetas(), + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, }, release.Note) if err != nil { ctx.ServerError("RenderString", err) diff --git a/routers/web/repo/render.go b/routers/web/repo/render.go index f07b4e8c11..c6bc0dcf19 100644 --- a/routers/web/repo/render.go +++ b/routers/web/repo/render.go @@ -57,16 +57,15 @@ func RenderFile(ctx *context.Context) { return } - treeLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL() - if ctx.Repo.TreePath != "" { - treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath) - } - ctx.Resp.Header().Add("Content-Security-Policy", "frame-src 'self'; sandbox allow-scripts") err = markup.Render(&markup.RenderContext{ - Ctx: ctx, - RelativePath: ctx.Repo.TreePath, - URLPrefix: path.Dir(treeLink), + Ctx: ctx, + RelativePath: ctx.Repo.TreePath, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + BranchPath: ctx.Repo.BranchNameSubURL(), + TreePath: path.Dir(ctx.Repo.TreePath), + }, Metas: ctx.Repo.Repository.ComposeDocumentMetas(), GitRepo: ctx.Repo.GitRepo, InStandalonePage: true, diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index b17d11ec63..759c011cb2 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -158,7 +158,7 @@ func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry, try return "", readmeFile, nil } -func renderDirectory(ctx *context.Context, treeLink string) { +func renderDirectory(ctx *context.Context) { entries := renderDirectoryFiles(ctx, 1*time.Second) if ctx.Written() { return @@ -175,7 +175,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { return } - renderReadmeFile(ctx, subfolder, readmeFile, treeLink) + renderReadmeFile(ctx, subfolder, readmeFile) } // localizedExtensions prepends the provided language code with and without a @@ -259,7 +259,7 @@ func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) ([]byte, return buf, dataRc, &fileInfo{st.IsText(), true, meta.Size, &meta.Pointer, st}, nil } -func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.TreeEntry, readmeTreelink string) { +func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.TreeEntry) { target := readmeFile if readmeFile != nil && readmeFile.IsLink() { target, _ = readmeFile.FollowLinks() @@ -312,9 +312,13 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{ Ctx: ctx, RelativePath: path.Join(ctx.Repo.TreePath, readmeFile.Name()), // ctx.Repo.TreePath is the directory not the Readme so we must append the Readme filename (and path). - URLPrefix: path.Join(readmeTreelink, subfolder), - Metas: ctx.Repo.Repository.ComposeDocumentMetas(), - GitRepo: ctx.Repo.GitRepo, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + BranchPath: ctx.Repo.BranchNameSubURL(), + TreePath: path.Join(ctx.Repo.TreePath, subfolder), + }, + Metas: ctx.Repo.Repository.ComposeDocumentMetas(), + GitRepo: ctx.Repo.GitRepo, }, rd) if err != nil { log.Error("Render failed for %s in %-v: %v Falling back to rendering source", readmeFile.Name(), ctx.Repo.Repository, err) @@ -333,7 +337,7 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr } } -func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink string) { +func renderFile(ctx *context.Context, entry *git.TreeEntry) { ctx.Data["IsViewFile"] = true ctx.Data["HideRepoInfo"] = true blob := entry.Blob() @@ -347,7 +351,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefName) ctx.Data["FileIsSymlink"] = entry.IsLink() ctx.Data["FileName"] = blob.Name() - ctx.Data["RawFileLink"] = rawLink + "/" + util.PathEscapeSegments(ctx.Repo.TreePath) + ctx.Data["RawFileLink"] = ctx.Repo.RepoLink + "/raw/" + ctx.Repo.BranchNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath) if ctx.Repo.TreePath == ".editorconfig" { _, editorconfigWarning, editorconfigErr := ctx.Repo.GetEditorconfig(ctx.Repo.Commit) @@ -475,9 +479,13 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st Ctx: ctx, Type: markupType, RelativePath: ctx.Repo.TreePath, - URLPrefix: path.Dir(treeLink), - Metas: metas, - GitRepo: ctx.Repo.GitRepo, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + BranchPath: ctx.Repo.BranchNameSubURL(), + TreePath: path.Dir(ctx.Repo.TreePath), + }, + Metas: metas, + GitRepo: ctx.Repo.GitRepo, }, rd) if err != nil { ctx.ServerError("Render", err) @@ -576,9 +584,13 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{ Ctx: ctx, RelativePath: ctx.Repo.TreePath, - URLPrefix: path.Dir(treeLink), - Metas: ctx.Repo.Repository.ComposeDocumentMetas(), - GitRepo: ctx.Repo.GitRepo, + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + BranchPath: ctx.Repo.BranchNameSubURL(), + TreePath: path.Dir(ctx.Repo.TreePath), + }, + Metas: ctx.Repo.Repository.ComposeDocumentMetas(), + GitRepo: ctx.Repo.GitRepo, }, rd) if err != nil { ctx.ServerError("Render", err) @@ -936,14 +948,6 @@ func renderCode(ctx *context.Context) { } ctx.Data["Title"] = title - branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL() - treeLink := branchLink - rawLink := ctx.Repo.RepoLink + "/raw/" + ctx.Repo.BranchNameSubURL() - - if len(ctx.Repo.TreePath) > 0 { - treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath) - } - // Get Topics of this repo renderRepoTopics(ctx) if ctx.Written() { @@ -968,9 +972,9 @@ func renderCode(ctx *context.Context) { } if entry.IsDir() { - renderDirectory(ctx, treeLink) + renderDirectory(ctx) } else { - renderFile(ctx, entry, treeLink, rawLink) + renderFile(ctx, entry) } if ctx.Written() { return @@ -1011,6 +1015,12 @@ func renderCode(ctx *context.Context) { } ctx.Data["Paths"] = paths + + branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL() + treeLink := branchLink + if len(ctx.Repo.TreePath) > 0 { + treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath) + } ctx.Data["TreeLink"] = treeLink ctx.Data["TreeNames"] = treeNames ctx.Data["BranchLink"] = branchLink diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index c9cec0313d..5634445b70 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -238,10 +238,12 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { } rctx := &markup.RenderContext{ - Ctx: ctx, - URLPrefix: ctx.Repo.RepoLink, - Metas: ctx.Repo.Repository.ComposeDocumentMetas(), - IsWiki: true, + Ctx: ctx, + Metas: ctx.Repo.Repository.ComposeDocumentMetas(), + Links: markup.Links{ + Base: ctx.Repo.RepoLink, + }, + IsWiki: true, } buf := &strings.Builder{} |