From 43d1183f67783ff5d5a7ebecaf22da36e57dbb8e Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Sun, 12 Feb 2023 11:39:52 +0200 Subject: [PATCH] escape filename when assemble URL (#22850) (#22871) Backport #22850 Fixes: #22843 ### Cause: https://github.com/go-gitea/gitea/blob/affdd40296960a08a4223330ccbd1fb88c96ea1a/services/repository/files/content.go#L161 Previously, we did not escape the **"%"** that might be in "treePath" when call "url.parse()". ![image](https://user-images.githubusercontent.com/33891828/218066318-5a909e50-2a17-46e6-b32f-684b2aa4b91f.png) This function will check whether "%" is the beginning of an escape character. Obviously, the "%" in the example (hello%mother.txt) is not that. So, the function will return a error. ### Solution: We can escape "treePath" by call "url.PathEscape()" function firstly. ### Screenshot: ![image](https://user-images.githubusercontent.com/33891828/218069781-1a030f8b-18d0-4804-b0f8-73997849ef43.png) Signed-off-by: Andrew Thornton Co-authored-by: sillyguodong <33891828+sillyguodong@users.noreply.github.com> Co-authored-by: Andrew Thornton --- modules/lfs/endpoint.go | 4 ++-- services/repository/files/content.go | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/lfs/endpoint.go b/modules/lfs/endpoint.go index 943966ed1..15c3d908a 100644 --- a/modules/lfs/endpoint.go +++ b/modules/lfs/endpoint.go @@ -5,7 +5,6 @@ package lfs import ( - "fmt" "net/url" "os" "path" @@ -13,6 +12,7 @@ import ( "strings" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" ) // DetermineEndpoint determines an endpoint from the clone url or uses the specified LFS url. @@ -96,7 +96,7 @@ func endpointFromLocalPath(path string) *url.URL { return nil } - path = fmt.Sprintf("file://%s%s", slash, filepath.ToSlash(path)) + path = "file://" + slash + util.PathEscapeSegments(filepath.ToSlash(path)) u, _ := url.Parse(path) diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 34c8aeec2..91e002188 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" ) // ContentType repo content type @@ -159,7 +160,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref return nil, fmt.Errorf("no commit found for the ref [ref: %s]", ref) } - selfURL, err := url.Parse(fmt.Sprintf("%s/contents/%s?ref=%s", repo.APIURL(), treePath, origRef)) + selfURL, err := url.Parse(repo.APIURL() + "/contents/" + util.PathEscapeSegments(treePath) + "?ref=" + url.QueryEscape(origRef)) if err != nil { return nil, err } @@ -218,7 +219,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref } // Handle links if entry.IsRegular() || entry.IsLink() { - downloadURL, err := url.Parse(fmt.Sprintf("%s/raw/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath)) + downloadURL, err := url.Parse(repo.HTMLURL() + "/raw/" + url.PathEscape(string(refType)) + "/" + util.PathEscapeSegments(ref) + "/" + util.PathEscapeSegments(treePath)) if err != nil { return nil, err } @@ -226,7 +227,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref contentsResponse.DownloadURL = &downloadURLString } if !entry.IsSubModule() { - htmlURL, err := url.Parse(fmt.Sprintf("%s/src/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath)) + htmlURL, err := url.Parse(repo.HTMLURL() + "/src/" + url.PathEscape(string(refType)) + "/" + util.PathEscapeSegments(ref) + "/" + util.PathEscapeSegments(treePath)) if err != nil { return nil, err } @@ -234,7 +235,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref contentsResponse.HTMLURL = &htmlURLString contentsResponse.Links.HTMLURL = &htmlURLString - gitURL, err := url.Parse(fmt.Sprintf("%s/git/blobs/%s", repo.APIURL(), entry.ID.String())) + gitURL, err := url.Parse(repo.APIURL() + "/git/blobs/" + url.PathEscape(entry.ID.String())) if err != nil { return nil, err }