Skip to content

Commit cc9449c

Browse files
Zettat123GiteaBot
authored andcommitted
Fix raw wiki links (go-gitea#31825)
Fix go-gitea#31395 This regression is introduced by go-gitea#30273. To find out how GitHub handles this case, I did [some tests](go-gitea#31395 (comment)). 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.
1 parent 5fa90ad commit cc9449c

File tree

5 files changed

+84
-32
lines changed

5 files changed

+84
-32
lines changed

modules/markup/html_link.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
package markup
55

66
import (
7-
"path"
8-
97
"code.gitea.io/gitea/modules/util"
108
)
119

@@ -14,13 +12,9 @@ func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (resu
1412
if !isAnchorFragment && !IsFullURLString(link) {
1513
linkBase := ctx.Links.Base
1614
if ctx.IsWiki {
17-
if ext := path.Ext(link); ext == "" || ext == ".-" {
18-
linkBase = ctx.Links.WikiLink() // the link is for a wiki page
19-
} else if DetectMarkupTypeByFileName(link) != "" {
20-
linkBase = ctx.Links.WikiLink() // the link is renderable as a wiki page
21-
} else {
22-
linkBase = ctx.Links.WikiRawLink() // otherwise, use a raw link instead to view&download medias
23-
}
15+
// no need to check if the link should be resolved as a wiki link or a wiki raw link
16+
// just use wiki link here and it will be redirected to a wiki raw link if necessary
17+
linkBase = ctx.Links.WikiLink()
2418
} else if ctx.Links.BranchPath != "" || ctx.Links.TreePath != "" {
2519
// if there is no BranchPath, then the link will be something like "/owner/repo/src/{the-file-path}"
2620
// and then this link will be handled by the "legacy-ref" code and be redirected to the default branch like "/owner/repo/src/branch/main/{the-file-path}"

modules/markup/html_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ func TestRender_ShortLinks(t *testing.T) {
435435
renderableFileURL := util.URLJoin(tree, "markdown_file.md")
436436
renderableFileURLWiki := util.URLJoin(markup.TestRepoURL, "wiki", "markdown_file.md")
437437
unrenderableFileURL := util.URLJoin(tree, "file.zip")
438-
unrenderableFileURLWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "file.zip")
438+
unrenderableFileURLWiki := util.URLJoin(markup.TestRepoURL, "wiki", "file.zip")
439439
favicon := "http://google.com/favicon.ico"
440440

441441
test(

modules/markup/markdown/markdown_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,9 @@ space</p>
655655
Expected: `<p>space @mention-user<br/>
656656
/just/a/path.bin<br/>
657657
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
658-
<a href="/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
658+
<a href="/wiki/file.bin" rel="nofollow">local link</a><br/>
659659
<a href="https://example.com" rel="nofollow">remote link</a><br/>
660-
<a href="/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
660+
<a href="/wiki/file.bin" rel="nofollow">local link</a><br/>
661661
<a href="https://example.com" rel="nofollow">remote link</a><br/>
662662
<a href="/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/image.jpg" alt="local image"/></a><br/>
663663
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
@@ -713,9 +713,9 @@ space</p>
713713
Expected: `<p>space @mention-user<br/>
714714
/just/a/path.bin<br/>
715715
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
716-
<a href="https://gitea.io/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
716+
<a href="https://gitea.io/wiki/file.bin" rel="nofollow">local link</a><br/>
717717
<a href="https://example.com" rel="nofollow">remote link</a><br/>
718-
<a href="https://gitea.io/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
718+
<a href="https://gitea.io/wiki/file.bin" rel="nofollow">local link</a><br/>
719719
<a href="https://example.com" rel="nofollow">remote link</a><br/>
720720
<a href="https://gitea.io/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/image.jpg" alt="local image"/></a><br/>
721721
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
@@ -771,9 +771,9 @@ space</p>
771771
Expected: `<p>space @mention-user<br/>
772772
/just/a/path.bin<br/>
773773
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
774-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
774+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
775775
<a href="https://example.com" rel="nofollow">remote link</a><br/>
776-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
776+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
777777
<a href="https://example.com" rel="nofollow">remote link</a><br/>
778778
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
779779
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
@@ -831,9 +831,9 @@ space</p>
831831
Expected: `<p>space @mention-user<br/>
832832
/just/a/path.bin<br/>
833833
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
834-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
834+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
835835
<a href="https://example.com" rel="nofollow">remote link</a><br/>
836-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
836+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
837837
<a href="https://example.com" rel="nofollow">remote link</a><br/>
838838
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
839839
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
@@ -891,9 +891,9 @@ space</p>
891891
Expected: `<p>space @mention-user<br/>
892892
/just/a/path.bin<br/>
893893
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
894-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
894+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
895895
<a href="https://example.com" rel="nofollow">remote link</a><br/>
896-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
896+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
897897
<a href="https://example.com" rel="nofollow">remote link</a><br/>
898898
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
899899
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
@@ -953,9 +953,9 @@ space</p>
953953
Expected: `<p>space @mention-user<br/>
954954
/just/a/path.bin<br/>
955955
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
956-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
956+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
957957
<a href="https://example.com" rel="nofollow">remote link</a><br/>
958-
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
958+
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/>
959959
<a href="https://example.com" rel="nofollow">remote link</a><br/>
960960
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
961961
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>

routers/web/repo/wiki.go

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,41 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
138138
return content
139139
}
140140

141-
// wikiContentsByName returns the contents of a wiki page, along with a boolean
142-
// indicating whether the page exists. Writes to ctx if an error occurs.
143-
func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) {
141+
// wikiEntryByName returns the entry of a wiki page, along with a boolean
142+
// indicating whether the entry exists. Writes to ctx if an error occurs.
143+
// The last return value indicates whether the file should be returned as a raw file
144+
func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) {
145+
isRaw := false
144146
gitFilename := wiki_service.WebPathToGitPath(wikiName)
145147
entry, err := findEntryForFile(commit, gitFilename)
146148
if err != nil && !git.IsErrNotExist(err) {
147149
ctx.ServerError("findEntryForFile", err)
148-
return nil, nil, "", false
149-
} else if entry == nil {
150+
return nil, "", false, false
151+
}
152+
if entry == nil {
153+
// check if the file without ".md" suffix exists
154+
gitFilename := strings.TrimSuffix(gitFilename, ".md")
155+
entry, err = findEntryForFile(commit, gitFilename)
156+
if err != nil && !git.IsErrNotExist(err) {
157+
ctx.ServerError("findEntryForFile", err)
158+
return nil, "", false, false
159+
}
160+
isRaw = true
161+
}
162+
if entry == nil {
163+
return nil, "", true, false
164+
}
165+
return entry, gitFilename, false, isRaw
166+
}
167+
168+
// wikiContentsByName returns the contents of a wiki page, along with a boolean
169+
// indicating whether the page exists. Writes to ctx if an error occurs.
170+
func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) {
171+
entry, gitFilename, noEntry, _ := wikiEntryByName(ctx, commit, wikiName)
172+
if entry == nil {
150173
return nil, nil, "", true
151174
}
152-
return wikiContentsByEntry(ctx, entry), entry, gitFilename, false
175+
return wikiContentsByEntry(ctx, entry), entry, gitFilename, noEntry
153176
}
154177

155178
func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
@@ -215,18 +238,30 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
215238
isSideBar := pageName == "_Sidebar"
216239
isFooter := pageName == "_Footer"
217240

218-
// lookup filename in wiki - get filecontent, gitTree entry , real filename
219-
data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
241+
// lookup filename in wiki - get gitTree entry , real filename
242+
entry, pageFilename, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName)
220243
if noEntry {
221244
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
222245
}
246+
if isRaw {
247+
ctx.Redirect(util.URLJoin(ctx.Repo.RepoLink, "wiki/raw", string(pageName)))
248+
}
223249
if entry == nil || ctx.Written() {
224250
if wikiRepo != nil {
225251
wikiRepo.Close()
226252
}
227253
return nil, nil
228254
}
229255

256+
// get filecontent
257+
data := wikiContentsByEntry(ctx, entry)
258+
if ctx.Written() {
259+
if wikiRepo != nil {
260+
wikiRepo.Close()
261+
}
262+
return nil, nil
263+
}
264+
230265
var sidebarContent []byte
231266
if !isSideBar {
232267
sidebarContent, _, _, _ = wikiContentsByName(ctx, commit, "_Sidebar")
@@ -442,15 +477,24 @@ func renderEditPage(ctx *context.Context) {
442477
ctx.Data["Title"] = displayName
443478
ctx.Data["title"] = displayName
444479

445-
// lookup filename in wiki - get filecontent, gitTree entry , real filename
446-
data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName)
480+
// lookup filename in wiki - gitTree entry , real filename
481+
entry, _, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName)
447482
if noEntry {
448483
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
449484
}
485+
if isRaw {
486+
ctx.Error(http.StatusForbidden, "Editing of raw wiki files is not allowed")
487+
}
450488
if entry == nil || ctx.Written() {
451489
return
452490
}
453491

492+
// get filecontent
493+
data := wikiContentsByEntry(ctx, entry)
494+
if ctx.Written() {
495+
return
496+
}
497+
454498
ctx.Data["content"] = string(data)
455499
ctx.Data["sidebarPresent"] = false
456500
ctx.Data["sidebarContent"] = ""

routers/web/repo/wiki_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ func TestWiki(t *testing.T) {
8787
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
8888
assert.EqualValues(t, "Home", ctx.Data["Title"])
8989
assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"])
90+
91+
ctx, _ = contexttest.MockContext(t, "user2/repo1/jpeg.jpg")
92+
ctx.SetPathParam("*", "jpeg.jpg")
93+
contexttest.LoadRepo(t, ctx, 1)
94+
Wiki(ctx)
95+
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
96+
assert.Equal(t, "/user2/repo1/wiki/raw/jpeg.jpg", ctx.Resp.Header().Get("Location"))
9097
}
9198

9299
func TestWikiPages(t *testing.T) {
@@ -160,6 +167,13 @@ func TestEditWiki(t *testing.T) {
160167
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
161168
assert.EqualValues(t, "Home", ctx.Data["Title"])
162169
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["content"])
170+
171+
ctx, _ = contexttest.MockContext(t, "user2/repo1/wiki/jpeg.jpg?action=_edit")
172+
ctx.SetPathParam("*", "jpeg.jpg")
173+
contexttest.LoadUser(t, ctx, 2)
174+
contexttest.LoadRepo(t, ctx, 1)
175+
EditWiki(ctx)
176+
assert.EqualValues(t, http.StatusForbidden, ctx.Resp.Status())
163177
}
164178

165179
func TestEditWikiPost(t *testing.T) {

0 commit comments

Comments
 (0)