diff options
author | Giteabot <teabot@gitea.io> | 2024-08-17 11:19:26 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-17 03:19:26 +0000 |
commit | 3fe1f732686989095abd25599c1dc75bda46246d (patch) | |
tree | b54dcd7471942f88cfc37b0e4c6c8b86d6ad9b5b /routers | |
parent | 1cf8f69b3840b04270042c53e3959e1caa623777 (diff) | |
download | gitea-3fe1f732686989095abd25599c1dc75bda46246d.tar.gz gitea-3fe1f732686989095abd25599c1dc75bda46246d.zip |
Fix raw wiki links (#31825) (#31845)
Backport #31825 by @Zettat123
Fix #31395
This regression is introduced by #30273. To find out how GitHub handles
this case, I did [some
tests](https://github.com/go-gitea/gitea/issues/31395#issuecomment-2278929115).
I use redirect in this PR instead of checking if the corresponding `.md`
file exists when rendering the link because GitHub also uses redirect.
With this PR, there is no need to resolve the raw wiki link when
rendering a wiki page. If a wiki link points to a raw file, access will
be redirected to the raw link.
---------
Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: yp05327 <576951401@qq.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'routers')
-rw-r--r-- | routers/web/repo/wiki.go | 64 | ||||
-rw-r--r-- | routers/web/repo/wiki_test.go | 14 |
2 files changed, 68 insertions, 10 deletions
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index 13b6a7b8e3..d2056353d8 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -138,18 +138,41 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte { return content } -// wikiContentsByName returns the contents of a wiki page, along with a boolean -// indicating whether the page exists. Writes to ctx if an error occurs. -func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) { +// wikiEntryByName returns the entry of a wiki page, along with a boolean +// indicating whether the entry exists. Writes to ctx if an error occurs. +// The last return value indicates whether the file should be returned as a raw file +func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) { + isRaw := false gitFilename := wiki_service.WebPathToGitPath(wikiName) entry, err := findEntryForFile(commit, gitFilename) if err != nil && !git.IsErrNotExist(err) { ctx.ServerError("findEntryForFile", err) - return nil, nil, "", false - } else if entry == nil { + return nil, "", false, false + } + if entry == nil { + // check if the file without ".md" suffix exists + gitFilename := strings.TrimSuffix(gitFilename, ".md") + entry, err = findEntryForFile(commit, gitFilename) + if err != nil && !git.IsErrNotExist(err) { + ctx.ServerError("findEntryForFile", err) + return nil, "", false, false + } + isRaw = true + } + if entry == nil { + return nil, "", true, false + } + return entry, gitFilename, false, isRaw +} + +// wikiContentsByName returns the contents of a wiki page, along with a boolean +// indicating whether the page exists. Writes to ctx if an error occurs. +func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) { + entry, gitFilename, noEntry, _ := wikiEntryByName(ctx, commit, wikiName) + if entry == nil { return nil, nil, "", true } - return wikiContentsByEntry(ctx, entry), entry, gitFilename, false + return wikiContentsByEntry(ctx, entry), entry, gitFilename, noEntry } func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { @@ -215,11 +238,14 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { isSideBar := pageName == "_Sidebar" isFooter := pageName == "_Footer" - // lookup filename in wiki - get filecontent, gitTree entry , real filename - data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) + // lookup filename in wiki - get gitTree entry , real filename + entry, pageFilename, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName) if noEntry { ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages") } + if isRaw { + ctx.Redirect(util.URLJoin(ctx.Repo.RepoLink, "wiki/raw", string(pageName))) + } if entry == nil || ctx.Written() { if wikiRepo != nil { wikiRepo.Close() @@ -227,6 +253,15 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { return nil, nil } + // get filecontent + data := wikiContentsByEntry(ctx, entry) + if ctx.Written() { + if wikiRepo != nil { + wikiRepo.Close() + } + return nil, nil + } + var sidebarContent []byte if !isSideBar { sidebarContent, _, _, _ = wikiContentsByName(ctx, commit, "_Sidebar") @@ -442,15 +477,24 @@ func renderEditPage(ctx *context.Context) { ctx.Data["Title"] = displayName ctx.Data["title"] = displayName - // lookup filename in wiki - get filecontent, gitTree entry , real filename - data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName) + // lookup filename in wiki - gitTree entry , real filename + entry, _, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName) if noEntry { ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages") } + if isRaw { + ctx.Error(http.StatusForbidden, "Editing of raw wiki files is not allowed") + } if entry == nil || ctx.Written() { return } + // get filecontent + data := wikiContentsByEntry(ctx, entry) + if ctx.Written() { + return + } + ctx.Data["content"] = string(data) ctx.Data["sidebarPresent"] = false ctx.Data["sidebarContent"] = "" diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go index 4602dcfeb4..86971f15f1 100644 --- a/routers/web/repo/wiki_test.go +++ b/routers/web/repo/wiki_test.go @@ -87,6 +87,13 @@ func TestWiki(t *testing.T) { assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) assert.EqualValues(t, "Home", ctx.Data["Title"]) assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"]) + + ctx, _ = contexttest.MockContext(t, "user2/repo1/jpeg.jpg") + ctx.SetParams("*", "jpeg.jpg") + contexttest.LoadRepo(t, ctx, 1) + Wiki(ctx) + assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status()) + assert.Equal(t, "/user2/repo1/wiki/raw/jpeg.jpg", ctx.Resp.Header().Get("Location")) } func TestWikiPages(t *testing.T) { @@ -160,6 +167,13 @@ func TestEditWiki(t *testing.T) { assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) assert.EqualValues(t, "Home", ctx.Data["Title"]) assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["content"]) + + ctx, _ = contexttest.MockContext(t, "user2/repo1/wiki/jpeg.jpg?action=_edit") + ctx.SetParams("*", "jpeg.jpg") + contexttest.LoadUser(t, ctx, 2) + contexttest.LoadRepo(t, ctx, 1) + EditWiki(ctx) + assert.EqualValues(t, http.StatusForbidden, ctx.Resp.Status()) } func TestEditWikiPost(t *testing.T) { |