From b26c3b482feb57704aa399d8d72a959ce667b879 Mon Sep 17 00:00:00 2001
From: 6543 <6543@obermui.de>
Date: Tue, 20 Jul 2021 15:16:20 +0200
Subject: [PATCH] Add TestPrepareWikiFileName (#16487)

* Add TestPrepareWikiFileName

* use LsTree as LsFiles is index only

* ajust other tests

Co-authored-by: Andrew Thornton <art27@cantab.net>
---
 .../0d/ca5bd9b5d7ef937710e056f575e86c0184ba85 | Bin 0 -> 820 bytes
 .../89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c | Bin 0 -> 206 bytes
 .../user2/repo1.wiki.git/refs/heads/master    |   2 +-
 modules/git/tree.go                           |  21 ++++++++
 routers/web/repo/wiki_test.go                 |   4 +-
 services/wiki/wiki.go                         |   2 +-
 services/wiki/wiki_test.go                    |  51 ++++++++++++++++++
 7 files changed, 76 insertions(+), 4 deletions(-)
 create mode 100644 integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85
 create mode 100644 integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c

diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85 b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/0d/ca5bd9b5d7ef937710e056f575e86c0184ba85
new file mode 100644
index 0000000000000000000000000000000000000000..a46c1925ece0ae2f91ef1421487c87707a484509
GIT binary patch
literal 820
zcmV-41Izq)0gaPM&!a{dgmdOs^c^KMZZ=DqQJTdV8=B2{yRq*!X0zef&o>k0mc!Jc
zRI1V|y_Y9`wrx2A77D^2W1pr#+Hxpl6F%Fb7(xzhzhV}{OiGcE@reM#C`>sarn<0C
zA0yy42(c)O5+uPbiXs*!FqV)cCefCKJO{V2kg;2V3a7Dn_CVk{1pfZ%|2(6#Z>RFF
zB>fIpVIzp_W-ADQh8qZ}_}61&`ui7omk(tQ{`@If(+vU~-2uL#6MPCh?N?6$3Y4y~
z${5QE#>uYKv@uh>i%iZZ)s)%$Ls{;V!s9_n1#X91m3?tHtmL)(Ur&LrWjtVpwv+HR
zwHRSxZ!PY2!^qlus*oOMufW(%>vimT$spRm@9o~r&g`kT?o%;PpwaEMTi;ox?%>Ql
zwcTsiXknR=s;Hqi(B}C*?yC9xvEDjy%(1H`E$&SV>K8k?H5&?CDi({4Qi`y^tXXoW
z>d*!IE<2PGQR8w#rZamr9*5h<gQ?Td?(51GTFu0lQ);GH3S9k5gVkb`I{wwVr`nFW
z)~%#FZFl~&u);jExC-8qRTaC}p)EFHLt=sl^|SKCdcP<TosH?P_;sSGb$ZQB7m1;z
z$aPf0+qK?Q^o>a)q}3;RVOL)^7oi+?1#ySRkp$;lr@-6wUWteeI(O8=rzh?X(LP<|
zD<SGm(%*r9vELtBy9dhqrc_xInzk`jOlPt&wvHwRU;w=%I?4ty81Fst)pW7^{-g?5
zv9JbfF!SX4u!Q`e9qZ!tv<kb>%Iw%LxqQrYTcyBy9&dM#_ch0_ng-hXG^N|-<{%{(
zj&{#>p9eur%jqU_Tb<INX)<UqB^$k1+JiJxV1#FpLx%)^hO*tCugqC@yUv`of#gSP
zVS?6ezEGG&Q3z(#C>?j$2q|6G$>Mv(%1}UH&YHEK_OmrE{Bv)%E-gPv=0Hrxm&jO-
zagKMnvoc=R%~|NUxg|=pe+g6LuDNtifvKINK<SM`-QfET!3oEw>vJl^Sth#Yr%N4}
yiLRDvvqX)ps6oPgqrkU*I^C&%nbC;)f5cE>l7Q)v4sqC}3CPMOrG5Z%Nltm)<ER$^

literal 0
HcmV?d00001

diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/objects/89/43a1d5f93c00439d5ffc0f8e36f5d60abae46c
new file mode 100644
index 0000000000000000000000000000000000000000..062641bee7da16a4831be6464c6f1373f097cb40
GIT binary patch
literal 206
zcmV;<05Sh~0V^p=O;s>5F=sF|FfcPQQSivmP1VayVR+T_r@efUH~XP%EAKClN_3cu
z?N&pT1SF=X>V{{QWaxV40+}GyMzKeJyfpDk%lIT}wrp;^tlw3e#TcrC3lfu4Q*`|j
zAvP5KNeVoZ(l^mZfMKqov;3mR-Ln*+dP4J3i<1)zQd1P%GIMY`$HV{#6f!|>C}t?R
zy5PF)&Ykb8R!;BRzF_8t{*WtiP}8ysQq%Ra3ep)0CrW>5PdhFlDshmVQ;>1~ZibD2
I03Qiqbs5QEzyJUM

literal 0
HcmV?d00001

diff --git a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master
index 1b1d96a1f0..38984b12b7 100644
--- a/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master
+++ b/integrations/gitea-repositories-meta/user2/repo1.wiki.git/refs/heads/master
@@ -1 +1 @@
-423313fbd38093bb10d0c8387db9105409c6f196
+0dca5bd9b5d7ef937710e056f575e86c0184ba85
diff --git a/modules/git/tree.go b/modules/git/tree.go
index 059f0a8287..3671f421e9 100644
--- a/modules/git/tree.go
+++ b/modules/git/tree.go
@@ -6,6 +6,7 @@
 package git
 
 import (
+	"bytes"
 	"strings"
 )
 
@@ -45,3 +46,23 @@ func (t *Tree) SubTree(rpath string) (*Tree, error) {
 	}
 	return g, nil
 }
+
+// LsTree checks if the given filenames are in the tree
+func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error) {
+	cmd := NewCommand("ls-tree", "-z", "--name-only", "--", ref)
+	for _, arg := range filenames {
+		if arg != "" {
+			cmd.AddArguments(arg)
+		}
+	}
+	res, err := cmd.RunInDirBytes(repo.Path)
+	if err != nil {
+		return nil, err
+	}
+	filelist := make([]string, 0, len(filenames))
+	for _, line := range bytes.Split(res, []byte{'\000'}) {
+		filelist = append(filelist, string(line))
+	}
+
+	return filelist, err
+}
diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go
index 8934a6619f..bcdb8023ac 100644
--- a/routers/web/repo/wiki_test.go
+++ b/routers/web/repo/wiki_test.go
@@ -81,7 +81,7 @@ func TestWiki(t *testing.T) {
 	Wiki(ctx)
 	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"}, ctx.Data["Pages"])
+	assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"])
 }
 
 func TestWikiPages(t *testing.T) {
@@ -91,7 +91,7 @@ func TestWikiPages(t *testing.T) {
 	test.LoadRepo(t, ctx, 1)
 	WikiPages(ctx)
 	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
-	assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name"}, ctx.Data["Pages"])
+	assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"])
 }
 
 func TestNewWiki(t *testing.T) {
diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go
index 94f36ea2f2..f1632c6bf7 100644
--- a/services/wiki/wiki.go
+++ b/services/wiki/wiki.go
@@ -88,7 +88,7 @@ func prepareWikiFileName(gitRepo *git.Repository, wikiName string) (bool, string
 	escaped := NameToFilename(wikiName)
 
 	// Look for both files
-	filesInIndex, err := gitRepo.LsFiles(unescaped, escaped)
+	filesInIndex, err := gitRepo.LsTree("master", unescaped, escaped)
 	if err != nil {
 		log.Error("%v", err)
 		return false, escaped, err
diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go
index b35b86d655..a1614b509c 100644
--- a/services/wiki/wiki_test.go
+++ b/services/wiki/wiki_test.go
@@ -210,3 +210,54 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
 	_, err = masterTree.GetTreeEntryByPath(wikiPath)
 	assert.Error(t, err)
 }
+
+func TestPrepareWikiFileName(t *testing.T) {
+	models.PrepareTestEnv(t)
+	repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
+	gitRepo, err := git.OpenRepository(repo.WikiPath())
+	defer gitRepo.Close()
+	assert.NoError(t, err)
+
+	tests := []struct {
+		name      string
+		arg       string
+		existence bool
+		wikiPath  string
+		wantErr   bool
+	}{{
+		name:      "add suffix",
+		arg:       "Home",
+		existence: true,
+		wikiPath:  "Home.md",
+		wantErr:   false,
+	}, {
+		name:      "test special chars",
+		arg:       "home of and & or wiki page!",
+		existence: false,
+		wikiPath:  "home-of-and-%26-or-wiki-page%21.md",
+		wantErr:   false,
+	}, {
+		name:      "fount unescaped cases",
+		arg:       "Unescaped File",
+		existence: true,
+		wikiPath:  "Unescaped File.md",
+		wantErr:   false,
+	}}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			existence, newWikiPath, err := prepareWikiFileName(gitRepo, tt.arg)
+			if (err != nil) != tt.wantErr {
+				assert.NoError(t, err)
+				return
+			}
+			if existence != tt.existence {
+				if existence {
+					t.Errorf("expect to find no escaped file but we detect one")
+				} else {
+					t.Errorf("expect to find an escaped file but we could not detect one")
+				}
+			}
+			assert.Equal(t, tt.wikiPath, newWikiPath)
+		})
+	}
+}