]> source.dussan.org Git - gitea.git/commitdiff
Multiple Escaping Improvements (#17551)
authorzeripath <art27@cantab.net>
Tue, 16 Nov 2021 18:18:25 +0000 (18:18 +0000)
committerGitHub <noreply@github.com>
Tue, 16 Nov 2021 18:18:25 +0000 (18:18 +0000)
There are multiple places where Gitea does not properly escape URLs that it is building and there are multiple places where it builds urls when there is already a simpler function available to use this.

This is an extensive PR attempting to fix these issues.

1. The first commit in this PR looks through all href, src and links in the Gitea codebase and has attempted to catch all the places where there is potentially incomplete escaping.
2. Whilst doing this we will prefer to use functions that create URLs over recreating them by hand.
3. All uses of strings should be directly escaped - even if they are not currently expected to contain escaping characters. The main benefit to doing this will be that we can consider relaxing the constraints on user names and reponames in future.
4. The next commit looks at escaping in the wiki and re-considers the urls that are used there. Using the improved escaping here wiki files containing '/'. (This implementation will currently still place all of the wiki files the root directory of the repo but this would not be difficult to change.)
5. The title generation in feeds is now properly escaped.
6. EscapePound is no longer needed - urls should be PathEscaped / QueryEscaped as necessary but then re-escaped with Escape when creating html with locales Signed-off-by: Andrew Thornton <art27@cantab.net>

Signed-off-by: Andrew Thornton <art27@cantab.net>
153 files changed:
integrations/issue_test.go
integrations/links_test.go
integrations/nonascii_branches_test.go
models/action.go
models/attachment.go
models/avatars/avatar.go
models/commit_status.go
models/issue.go
models/notification.go
models/release.go
models/repo.go
models/repo_avatar.go
models/user.go
modules/context/context.go
modules/context/repo.go
modules/convert/git_commit.go
modules/convert/issue.go
modules/convert/notification.go
modules/git/utils.go
modules/repofiles/action.go
modules/repofiles/blob.go
modules/repofiles/file.go
modules/repofiles/tree.go
modules/repository/commits.go
modules/templates/helper.go
modules/upload/upload.go
options/locale/locale_en-US.ini
routers/api/v1/org/member.go
routers/api/v1/repo/git_ref.go
routers/api/v1/repo/key.go
routers/web/admin/auths.go
routers/web/admin/repos.go
routers/web/admin/users.go
routers/web/feed/convert.go
routers/web/org/setting.go
routers/web/org/teams.go
routers/web/repo/blame.go
routers/web/repo/commit.go
routers/web/repo/compare.go
routers/web/repo/editor.go
routers/web/repo/issue.go
routers/web/repo/issue_stopwatch.go
routers/web/repo/lfs.go
routers/web/repo/migrate.go
routers/web/repo/milestone.go
routers/web/repo/projects.go
routers/web/repo/pull.go
routers/web/repo/release.go
routers/web/repo/repo.go
routers/web/repo/setting.go
routers/web/repo/setting_protected_branch.go
routers/web/repo/tag.go
routers/web/repo/view.go
routers/web/repo/webhook.go
routers/web/repo/wiki.go
routers/web/repo/wiki_test.go
routers/web/user/home.go
routers/web/user/notification.go
routers/web/user/oauth.go
routers/web/user/profile.go
routers/web/web.go
services/lfs/server.go
services/webhook/dingtalk.go
services/webhook/discord.go
services/webhook/general.go
services/webhook/matrix.go
services/webhook/msteams.go
services/wiki/wiki.go
templates/admin/emails/list.tmpl
templates/admin/repo/list.tmpl
templates/admin/user/list.tmpl
templates/base/head.tmpl
templates/base/head_navbar.tmpl
templates/explore/code.tmpl
templates/mail/auth/activate.tmpl
templates/mail/auth/activate_email.tmpl
templates/mail/auth/register_notify.tmpl
templates/mail/auth/reset_passwd.tmpl
templates/mail/issue/assigned.tmpl
templates/mail/issue/default.tmpl
templates/mail/notify/repo_transfer.tmpl
templates/mail/release.tmpl
templates/org/home.tmpl
templates/org/team/members.tmpl
templates/org/team/navbar.tmpl
templates/org/team/new.tmpl
templates/org/team/repositories.tmpl
templates/org/team/sidebar.tmpl
templates/org/team/teams.tmpl
templates/repo/activity.tmpl
templates/repo/blame.tmpl
templates/repo/branch/list.tmpl
templates/repo/branch_dropdown.tmpl
templates/repo/commit_page.tmpl
templates/repo/commits_list.tmpl
templates/repo/commits_list_small.tmpl
templates/repo/commits_table.tmpl
templates/repo/create.tmpl
templates/repo/diff/blob_excerpt.tmpl
templates/repo/diff/box.tmpl
templates/repo/diff/comments.tmpl
templates/repo/diff/compare.tmpl
templates/repo/diff/image_diff.tmpl
templates/repo/diff/options_dropdown.tmpl
templates/repo/diff/section_split.tmpl
templates/repo/diff/section_unified.tmpl
templates/repo/editor/commit_form.tmpl
templates/repo/editor/edit.tmpl
templates/repo/editor/upload.tmpl
templates/repo/forks.tmpl
templates/repo/graph/commits.tmpl
templates/repo/header.tmpl
templates/repo/home.tmpl
templates/repo/issue/labels/label.tmpl
templates/repo/issue/list.tmpl
templates/repo/issue/view.tmpl
templates/repo/issue/view_content.tmpl
templates/repo/issue/view_content/comments.tmpl
templates/repo/issue/view_content/context_menu.tmpl
templates/repo/issue/view_content/pull.tmpl
templates/repo/issue/view_content/sidebar.tmpl
templates/repo/issue/view_title.tmpl
templates/repo/projects/view.tmpl
templates/repo/pulls/commits.tmpl
templates/repo/pulls/files.tmpl
templates/repo/pulls/fork.tmpl
templates/repo/pulls/tab_menu.tmpl
templates/repo/release/list.tmpl
templates/repo/search.tmpl
templates/repo/settings/branches.tmpl
templates/repo/settings/collaboration.tmpl
templates/repo/settings/githooks.tmpl
templates/repo/settings/lfs_file.tmpl
templates/repo/settings/lfs_file_find.tmpl
templates/repo/settings/lfs_locks.tmpl
templates/repo/settings/tags.tmpl
templates/repo/sub_menu.tmpl
templates/repo/view_file.tmpl
templates/repo/view_list.tmpl
templates/repo/wiki/new.tmpl
templates/repo/wiki/pages.tmpl
templates/repo/wiki/start.tmpl
templates/repo/wiki/view.tmpl
templates/shared/issuelist.tmpl
templates/user/auth/grant.tmpl
templates/user/dashboard/feeds.tmpl
templates/user/dashboard/issues.tmpl
templates/user/dashboard/milestones.tmpl
templates/user/dashboard/navbar.tmpl
templates/user/dashboard/repolist.tmpl
templates/user/notification/notification_div.tmpl
templates/user/settings/repos.tmpl
web_src/js/features/repo-branch.js

index 03ca382de43ddbd7ba67079caa7e845516757018..56cddcb0639c2291971bcd3a72571739533f2401 100644 (file)
@@ -65,7 +65,7 @@ func TestViewIssuesSortByType(t *testing.T) {
        repo := unittest.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
 
        session := loginUser(t, user.Name)
-       req := NewRequest(t, "GET", repo.RelLink()+"/issues?type=created_by")
+       req := NewRequest(t, "GET", repo.Link()+"/issues?type=created_by")
        resp := session.MakeRequest(t, req, http.StatusOK)
 
        htmlDoc := NewHTMLParser(t, resp.Body)
@@ -97,7 +97,7 @@ func TestViewIssuesKeyword(t *testing.T) {
        issues.UpdateIssueIndexer(issue)
        time.Sleep(time.Second * 1)
        const keyword = "first"
-       req := NewRequestf(t, "GET", "%s/issues?q=%s", repo.RelLink(), keyword)
+       req := NewRequestf(t, "GET", "%s/issues?q=%s", repo.Link(), keyword)
        resp := MakeRequest(t, req, http.StatusOK)
 
        htmlDoc := NewHTMLParser(t, resp.Body)
index 03229e10e1222187912edde6b33286d65429f26f..91166274a238197d051335747e81876369cccba5 100644 (file)
@@ -156,7 +156,7 @@ func testLinksAsUser(userName string, t *testing.T) {
                "/releases",
                "/releases/new",
                //"/wiki/_pages",
-               "/wiki/_new",
+               "/wiki/?action=_new",
        }
 
        for _, repo := range apiRepos {
index 22d71e6ee20e16fd86e9a177186fea66b7e0529f..cf6261dffe054d6e99e7abc4733acfc7cb53262d 100644 (file)
@@ -63,17 +63,17 @@ func TestNonasciiBranches(t *testing.T) {
                },
                {
                        from:   "ГлавнаяВетка",
-                       to:     "branch/%d0%93%d0%bb%d0%b0%d0%b2%d0%bd%d0%b0%d1%8f%d0%92%d0%b5%d1%82%d0%ba%d0%b0",
+                       to:     "branch/%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F%D0%92%D0%B5%D1%82%D0%BA%D0%B0",
                        status: http.StatusOK,
                },
                {
                        from:   "а/б/в",
-                       to:     "branch/%d0%b0/%d0%b1/%d0%b2",
+                       to:     "branch/%D0%B0/%D0%B1/%D0%B2",
                        status: http.StatusOK,
                },
                {
                        from:   "Grüßen/README.md",
-                       to:     "branch/Gr%c3%bc%c3%9fen/README.md",
+                       to:     "branch/Gr%C3%BC%C3%9Fen/README.md",
                        status: http.StatusOK,
                },
                {
@@ -83,7 +83,7 @@ func TestNonasciiBranches(t *testing.T) {
                },
                {
                        from:   "Plus+Is+Not+Space/Файл.md",
-                       to:     "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
+                       to:     "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
                        status: http.StatusOK,
                },
                {
@@ -93,28 +93,28 @@ func TestNonasciiBranches(t *testing.T) {
                },
                {
                        from:   "ブランチ",
-                       to:     "branch/%e3%83%96%e3%83%a9%e3%83%b3%e3%83%81",
+                       to:     "branch/%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81",
                        status: http.StatusOK,
                },
                // Tags
                {
                        from:   "Тэг",
-                       to:     "tag/%d0%a2%d1%8d%d0%b3",
+                       to:     "tag/%D0%A2%D1%8D%D0%B3",
                        status: http.StatusOK,
                },
                {
                        from:   "Ё/人",
-                       to:     "tag/%d0%81/%e4%ba%ba",
+                       to:     "tag/%D0%81/%E4%BA%BA",
                        status: http.StatusOK,
                },
                {
                        from:   "タグ",
-                       to:     "tag/%e3%82%bf%e3%82%b0",
+                       to:     "tag/%E3%82%BF%E3%82%B0",
                        status: http.StatusOK,
                },
                {
                        from:   "タグ/ファイル.md",
-                       to:     "tag/%e3%82%bf%e3%82%b0/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md",
+                       to:     "tag/%E3%82%BF%E3%82%B0/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md",
                        status: http.StatusOK,
                },
                // Files
@@ -125,38 +125,38 @@ func TestNonasciiBranches(t *testing.T) {
                },
                {
                        from:   "Файл.md",
-                       to:     "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
+                       to:     "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
                        status: http.StatusOK,
                },
                {
                        from:   "ファイル.md",
-                       to:     "branch/Plus+Is+Not+Space/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md",
+                       to:     "branch/Plus+Is+Not+Space/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md",
                        status: http.StatusNotFound, // it's not on default branch
                },
                // Same but url-encoded (few tests)
                {
                        from:   "%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81",
-                       to:     "branch/%e3%83%96%e3%83%a9%e3%83%b3%e3%83%81",
+                       to:     "branch/%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81",
                        status: http.StatusOK,
                },
                {
                        from:   "%E3%82%BF%E3%82%b0",
-                       to:     "tag/%e3%82%bf%e3%82%b0",
+                       to:     "tag/%E3%82%BF%E3%82%B0",
                        status: http.StatusOK,
                },
                {
                        from:   "%D0%A4%D0%B0%D0%B9%D0%BB.md",
-                       to:     "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
+                       to:     "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
                        status: http.StatusOK,
                },
                {
                        from:   "%D0%81%2F%E4%BA%BA",
-                       to:     "tag/%d0%81/%e4%ba%ba",
+                       to:     "tag/%D0%81/%E4%BA%BA",
                        status: http.StatusOK,
                },
                {
                        from:   "Ё%2F%E4%BA%BA",
-                       to:     "tag/%d0%81/%e4%ba%ba",
+                       to:     "tag/%D0%81/%E4%BA%BA",
                        status: http.StatusOK,
                },
        }
index 7c970e1fdb6f5a4eeab552c996faa241411abce3..80ac3e16f8524878e6ee56f9e778166919483fe5 100644 (file)
@@ -7,6 +7,7 @@ package models
 
 import (
        "fmt"
+       "net/url"
        "path"
        "strconv"
        "strings"
@@ -185,10 +186,8 @@ func (a *Action) ShortRepoPath() string {
 
 // GetRepoLink returns relative link to action repository.
 func (a *Action) GetRepoLink() string {
-       if len(setting.AppSubURL) > 0 {
-               return path.Join(setting.AppSubURL, a.GetRepoPath())
-       }
-       return "/" + a.GetRepoPath()
+       // path.Join will skip empty strings
+       return path.Join(setting.AppSubURL, "/", url.PathEscape(a.GetRepoUserName()), url.PathEscape(a.GetRepoName()))
 }
 
 // GetRepositoryFromMatch returns a *Repository from a username and repo strings
index ed82aaf483bccf3de5ec671ff38de97f0621f834..34edc676cfd27aa8696f13c11dd8e1734e6bc420 100644 (file)
@@ -7,6 +7,7 @@ package models
 import (
        "context"
        "fmt"
+       "net/url"
        "path"
 
        "code.gitea.io/gitea/models/db"
@@ -59,7 +60,7 @@ func (a *Attachment) RelativePath() string {
 
 // DownloadURL returns the download url of the attached file
 func (a *Attachment) DownloadURL() string {
-       return fmt.Sprintf("%sattachments/%s", setting.AppURL, a.UUID)
+       return setting.AppURL + "attachments/" + url.PathEscape(a.UUID)
 }
 
 // LinkedRepository returns the linked repo if any
index 0a1445d2f2d09168022c198dca388d9d54ff6bc6..da63dfd106aa070468c3f9b9d80edfa8fa681f54 100644 (file)
@@ -112,15 +112,15 @@ func GenerateUserAvatarFastLink(userName string, size int) string {
        if size < 0 {
                size = 0
        }
-       return setting.AppSubURL + "/user/avatar/" + userName + "/" + strconv.Itoa(size)
+       return setting.AppSubURL + "/user/avatar/" + url.PathEscape(userName) + "/" + strconv.Itoa(size)
 }
 
 // GenerateUserAvatarImageLink returns a link for `User.Avatar` image file: "/avatars/${User.Avatar}"
 func GenerateUserAvatarImageLink(userAvatar string, size int) string {
        if size > 0 {
-               return setting.AppSubURL + "/avatars/" + userAvatar + "?size=" + strconv.Itoa(size)
+               return setting.AppSubURL + "/avatars/" + url.PathEscape(userAvatar) + "?size=" + strconv.Itoa(size)
        }
-       return setting.AppSubURL + "/avatars/" + userAvatar
+       return setting.AppSubURL + "/avatars/" + url.PathEscape(userAvatar)
 }
 
 // generateRecognizedAvatarURL generate a recognized avatar (Gravatar/Libravatar) URL, it modifies the URL so the parameter is passed by a copy
@@ -155,7 +155,7 @@ func generateEmailAvatarLink(email string, size int, final bool) string {
                        return generateRecognizedAvatarURL(*avatarURL, size)
                }
                // for non-final link, we should return fast (use a 302 redirection link)
-               urlStr := setting.AppSubURL + "/avatar/" + emailHash
+               urlStr := setting.AppSubURL + "/avatar/" + url.PathEscape(emailHash)
                if size > 0 {
                        urlStr += "?size=" + strconv.Itoa(size)
                }
index a6ded049c31cd2bbb6ead8f154bdbe09fb663789..df34b93ec53cd810acf8ae217290e3e6beccc6cb 100644 (file)
@@ -7,6 +7,7 @@ package models
 import (
        "crypto/sha1"
        "fmt"
+       "net/url"
        "strings"
        "time"
 
@@ -137,8 +138,7 @@ func (status *CommitStatus) loadAttributes(e db.Engine) (err error) {
 // APIURL returns the absolute APIURL to this commit-status.
 func (status *CommitStatus) APIURL() string {
        _ = status.loadAttributes(db.GetEngine(db.DefaultContext))
-       return fmt.Sprintf("%sapi/v1/repos/%s/statuses/%s",
-               setting.AppURL, status.Repo.FullName(), status.SHA)
+       return status.Repo.APIURL() + "/statuses/" + url.PathEscape(status.SHA)
 }
 
 // CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
index 0d34bdcaf33949dcb00b77374e8f70a89783bae2..983fb7aa8dc9ab3fead20045d098f79a986beb53 100644 (file)
@@ -372,6 +372,17 @@ func (issue *Issue) HTMLURL() string {
        return fmt.Sprintf("%s/%s/%d", issue.Repo.HTMLURL(), path, issue.Index)
 }
 
+// Link returns the Link URL to this issue.
+func (issue *Issue) Link() string {
+       var path string
+       if issue.IsPull {
+               path = "pulls"
+       } else {
+               path = "issues"
+       }
+       return fmt.Sprintf("%s/%s/%d", issue.Repo.Link(), path, issue.Index)
+}
+
 // DiffURL returns the absolute URL to this diff
 func (issue *Issue) DiffURL() string {
        if issue.IsPull {
index 48249ae84c67703e5e4a1e335c74ccdc821bce2e..1e180736183a38025c4e1aaf10b6546e9b668340 100644 (file)
@@ -6,6 +6,7 @@ package models
 
 import (
        "fmt"
+       "net/url"
        "strconv"
 
        "code.gitea.io/gitea/models/db"
@@ -475,7 +476,7 @@ func (n *Notification) HTMLURL() string {
                }
                return n.Issue.HTMLURL()
        case NotificationSourceCommit:
-               return n.Repository.HTMLURL() + "/commit/" + n.CommitID
+               return n.Repository.HTMLURL() + "/commit/" + url.PathEscape(n.CommitID)
        case NotificationSourceRepository:
                return n.Repository.HTMLURL()
        }
index 4624791b8ff41d89ad37a49dddeeeb23e22f531b..f7bd67b8ca7221c0a4f88a529b18decca3675d48 100644 (file)
@@ -10,10 +10,10 @@ import (
        "errors"
        "fmt"
        "sort"
+       "strconv"
        "strings"
 
        "code.gitea.io/gitea/models/db"
-       "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/structs"
        "code.gitea.io/gitea/modules/timeutil"
        "code.gitea.io/gitea/modules/util"
@@ -78,23 +78,22 @@ func (r *Release) LoadAttributes() error {
 
 // APIURL the api url for a release. release must have attributes loaded
 func (r *Release) APIURL() string {
-       return fmt.Sprintf("%sapi/v1/repos/%s/releases/%d",
-               setting.AppURL, r.Repo.FullName(), r.ID)
+       return r.Repo.APIURL() + "/releases/" + strconv.FormatInt(r.ID, 10)
 }
 
 // ZipURL the zip url for a release. release must have attributes loaded
 func (r *Release) ZipURL() string {
-       return fmt.Sprintf("%s/archive/%s.zip", r.Repo.HTMLURL(), r.TagName)
+       return r.Repo.HTMLURL() + "/archive/" + util.PathEscapeSegments(r.TagName) + ".zip"
 }
 
 // TarURL the tar.gz url for a release. release must have attributes loaded
 func (r *Release) TarURL() string {
-       return fmt.Sprintf("%s/archive/%s.tar.gz", r.Repo.HTMLURL(), r.TagName)
+       return r.Repo.HTMLURL() + "/archive/" + util.PathEscapeSegments(r.TagName) + ".tar.gz"
 }
 
 // HTMLURL the url for a release on the web UI. release must have attributes loaded
 func (r *Release) HTMLURL() string {
-       return fmt.Sprintf("%s/releases/tag/%s", r.Repo.HTMLURL(), r.TagName)
+       return r.Repo.HTMLURL() + "/releases/tag/" + util.PathEscapeSegments(r.TagName)
 }
 
 // IsReleaseExist returns true if release with given tag name already exists.
index f44fc763a56ecad4785e3731b0b37798b0a2501a..16396e181db7a29019dc99fc75c5c3eee30e05c0 100644 (file)
@@ -314,7 +314,7 @@ func (repo *Repository) FullName() string {
 
 // HTMLURL returns the repository HTML URL
 func (repo *Repository) HTMLURL() string {
-       return setting.AppURL + repo.FullName()
+       return setting.AppURL + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(repo.Name)
 }
 
 // CommitLink make link to by commit full ID
@@ -323,14 +323,14 @@ func (repo *Repository) CommitLink(commitID string) (result string) {
        if commitID == "" || commitID == "0000000000000000000000000000000000000000" {
                result = ""
        } else {
-               result = repo.HTMLURL() + "/commit/" + commitID
+               result = repo.HTMLURL() + "/commit/" + url.PathEscape(commitID)
        }
        return
 }
 
 // APIURL returns the repository API URL
 func (repo *Repository) APIURL() string {
-       return setting.AppURL + "api/v1/repos/" + repo.FullName()
+       return setting.AppURL + "api/v1/repos/" + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(repo.Name)
 }
 
 // GetCommitsCountCacheKey returns cache key used for commits count caching.
@@ -709,19 +709,14 @@ func (repo *Repository) GitConfigPath() string {
        return GitConfigPath(repo.RepoPath())
 }
 
-// RelLink returns the repository relative link
-func (repo *Repository) RelLink() string {
-       return "/" + repo.FullName()
-}
-
 // Link returns the repository link
 func (repo *Repository) Link() string {
-       return setting.AppSubURL + "/" + repo.FullName()
+       return setting.AppSubURL + "/" + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(repo.Name)
 }
 
 // ComposeCompareURL returns the repository comparison URL
 func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string {
-       return fmt.Sprintf("%s/compare/%s...%s", repo.FullName(), oldCommitID, newCommitID)
+       return fmt.Sprintf("%s/%s/compare/%s...%s", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name), util.PathEscapeSegments(oldCommitID), util.PathEscapeSegments(newCommitID))
 }
 
 // UpdateDefaultBranch updates the default branch
@@ -930,11 +925,11 @@ func (repo *Repository) cloneLink(isWiki bool) *CloneLink {
        }
 
        if setting.SSH.Port != 22 {
-               cl.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, net.JoinHostPort(setting.SSH.Domain, strconv.Itoa(setting.SSH.Port)), repo.OwnerName, repoName)
+               cl.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, net.JoinHostPort(setting.SSH.Domain, strconv.Itoa(setting.SSH.Port)), url.PathEscape(repo.OwnerName), url.PathEscape(repoName))
        } else if setting.Repository.UseCompatSSHURI {
-               cl.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshDomain, repo.OwnerName, repoName)
+               cl.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshDomain, url.PathEscape(repo.OwnerName), url.PathEscape(repoName))
        } else {
-               cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshDomain, repo.OwnerName, repoName)
+               cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshDomain, url.PathEscape(repo.OwnerName), url.PathEscape(repoName))
        }
        cl.HTTPS = ComposeHTTPSCloneURL(repo.OwnerName, repoName)
        return cl
index 6c5e03c0d0d80b21ffbf34932cbe96445d1fc57a..aa1b3bc15f3ccec8fa8a6dd9a11e496922f32d7c 100644 (file)
@@ -10,6 +10,7 @@ import (
        "fmt"
        "image/png"
        "io"
+       "net/url"
        "strconv"
        "strings"
 
@@ -96,7 +97,7 @@ func (repo *Repository) relAvatarLink(e db.Engine) string {
                        return ""
                }
        }
-       return setting.AppSubURL + "/repo-avatars/" + repo.Avatar
+       return setting.AppSubURL + "/repo-avatars/" + url.PathEscape(repo.Avatar)
 }
 
 // AvatarLink returns a link to the repository's avatar.
index 12035dbe42375c5d891ffb341d8fc2934690ff8a..8146c184e70a3d3001f70c054fad9c26cca743b5 100644 (file)
@@ -13,6 +13,7 @@ import (
        "errors"
        "fmt"
        _ "image/jpeg" // Needed for jpeg support
+       "net/url"
        "os"
        "path/filepath"
        "regexp"
@@ -315,17 +316,17 @@ func (u *User) DashboardLink() string {
 
 // HomeLink returns the user or organization home page link.
 func (u *User) HomeLink() string {
-       return setting.AppSubURL + "/" + u.Name
+       return setting.AppSubURL + "/" + url.PathEscape(u.Name)
 }
 
 // HTMLURL returns the user or organization's full link.
 func (u *User) HTMLURL() string {
-       return setting.AppURL + u.Name
+       return setting.AppURL + url.PathEscape(u.Name)
 }
 
 // OrganisationLink returns the organization sub page link.
 func (u *User) OrganisationLink() string {
-       return setting.AppSubURL + "/org/" + u.Name
+       return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
 }
 
 // GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
index cb7131907eff593e2b724e51f7e91391c711a108..8adf1f306bd6d035f45673ffab6c582d10beff9f 100644 (file)
@@ -70,6 +70,16 @@ type Context struct {
        Org  *Organization
 }
 
+// TrHTMLEscapeArgs runs Tr but pre-escapes all arguments with html.EscapeString.
+// This is useful if the locale message is intended to only produce HTML content.
+func (ctx *Context) TrHTMLEscapeArgs(msg string, args ...string) string {
+       trArgs := make([]interface{}, len(args))
+       for i, arg := range args {
+               trArgs[i] = html.EscapeString(arg)
+       }
+       return ctx.Tr(msg, trArgs...)
+}
+
 // GetData returns the data
 func (ctx *Context) GetData() map[string]interface{} {
        return ctx.Data
@@ -120,9 +130,9 @@ func RedirectToUser(ctx *Context, userName string, redirectUserID int64) {
        }
 
        redirectPath := strings.Replace(
-               ctx.Req.URL.Path,
-               userName,
-               user.Name,
+               ctx.Req.URL.EscapedPath(),
+               url.PathEscape(userName),
+               url.PathEscape(user.Name),
                1,
        )
        if ctx.Req.URL.RawQuery != "" {
index d5763c78a366b2c6052355dcdb68ba30cc006836..3be33f2483808c7432ac2b1f58c7ce5ea516ab0f 100644 (file)
@@ -41,10 +41,10 @@ var IssueTemplateDirCandidates = []string{
 
 // PullRequest contains information to make a pull request
 type PullRequest struct {
-       BaseRepo *models.Repository
-       Allowed  bool
-       SameRepo bool
-       HeadInfo string // [<user>:]<branch>
+       BaseRepo       *models.Repository
+       Allowed        bool
+       SameRepo       bool
+       HeadInfoSubURL string // [<user>:]<branch> url segment
 }
 
 // Repository contains information to operate a repository
@@ -189,11 +189,11 @@ func (r *Repository) GetCommitGraphsCount(hidePRRefs bool, branches []string, fi
 func (r *Repository) BranchNameSubURL() string {
        switch {
        case r.IsViewBranch:
-               return "branch/" + r.BranchName
+               return "branch/" + util.PathEscapeSegments(r.BranchName)
        case r.IsViewTag:
-               return "tag/" + r.BranchName
+               return "tag/" + util.PathEscapeSegments(r.BranchName)
        case r.IsViewCommit:
-               return "commit/" + r.BranchName
+               return "commit/" + util.PathEscapeSegments(r.BranchName)
        }
        log.Error("Unknown view type for repo: %v", r)
        return ""
@@ -321,9 +321,9 @@ func RedirectToRepo(ctx *Context, redirectRepoID int64) {
        }
 
        redirectPath := strings.Replace(
-               ctx.Req.URL.Path,
-               fmt.Sprintf("%s/%s", ownerName, previousRepoName),
-               repo.FullName(),
+               ctx.Req.URL.EscapedPath(),
+               url.PathEscape(ownerName)+"/"+url.PathEscape(previousRepoName),
+               url.PathEscape(repo.OwnerName)+"/"+url.PathEscape(repo.Name),
                1,
        )
        if ctx.Req.URL.RawQuery != "" {
@@ -588,7 +588,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
                ctx.Data["BaseRepo"] = repo.BaseRepo
                ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo
                ctx.Repo.PullRequest.Allowed = canPush
-               ctx.Repo.PullRequest.HeadInfo = ctx.Repo.Owner.Name + ":" + ctx.Repo.BranchName
+               ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.Repo.Owner.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName)
        } else if repo.AllowsPulls() {
                // Or, this is repository accepts pull requests between branches.
                canCompare = true
@@ -596,7 +596,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
                ctx.Repo.PullRequest.BaseRepo = repo
                ctx.Repo.PullRequest.Allowed = canPush
                ctx.Repo.PullRequest.SameRepo = true
-               ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName
+               ctx.Repo.PullRequest.HeadInfoSubURL = util.PathEscapeSegments(ctx.Repo.BranchName)
        }
        ctx.Data["CanCompareOrPull"] = canCompare
        ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
@@ -621,7 +621,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 
        if ctx.FormString("go-get") == "1" {
                ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name)
-               prefix := setting.AppURL + path.Join(owner.Name, repo.Name, "src", "branch", ctx.Repo.BranchName)
+               prefix := repo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName)
                ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
                ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
        }
@@ -810,7 +810,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
                        if isRenamedBranch && has {
                                renamedBranchName := ctx.Data["RenamedBranchName"].(string)
                                ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refName, renamedBranchName))
-                               link := strings.Replace(ctx.Req.RequestURI, refName, renamedBranchName, 1)
+                               link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refName), util.PathEscapeSegments(renamedBranchName), 1)
                                ctx.Redirect(link)
                                return
                        }
@@ -845,7 +845,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
                                // If short commit ID add canonical link header
                                if len(refName) < 40 {
                                        ctx.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"",
-                                               util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), refName, ctx.Repo.Commit.ID.String(), 1))))
+                                               util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))))
                                }
                        } else {
                                if len(ignoreNotExistErr) > 0 && ignoreNotExistErr[0] {
@@ -857,11 +857,13 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
 
                        if refType == RepoRefLegacy {
                                // redirect from old URL scheme to new URL scheme
+                               prefix := strings.TrimPrefix(setting.AppSubURL+strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*")), ctx.Repo.RepoLink)
+
                                ctx.Redirect(path.Join(
-                                       setting.AppSubURL,
-                                       strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*")),
+                                       ctx.Repo.RepoLink,
+                                       util.PathEscapeSegments(prefix),
                                        ctx.Repo.BranchNameSubURL(),
-                                       ctx.Repo.TreePath))
+                                       util.PathEscapeSegments(ctx.Repo.TreePath)))
                                return
                        }
                }
index 9f43bb82f8a7b7401c91e3c0e54ee20216a8b83f..9905b51fe4532b8d16b3e3ab96e5c6afad29e0d4 100644 (file)
@@ -5,6 +5,7 @@
 package convert
 
 import (
+       "net/url"
        "time"
 
        "code.gitea.io/gitea/models"
@@ -126,7 +127,7 @@ func ToCommit(repo *models.Repository, commit *git.Commit, userCache map[string]
        for i := 0; i < commit.ParentCount(); i++ {
                sha, _ := commit.ParentID(i)
                apiParents[i] = &api.CommitMeta{
-                       URL: repo.APIURL() + "/git/commits/" + sha.String(),
+                       URL: repo.APIURL() + "/git/commits/" + url.PathEscape(sha.String()),
                        SHA: sha.String(),
                }
        }
@@ -147,13 +148,13 @@ func ToCommit(repo *models.Repository, commit *git.Commit, userCache map[string]
 
        return &api.Commit{
                CommitMeta: &api.CommitMeta{
-                       URL:     repo.APIURL() + "/git/commits/" + commit.ID.String(),
+                       URL:     repo.APIURL() + "/git/commits/" + url.PathEscape(commit.ID.String()),
                        SHA:     commit.ID.String(),
                        Created: commit.Committer.When,
                },
-               HTMLURL: repo.HTMLURL() + "/commit/" + commit.ID.String(),
+               HTMLURL: repo.HTMLURL() + "/commit/" + url.PathEscape(commit.ID.String()),
                RepoCommit: &api.RepoCommit{
-                       URL: repo.APIURL() + "/git/commits/" + commit.ID.String(),
+                       URL: repo.APIURL() + "/git/commits/" + url.PathEscape(commit.ID.String()),
                        Author: &api.CommitUser{
                                Identity: api.Identity{
                                        Name:  commit.Author.Name,
@@ -170,7 +171,7 @@ func ToCommit(repo *models.Repository, commit *git.Commit, userCache map[string]
                        },
                        Message: commit.Message(),
                        Tree: &api.CommitMeta{
-                               URL:     repo.APIURL() + "/git/trees/" + commit.ID.String(),
+                               URL:     repo.APIURL() + "/git/trees/" + url.PathEscape(commit.ID.String()),
                                SHA:     commit.ID.String(),
                                Created: commit.Committer.When,
                        },
index 3974d460e0e5d306b29c321307c78b9e944556b4..7363cfb8fb8924dc9fcc4bffce63ab4b7ddb1dc8 100644 (file)
@@ -6,6 +6,7 @@ package convert
 
 import (
        "fmt"
+       "net/url"
        "strings"
 
        "code.gitea.io/gitea/models"
@@ -191,7 +192,7 @@ func ToLabel(label *models.Label, repo *models.Repository, org *models.User) *ap
                }
        } else { // BelongsToOrg
                if org != nil {
-                       result.URL = fmt.Sprintf("%sapi/v1/orgs/%s/labels/%d", setting.AppURL, org.Name, label.ID)
+                       result.URL = fmt.Sprintf("%sapi/v1/orgs/%s/labels/%d", setting.AppURL, url.PathEscape(org.Name), label.ID)
                } else {
                        log.Error("ToLabel did not get org to calculate url for label with id '%d'", label.ID)
                }
index fae7be1257d2da27223a50ff2ee65a7e2635fab1..5f4fef02b9e8418f1f12415f6d941956f2d19993 100644 (file)
@@ -5,6 +5,8 @@
 package convert
 
 import (
+       "net/url"
+
        "code.gitea.io/gitea/models"
        api "code.gitea.io/gitea/modules/structs"
 )
@@ -58,7 +60,7 @@ func ToNotificationThread(n *models.Notification) *api.NotificationThread {
                        }
                }
        case models.NotificationSourceCommit:
-               url := n.Repository.HTMLURL() + "/commit/" + n.CommitID
+               url := n.Repository.HTMLURL() + "/commit/" + url.PathEscape(n.CommitID)
                result.Subject = &api.NotificationSubject{
                        Type:    api.NotifySubjectCommit,
                        Title:   n.CommitID,
index 13926fba72df3b130970e64bda938223698f8d8d..6988f31a367fcf4b5b7ac14c494988acb07d8872 100644 (file)
@@ -11,6 +11,8 @@ import (
        "strconv"
        "strings"
        "sync"
+
+       "code.gitea.io/gitea/modules/util"
 )
 
 // ObjectCache provides thread-safe cache operations.
@@ -92,7 +94,7 @@ func RefEndName(refStr string) string {
 
 // RefURL returns the absolute URL for a ref in a repository
 func RefURL(repoURL, ref string) string {
-       refName := RefEndName(ref)
+       refName := util.PathEscapeSegments(RefEndName(ref))
        switch {
        case strings.HasPrefix(ref, BranchPrefix):
                return repoURL + "/src/branch/" + refName
index d7e3ff452588c3c81202137081accbe47649d3be..0bcdb8c3a1ac97b4e552bd499e4f2a6278903ff4 100644 (file)
@@ -7,6 +7,7 @@ package repofiles
 import (
        "fmt"
        "html"
+       "net/url"
        "regexp"
        "strconv"
        "strings"
@@ -175,7 +176,7 @@ func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*r
                                continue
                        }
 
-                       message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, html.EscapeString(strings.SplitN(c.Message, "\n", 2)[0]))
+                       message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, html.EscapeString(repo.Link()), html.EscapeString(url.PathEscape(c.Sha1)), html.EscapeString(strings.SplitN(c.Message, "\n", 2)[0]))
                        if err = models.CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil {
                                return err
                        }
index 60a05e280e8641d6efd866c67f9abe0cf3b6a248..02bc1ebcab93ac0eb63ab13da296d65b89a76ad9 100644 (file)
@@ -5,6 +5,8 @@
 package repofiles
 
 import (
+       "net/url"
+
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/git"
        "code.gitea.io/gitea/modules/setting"
@@ -31,7 +33,7 @@ func GetBlobBySHA(repo *models.Repository, sha string) (*api.GitBlobResponse, er
        }
        return &api.GitBlobResponse{
                SHA:      gitBlob.ID.String(),
-               URL:      repo.APIURL() + "/git/blobs/" + gitBlob.ID.String(),
+               URL:      repo.APIURL() + "/git/blobs/" + url.PathEscape(gitBlob.ID.String()),
                Size:     gitBlob.Size(),
                Encoding: "base64",
                Content:  content,
index abd14b1db817f6943ee718a34c0f9e2380cb47c2..403092401768a1d38b103b4602c6118a51cea68e 100644 (file)
@@ -36,19 +36,19 @@ func GetFileCommitResponse(repo *models.Repository, commit *git.Commit) (*api.Fi
        if commit == nil {
                return nil, fmt.Errorf("commit cannot be nil")
        }
-       commitURL, _ := url.Parse(repo.APIURL() + "/git/commits/" + commit.ID.String())
-       commitTreeURL, _ := url.Parse(repo.APIURL() + "/git/trees/" + commit.Tree.ID.String())
+       commitURL, _ := url.Parse(repo.APIURL() + "/git/commits/" + url.PathEscape(commit.ID.String()))
+       commitTreeURL, _ := url.Parse(repo.APIURL() + "/git/trees/" + url.PathEscape(commit.Tree.ID.String()))
        parents := make([]*api.CommitMeta, commit.ParentCount())
        for i := 0; i <= commit.ParentCount(); i++ {
                if parent, err := commit.Parent(i); err == nil && parent != nil {
-                       parentCommitURL, _ := url.Parse(repo.APIURL() + "/git/commits/" + parent.ID.String())
+                       parentCommitURL, _ := url.Parse(repo.APIURL() + "/git/commits/" + url.PathEscape(parent.ID.String()))
                        parents[i] = &api.CommitMeta{
                                SHA: parent.ID.String(),
                                URL: parentCommitURL.String(),
                        }
                }
        }
-       commitHTMLURL, _ := url.Parse(repo.HTMLURL() + "/commit/" + commit.ID.String())
+       commitHTMLURL, _ := url.Parse(repo.HTMLURL() + "/commit/" + url.PathEscape(commit.ID.String()))
        fileCommit := &api.FileCommitResponse{
                CommitMeta: api.CommitMeta{
                        SHA: commit.ID.String(),
index b3edea341f14c3f4ab3e49d6fb773cd590fd207b..81579dccc53a70b91cde439ddb5c25a8dd126124 100644 (file)
@@ -6,6 +6,7 @@ package repofiles
 
 import (
        "fmt"
+       "net/url"
 
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/git"
@@ -28,7 +29,7 @@ func GetTreeBySHA(repo *models.Repository, sha string, page, perPage int, recurs
        }
        tree := new(api.GitTreeResponse)
        tree.SHA = gitTree.ResolvedID.String()
-       tree.URL = repo.APIURL() + "/git/trees/" + tree.SHA
+       tree.URL = repo.APIURL() + "/git/trees/" + url.PathEscape(tree.SHA)
        var entries git.Entries
        if recursive {
                entries, err = gitTree.ListEntriesRecursive()
index c86f0d570be4fa2f11c17067f5cc4d193d5c3637..a545ce952ba771ccb1b6534a86cf1137790f8884 100644 (file)
@@ -6,6 +6,7 @@ package repository
 
 import (
        "fmt"
+       "net/url"
        "time"
 
        "code.gitea.io/gitea/models"
@@ -81,7 +82,7 @@ func (pc *PushCommits) toAPIPayloadCommit(repoPath, repoLink string, commit *Pus
        return &api.PayloadCommit{
                ID:      commit.Sha1,
                Message: commit.Message,
-               URL:     fmt.Sprintf("%s/commit/%s", repoLink, commit.Sha1),
+               URL:     fmt.Sprintf("%s/commit/%s", repoLink, url.PathEscape(commit.Sha1)),
                Author: &api.PayloadUser{
                        Name:     commit.AuthorName,
                        Email:    commit.AuthorEmail,
index 991816c10332d2ca0c0b3da63aac1a4d6bffe0c9..8b46ed40cec8e35c2f7e0aaf9da9f336bf519dcc 100644 (file)
@@ -139,17 +139,14 @@ func NewFuncMap() []template.FuncMap {
                        }
                        return str[start:end]
                },
-               "EllipsisString":        base.EllipsisString,
-               "DiffTypeToStr":         DiffTypeToStr,
-               "DiffLineTypeToStr":     DiffLineTypeToStr,
-               "Sha1":                  Sha1,
-               "ShortSha":              base.ShortSha,
-               "MD5":                   base.EncodeMD5,
-               "ActionContent2Commits": ActionContent2Commits,
-               "PathEscape":            url.PathEscape,
-               "EscapePound": func(str string) string {
-                       return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
-               },
+               "EllipsisString":                 base.EllipsisString,
+               "DiffTypeToStr":                  DiffTypeToStr,
+               "DiffLineTypeToStr":              DiffLineTypeToStr,
+               "Sha1":                           Sha1,
+               "ShortSha":                       base.ShortSha,
+               "MD5":                            base.EncodeMD5,
+               "ActionContent2Commits":          ActionContent2Commits,
+               "PathEscape":                     url.PathEscape,
                "PathEscapeSegments":             util.PathEscapeSegments,
                "URLJoin":                        util.URLJoin,
                "RenderCommitMessage":            RenderCommitMessage,
@@ -742,7 +739,7 @@ func ReactionToEmoji(reaction string) template.HTML {
        if val != nil {
                return template.HTML(val.Emoji)
        }
-       return template.HTML(fmt.Sprintf(`<img alt=":%s:" src="%s/assets/img/emoji/%s.png"></img>`, reaction, setting.StaticURLPrefix, reaction))
+       return template.HTML(fmt.Sprintf(`<img alt=":%s:" src="%s/assets/img/emoji/%s.png"></img>`, reaction, setting.StaticURLPrefix, url.PathEscape(reaction)))
 }
 
 // RenderNote renders the contents of a git-notes file as a commit message.
index e430a5d8b3c22c587f45132391e91695afc30d44..097facb4d5fad902bb811ead33dcb1c588629798 100644 (file)
@@ -6,6 +6,7 @@ package upload
 
 import (
        "net/http"
+       "net/url"
        "path"
        "regexp"
        "strings"
@@ -83,7 +84,7 @@ func AddUploadContext(ctx *context.Context, uploadType string) {
                ctx.Data["UploadUrl"] = ctx.Repo.RepoLink + "/issues/attachments"
                ctx.Data["UploadRemoveUrl"] = ctx.Repo.RepoLink + "/issues/attachments/remove"
                if len(ctx.Params(":index")) > 0 {
-                       ctx.Data["UploadLinkUrl"] = ctx.Repo.RepoLink + "/issues/" + ctx.Params(":index") + "/attachments"
+                       ctx.Data["UploadLinkUrl"] = ctx.Repo.RepoLink + "/issues/" + url.PathEscape(ctx.Params(":index")) + "/attachments"
                } else {
                        ctx.Data["UploadLinkUrl"] = ctx.Repo.RepoLink + "/issues/attachments"
                }
index af6887640819eec7bb8602d85557ab1c010fea3a..c39063e46e7529b329e424ee2f93cc0467630916 100644 (file)
@@ -1409,7 +1409,7 @@ pulls.filter_branch = Filter branch
 pulls.no_results = No results found.
 pulls.nothing_to_compare = These branches are equal. There is no need to create a pull request.
 pulls.nothing_to_compare_and_allow_empty_pr = These branches are equal. This PR will be empty.
-pulls.has_pull_request = `A pull request between these branches already exists: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
+pulls.has_pull_request = `A pull request between these branches already exists: <a href="%[1]s">%[2]s#%[3]d</a>`
 pulls.create = Create Pull Request
 pulls.title_desc = wants to merge %[1]d commits from <code>%[2]s</code> into <code id="branch_target">%[3]s</code>
 pulls.merged_title_desc = merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s
@@ -2761,32 +2761,32 @@ notices.delete_success = The system notices have been deleted.
 [action]
 create_repo = created repository <a href="%s">%s</a>
 rename_repo = renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
-commit_repo = pushed to <a href="%[1]s/src/branch/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
-create_issue = `opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
-close_issue = `closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
-reopen_issue = `reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
-create_pull_request = `created pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
-close_pull_request = `closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
-reopen_pull_request = `reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
-comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
-comment_pull = `commented on pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
-merge_pull_request = `merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
+commit_repo = pushed to <a href="%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
+create_issue = `opened issue <a href="%[1]s">%[3]s#%[2]s</a>`
+close_issue = `closed issue <a href="%[1]s">%[3]s#%[2]s</a>`
+reopen_issue = `reopened issue <a href="%[1]s">%[3]s#%[2]s</a>`
+create_pull_request = `created pull request <a href="%[1]s">%[3]s#%[2]s</a>`
+close_pull_request = `closed pull request <a href="%[1]s">%[3]s#%[2]s</a>`
+reopen_pull_request = `reopened pull request <a href="%[1]s">%[3]s#%[2]s</a>`
+comment_issue = `commented on issue <a href="%[1]s">%[3]s#%[2]s</a>`
+comment_pull = `commented on pull request <a href="%[1]s">%[3]s#%[2]s</a>`
+merge_pull_request = `merged pull request <a href="%[1]s">%[3]s#%[2]s</a>`
 transfer_repo = transferred repository <code>%s</code> to <a href="%s">%s</a>
-push_tag = pushed tag <a href="%s/src/tag/%s">%[4]s</a> to <a href="%[1]s">%[3]s</a>
+push_tag = pushed tag <a href="%[2]s">%[3]s</a> to <a href="%[1]s">%[4]s</a>
 delete_tag = deleted tag %[2]s from <a href="%[1]s">%[3]s</a>
 delete_branch = deleted branch %[2]s from <a href="%[1]s">%[3]s</a>
 compare_branch = Compare
 compare_commits = Compare %d commits
 compare_commits_general = Compare commits
-mirror_sync_push = synced commits to <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a> from mirror
-mirror_sync_create = synced new reference <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a> from mirror
+mirror_sync_push = synced commits to <a href="%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a> from mirror
+mirror_sync_create = synced new reference <a href="%[2]s">%[3]s</a> to <a href="%[1]s">%[4]s</a> from mirror
 mirror_sync_delete = synced and deleted reference <code>%[2]s</code> at <a href="%[1]s">%[3]s</a> from mirror
-approve_pull_request = `approved <a href="%s/pulls/%s">%s#%[2]s</a>`
-reject_pull_request = `suggested changes for <a href="%s/pulls/%s">%s#%[2]s</a>`
-publish_release  = `released <a href="%s/releases/tag/%s"> "%[4]s" </a> at <a href="%[1]s">%[3]s</a>`
-review_dismissed = `dismissed review from <b>%[4]s</b> for <a href="%[1]s/pulls/%[2]s">%[3]s#%[2]s</a>`
+approve_pull_request = `approved <a href="%[1]s">%[3]s#%[2]s</a>`
+reject_pull_request = `suggested changes for <a href="%[1]s">%[3]s#%[2]s</a>`
+publish_release  = `released <a href="%[2]s"> "%[4]s" </a> at <a href="%[1]s">%[3]s</a>`
+review_dismissed = `dismissed review from <b>%[4]s</b> for <a href="%[1]s">%[3]s#%[2]s</a>`
 review_dismissed_reason = Reason:
-create_branch = created branch <a href="%[1]s/src/branch/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>
+create_branch = created branch <a href="%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>
 starred_repo = starred <a href="%[1]s">%[2]s</a>
 watched_repo = started watching <a href="%[1]s">%[2]s</a>
 
index a6f140c38f65ec129b8000174f39ce11ce04fcf0..4530349f2c20c8df38188b0f1370e52ae0e7daca 100644 (file)
@@ -6,6 +6,7 @@ package org
 
 import (
        "net/http"
+       "net/url"
 
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/context"
@@ -159,7 +160,7 @@ func IsMember(ctx *context.APIContext) {
                }
        }
 
-       redirectURL := setting.AppSubURL + "/api/v1/orgs/" + ctx.Org.Organization.Name + "/public_members/" + userToCheck.Name
+       redirectURL := setting.AppSubURL + "/api/v1/orgs/" + url.PathEscape(ctx.Org.Organization.Name) + "/public_members/" + url.PathEscape(userToCheck.Name)
        ctx.Redirect(redirectURL, 302)
 }
 
index e304e06740bea96a1c8949d460fcfe0d41d13064..29b126db9a49a06278d6beea096b257ea161e960 100644 (file)
@@ -6,9 +6,11 @@ package repo
 
 import (
        "net/http"
+       "net/url"
 
        "code.gitea.io/gitea/modules/context"
        api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/util"
        "code.gitea.io/gitea/routers/api/v1/utils"
 )
 
@@ -89,11 +91,11 @@ func getGitRefsInternal(ctx *context.APIContext, filter string) {
        for i := range refs {
                apiRefs[i] = &api.Reference{
                        Ref: refs[i].Name,
-                       URL: ctx.Repo.Repository.APIURL() + "/git/" + refs[i].Name,
+                       URL: ctx.Repo.Repository.APIURL() + "/git/" + util.PathEscapeSegments(refs[i].Name),
                        Object: &api.GitObject{
                                SHA:  refs[i].Object.String(),
                                Type: refs[i].Type,
-                               URL:  ctx.Repo.Repository.APIURL() + "/git/" + refs[i].Type + "s/" + refs[i].Object.String(),
+                               URL:  ctx.Repo.Repository.APIURL() + "/git/" + url.PathEscape(refs[i].Type) + "s/" + url.PathEscape(refs[i].Object.String()),
                        },
                }
        }
index 98ee2b4de5cfd5cb364b89991cb00d7a4f2fdd85..c20a4776cc06455f363ddd65ff1e73babc220b76 100644 (file)
@@ -8,6 +8,7 @@ package repo
 import (
        "fmt"
        "net/http"
+       "net/url"
 
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/context"
@@ -33,8 +34,8 @@ func appendPrivateInformation(apiKey *api.DeployKey, key *models.DeployKey, repo
        return apiKey, nil
 }
 
-func composeDeployKeysAPILink(repoPath string) string {
-       return setting.AppURL + "api/v1/repos/" + repoPath + "/keys/"
+func composeDeployKeysAPILink(owner, name string) string {
+       return setting.AppURL + "api/v1/repos/" + url.PathEscape(owner) + "/" + url.PathEscape(name) + "/keys/"
 }
 
 // ListDeployKeys list all the deploy keys of a repository
@@ -94,7 +95,7 @@ func ListDeployKeys(ctx *context.APIContext) {
                return
        }
 
-       apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
+       apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
        apiKeys := make([]*api.DeployKey, len(keys))
        for i := range keys {
                if err := keys[i].GetContent(); err != nil {
@@ -154,7 +155,7 @@ func GetDeployKey(ctx *context.APIContext) {
                return
        }
 
-       apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
+       apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
        apiKey := convert.ToDeployKey(apiLink, key)
        if ctx.User.IsAdmin || ((ctx.Repo.Repository.ID == key.RepoID) && (ctx.User.ID == ctx.Repo.Owner.ID)) {
                apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Repo.Repository)
@@ -233,7 +234,7 @@ func CreateDeployKey(ctx *context.APIContext) {
        }
 
        key.Content = content
-       apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
+       apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
        ctx.JSON(http.StatusCreated, convert.ToDeployKey(apiLink, key))
 }
 
index 460b740171c21b6c1e0be3eee750e25703fa41d6..5fd15b5c5a9e0836d9d862815451f1cab8a77919 100644 (file)
@@ -8,7 +8,9 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "net/url"
        "regexp"
+       "strconv"
 
        "code.gitea.io/gitea/models/login"
        "code.gitea.io/gitea/modules/auth/pam"
@@ -396,7 +398,7 @@ func EditAuthSourcePost(ctx *context.Context) {
        log.Trace("Authentication changed by admin(%s): %d", ctx.User.Name, source.ID)
 
        ctx.Flash.Success(ctx.Tr("admin.auths.update_success"))
-       ctx.Redirect(setting.AppSubURL + "/admin/auths/" + fmt.Sprint(form.ID))
+       ctx.Redirect(setting.AppSubURL + "/admin/auths/" + strconv.FormatInt(form.ID, 10))
 }
 
 // DeleteAuthSource response for deleting an auth source
@@ -414,7 +416,7 @@ func DeleteAuthSource(ctx *context.Context) {
                        ctx.Flash.Error(fmt.Sprintf("DeleteLoginSource: %v", err))
                }
                ctx.JSON(http.StatusOK, map[string]interface{}{
-                       "redirect": setting.AppSubURL + "/admin/auths/" + ctx.Params(":authid"),
+                       "redirect": setting.AppSubURL + "/admin/auths/" + url.PathEscape(ctx.Params(":authid")),
                })
                return
        }
index a13f7317e4cb358e111219fd94e21d81df4ab2ac..432dd2f6ae60706d3c5fba8881f5dcb22ef984d4 100644 (file)
@@ -58,7 +58,7 @@ func DeleteRepo(ctx *context.Context) {
 
        ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success"))
        ctx.JSON(http.StatusOK, map[string]interface{}{
-               "redirect": setting.AppSubURL + "/admin/repos?page=" + ctx.FormString("page") + "&sort=" + ctx.FormString("sort"),
+               "redirect": setting.AppSubURL + "/admin/repos?page=" + url.QueryEscape(ctx.FormString("page")) + "&sort=" + url.QueryEscape(ctx.FormString("sort")),
        })
 }
 
@@ -161,5 +161,5 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
                }
                ctx.Flash.Success(ctx.Tr("repo.delete_preexisting_success", dir))
        }
-       ctx.Redirect(setting.AppSubURL + "/admin/repos/unadopted?search=true&q=" + url.QueryEscape(q) + "&page=" + page)
+       ctx.Redirect(setting.AppSubURL + "/admin/repos/unadopted?search=true&q=" + url.QueryEscape(q) + "&page=" + url.QueryEscape(page))
 }
index db7fe7b36f6eee2f91c4ebcd9060e98efd9a1b5d..8bafd1f19c343279c222c2978e3389c873de1e81 100644 (file)
@@ -6,8 +6,8 @@
 package admin
 
 import (
-       "fmt"
        "net/http"
+       "net/url"
        "strconv"
        "strings"
 
@@ -188,7 +188,7 @@ func NewUserPost(ctx *context.Context) {
        }
 
        ctx.Flash.Success(ctx.Tr("admin.users.new_success", u.Name))
-       ctx.Redirect(setting.AppSubURL + "/admin/users/" + fmt.Sprint(u.ID))
+       ctx.Redirect(setting.AppSubURL + "/admin/users/" + strconv.FormatInt(u.ID, 10))
 }
 
 func prepareUserInfo(ctx *context.Context) *models.User {
@@ -366,7 +366,7 @@ func EditUserPost(ctx *context.Context) {
        log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
 
        ctx.Flash.Success(ctx.Tr("admin.users.update_profile_success"))
-       ctx.Redirect(setting.AppSubURL + "/admin/users/" + ctx.Params(":userid"))
+       ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.Params(":userid")))
 }
 
 // DeleteUser response for deleting a user
@@ -382,12 +382,12 @@ func DeleteUser(ctx *context.Context) {
                case models.IsErrUserOwnRepos(err):
                        ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo"))
                        ctx.JSON(http.StatusOK, map[string]interface{}{
-                               "redirect": setting.AppSubURL + "/admin/users/" + ctx.Params(":userid"),
+                               "redirect": setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.Params(":userid")),
                        })
                case models.IsErrUserHasOrgs(err):
                        ctx.Flash.Error(ctx.Tr("admin.users.still_has_org"))
                        ctx.JSON(http.StatusOK, map[string]interface{}{
-                               "redirect": setting.AppSubURL + "/admin/users/" + ctx.Params(":userid"),
+                               "redirect": setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.Params(":userid")),
                        })
                default:
                        ctx.ServerError("DeleteUser", err)
index dfb03785a64382855f22cda877ca3e107dbb7dec..4743668621dd436a2f154b78653a77109fb0aa24 100644 (file)
@@ -15,10 +15,35 @@ import (
        "code.gitea.io/gitea/modules/context"
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/templates"
+       "code.gitea.io/gitea/modules/util"
 
        "github.com/gorilla/feeds"
 )
 
+func toBranchLink(act *models.Action) string {
+       return act.GetRepoLink() + "/src/branch/" + util.PathEscapeSegments(act.GetBranch())
+}
+
+func toTagLink(act *models.Action) string {
+       return act.GetRepoLink() + "/src/tag/" + util.PathEscapeSegments(act.GetTag())
+}
+
+func toIssueLink(act *models.Action) string {
+       return act.GetRepoLink() + "/issues/" + url.PathEscape(act.GetIssueInfos()[0])
+}
+
+func toPullLink(act *models.Action) string {
+       return act.GetRepoLink() + "/pulls/" + url.PathEscape(act.GetIssueInfos()[0])
+}
+
+func toSrcLink(act *models.Action) string {
+       return act.GetRepoLink() + "/src/" + util.PathEscapeSegments(act.GetBranch())
+}
+
+func toReleaseLink(act *models.Action) string {
+       return act.GetRepoLink() + "/releases/tag/" + util.PathEscapeSegments(act.GetBranch())
+}
+
 // feedActionsToFeedItems convert gitea's Action feed to feeds Item
 func feedActionsToFeedItems(ctx *context.Context, actions []*models.Action) (items []*feeds.Item, err error) {
        for _, act := range actions {
@@ -32,62 +57,111 @@ func feedActionsToFeedItems(ctx *context.Context, actions []*models.Action) (ite
                title = act.ActUser.DisplayName() + " "
                switch act.OpType {
                case models.ActionCreateRepo:
-                       title += ctx.Tr("action.create_repo", act.GetRepoLink(), act.ShortRepoPath())
+                       title += ctx.TrHTMLEscapeArgs("action.create_repo", act.GetRepoLink(), act.ShortRepoPath())
+                       link.Href = act.GetRepoLink()
                case models.ActionRenameRepo:
-                       title += ctx.Tr("action.rename_repo", act.GetContent(), act.GetRepoLink(), act.ShortRepoPath())
+                       title += ctx.TrHTMLEscapeArgs("action.rename_repo", act.GetContent(), act.GetRepoLink(), act.ShortRepoPath())
+                       link.Href = act.GetRepoLink()
                case models.ActionCommitRepo:
-                       branchLink := act.GetBranch()
+                       link.Href = toBranchLink(act)
                        if len(act.Content) != 0 {
-                               title += ctx.Tr("action.commit_repo", act.GetRepoLink(), branchLink, act.GetBranch(), act.ShortRepoPath())
+                               title += ctx.TrHTMLEscapeArgs("action.commit_repo", act.GetRepoLink(), link.Href, act.GetBranch(), act.ShortRepoPath())
                        } else {
-                               title += ctx.Tr("action.create_branch", act.GetRepoLink(), branchLink, act.GetBranch(), act.ShortRepoPath())
+                               title += ctx.TrHTMLEscapeArgs("action.create_branch", act.GetRepoLink(), link.Href, act.GetBranch(), act.ShortRepoPath())
                        }
                case models.ActionCreateIssue:
-                       title += ctx.Tr("action.create_issue", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       link.Href = toIssueLink(act)
+                       title += ctx.TrHTMLEscapeArgs("action.create_issue", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionCreatePullRequest:
-                       title += ctx.Tr("action.create_pull_request", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       link.Href = toPullLink(act)
+                       title += ctx.TrHTMLEscapeArgs("action.create_pull_request", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionTransferRepo:
-                       title += ctx.Tr("action.transfer_repo", act.GetContent(), act.GetRepoLink(), act.ShortRepoPath())
+                       link.Href = act.GetRepoLink()
+                       title += ctx.TrHTMLEscapeArgs("action.transfer_repo", act.GetContent(), act.GetRepoLink(), act.ShortRepoPath())
                case models.ActionPushTag:
-                       title += ctx.Tr("action.push_tag", act.GetRepoLink(), url.QueryEscape(act.GetTag()), act.ShortRepoPath())
+                       link.Href = toTagLink(act)
+                       title += ctx.TrHTMLEscapeArgs("action.push_tag", act.GetRepoLink(), link.Href, act.GetTag(), act.ShortRepoPath())
                case models.ActionCommentIssue:
-                       title += ctx.Tr("action.comment_issue", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       issueLink := toIssueLink(act)
+                       if link.Href == "#" {
+                               link.Href = issueLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.comment_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionMergePullRequest:
-                       title += ctx.Tr("action.merge_pull_request", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       pullLink := toPullLink(act)
+                       if link.Href == "#" {
+                               link.Href = pullLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionCloseIssue:
-                       title += ctx.Tr("action.close_issue", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       issueLink := toIssueLink(act)
+                       if link.Href == "#" {
+                               link.Href = issueLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.close_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionReopenIssue:
-                       title += ctx.Tr("action.reopen_issue", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       issueLink := toIssueLink(act)
+                       if link.Href == "#" {
+                               link.Href = issueLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.reopen_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionClosePullRequest:
-                       title += ctx.Tr("action.close_pull_request", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       pullLink := toPullLink(act)
+                       if link.Href == "#" {
+                               link.Href = pullLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.close_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionReopenPullRequest:
-                       title += ctx.Tr("action.reopen_pull_request", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath)
+                       pullLink := toPullLink(act)
+                       if link.Href == "#" {
+                               link.Href = pullLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.reopen_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionDeleteTag:
-                       title += ctx.Tr("action.delete_tag", act.GetRepoLink(), html.EscapeString(act.GetTag()), act.ShortRepoPath())
+                       link.Href = act.GetRepoLink()
+                       title += ctx.TrHTMLEscapeArgs("action.delete_tag", act.GetRepoLink(), act.GetTag(), act.ShortRepoPath())
                case models.ActionDeleteBranch:
-                       title += ctx.Tr("action.delete_branch", act.GetRepoLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath())
+                       link.Href = act.GetRepoLink()
+                       title += ctx.TrHTMLEscapeArgs("action.delete_branch", act.GetRepoLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath())
                case models.ActionMirrorSyncPush:
-                       title += ctx.Tr("action.mirror_sync_push", act.GetRepoLink(), url.QueryEscape(act.GetBranch()), html.EscapeString(act.GetBranch()), act.ShortRepoPath())
+                       srcLink := toSrcLink(act)
+                       if link.Href == "#" {
+                               link.Href = srcLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.mirror_sync_push", act.GetRepoLink(), srcLink, act.GetBranch(), act.ShortRepoPath())
                case models.ActionMirrorSyncCreate:
-                       title += ctx.Tr("action.mirror_sync_create", act.GetRepoLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath())
+                       srcLink := toSrcLink(act)
+                       if link.Href == "#" {
+                               link.Href = srcLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.mirror_sync_create", act.GetRepoLink(), srcLink, act.GetBranch(), act.ShortRepoPath())
                case models.ActionMirrorSyncDelete:
-                       title += ctx.Tr("action.mirror_sync_delete", act.GetRepoLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath())
+                       link.Href = act.GetRepoLink()
+                       title += ctx.TrHTMLEscapeArgs("action.mirror_sync_delete", act.GetRepoLink(), act.GetBranch(), act.ShortRepoPath())
                case models.ActionApprovePullRequest:
-                       title += ctx.Tr("action.approve_pull_request", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       pullLink := toPullLink(act)
+                       title += ctx.TrHTMLEscapeArgs("action.approve_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionRejectPullRequest:
-                       title += ctx.Tr("action.reject_pull_request", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       pullLink := toPullLink(act)
+                       title += ctx.TrHTMLEscapeArgs("action.reject_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionCommentPull:
-                       title += ctx.Tr("action.comment_pull", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath())
+                       pullLink := toPullLink(act)
+                       title += ctx.TrHTMLEscapeArgs("action.comment_pull", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
                case models.ActionPublishRelease:
-                       title += ctx.Tr("action.publish_release", act.GetRepoLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath(), act.Content)
+                       releaseLink := toReleaseLink(act)
+                       if link.Href == "#" {
+                               link.Href = releaseLink
+                       }
+                       title += ctx.TrHTMLEscapeArgs("action.publish_release", act.GetRepoLink(), releaseLink, act.ShortRepoPath(), act.Content)
                case models.ActionPullReviewDismissed:
-                       title += ctx.Tr("action.review_dismissed", act.GetRepoLink(), act.GetIssueInfos()[0], act.ShortRepoPath(), act.GetIssueInfos()[1])
+                       pullLink := toPullLink(act)
+                       title += ctx.TrHTMLEscapeArgs("action.review_dismissed", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(), act.GetIssueInfos()[1])
                case models.ActionStarRepo:
-                       title += ctx.Tr("action.starred_repo", act.GetRepoLink(), act.GetRepoPath())
-                       link = &feeds.Link{Href: act.GetRepoLink()}
+                       link.Href = act.GetRepoLink()
+                       title += ctx.TrHTMLEscapeArgs("action.starred_repo", act.GetRepoLink(), act.GetRepoPath())
                case models.ActionWatchRepo:
-                       title += ctx.Tr("action.watched_repo", act.GetRepoLink(), act.GetRepoPath())
-                       link = &feeds.Link{Href: act.GetRepoLink()}
+                       link.Href = act.GetRepoLink()
+                       title += ctx.TrHTMLEscapeArgs("action.watched_repo", act.GetRepoLink(), act.GetRepoPath())
                default:
                        return nil, fmt.Errorf("unknown action type: %v", act.OpType)
                }
@@ -104,7 +178,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions []*models.Action) (ite
                                                desc += "\n\n"
                                        }
                                        desc += fmt.Sprintf("<a href=\"%s\">%s</a>\n%s",
-                                               fmt.Sprintf("%s/commit/%s", act.GetRepoLink(), commit.Sha1),
+                                               html.EscapeString(fmt.Sprintf("%s/commit/%s", act.GetRepoLink(), commit.Sha1)),
                                                commit.Sha1,
                                                templates.RenderCommitMessage(commit.Message, repoLink, nil),
                                        )
index d8add77f66000b92f9f02e19ace4eb6cf47d78f4..53c31a1c6059eb767f3a91b8aeeb2d34869f743e 100644 (file)
@@ -7,6 +7,7 @@ package org
 
 import (
        "net/http"
+       "net/url"
        "strings"
 
        "code.gitea.io/gitea/models"
@@ -76,7 +77,7 @@ func SettingsPost(ctx *context.Context) {
                        return
                }
                // reset ctx.org.OrgLink with new name
-               ctx.Org.OrgLink = setting.AppSubURL + "/org/" + form.Name
+               ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(form.Name)
                log.Trace("Organization name changed: %s -> %s", org.Name, form.Name)
                nameChanged = false
        }
index 3fe97142ae2f590908ee233ac56b5f8cb9077219..2fc72f06208eeb8d03b2a74de1b5c704835a064c 100644 (file)
@@ -7,6 +7,7 @@ package org
 
 import (
        "net/http"
+       "net/url"
        "path"
        "strings"
 
@@ -105,7 +106,7 @@ func TeamsAction(ctx *context.Context) {
                }
                ctx.JSON(http.StatusOK,
                        map[string]interface{}{
-                               "redirect": ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName,
+                               "redirect": ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName),
                        })
                return
        case "add":
@@ -119,7 +120,7 @@ func TeamsAction(ctx *context.Context) {
                if err != nil {
                        if models.IsErrUserNotExist(err) {
                                ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
-                               ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName)
+                               ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName))
                        } else {
                                ctx.ServerError(" GetUserByName", err)
                        }
@@ -128,7 +129,7 @@ func TeamsAction(ctx *context.Context) {
 
                if u.IsOrganization() {
                        ctx.Flash.Error(ctx.Tr("form.cannot_add_org_to_team"))
-                       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName)
+                       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName))
                        return
                }
 
@@ -156,7 +157,7 @@ func TeamsAction(ctx *context.Context) {
 
        switch page {
        case "team":
-               ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName)
+               ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName))
        case "home":
                ctx.Redirect(ctx.Org.Organization.HomeLink())
        default:
@@ -181,7 +182,7 @@ func TeamsRepoAction(ctx *context.Context) {
                if err != nil {
                        if models.IsErrRepoNotExist(err) {
                                ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo"))
-                               ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories")
+                               ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName) + "/repositories")
                                return
                        }
                        ctx.ServerError("GetRepositoryByName", err)
@@ -204,11 +205,11 @@ func TeamsRepoAction(ctx *context.Context) {
 
        if action == "addall" || action == "removeall" {
                ctx.JSON(http.StatusOK, map[string]interface{}{
-                       "redirect": ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories",
+                       "redirect": ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName) + "/repositories",
                })
                return
        }
-       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories")
+       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName) + "/repositories")
 }
 
 // NewTeam render create new team page
@@ -273,7 +274,7 @@ func NewTeamPost(ctx *context.Context) {
                return
        }
        log.Trace("Team created: %s/%s", ctx.Org.Organization.Name, t.Name)
-       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + t.LowerName)
+       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(t.LowerName))
 }
 
 // TeamMembers render team members page
@@ -375,7 +376,7 @@ func EditTeamPost(ctx *context.Context) {
                }
                return
        }
-       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + t.LowerName)
+       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(t.LowerName))
 }
 
 // DeleteTeam response for the delete team request
index 3632d1846eaeb2a634ce7680177bfbb3ac74d9bc..110ec037e1dc3839f3ae31275201b5ac63f3a417 100644 (file)
@@ -8,6 +8,7 @@ import (
        "fmt"
        gotemplate "html/template"
        "net/http"
+       "net/url"
        "strings"
 
        "code.gitea.io/gitea/models"
@@ -17,6 +18,7 @@ import (
        "code.gitea.io/gitea/modules/highlight"
        "code.gitea.io/gitea/modules/templates"
        "code.gitea.io/gitea/modules/timeutil"
+       "code.gitea.io/gitea/modules/util"
 )
 
 const (
@@ -54,7 +56,7 @@ func RefBlame(ctx *context.Context) {
        rawLink := ctx.Repo.RepoLink + "/raw/" + ctx.Repo.BranchNameSubURL()
 
        if len(ctx.Repo.TreePath) > 0 {
-               treeLink += "/" + ctx.Repo.TreePath
+               treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
        }
 
        var treeNames []string
@@ -85,7 +87,7 @@ func RefBlame(ctx *context.Context) {
        ctx.Data["TreeNames"] = treeNames
        ctx.Data["BranchLink"] = branchLink
 
-       ctx.Data["RawFileLink"] = rawLink + "/" + ctx.Repo.TreePath
+       ctx.Data["RawFileLink"] = rawLink + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
        ctx.Data["PageIsViewCode"] = true
 
        ctx.Data["IsBlame"] = true
@@ -236,8 +238,8 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
                                br.RepoLink = repoLink
                                br.PartSha = part.Sha
                                br.PreviousSha = previousSha
-                               br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, previousSha, ctx.Repo.TreePath)
-                               br.CommitURL = fmt.Sprintf("%s/commit/%s", repoLink, part.Sha)
+                               br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, url.PathEscape(previousSha), util.PathEscapeSegments(ctx.Repo.TreePath))
+                               br.CommitURL = fmt.Sprintf("%s/commit/%s", repoLink, url.PathEscape(part.Sha))
                                br.CommitMessage = commit.CommitMessage
                                br.CommitSince = commitSince
                        }
index 4c0f94f15db7a9a6661c31e269e5318f8a34b5a3..06cce92417a2080a27701d6b77eb3c616f5e351d 100644 (file)
@@ -8,7 +8,6 @@ package repo
 import (
        "errors"
        "net/http"
-       "path"
        "strings"
 
        "code.gitea.io/gitea/models"
@@ -323,8 +322,7 @@ func Diff(ctx *context.Context) {
                        return
                }
        }
-       headTarget := path.Join(userName, repoName)
-       setCompareContext(ctx, parentCommit, commit, headTarget)
+       setCompareContext(ctx, parentCommit, commit, userName, repoName)
        ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
        ctx.Data["Commit"] = commit
        ctx.Data["Diff"] = diff
index 86ecc2bab1675da7ee07f7f9768f2feeb98e4ac6..01c324e9e9385f0e00784752b6089bff0af04efa 100644 (file)
@@ -12,7 +12,7 @@ import (
        "html"
        "io"
        "net/http"
-       "path"
+       "net/url"
        "path/filepath"
        "strings"
 
@@ -38,7 +38,7 @@ const (
 )
 
 // setCompareContext sets context data.
-func setCompareContext(ctx *context.Context, base *git.Commit, head *git.Commit, headTarget string) {
+func setCompareContext(ctx *context.Context, base *git.Commit, head *git.Commit, headOwner, headName string) {
        ctx.Data["BaseCommit"] = base
        ctx.Data["HeadCommit"] = head
 
@@ -54,22 +54,28 @@ func setCompareContext(ctx *context.Context, base *git.Commit, head *git.Commit,
                return blob
        }
 
-       setPathsCompareContext(ctx, base, head, headTarget)
+       setPathsCompareContext(ctx, base, head, headOwner, headName)
        setImageCompareContext(ctx)
        setCsvCompareContext(ctx)
 }
 
-// setPathsCompareContext sets context data for source and raw paths
-func setPathsCompareContext(ctx *context.Context, base *git.Commit, head *git.Commit, headTarget string) {
-       sourcePath := setting.AppSubURL + "/%s/src/commit/%s"
-       rawPath := setting.AppSubURL + "/%s/raw/commit/%s"
+// SourceCommitURL creates a relative URL for a commit in the given repository
+func SourceCommitURL(owner, name string, commit *git.Commit) string {
+       return setting.AppSubURL + "/" + url.PathEscape(owner) + "/" + url.PathEscape(name) + "/src/commit/" + url.PathEscape(commit.ID.String())
+}
 
-       ctx.Data["SourcePath"] = fmt.Sprintf(sourcePath, headTarget, head.ID)
-       ctx.Data["RawPath"] = fmt.Sprintf(rawPath, headTarget, head.ID)
+// RawCommitURL creates a relative URL for the raw commit in the given repository
+func RawCommitURL(owner, name string, commit *git.Commit) string {
+       return setting.AppSubURL + "/" + url.PathEscape(owner) + "/" + url.PathEscape(name) + "/raw/commit/" + url.PathEscape(commit.ID.String())
+}
+
+// setPathsCompareContext sets context data for source and raw paths
+func setPathsCompareContext(ctx *context.Context, base *git.Commit, head *git.Commit, headOwner, headName string) {
+       ctx.Data["SourcePath"] = SourceCommitURL(headOwner, headName, head)
+       ctx.Data["RawPath"] = RawCommitURL(headOwner, headName, head)
        if base != nil {
-               baseTarget := path.Join(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
-               ctx.Data["BeforeSourcePath"] = fmt.Sprintf(sourcePath, baseTarget, base.ID)
-               ctx.Data["BeforeRawPath"] = fmt.Sprintf(rawPath, baseTarget, base.ID)
+               ctx.Data["BeforeSourcePath"] = SourceCommitURL(headOwner, headName, head)
+               ctx.Data["BeforeRawPath"] = RawCommitURL(headOwner, headName, head)
        }
 }
 
@@ -619,8 +625,7 @@ func PrepareCompareDiff(
        ctx.Data["Username"] = ci.HeadUser.Name
        ctx.Data["Reponame"] = ci.HeadRepo.Name
 
-       headTarget := path.Join(ci.HeadUser.Name, repo.Name)
-       setCompareContext(ctx, baseCommit, headCommit, headTarget)
+       setCompareContext(ctx, baseCommit, headCommit, ci.HeadUser.Name, repo.Name)
 
        return false
 }
index d9f8c2009262af4961fe76aa190136a0f9832e65..088edbfd29b8d41b9dbee366c7c6191e2d80f0ab 100644 (file)
@@ -204,7 +204,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
        ctx.Data["TreePath"] = form.TreePath
        ctx.Data["TreeNames"] = treeNames
        ctx.Data["TreePaths"] = treePaths
-       ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/branch/" + ctx.Repo.BranchName
+       ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName)
        ctx.Data["FileContent"] = form.Content
        ctx.Data["commit_summary"] = form.CommitSummary
        ctx.Data["commit_message"] = form.CommitMessage
@@ -299,9 +299,9 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
                                ctx.Error(http.StatusInternalServerError, err.Error())
                        }
                } else if models.IsErrCommitIDDoesNotMatch(err) {
-                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplEditFile, &form)
+                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplEditFile, &form)
                } else if git.IsErrPushOutOfDate(err) {
-                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+util.PathEscapeSegments(form.NewBranchName)), tplEditFile, &form)
+                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(form.NewBranchName)), tplEditFile, &form)
                } else if git.IsErrPushRejected(err) {
                        errPushRej := err.(*git.ErrPushRejected)
                        if len(errPushRej.Message) == 0 {
@@ -495,7 +495,7 @@ func DeleteFilePost(ctx *context.Context) {
                                ctx.Error(http.StatusInternalServerError, err.Error())
                        }
                } else if models.IsErrCommitIDDoesNotMatch(err) || git.IsErrPushOutOfDate(err) {
-                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_deleting", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplDeleteFile, &form)
+                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_deleting", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplDeleteFile, &form)
                } else if git.IsErrPushRejected(err) {
                        errPushRej := err.(*git.ErrPushRejected)
                        if len(errPushRej.Message) == 0 {
@@ -602,7 +602,7 @@ func UploadFilePost(ctx *context.Context) {
        ctx.Data["TreePath"] = form.TreePath
        ctx.Data["TreeNames"] = treeNames
        ctx.Data["TreePaths"] = treePaths
-       ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/branch/" + branchName
+       ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName)
        ctx.Data["commit_summary"] = form.CommitSummary
        ctx.Data["commit_message"] = form.CommitMessage
        ctx.Data["commit_choice"] = form.CommitChoice
@@ -698,7 +698,7 @@ func UploadFilePost(ctx *context.Context) {
                        branchErr := err.(models.ErrBranchAlreadyExists)
                        ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplUploadFile, &form)
                } else if git.IsErrPushOutOfDate(err) {
-                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+ctx.Repo.CommitID+"..."+util.PathEscapeSegments(form.NewBranchName)), tplUploadFile, &form)
+                       ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(ctx.Repo.CommitID)+"..."+util.PathEscapeSegments(form.NewBranchName)), tplUploadFile, &form)
                } else if git.IsErrPushRejected(err) {
                        errPushRej := err.(*git.ErrPushRejected)
                        if len(errPushRej.Message) == 0 {
index d9e15a784fecfa9dadc794b70705dea2e37d86ad..95363258e9d554a45f7c59f58964b558ec1dc250 100644 (file)
@@ -11,6 +11,7 @@ import (
        "fmt"
        "io"
        "net/http"
+       "net/url"
        "path"
        "strconv"
        "strings"
@@ -106,7 +107,7 @@ func MustAllowPulls(ctx *context.Context) {
        // User can send pull request if owns a forked repository.
        if ctx.IsSigned && ctx.User.HasForkedRepo(ctx.Repo.Repository.ID) {
                ctx.Repo.PullRequest.Allowed = true
-               ctx.Repo.PullRequest.HeadInfo = ctx.User.Name + ":" + ctx.Repo.BranchName
+               ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.User.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName)
        }
 }
 
@@ -764,7 +765,7 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleDirs [
                                        for _, repoLabel := range repoLabels {
                                                if strings.EqualFold(repoLabel.Name, metaLabel) {
                                                        repoLabel.IsChecked = true
-                                                       labelIDs = append(labelIDs, fmt.Sprintf("%d", repoLabel.ID))
+                                                       labelIDs = append(labelIDs, strconv.FormatInt(repoLabel.ID, 10))
                                                        break
                                                }
                                        }
@@ -983,6 +984,7 @@ func NewIssuePost(ctx *context.Context) {
 
        issue := &models.Issue{
                RepoID:      repo.ID,
+               Repo:        repo,
                Title:       form.Title,
                PosterID:    ctx.User.ID,
                Poster:      ctx.User,
@@ -1009,9 +1011,9 @@ func NewIssuePost(ctx *context.Context) {
 
        log.Trace("Issue created: %d/%d", repo.ID, issue.ID)
        if ctx.FormString("redirect_after_creation") == "project" {
-               ctx.Redirect(ctx.Repo.RepoLink + "/projects/" + fmt.Sprint(form.ProjectID))
+               ctx.Redirect(ctx.Repo.RepoLink + "/projects/" + strconv.FormatInt(form.ProjectID, 10))
        } else {
-               ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + fmt.Sprint(issue.Index))
+               ctx.Redirect(issue.Link())
        }
 }
 
@@ -1097,13 +1099,16 @@ func ViewIssue(ctx *context.Context) {
                }
                return
        }
+       if issue.Repo == nil {
+               issue.Repo = ctx.Repo.Repository
+       }
 
        // Make sure type and URL matches.
        if ctx.Params(":type") == "issues" && issue.IsPull {
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        } else if ctx.Params(":type") == "pulls" && !issue.IsPull {
-               ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + fmt.Sprint(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
@@ -1496,7 +1501,7 @@ func ViewIssue(ctx *context.Context) {
                                                log.Error("IsProtectedBranch: %v", err)
                                        } else if !protected {
                                                canDelete = true
-                                               ctx.Data["DeleteBranchLink"] = ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index) + "/cleanup"
+                                               ctx.Data["DeleteBranchLink"] = issue.Link() + "/cleanup"
                                        }
                                }
                        }
@@ -1624,7 +1629,7 @@ func ViewIssue(ctx *context.Context) {
        ctx.Data["NumParticipants"] = len(participants)
        ctx.Data["Issue"] = issue
        ctx.Data["ReadOnly"] = false
-       ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + ctx.Data["Link"].(string)
+       ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + url.QueryEscape(ctx.Data["Link"].(string))
        ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.User.ID)
        ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
        ctx.Data["HasProjectsWritePermission"] = ctx.Repo.CanWrite(unit.TypeProjects)
@@ -1773,7 +1778,7 @@ func UpdateIssueContent(ctx *context.Context) {
        }
 
        content, err := markdown.RenderString(&markup.RenderContext{
-               URLPrefix: ctx.FormString("context"),
+               URLPrefix: ctx.FormString("context"), // FIXME: <- IS THIS SAFE ?
                Metas:     ctx.Repo.Repository.ComposeMetas(),
                GitRepo:   ctx.Repo.GitRepo,
                Ctx:       ctx,
@@ -2205,7 +2210,7 @@ func UpdateCommentContent(ctx *context.Context) {
        }
 
        content, err := markdown.RenderString(&markup.RenderContext{
-               URLPrefix: ctx.FormString("context"),
+               URLPrefix: ctx.FormString("context"), // FIXME: <- IS THIS SAFE ?
                Metas:     ctx.Repo.Repository.ComposeMetas(),
                GitRepo:   ctx.Repo.GitRepo,
                Ctx:       ctx,
index b8efb3b8413633b4a0c75f5fd0156087d90c12b4..0e9405fde4dbdd79ceb73549d08d0f3fbb2f302b 100644 (file)
@@ -94,6 +94,7 @@ func GetActiveStopwatch(c *context.Context) {
        }
 
        c.Data["ActiveStopwatch"] = StopwatchTmplInfo{
+               issue.Link(),
                issue.Repo.FullName(),
                issue.Index,
                sw.Seconds() + 1, // ensure time is never zero in ui
@@ -102,6 +103,7 @@ func GetActiveStopwatch(c *context.Context) {
 
 // StopwatchTmplInfo is a view on a stopwatch specifically for template rendering
 type StopwatchTmplInfo struct {
+       IssueLink  string
        RepoSlug   string
        IssueIndex int64
        Seconds    int64
index 5e24cfa3c0a88a52d3a6c362e103a718eeb9b56b..b15c7628db6ed9f707005ebfd06144674178a507 100644 (file)
@@ -10,6 +10,7 @@ import (
        gotemplate "html/template"
        "io"
        "net/http"
+       "net/url"
        "path"
        "strconv"
        "strings"
@@ -285,7 +286,7 @@ func LFSFileGet(ctx *context.Context) {
 
        fileSize := meta.Size
        ctx.Data["FileSize"] = meta.Size
-       ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s.git/info/lfs/objects/%s/%s", setting.AppURL, ctx.Repo.Repository.FullName(), meta.Oid, "direct")
+       ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s/%s.git/info/lfs/objects/%s/%s", setting.AppURL, url.PathEscape(ctx.Repo.Repository.OwnerName), url.PathEscape(ctx.Repo.Repository.Name), url.PathEscape(meta.Oid), "direct")
        switch {
        case isRepresentableAsText:
                if st.IsSvgImage() {
index d5e0a7696bcf8665d62a97ef53086b814f1bd8ee..f91c344e94b8c82fa5af63812a051e7904efa15b 100644 (file)
@@ -7,6 +7,7 @@ package repo
 
 import (
        "net/http"
+       "net/url"
        "strings"
 
        "code.gitea.io/gitea/models"
@@ -237,7 +238,7 @@ func MigratePost(ctx *context.Context) {
 
        err = task.MigrateRepository(ctx.User, ctxUser, opts)
        if err == nil {
-               ctx.Redirect(ctxUser.HomeLink() + "/" + opts.RepoName)
+               ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(opts.RepoName))
                return
        }
 
index 21e1fb2eab8d9b9a161ffd240e10ee58c74168cc..eadc89333f90bccccdbe8c8008bc2f066ef20675 100644 (file)
@@ -6,6 +6,7 @@ package repo
 
 import (
        "net/http"
+       "net/url"
        "time"
 
        "code.gitea.io/gitea/models"
@@ -244,7 +245,7 @@ func ChangeMilestoneStatus(ctx *context.Context) {
                }
                return
        }
-       ctx.Redirect(ctx.Repo.RepoLink + "/milestones?state=" + ctx.Params(":action"))
+       ctx.Redirect(ctx.Repo.RepoLink + "/milestones?state=" + url.QueryEscape(ctx.Params(":action")))
 }
 
 // DeleteMilestone delete a milestone
index 08b285df0a1ea537394a8329a46fcc2dbb0c5d7f..437da14d45dcfdfafba2e71ee25e628fdd9b3a7a 100644 (file)
@@ -7,6 +7,7 @@ package repo
 import (
        "fmt"
        "net/http"
+       "net/url"
        "strings"
 
        "code.gitea.io/gitea/models"
@@ -173,7 +174,7 @@ func ChangeProjectStatus(ctx *context.Context) {
                }
                return
        }
-       ctx.Redirect(ctx.Repo.RepoLink + "/projects?state=" + ctx.Params(":action"))
+       ctx.Redirect(ctx.Repo.RepoLink + "/projects?state=" + url.QueryEscape(ctx.Params(":action")))
 }
 
 // DeleteProject delete a project
index 0ac05a76093d4f245872911587cc7c51e49d9a03..43372782143464077be5d96575274de469156f37 100644 (file)
@@ -10,8 +10,10 @@ import (
        "crypto/subtle"
        "errors"
        "fmt"
+       "html"
        "net/http"
-       "path"
+       "net/url"
+       "strconv"
        "strings"
        "time"
 
@@ -34,7 +36,6 @@ import (
        "code.gitea.io/gitea/services/gitdiff"
        pull_service "code.gitea.io/gitea/services/pull"
        repo_service "code.gitea.io/gitea/services/repository"
-       "github.com/unknwon/com"
 )
 
 const (
@@ -109,8 +110,7 @@ func getForkRepository(ctx *context.Context) *models.Repository {
        ctx.Data["IsPrivate"] = forkRepo.IsPrivate || forkRepo.Owner.Visibility == structs.VisibleTypePrivate
        canForkToUser := forkRepo.OwnerID != ctx.User.ID && !ctx.User.HasForkedRepo(forkRepo.ID)
 
-       ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name
-       ctx.Data["ForkFromOwnerID"] = forkRepo.Owner.ID
+       ctx.Data["ForkRepo"] = forkRepo
 
        if err := ctx.User.GetOwnedOrganizations(); err != nil {
                ctx.ServerError("GetOwnedOrganizations", err)
@@ -202,7 +202,7 @@ func ForkPost(ctx *context.Context) {
                }
                repo, has := models.HasForkedRepo(ctxUser.ID, traverseParentRepo.ID)
                if has {
-                       ctx.Redirect(ctxUser.HomeLink() + "/" + repo.Name)
+                       ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(repo.Name))
                        return
                }
                if !traverseParentRepo.IsFork {
@@ -248,7 +248,7 @@ func ForkPost(ctx *context.Context) {
        }
 
        log.Trace("Repository forked[%d]: %s/%s", forkRepo.ID, ctxUser.Name, repo.Name)
-       ctx.Redirect(ctxUser.HomeLink() + "/" + repo.Name)
+       ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(repo.Name))
 }
 
 func checkPullInfo(ctx *context.Context) *models.Issue {
@@ -682,8 +682,7 @@ func ViewPullFiles(ctx *context.Context) {
                }
        }
 
-       headTarget := path.Join(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
-       setCompareContext(ctx, baseCommit, commit, headTarget)
+       setCompareContext(ctx, baseCommit, commit, ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
 
        ctx.Data["RequireHighlightJS"] = true
        ctx.Data["RequireSimpleMDE"] = true
@@ -746,7 +745,7 @@ func UpdatePullRequest(ctx *context.Context) {
        // ToDo: add check if maintainers are allowed to change branch ... (need migration & co)
        if (!allowedUpdateByMerge && !rebase) || (rebase && !allowedUpdateByRebase) {
                ctx.Flash.Error(ctx.Tr("repo.pulls.update_not_allowed"))
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
@@ -766,7 +765,7 @@ func UpdatePullRequest(ctx *context.Context) {
                                return
                        }
                        ctx.Flash.Error(flashError)
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+                       ctx.Redirect(issue.Link())
                        return
                } else if models.IsErrRebaseConflicts(err) {
                        conflictError := err.(models.ErrRebaseConflicts)
@@ -780,19 +779,19 @@ func UpdatePullRequest(ctx *context.Context) {
                                return
                        }
                        ctx.Flash.Error(flashError)
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+                       ctx.Redirect(issue.Link())
                        return
 
                }
                ctx.Flash.Error(err.Error())
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
        time.Sleep(1 * time.Second)
 
        ctx.Flash.Success(ctx.Tr("repo.pulls.update_branch_success"))
-       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+       ctx.Redirect(issue.Link())
 }
 
 // MergePullRequest response for merging pull request
@@ -805,11 +804,11 @@ func MergePullRequest(ctx *context.Context) {
        if issue.IsClosed {
                if issue.IsPull {
                        ctx.Flash.Error(ctx.Tr("repo.pulls.is_closed"))
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+                       ctx.Redirect(issue.Link())
                        return
                }
                ctx.Flash.Error(ctx.Tr("repo.issues.closed_title"))
-               ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + fmt.Sprint(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
@@ -822,13 +821,13 @@ func MergePullRequest(ctx *context.Context) {
        }
        if !allowedMerge {
                ctx.Flash.Error(ctx.Tr("repo.pulls.update_not_allowed"))
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
        if pr.HasMerged {
                ctx.Flash.Error(ctx.Tr("repo.pulls.has_merged"))
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
@@ -837,11 +836,11 @@ func MergePullRequest(ctx *context.Context) {
                if err = pull_service.MergedManually(pr, ctx.User, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
                        if models.IsErrInvalidMergeStyle(err) {
                                ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
-                               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
+                               ctx.Redirect(issue.Link())
                                return
                        } else if strings.Contains(err.Error(), "Wrong commit ID") {
                                ctx.Flash.Error(ctx.Tr("repo.pulls.wrong_commit_id"))
-                               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
+                               ctx.Redirect(issue.Link())
                                return
                        }
 
@@ -849,19 +848,19 @@ func MergePullRequest(ctx *context.Context) {
                        return
                }
 
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
        if !pr.CanAutoMerge() {
                ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_not_ready"))
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
        if pr.IsWorkInProgress() {
                ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_wip"))
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
@@ -875,14 +874,14 @@ func MergePullRequest(ctx *context.Context) {
                        return
                } else if !isRepoAdmin {
                        ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_not_ready"))
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+                       ctx.Redirect(issue.Link())
                        return
                }
        }
 
        if ctx.HasError() {
                ctx.Flash.Error(ctx.Data["ErrorMsg"].(string))
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
@@ -914,14 +913,14 @@ func MergePullRequest(ctx *context.Context) {
 
        if !noDeps {
                ctx.Flash.Error(ctx.Tr("repo.issues.dependency.pr_close_blocked"))
-               ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+               ctx.Redirect(issue.Link())
                return
        }
 
        if err = pull_service.Merge(pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil {
                if models.IsErrInvalidMergeStyle(err) {
                        ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+                       ctx.Redirect(issue.Link())
                        return
                } else if models.IsErrMergeConflicts(err) {
                        conflictError := err.(models.ErrMergeConflicts)
@@ -935,7 +934,7 @@ func MergePullRequest(ctx *context.Context) {
                                return
                        }
                        ctx.Flash.Error(flashError)
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+                       ctx.Redirect(issue.Link())
                        return
                } else if models.IsErrRebaseConflicts(err) {
                        conflictError := err.(models.ErrRebaseConflicts)
@@ -949,17 +948,17 @@ func MergePullRequest(ctx *context.Context) {
                                return
                        }
                        ctx.Flash.Error(flashError)
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+                       ctx.Redirect(issue.Link())
                        return
                } else if models.IsErrMergeUnrelatedHistories(err) {
                        log.Debug("MergeUnrelatedHistories error: %v", err)
                        ctx.Flash.Error(ctx.Tr("repo.pulls.unrelated_histories"))
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+                       ctx.Redirect(issue.Link())
                        return
                } else if git.IsErrPushOutOfDate(err) {
                        log.Debug("MergePushOutOfDate error: %v", err)
                        ctx.Flash.Error(ctx.Tr("repo.pulls.merge_out_of_date"))
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+                       ctx.Redirect(issue.Link())
                        return
                } else if git.IsErrPushRejected(err) {
                        log.Debug("MergePushRejected error: %v", err)
@@ -979,7 +978,7 @@ func MergePullRequest(ctx *context.Context) {
                                }
                                ctx.Flash.Error(flashError)
                        }
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+                       ctx.Redirect(issue.Link())
                        return
                }
                ctx.ServerError("Merge", err)
@@ -1008,7 +1007,7 @@ func MergePullRequest(ctx *context.Context) {
                deleteBranch(ctx, pr, headRepo)
        }
 
-       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
+       ctx.Redirect(issue.Link())
 }
 
 func stopTimerIfAvailable(user *models.User, issue *models.Issue) error {
@@ -1097,6 +1096,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
 
        pullIssue := &models.Issue{
                RepoID:      repo.ID,
+               Repo:        repo,
                Title:       form.Title,
                PosterID:    ctx.User.ID,
                Poster:      ctx.User,
@@ -1138,7 +1138,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
                                }
                                ctx.Flash.Error(flashError)
                        }
-                       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pullIssue.Index))
+                       ctx.Redirect(pullIssue.Link())
                        return
                }
                ctx.ServerError("NewPullRequest", err)
@@ -1146,7 +1146,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
        }
 
        log.Trace("Pull request created: %d/%d", repo.ID, pullIssue.ID)
-       ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pullIssue.Index))
+       ctx.Redirect(pullIssue.Link())
 }
 
 // TriggerTask response for a trigger task request
@@ -1261,7 +1261,7 @@ func CleanUpPullRequest(ctx *context.Context) {
 
        defer func() {
                ctx.JSON(http.StatusOK, map[string]interface{}{
-                       "redirect": pr.BaseRepo.Link() + "/pulls/" + fmt.Sprint(issue.Index),
+                       "redirect": issue.Link(),
                })
        }()
 
@@ -1369,7 +1369,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
                        err := err.(models.ErrPullRequestAlreadyExists)
 
                        RepoRelPath := ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
-                       errorMessage := ctx.Tr("repo.pulls.has_pull_request", ctx.Repo.RepoLink, RepoRelPath, err.IssueID)
+                       errorMessage := ctx.Tr("repo.pulls.has_pull_request", html.EscapeString(ctx.Repo.RepoLink+"/pulls/"+strconv.FormatInt(err.IssueID, 10)), html.EscapeString(RepoRelPath), err.IssueID) // FIXME: Creates url insidde locale string
 
                        ctx.Flash.Error(errorMessage)
                        ctx.JSON(http.StatusConflict, map[string]interface{}{
index 20f6ddd2a57604d4af071c6a414db58f1ada5e9f..3f12ee72bcb4554265f737eda15c55515fb4bc17 100644 (file)
@@ -20,6 +20,7 @@ import (
        "code.gitea.io/gitea/modules/markup/markdown"
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/upload"
+       "code.gitea.io/gitea/modules/util"
        "code.gitea.io/gitea/modules/web"
        "code.gitea.io/gitea/services/forms"
        releaseservice "code.gitea.io/gitea/services/release"
@@ -350,7 +351,7 @@ func NewReleasePost(ctx *context.Context) {
                        }
 
                        ctx.Flash.Success(ctx.Tr("repo.tag.create_success", form.TagName))
-                       ctx.Redirect(ctx.Repo.RepoLink + "/src/tag/" + form.TagName)
+                       ctx.Redirect(ctx.Repo.RepoLink + "/src/tag/" + util.PathEscapeSegments(form.TagName))
                        return
                }
 
index c70dec64811b59d9cac72edac9f433f5465e9406..46cef7664ace8596cc1c42daafadbad6366aae41 100644 (file)
@@ -244,7 +244,7 @@ func CreatePost(ctx *context.Context) {
                repo, err = repo_service.GenerateRepository(ctx.User, ctxUser, templateRepo, opts)
                if err == nil {
                        log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
-                       ctx.Redirect(ctxUser.HomeLink() + "/" + repo.Name)
+                       ctx.Redirect(repo.Link())
                        return
                }
        } else {
@@ -263,7 +263,7 @@ func CreatePost(ctx *context.Context) {
                })
                if err == nil {
                        log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
-                       ctx.Redirect(ctxUser.HomeLink() + "/" + repo.Name)
+                       ctx.Redirect(repo.Link())
                        return
                }
        }
index cecd1da07cf9bd765eaeb3019881cd06599e9671..641052316c266e0e333dbc7d869799d59c40a882 100644 (file)
@@ -615,7 +615,7 @@ func SettingsPost(ctx *context.Context) {
 
                log.Trace("Repository transfer process was started: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newOwner)
                ctx.Flash.Success(ctx.Tr("repo.settings.transfer_started", newOwner.DisplayName()))
-               ctx.Redirect(ctx.Repo.Owner.HomeLink() + "/" + repo.Name + "/settings")
+               ctx.Redirect(repo.Link() + "/settings")
 
        case "cancel_transfer":
                if !ctx.Repo.IsOwner() {
@@ -627,7 +627,7 @@ func SettingsPost(ctx *context.Context) {
                if err != nil {
                        if models.IsErrNoPendingTransfer(err) {
                                ctx.Flash.Error("repo.settings.transfer_abort_invalid")
-                               ctx.Redirect(ctx.User.HomeLink() + "/" + repo.Name + "/settings")
+                               ctx.Redirect(repo.Link() + "/settings")
                        } else {
                                ctx.ServerError("GetPendingRepositoryTransfer", err)
                        }
@@ -647,7 +647,7 @@ func SettingsPost(ctx *context.Context) {
 
                log.Trace("Repository transfer process was cancelled: %s/%s ", ctx.Repo.Owner.Name, repo.Name)
                ctx.Flash.Success(ctx.Tr("repo.settings.transfer_abort_success", repoTransfer.Recipient.Name))
-               ctx.Redirect(ctx.Repo.Owner.HomeLink() + "/" + repo.Name + "/settings")
+               ctx.Redirect(repo.Link() + "/settings")
 
        case "delete":
                if !ctx.Repo.IsOwner() {
@@ -796,7 +796,7 @@ func Collaboration(ctx *context.Context) {
 func CollaborationPost(ctx *context.Context) {
        name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("collaborator")))
        if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
-               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
+               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
                return
        }
 
@@ -804,7 +804,7 @@ func CollaborationPost(ctx *context.Context) {
        if err != nil {
                if models.IsErrUserNotExist(err) {
                        ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
-                       ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
+                       ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
                } else {
                        ctx.ServerError("GetUserByName", err)
                }
@@ -813,14 +813,14 @@ func CollaborationPost(ctx *context.Context) {
 
        if !u.IsActive {
                ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_inactive_user"))
-               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
+               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
                return
        }
 
        // Organization is not allowed to be added as a collaborator.
        if u.IsOrganization() {
                ctx.Flash.Error(ctx.Tr("repo.settings.org_not_allowed_to_be_collaborator"))
-               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
+               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
                return
        }
 
@@ -840,7 +840,7 @@ func CollaborationPost(ctx *context.Context) {
        }
 
        ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success"))
-       ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
+       ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 }
 
 // ChangeCollaborationAccessMode response for changing access of a collaboration
index 876ff9ba460b6deae47d0aed698fbb35ed89be64..32105b1d43cd98578992427b71b1759322bc48a2 100644 (file)
@@ -16,6 +16,7 @@ import (
        "code.gitea.io/gitea/modules/git"
        "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/setting"
+       "code.gitea.io/gitea/modules/util"
        "code.gitea.io/gitea/modules/web"
        "code.gitea.io/gitea/services/forms"
        pull_service "code.gitea.io/gitea/services/pull"
@@ -89,7 +90,7 @@ func ProtectedBranchPost(ctx *context.Context) {
                log.Trace("Repository basic settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 
                ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
-               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
+               ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
        default:
                ctx.NotFound("", nil)
        }
@@ -197,7 +198,7 @@ func SettingsProtectedBranchPost(ctx *context.Context) {
                }
                if f.RequiredApprovals < 0 {
                        ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_required_approvals_min"))
-                       ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, branch))
+                       ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
                }
 
                var whitelistUsers, whitelistTeams, mergeWhitelistUsers, mergeWhitelistTeams, approvalsWhitelistUsers, approvalsWhitelistTeams []int64
@@ -274,7 +275,7 @@ func SettingsProtectedBranchPost(ctx *context.Context) {
                        return
                }
                ctx.Flash.Success(ctx.Tr("repo.settings.update_protect_branch_success", branch))
-               ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, branch))
+               ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
        } else {
                if protectBranch != nil {
                        if err := ctx.Repo.Repository.DeleteProtectedBranch(protectBranch.ID); err != nil {
index a180399c9ebe083d74cead4933ce1b06a98cea68..b4d268759c7ff5e327856c8ea0afc16c2b2ff022 100644 (file)
@@ -58,7 +58,7 @@ func NewProtectedTagPost(ctx *context.Context) {
        }
 
        ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
-       ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
+       ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 }
 
 // EditProtectedTag render the page to edit a protect tag
index cecd8437b6962f0193e47597b4ff9fe45baa00d5..12b3aef505ea296b0b2511143a4ac5816a664c31 100644 (file)
@@ -232,7 +232,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
                        }
                        if readmeFile != nil {
                                readmeFile.name = entry.Name() + "/" + readmeFile.name
-                               readmeTreelink = treeLink + "/" + entry.GetSubJumpablePathName()
+                               readmeTreelink = treeLink + "/" + util.PathEscapeSegments(entry.GetSubJumpablePathName())
                                break
                        }
                }
@@ -301,7 +301,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
                                        fileSize = meta.Size
                                        ctx.Data["FileSize"] = meta.Size
                                        filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name))
-                                       ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s.git/info/lfs/objects/%s/%s", setting.AppURL, ctx.Repo.Repository.FullName(), meta.Oid, filenameBase64)
+                                       ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.HTMLURL(), url.PathEscape(meta.Oid), url.PathEscape(filenameBase64))
                                }
                        }
                }
@@ -376,7 +376,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
        fileSize := blob.Size()
        ctx.Data["FileIsSymlink"] = entry.IsLink()
        ctx.Data["FileName"] = blob.Name()
-       ctx.Data["RawFileLink"] = rawLink + "/" + ctx.Repo.TreePath
+       ctx.Data["RawFileLink"] = rawLink + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
 
        buf := make([]byte, 1024)
        n, _ := util.ReadAtMost(dataRc, buf)
@@ -422,7 +422,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
                                isTextFile = st.IsText()
 
                                fileSize = meta.Size
-                               ctx.Data["RawFileLink"] = fmt.Sprintf("%s/media/%s/%s", ctx.Repo.RepoLink, ctx.Repo.BranchNameSubURL(), ctx.Repo.TreePath)
+                               ctx.Data["RawFileLink"] = ctx.Repo.RepoLink + "/media/" + ctx.Repo.BranchNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
                        }
                }
        }
@@ -628,7 +628,7 @@ func checkHomeCodeViewable(ctx *context.Context) {
                }
 
                if firstUnit != nil {
-                       ctx.Redirect(fmt.Sprintf("%s/%s%s", setting.AppSubURL, ctx.Repo.Repository.FullName(), firstUnit.URI))
+                       ctx.Redirect(fmt.Sprintf("%s%s", ctx.Repo.Repository.Link(), firstUnit.URI))
                        return
                }
        }
@@ -684,7 +684,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
                return nil
        }
 
-       ctx.Data["LastCommitLoaderURL"] = ctx.Repo.RepoLink + "/lastcommit/" + ctx.Repo.CommitID + "/" + ctx.Repo.TreePath
+       ctx.Data["LastCommitLoaderURL"] = ctx.Repo.RepoLink + "/lastcommit/" + url.PathEscape(ctx.Repo.CommitID) + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
 
        // Get current entry user currently looking at.
        entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
@@ -766,7 +766,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
        treeLink := branchLink
 
        if len(ctx.Repo.TreePath) > 0 {
-               treeLink += "/" + ctx.Repo.TreePath
+               treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
        }
 
        ctx.Data["TreeLink"] = treeLink
@@ -815,7 +815,7 @@ func renderCode(ctx *context.Context) {
        rawLink := ctx.Repo.RepoLink + "/raw/" + ctx.Repo.BranchNameSubURL()
 
        if len(ctx.Repo.TreePath) > 0 {
-               treeLink += "/" + ctx.Repo.TreePath
+               treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
        }
 
        // Get Topics of this repo
index f47f8d651d73ce13cb2ce5f4c968e55e83924a1b..4f6660926ee1e630bf71a720b9b505a1cdcea1f8 100644 (file)
@@ -9,6 +9,7 @@ import (
        "errors"
        "fmt"
        "net/http"
+       "net/url"
        "path"
        "strings"
 
@@ -414,7 +415,7 @@ func TelegramHooksNewPost(ctx *context.Context) {
 
        w := &webhook.Webhook{
                RepoID:          orCtx.RepoID,
-               URL:             fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", form.BotToken, form.ChatID),
+               URL:             fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", url.PathEscape(form.BotToken), url.QueryEscape(form.ChatID)),
                ContentType:     webhook.ContentTypeJSON,
                HookEvent:       ParseHookEvent(form.WebhookForm),
                IsActive:        form.Active,
@@ -468,7 +469,7 @@ func MatrixHooksNewPost(ctx *context.Context) {
 
        w := &webhook.Webhook{
                RepoID:          orCtx.RepoID,
-               URL:             fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, form.RoomID),
+               URL:             fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID)),
                ContentType:     webhook.ContentTypeJSON,
                HTTPMethod:      "PUT",
                HookEvent:       ParseHookEvent(form.WebhookForm),
@@ -976,7 +977,7 @@ func TelegramHooksEditPost(ctx *context.Context) {
                return
        }
        w.Meta = string(meta)
-       w.URL = fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", form.BotToken, form.ChatID)
+       w.URL = fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", url.PathEscape(form.BotToken), url.QueryEscape(form.ChatID))
        w.HookEvent = ParseHookEvent(form.WebhookForm)
        w.IsActive = form.Active
        if err := w.UpdateEvent(); err != nil {
@@ -1020,7 +1021,7 @@ func MatrixHooksEditPost(ctx *context.Context) {
                return
        }
        w.Meta = string(meta)
-       w.URL = fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, form.RoomID)
+       w.URL = fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID))
 
        w.HookEvent = ParseHookEvent(form.WebhookForm)
        w.IsActive = form.Active
@@ -1162,7 +1163,7 @@ func TestWebhook(ctx *context.Context) {
        apiCommit := &api.PayloadCommit{
                ID:      commit.ID.String(),
                Message: commit.Message(),
-               URL:     ctx.Repo.Repository.HTMLURL() + "/commit/" + commit.ID.String(),
+               URL:     ctx.Repo.Repository.HTMLURL() + "/commit/" + url.PathEscape(commit.ID.String()),
                Author: &api.PayloadUser{
                        Name:  commit.Author.Name,
                        Email: commit.Author.Email,
index 16927de2e9fe30d0dc73eb736c366b81420db072..82f56a8c4a124f1bff920f5f977a99298a2f16a2 100644 (file)
@@ -180,7 +180,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
        ctx.Data["Pages"] = pages
 
        // get requested pagename
-       pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
+       pageName := wiki_service.NormalizeWikiName(ctx.Params("*"))
        if len(pageName) == 0 {
                pageName = "Home"
        }
@@ -193,7 +193,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
        //lookup filename in wiki - get filecontent, gitTree entry , real filename
        data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
        if noEntry {
-               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
+               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
        }
        if entry == nil || ctx.Written() {
                if wikiRepo != nil {
@@ -276,7 +276,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
        }
 
        // get requested pagename
-       pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
+       pageName := wiki_service.NormalizeWikiName(ctx.Params("*"))
        if len(pageName) == 0 {
                pageName = "Home"
        }
@@ -291,7 +291,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
        //lookup filename in wiki - get filecontent, gitTree entry , real filename
        data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
        if noEntry {
-               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
+               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
        }
        if entry == nil || ctx.Written() {
                if wikiRepo != nil {
@@ -352,7 +352,7 @@ func renderEditPage(ctx *context.Context) {
        }()
 
        // get requested pagename
-       pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
+       pageName := wiki_service.NormalizeWikiName(ctx.Params("*"))
        if len(pageName) == 0 {
                pageName = "Home"
        }
@@ -365,7 +365,7 @@ func renderEditPage(ctx *context.Context) {
        //lookup filename in wiki - get filecontent, gitTree entry , real filename
        data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName)
        if noEntry {
-               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
+               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
        }
        if entry == nil || ctx.Written() {
                return
@@ -378,6 +378,32 @@ func renderEditPage(ctx *context.Context) {
        ctx.Data["footerContent"] = ""
 }
 
+// WikiPost renders post of wiki page
+func WikiPost(ctx *context.Context) {
+       switch ctx.FormString("action") {
+       case "_new":
+               if !ctx.Repo.CanWrite(unit.TypeWiki) {
+                       ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
+                       return
+               }
+               NewWikiPost(ctx)
+               return
+       case "_delete":
+               if !ctx.Repo.CanWrite(unit.TypeWiki) {
+                       ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
+                       return
+               }
+               DeleteWikiPagePost(ctx)
+               return
+       }
+
+       if !ctx.Repo.CanWrite(unit.TypeWiki) {
+               ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
+               return
+       }
+       EditWikiPost(ctx)
+}
+
 // Wiki renders single wiki page
 func Wiki(ctx *context.Context) {
        ctx.Data["PageIsWiki"] = true
@@ -389,6 +415,29 @@ func Wiki(ctx *context.Context) {
                return
        }
 
+       switch ctx.FormString("action") {
+       case "_pages":
+               WikiPages(ctx)
+               return
+       case "_revision":
+               WikiRevision(ctx)
+               return
+       case "_edit":
+               if !ctx.Repo.CanWrite(unit.TypeWiki) {
+                       ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
+                       return
+               }
+               EditWiki(ctx)
+               return
+       case "_new":
+               if !ctx.Repo.CanWrite(unit.TypeWiki) {
+                       ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
+                       return
+               }
+               NewWiki(ctx)
+               return
+       }
+
        wikiRepo, entry := renderViewPage(ctx)
        defer func() {
                if wikiRepo != nil {
@@ -652,7 +701,7 @@ func EditWikiPost(ctx *context.Context) {
                return
        }
 
-       oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
+       oldWikiName := wiki_service.NormalizeWikiName(ctx.Params("*"))
        newWikiName := wiki_service.NormalizeWikiName(form.Title)
 
        if len(form.Message) == 0 {
@@ -669,7 +718,7 @@ func EditWikiPost(ctx *context.Context) {
 
 // DeleteWikiPagePost delete wiki page
 func DeleteWikiPagePost(ctx *context.Context) {
-       wikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
+       wikiName := wiki_service.NormalizeWikiName(ctx.Params("*"))
        if len(wikiName) == 0 {
                wikiName = "Home"
        }
index cf49f19afe446b82981cd9e49bc6646d971583b8..87f2779c1a8486ea5d9b594f47bd3bffbc481a8b 100644 (file)
@@ -76,8 +76,8 @@ func assertPagesMetas(t *testing.T, expectedNames []string, metas interface{}) {
 func TestWiki(t *testing.T) {
        unittest.PrepareTestEnv(t)
 
-       ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
-       ctx.SetParams(":page", "Home")
+       ctx := test.MockContext(t, "user2/repo1/wiki/?action=_pages")
+       ctx.SetParams("*", "Home")
        test.LoadRepo(t, ctx, 1)
        Wiki(ctx)
        assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
@@ -88,7 +88,7 @@ func TestWiki(t *testing.T) {
 func TestWikiPages(t *testing.T) {
        unittest.PrepareTestEnv(t)
 
-       ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
+       ctx := test.MockContext(t, "user2/repo1/wiki/?action=_pages")
        test.LoadRepo(t, ctx, 1)
        WikiPages(ctx)
        assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
@@ -98,7 +98,7 @@ func TestWikiPages(t *testing.T) {
 func TestNewWiki(t *testing.T) {
        unittest.PrepareTestEnv(t)
 
-       ctx := test.MockContext(t, "user2/repo1/wiki/_new")
+       ctx := test.MockContext(t, "user2/repo1/wiki/?action=_new")
        test.LoadUser(t, ctx, 2)
        test.LoadRepo(t, ctx, 1)
        NewWiki(ctx)
@@ -113,7 +113,7 @@ func TestNewWikiPost(t *testing.T) {
        } {
                unittest.PrepareTestEnv(t)
 
-               ctx := test.MockContext(t, "user2/repo1/wiki/_new")
+               ctx := test.MockContext(t, "user2/repo1/wiki/?action=_new")
                test.LoadUser(t, ctx, 2)
                test.LoadRepo(t, ctx, 1)
                web.SetForm(ctx, &forms.NewWikiForm{
@@ -131,7 +131,7 @@ func TestNewWikiPost(t *testing.T) {
 func TestNewWikiPost_ReservedName(t *testing.T) {
        unittest.PrepareTestEnv(t)
 
-       ctx := test.MockContext(t, "user2/repo1/wiki/_new")
+       ctx := test.MockContext(t, "user2/repo1/wiki/?action=_new")
        test.LoadUser(t, ctx, 2)
        test.LoadRepo(t, ctx, 1)
        web.SetForm(ctx, &forms.NewWikiForm{
@@ -148,8 +148,8 @@ func TestNewWikiPost_ReservedName(t *testing.T) {
 func TestEditWiki(t *testing.T) {
        unittest.PrepareTestEnv(t)
 
-       ctx := test.MockContext(t, "user2/repo1/wiki/_edit/Home")
-       ctx.SetParams(":page", "Home")
+       ctx := test.MockContext(t, "user2/repo1/wiki/Home?action=_edit")
+       ctx.SetParams("*", "Home")
        test.LoadUser(t, ctx, 2)
        test.LoadRepo(t, ctx, 1)
        EditWiki(ctx)
@@ -164,8 +164,8 @@ func TestEditWikiPost(t *testing.T) {
                "New/<page>",
        } {
                unittest.PrepareTestEnv(t)
-               ctx := test.MockContext(t, "user2/repo1/wiki/_new/Home")
-               ctx.SetParams(":page", "Home")
+               ctx := test.MockContext(t, "user2/repo1/wiki/Home?action=_new")
+               ctx.SetParams("*", "Home")
                test.LoadUser(t, ctx, 2)
                test.LoadRepo(t, ctx, 1)
                web.SetForm(ctx, &forms.NewWikiForm{
@@ -186,7 +186,7 @@ func TestEditWikiPost(t *testing.T) {
 func TestDeleteWikiPagePost(t *testing.T) {
        unittest.PrepareTestEnv(t)
 
-       ctx := test.MockContext(t, "user2/repo1/wiki/Home/delete")
+       ctx := test.MockContext(t, "user2/repo1/wiki/Home?action=_delete")
        test.LoadUser(t, ctx, 2)
        test.LoadRepo(t, ctx, 1)
        DeleteWikiPagePost(ctx)
index 1305b0095ad59e792d120ef49ca3bcc6387a95bb..b9f5d044fa5527ec361899ff74aedd29954d6d7e 100644 (file)
@@ -887,5 +887,5 @@ func Email2User(ctx *context.Context) {
                }
                return
        }
-       ctx.Redirect(setting.AppSubURL + "/user/" + u.Name)
+       ctx.Redirect(u.HomeLink())
 }
index 080ec4b5822177bdc6490d2932088a2e19ce015e..08cd1b8b310e31cbf06090d944e391d1429f05c6 100644 (file)
@@ -167,7 +167,7 @@ func NotificationStatusPost(c *context.Context) {
        }
 
        if !c.FormBool("noredirect") {
-               url := fmt.Sprintf("%s/notifications?page=%s", setting.AppSubURL, c.FormString("page"))
+               url := fmt.Sprintf("%s/notifications?page=%s", setting.AppSubURL, url.QueryEscape(c.FormString("page")))
                c.Redirect(url, http.StatusSeeOther)
        }
 
@@ -189,6 +189,5 @@ func NotificationPurgePost(c *context.Context) {
                return
        }
 
-       url := fmt.Sprintf("%s/notifications", setting.AppSubURL)
-       c.Redirect(url, http.StatusSeeOther)
+       c.Redirect(setting.AppSubURL+"/notifications", http.StatusSeeOther)
 }
index 642a7f33b00a84f53b23ccde174f06417cf767a9..3210d033d3c2260d296ed4673debb0b6e6c77e8c 100644 (file)
@@ -454,7 +454,7 @@ func AuthorizeOAuth(ctx *context.Context) {
        ctx.Data["State"] = form.State
        ctx.Data["Scope"] = form.Scope
        ctx.Data["Nonce"] = form.Nonce
-       ctx.Data["ApplicationUserLink"] = "<a href=\"" + html.EscapeString(setting.AppURL) + html.EscapeString(url.PathEscape(user.LowerName)) + "\">@" + html.EscapeString(user.Name) + "</a>"
+       ctx.Data["ApplicationUserLink"] = "<a href=\"" + html.EscapeString(user.HTMLURL()) + "\">@" + html.EscapeString(user.Name) + "</a>"
        ctx.Data["ApplicationRedirectDomainHTML"] = "<strong>" + html.EscapeString(form.RedirectURI) + "</strong>"
        // TODO document SESSION <=> FORM
        err = ctx.Session.Set("client_id", app.ClientID)
index f8fcbf65650705eaaccf61719ac51049496a0373..17c4783c694c7e24440cc30fec781264799ea1d0 100644 (file)
@@ -364,6 +364,6 @@ func Action(ctx *context.Context) {
                ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.Params(":action")), err)
                return
        }
-
+       // FIXME: We should check this URL and make sure that it's a valid Gitea URL
        ctx.RedirectToFirst(ctx.FormString("redirect_to"), u.HomeLink())
 }
index 69f737c3e1f405442c7f97f9961ebad36d324a6c..a20bf484b3d4e61ede0b2c58aaa2d2ec5b1b3c41 100644 (file)
@@ -895,21 +895,23 @@ func RegisterRoutes(m *web.Route) {
                }, reqRepoProjectsReader, repo.MustEnableProjects)
 
                m.Group("/wiki", func() {
-                       m.Get("/", repo.Wiki)
-                       m.Get("/{page}", repo.Wiki)
-                       m.Get("/_pages", repo.WikiPages)
-                       m.Get("/{page}/_revision", repo.WikiRevision)
+                       m.Combo("/").
+                               Get(repo.Wiki).
+                               Post(context.RepoMustNotBeArchived(),
+                                       reqSignIn,
+                                       reqRepoWikiWriter,
+                                       bindIgnErr(forms.NewWikiForm{}),
+                                       repo.WikiPost)
+                       m.Combo("/*").
+                               Get(repo.Wiki).
+                               Post(context.RepoMustNotBeArchived(),
+                                       reqSignIn,
+                                       reqRepoWikiWriter,
+                                       bindIgnErr(forms.NewWikiForm{}),
+                                       repo.WikiPost)
                        m.Get("/commit/{sha:[a-f0-9]{7,40}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
                        m.Get("/commit/{sha:[a-f0-9]{7,40}}.{ext:patch|diff}", repo.RawDiff)
-
-                       m.Group("", func() {
-                               m.Combo("/_new").Get(repo.NewWiki).
-                                       Post(bindIgnErr(forms.NewWikiForm{}), repo.NewWikiPost)
-                               m.Combo("/{page}/_edit").Get(repo.EditWiki).
-                                       Post(bindIgnErr(forms.NewWikiForm{}), repo.EditWikiPost)
-                               m.Post("/{page}/delete", repo.DeleteWikiPagePost)
-                       }, context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter)
-               }, repo.MustEnableWiki, context.RepoRef(), func(ctx *context.Context) {
+               }, repo.MustEnableWiki, func(ctx *context.Context) {
                        ctx.Data["PageIsWiki"] = true
                })
 
index 5ce2a5498a466fdb402ef150aa89c34a0ded17e7..788765881656b403174e99bc58bf912006e9fee2 100644 (file)
@@ -12,6 +12,7 @@ import (
        "fmt"
        "io"
        "net/http"
+       "net/url"
        "path"
        "regexp"
        "strconv"
@@ -46,17 +47,17 @@ type Claims struct {
 
 // DownloadLink builds a URL to download the object.
 func (rc *requestContext) DownloadLink(p lfs_module.Pointer) string {
-       return setting.AppURL + path.Join(rc.User, rc.Repo+".git", "info/lfs/objects", p.Oid)
+       return setting.AppURL + path.Join(url.PathEscape(rc.User), url.PathEscape(rc.Repo+".git"), "info/lfs/objects", url.PathEscape(p.Oid))
 }
 
 // UploadLink builds a URL to upload the object.
 func (rc *requestContext) UploadLink(p lfs_module.Pointer) string {
-       return setting.AppURL + path.Join(rc.User, rc.Repo+".git", "info/lfs/objects", p.Oid, strconv.FormatInt(p.Size, 10))
+       return setting.AppURL + path.Join(url.PathEscape(rc.User), url.PathEscape(rc.Repo+".git"), "info/lfs/objects", url.PathEscape(p.Oid), strconv.FormatInt(p.Size, 10))
 }
 
 // VerifyLink builds a URL for verifying the object.
 func (rc *requestContext) VerifyLink(p lfs_module.Pointer) string {
-       return setting.AppURL + path.Join(rc.User, rc.Repo+".git", "info/lfs/verify")
+       return setting.AppURL + path.Join(url.PathEscape(rc.User), url.PathEscape(rc.Repo+".git"), "info/lfs/verify")
 }
 
 // CheckAcceptMediaType checks if the client accepts the LFS media type.
index 88e4078922bab505bd8633494a923f385a4693e3..a949b073a52995e510c28579a1567f2e517bacda 100644 (file)
@@ -13,6 +13,7 @@ import (
        "code.gitea.io/gitea/modules/git"
        "code.gitea.io/gitea/modules/json"
        api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/util"
 
        dingtalk "github.com/lunny/dingtalk_webhook"
 )
@@ -41,7 +42,7 @@ func (d *DingtalkPayload) Create(p *api.CreatePayload) (api.Payloader, error) {
        refName := git.RefEndName(p.Ref)
        title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName)
 
-       return createDingtalkPayload(title, title, fmt.Sprintf("view ref %s", refName), p.Repo.HTMLURL+"/src/"+refName), nil
+       return createDingtalkPayload(title, title, fmt.Sprintf("view ref %s", refName), p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName)), nil
 }
 
 // Delete implements PayloadConvertor Delete method
@@ -50,7 +51,7 @@ func (d *DingtalkPayload) Delete(p *api.DeletePayload) (api.Payloader, error) {
        refName := git.RefEndName(p.Ref)
        title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName)
 
-       return createDingtalkPayload(title, title, fmt.Sprintf("view ref %s", refName), p.Repo.HTMLURL+"/src/"+refName), nil
+       return createDingtalkPayload(title, title, fmt.Sprintf("view ref %s", refName), p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName)), nil
 }
 
 // Fork implements PayloadConvertor Fork method
@@ -78,7 +79,7 @@ func (d *DingtalkPayload) Push(p *api.PushPayload) (api.Payloader, error) {
                linkText = fmt.Sprintf("view commit %s...%s", p.Commits[0].ID[:7], p.Commits[len(p.Commits)-1].ID[:7])
        }
        if titleLink == "" {
-               titleLink = p.Repo.HTMLURL + "/src/" + branchName
+               titleLink = p.Repo.HTMLURL + "/src/" + util.PathEscapeSegments(branchName)
        }
 
        title := fmt.Sprintf("[%s:%s] %s", p.Repo.FullName, branchName, commitDesc)
index 3de50a8a2ffa91bd450b87a242b18797414a2469..587d2098ebaa9da4fe6693bfbc92938e1279b9e7 100644 (file)
@@ -16,6 +16,7 @@ import (
        "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/setting"
        api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/util"
 )
 
 type (
@@ -115,7 +116,7 @@ func (d *DiscordPayload) Create(p *api.CreatePayload) (api.Payloader, error) {
        refName := git.RefEndName(p.Ref)
        title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName)
 
-       return d.createPayload(p.Sender, title, "", p.Repo.HTMLURL+"/src/"+refName, greenColor), nil
+       return d.createPayload(p.Sender, title, "", p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName), greenColor), nil
 }
 
 // Delete implements PayloadConvertor Delete method
@@ -124,7 +125,7 @@ func (d *DiscordPayload) Delete(p *api.DeletePayload) (api.Payloader, error) {
        refName := git.RefEndName(p.Ref)
        title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName)
 
-       return d.createPayload(p.Sender, title, "", p.Repo.HTMLURL+"/src/"+refName, redColor), nil
+       return d.createPayload(p.Sender, title, "", p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName), redColor), nil
 }
 
 // Fork implements PayloadConvertor Fork method
@@ -150,7 +151,7 @@ func (d *DiscordPayload) Push(p *api.PushPayload) (api.Payloader, error) {
                titleLink = p.CompareURL
        }
        if titleLink == "" {
-               titleLink = p.Repo.HTMLURL + "/src/" + branchName
+               titleLink = p.Repo.HTMLURL + "/src/" + util.PathEscapeSegments(branchName)
        }
 
        title := fmt.Sprintf("[%s:%s] %s", p.Repo.FullName, branchName, commitDesc)
index 777ae086b5e966fc1343ed92ccf829e7dd89b8fe..32a79c0783f0534da8c8232ba79c8a3ab2c304e2 100644 (file)
@@ -7,10 +7,12 @@ package webhook
 import (
        "fmt"
        "html"
+       "net/url"
        "strings"
 
        "code.gitea.io/gitea/modules/setting"
        api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/util"
 )
 
 type linkFormatter = func(string, string) string
@@ -22,7 +24,7 @@ func noneLinkFormatter(url string, text string) string {
 
 // htmlLinkFormatter creates a HTML link
 func htmlLinkFormatter(url string, text string) string {
-       return fmt.Sprintf(`<a href="%s">%s</a>`, url, html.EscapeString(text))
+       return fmt.Sprintf(`<a href="%s">%s</a>`, html.EscapeString(url), html.EscapeString(text))
 }
 
 func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, withSender bool) (string, string, string, int) {
@@ -46,7 +48,7 @@ func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, with
        case api.HookIssueAssigned:
                list := make([]string, len(p.Issue.Assignees))
                for i, user := range p.Issue.Assignees {
-                       list[i] = linkFormatter(setting.AppURL+user.UserName, user.UserName)
+                       list[i] = linkFormatter(setting.AppURL+url.PathEscape(user.UserName), user.UserName)
                }
                text = fmt.Sprintf("[%s] Issue assigned to %s: %s", repoLink, strings.Join(list, ", "), titleLink)
                color = greenColor
@@ -66,7 +68,7 @@ func getIssuesPayloadInfo(p *api.IssuePayload, linkFormatter linkFormatter, with
                text = fmt.Sprintf("[%s] Issue milestone cleared: %s", repoLink, titleLink)
        }
        if withSender {
-               text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName))
+               text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName))
        }
 
        var attachmentText string
@@ -139,7 +141,7 @@ func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkForm
 
 func getReleasePayloadInfo(p *api.ReleasePayload, linkFormatter linkFormatter, withSender bool) (text string, color int) {
        repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
-       refLink := linkFormatter(p.Repository.HTMLURL+"/src/"+p.Release.TagName, p.Release.TagName)
+       refLink := linkFormatter(p.Repository.HTMLURL+"/src/"+util.PathEscapeSegments(p.Release.TagName), p.Release.TagName)
 
        switch p.Action {
        case api.HookReleasePublished:
@@ -153,7 +155,7 @@ func getReleasePayloadInfo(p *api.ReleasePayload, linkFormatter linkFormatter, w
                color = redColor
        }
        if withSender {
-               text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName))
+               text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName))
        }
 
        return text, color
@@ -189,7 +191,7 @@ func getIssueCommentPayloadInfo(p *api.IssueCommentPayload, linkFormatter linkFo
                color = redColor
        }
        if withSender {
-               text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName))
+               text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName))
        }
 
        return text, issueTitle, color
index 08adaef6fd08428b9a9e5962e9f4bdf1eca5ea31..4fd78ff5bb0141a7b71f0743931f95725e176ea7 100644 (file)
@@ -10,6 +10,7 @@ import (
        "fmt"
        "html"
        "net/http"
+       "net/url"
        "regexp"
        "strings"
 
@@ -19,6 +20,7 @@ import (
        "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/setting"
        api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/util"
 )
 
 const matrixPayloadSizeLimit = 1024 * 64
@@ -94,11 +96,11 @@ func MatrixLinkToRef(repoURL, ref string) string {
        refName := git.RefEndName(ref)
        switch {
        case strings.HasPrefix(ref, git.BranchPrefix):
-               return MatrixLinkFormatter(repoURL+"/src/branch/"+refName, refName)
+               return MatrixLinkFormatter(repoURL+"/src/branch/"+util.PathEscapeSegments(refName), refName)
        case strings.HasPrefix(ref, git.TagPrefix):
-               return MatrixLinkFormatter(repoURL+"/src/tag/"+refName, refName)
+               return MatrixLinkFormatter(repoURL+"/src/tag/"+util.PathEscapeSegments(refName), refName)
        default:
-               return MatrixLinkFormatter(repoURL+"/src/commit/"+refName, refName)
+               return MatrixLinkFormatter(repoURL+"/src/commit/"+util.PathEscapeSegments(refName), refName)
        }
 }
 
@@ -186,7 +188,7 @@ func (m *MatrixPayloadUnsafe) PullRequest(p *api.PullRequestPayload) (api.Payloa
 
 // Review implements PayloadConvertor Review method
 func (m *MatrixPayloadUnsafe) Review(p *api.PullRequestPayload, event webhook_model.HookEventType) (api.Payloader, error) {
-       senderLink := MatrixLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
+       senderLink := MatrixLinkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName)
        title := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title)
        titleLink := fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index)
        repoLink := MatrixLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
@@ -281,7 +283,7 @@ func getMatrixHookRequest(w *webhook_model.Webhook, t *webhook_model.HookTask) (
                return nil, fmt.Errorf("getMatrixHookRequest: unable to hash payload: %+v", err)
        }
 
-       url := fmt.Sprintf("%s/%s", w.URL, txnID)
+       url := fmt.Sprintf("%s/%s", w.URL, url.PathEscape(txnID))
 
        req, err := http.NewRequest(w.HTTPMethod, url, strings.NewReader(string(payload)))
        if err != nil {
index 2b88bb23ff4e29a8f20da38db5c1a215a047b23c..ae5af8d9b6f0256cb5971dff4a492c2497e17b61 100644 (file)
@@ -12,6 +12,7 @@ import (
        "code.gitea.io/gitea/modules/git"
        "code.gitea.io/gitea/modules/json"
        api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/util"
 )
 
 type (
@@ -79,7 +80,7 @@ func (m *MSTeamsPayload) Create(p *api.CreatePayload) (api.Payloader, error) {
                p.Sender,
                title,
                "",
-               p.Repo.HTMLURL+"/src/"+refName,
+               p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName),
                greenColor,
                &MSTeamsFact{fmt.Sprintf("%s:", p.RefType), refName},
        ), nil
@@ -96,7 +97,7 @@ func (m *MSTeamsPayload) Delete(p *api.DeletePayload) (api.Payloader, error) {
                p.Sender,
                title,
                "",
-               p.Repo.HTMLURL+"/src/"+refName,
+               p.Repo.HTMLURL+"/src/"+util.PathEscapeSegments(refName),
                yellowColor,
                &MSTeamsFact{fmt.Sprintf("%s:", p.RefType), refName},
        ), nil
@@ -133,7 +134,7 @@ func (m *MSTeamsPayload) Push(p *api.PushPayload) (api.Payloader, error) {
                titleLink = p.CompareURL
        }
        if titleLink == "" {
-               titleLink = p.Repo.HTMLURL + "/src/" + branchName
+               titleLink = p.Repo.HTMLURL + "/src/" + util.PathEscapeSegments(branchName)
        }
 
        title := fmt.Sprintf("[%s:%s] %s", p.Repo.FullName, branchName, commitDesc)
index 944099de1fd81168e54e14a45d23ef4d1e5861aa..9d57ac432f405b1aea51b1586c530959f83cc897 100644 (file)
@@ -36,7 +36,7 @@ func nameAllowed(name string) error {
 
 // NameToSubURL converts a wiki name to its corresponding sub-URL.
 func NameToSubURL(name string) string {
-       return url.QueryEscape(strings.ReplaceAll(name, " ", "-"))
+       return url.PathEscape(strings.ReplaceAll(name, " ", "-"))
 }
 
 // NormalizeWikiName normalizes a wiki name
index 2d489a495d184c44a0d52cd7b51e660958619238..e73213c1dfa7f4070c0e625e30c47f69e59281db 100644 (file)
@@ -49,7 +49,7 @@
                                <tbody>
                                        {{range .Emails}}
                                                <tr>
-                                                       <td><a href="{{AppSubUrl}}/{{.Name}}">{{.Name}}</a></td>
+                                                       <td><a href="{{AppSubUrl}}/{{.Name | PathEscape}}">{{.Name}}</a></td>
                                                        <td><span class="text truncate">{{.FullName}}</span></td>
                                                        <td><span class="text email">{{.Email}}</span></td>
                                                        <td>{{if .IsPrimary}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
index e96d9ebb33dc2af5c7e1b40078d15ba889f4383c..4059cb5debf0096233667e0ffe16a34e4df54acf 100644 (file)
                                                <tr>
                                                        <td>{{.ID}}</td>
                                                        <td>
-                                                               <a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
+                                                               <a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a>
                                                                {{if .Owner.Visibility.IsPrivate}}
                                                                        <span class="text gold">{{svg "octicon-lock"}}</span>
                                                                {{end}}
                                                        </td>
                                                        <td>
-                                                               <a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">{{.Name}}</a>
+                                                               <a href="{{.Link}}">{{.Name}}</a>
                                                                {{if .IsArchived}}
                                                                        <span class="ui basic mini label">{{$.i18n.Tr "repo.desc.archived"}}</span>
                                                                {{end}}
index ceab7a9b1b0aed4f000b2b60f9fac282c6e9f75c..93e6f38c270189ee934b88f029be1b5f58a2a2b5 100644 (file)
@@ -87,7 +87,7 @@
                                        {{range .Users}}
                                                <tr>
                                                        <td>{{.ID}}</td>
-                                                       <td><a href="{{AppSubUrl}}/{{.Name}}">{{.Name}}</a></td>
+                                                       <td><a href="{{.HomeLink}}">{{.Name}}</a></td>
                                                        <td><span class="text truncate email">{{.Email}}</span></td>
                                                        <td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
                                                        <td>{{if .IsAdmin}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
index bf1fcd24bcbfa0139b5b77133f06db067ed8a9db..d529e6bfda76bcc3f079003edb0fb89b5593a786 100644 (file)
 <meta property="og:site_name" content="{{AppName}}" />
 {{if .IsSigned }}
        {{ if ne .SignedUser.Theme "gitea" }}
-               <link rel="stylesheet" href="{{AssetUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css?v={{MD5 AppVer}}">
+               <link rel="stylesheet" href="{{AssetUrlPrefix}}/css/theme-{{.SignedUser.Theme | PathEscape}}.css?v={{MD5 AppVer}}">
        {{end}}
 {{else if ne DefaultTheme "gitea"}}
-       <link rel="stylesheet" href="{{AssetUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}">
+       <link rel="stylesheet" href="{{AssetUrlPrefix}}/css/theme-{{DefaultTheme | PathEscape}}.css?v={{MD5 AppVer}}">
 {{end}}
 {{template "custom/header" .}}
 </head>
index 348e7671a57e06a922d8be64bea3c2453c4f46ef..57ddbf732a2c2067cc0679db3063b5942e5ab1e6 100644 (file)
@@ -63,8 +63,7 @@
                </div>
        {{else if .IsSigned}}
                <div class="right stackable menu">
-                       {{$issueURL := Printf "%s/%s/issues/%d" AppSubUrl .ActiveStopwatch.RepoSlug .ActiveStopwatch.IssueIndex}}
-                       <a class="active-stopwatch-trigger item ui label {{if not .ActiveStopwatch}}hidden{{end}}" href="{{$issueURL}}">
+                       <a class="active-stopwatch-trigger item ui label {{if not .ActiveStopwatch}}hidden{{end}}" href="{{.ActiveStopwatch.IssueLink}}">
                                <span class="text">
                                        <span class="fitted item">
                                                {{svg "octicon-stopwatch"}}
                        </a>
                        <div class="ui popup very wide">
                                <div class="df ac">
-                                       <a class="stopwatch-link df ac" href="{{$issueURL}}">
+                                       <a class="stopwatch-link df ac" href="{{.ActiveStopwatch.IssueLink}}">
                                                {{svg "octicon-issue-opened"}}
                                                <span class="stopwatch-issue">{{.ActiveStopwatch.RepoSlug}}#{{.ActiveStopwatch.IssueIndex}}</span>
                                                <span class="ui label blue stopwatch-time my-0 mx-4" data-seconds="{{.ActiveStopwatch.Seconds}}">
                                                        {{if .ActiveStopwatch}}{{Sec2Time .ActiveStopwatch.Seconds}}{{end}}
                                                </span>
                                        </a>
-                                       <form class="stopwatch-commit" method="POST" action="{{$issueURL}}/times/stopwatch/toggle">
+                                       <form class="stopwatch-commit" method="POST" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/toggle">
                                                {{.CsrfTokenHtml}}
                                                <button
                                                        class="ui button mini compact basic icon fitted poping up"
@@ -90,7 +89,7 @@
                                                        data-position="top right" data-variation="small inverted"
                                                >{{svg "octicon-square-fill"}}</button>
                                        </form>
-                                       <form class="stopwatch-cancel" method="POST" action="{{$issueURL}}/times/stopwatch/cancel">
+                                       <form class="stopwatch-cancel" method="POST" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/cancel">
                                                {{.CsrfTokenHtml}}
                                                <button
                                                        class="ui button mini compact basic icon fitted poping up"
                                        </div>
 
                                        <div class="divider"></div>
-                                       <a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}">
+                                       <a class="item" href="{{.SignedUser.HomeLink}}">
                                                {{svg "octicon-person"}}
                                                {{.i18n.Tr "your_profile"}}<!-- Your profile -->
                                        </a>
                                        {{if not .DisableStars}}
-                                               <a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}?tab=stars">
+                                               <a class="item" href="{{.SignedUser.HomeLink}}?tab=stars">
                                                        {{svg "octicon-star"}}
                                                        {{.i18n.Tr "your_starred"}}
                                                </a>
index 8cc1b71a7ad0a769161b2dec2e9f01a278a5f36c..29d4075cce3d1f6227dd51087c54bd17739801e3 100644 (file)
@@ -37,8 +37,8 @@
                                                {{$repo := (index $.RepoMaps .RepoID)}}
                                                <div class="diff-file-box diff-box file-content non-diff-file-content repo-search-result">
                                                        <h4 class="ui top attached normal header">
-                                                               <span class="file"><a rel="nofollow" href="{{EscapePound $repo.HTMLURL}}">{{$repo.FullName}}</a> - {{.Filename}}</span>
-                                                               <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $repo.HTMLURL}}/src/commit/{{$result.CommitID}}/{{EscapePound .Filename}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+                                                               <span class="file"><a rel="nofollow" href="{{$repo.HTMLURL}}">{{$repo.FullName}}</a> - {{.Filename}}</span>
+                                                               <a class="ui basic tiny button" rel="nofollow" href="{{$repo.HTMLURL}}/src/commit/{{$result.CommitID | PathEscape}}/{{.Filename | PathEscapeSegments}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
                                                        </h4>
                                                        <div class="ui attached table segment">
                                                                <div class="file-body file-code code-view">
@@ -47,7 +47,7 @@
                                                                                        <tr>
                                                                                                <td class="lines-num">
                                                                                                        {{range .LineNumbers}}
-                                                                                                               <a href="{{EscapePound $repo.HTMLURL}}/src/commit/{{$result.CommitID}}/{{EscapePound $result.Filename}}#L{{.}}"><span>{{.}}</span></a>
+                                                                                                               <a href="{{$repo.HTMLURL}}/src/commit/{{$result.CommitID | PathEscape}}/{{$result.Filename | PathEscapeSegments}}#L{{.}}"><span>{{.}}</span></a>
                                                                                                        {{end}}
                                                                                                </td>
                                                                                                <td class="lines-code chroma"><code class="code-inner">{{.FormattedLines | Safe}}</code></td>
index ad34d9eebe9e9cfd5bdf2e570a80de8f4d24cf5f..31e9a9688276cd8530ccae4f35c84a92d8e327c0 100644 (file)
@@ -5,7 +5,7 @@
        <title>{{.i18n.Tr "mail.activate_account.title" .DisplayName}}</title>
 </head>
 
-{{ $activate_url := printf "%suser/activate?code=%s" AppUrl .Code}}
+{{ $activate_url := printf "%suser/activate?code=%s" AppUrl (QueryEscape .Code)}}
 <body>
        <p>{{.i18n.Tr "mail.activate_account.text_1" .DisplayName AppName | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.activate_account.text_2" .ActiveCodeLives | Str2html}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
index a1d7ec37ec5dc787cef8a3f40e374f74d1f1d1f6..8bd037ae4f685cc89eb66527862f5a1864ef71bf 100644 (file)
@@ -5,7 +5,7 @@
        <title>{{.i18n.Tr "mail.activate_email.title" .DisplayName}}</title>
 </head>
 
-{{ $activate_url := printf "%suser/activate_email?code=%s&email=%s" AppUrl .Code (QueryEscape .Email)}}
+{{ $activate_url := printf "%suser/activate_email?code=%s&email=%s" AppUrl (QueryEscape .Code) (QueryEscape .Email)}}
 <body>
        <p>{{.i18n.Tr "mail.hi_user_x" .DisplayName | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.activate_email.text" .ActiveCodeLives | Str2html}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
index e1ab97b760e1f49af223cdca5d4c8f4e49b85b87..45ca95f2c3e0f1754c915dc181dce5fc46fce84b 100644 (file)
@@ -10,7 +10,7 @@
        <p>{{.i18n.Tr "mail.hi_user_x" .DisplayName | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.register_notify.text_1" AppName}}</p><br>
        <p>{{.i18n.Tr "mail.register_notify.text_2" .Username}}</p><p><a href="{{AppUrl}}user/login">{{AppUrl}}user/login</a></p><br>
-       <p>{{.i18n.Tr "mail.register_notify.text_3" $set_pwd_url | Str2html}}</p><br>
+       <p>{{.i18n.Tr "mail.register_notify.text_3" ($set_pwd_url | Escape) | Str2html}}</p><br>
 
        <p>© <a target="_blank" rel="noopener noreferrer" href="{{AppUrl}}">{{AppName}}</a></p>
 </body>
index 7cab33bf4e3127b15e423f38e9b0bbfce4404a70..bf10c1f96787a77b64fed2df29fb501fcd2c3fd3 100644 (file)
@@ -5,7 +5,7 @@
        <title>{{.i18n.Tr "mail.reset_password.title" .DisplayName}}</title>
 </head>
 
-{{ $recover_url := printf "%suser/recover_account?code=%s" AppUrl .Code}}
+{{ $recover_url := printf "%suser/recover_account?code=%s" AppUrl (QueryEscape .Code)}}
 <body>
        <p>{{.i18n.Tr "mail.hi_user_x" .DisplayName | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.reset_password.text" .ResetPwdCodeLives | Str2html}}</p><p><a href="{{$recover_url}}">{{$recover_url}}</a></p><br>
index 1c3b93097815cef1ecf34bc194e3dc863e012af9..e1156c53358368ac7a6022287497172017956c17 100644 (file)
@@ -8,8 +8,8 @@
        <title>{{.Subject}}</title>
 </head>
 
-{{$repo_url := printf "<a href='%s'>%s</a>" .Issue.Repo.HTMLURL .Issue.Repo.FullName}}
-{{$link := printf "<a href='%s'>#%d</a>" .Link .Issue.Index}}
+{{$repo_url := printf "<a href='%s'>%s</a>" (Escape .Issue.Repo.HTMLURL) (Escape .Issue.Repo.FullName)}}
+{{$link := printf "<a href='%s'>#%d</a>" (Escape .Link) (Escape .Issue.Index)}}
 <body>
        <p>
                {{if .IsPull}}
index 0c09c6d043acb49159ea49fb67769b84d82e6d3e..e01ec667eedc88f4081ef7425e5a110046ec7da0 100644 (file)
        {{if eq .ActionName "push"}}
                <p>
                        {{if .Comment.IsForcePush}}
-                               {{$oldCommitUrl := printf "%s%s/%s/commit/%s" AppUrl  .Comment.Issue.PullRequest.BaseRepo.OwnerName .Comment.Issue.PullRequest.BaseRepo.Name .Comment.OldCommit}}
+                               {{$oldCommitUrl := printf "%s/commit/%s" .Comment.Issue.PullRequest.BaseRepo.HTMLURL .Comment.OldCommit}}
                                {{$oldShortSha := ShortSha .Comment.OldCommit}}
-                               {{$oldCommitLink := printf "<a href='%[1]s'><b>%[2]s</b></a>" $oldCommitUrl $oldShortSha}}
+                               {{$oldCommitLink := printf "<a href='%[1]s'><b>%[2]s</b></a>" (Escape $oldCommitUrl) (Escape $oldShortSha)}}
 
-                               {{$newCommitUrl := printf "%s%s/%s/commit/%s" AppUrl  .Comment.Issue.PullRequest.BaseRepo.OwnerName .Comment.Issue.PullRequest.BaseRepo.Name .Comment.NewCommit}}
+                               {{$newCommitUrl := printf "%s/commit/%s" .Comment.Issue.PullRequest.BaseRepo.HTMLURL .Comment.NewCommit}}
                                {{$newShortSha := ShortSha .Comment.NewCommit}}
-                               {{$newCommitLink := printf "<a href='%[1]s'><b>%[2]s</b></a>" $newCommitUrl $newShortSha}}
+                               {{$newCommitLink := printf "<a href='%[1]s'><b>%[2]s</b></a>" (Escape $newCommitUrl) (Escape $newShortSha)}}
 
                                {{.i18n.Tr "mail.issue.action.force_push" .Doer.Name .Comment.Issue.PullRequest.HeadBranch $oldCommitLink $newCommitLink | Str2html}}
                        {{else}}
        {{end}}
        <p>
                {{if eq .ActionName "close"}}
-                       {{.i18n.Tr "mail.issue.action.close" .Doer.Name .Issue.Index | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.close" (Escape .Doer.Name) .Issue.Index | Str2html}}
                {{else if eq .ActionName "reopen"}}
-                       {{.i18n.Tr "mail.issue.action.reopen" .Doer.Name .Issue.Index | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.reopen" (Escape .Doer.Name) .Issue.Index | Str2html}}
                {{else if eq .ActionName "merge"}}
-                       {{.i18n.Tr "mail.issue.action.merge" .Doer.Name .Issue.Index .Issue.PullRequest.BaseBranch | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.merge" (Escape .Doer.Name) .Issue.Index (Escape .Issue.PullRequest.BaseBranch) | Str2html}}
                {{else if eq .ActionName "approve"}}
-                       {{.i18n.Tr "mail.issue.action.approve" .Doer.Name | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.approve" (Escape .Doer.Name) | Str2html}}
                {{else if eq .ActionName "reject"}}
-                       {{.i18n.Tr "mail.issue.action.reject" .Doer.Name | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.reject" (Escape .Doer.Name) | Str2html}}
                {{else if eq .ActionName "review"}}
-                       {{.i18n.Tr "mail.issue.action.review" .Doer.Name | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.review" (Escape .Doer.Name) | Str2html}}
                {{else if eq .ActionName "review_dismissed"}}
-                       {{.i18n.Tr "mail.issue.action.review_dismissed" .Doer.Name .Comment.Review.Reviewer.Name | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.review_dismissed" (Escape .Doer.Name) (Escape .Comment.Review.Reviewer.Name) | Str2html}}
                {{else if eq .ActionName "ready_for_review"}}
-                       {{.i18n.Tr "mail.issue.action.ready_for_review" .Doer.Name | Str2html}}
+                       {{.i18n.Tr "mail.issue.action.ready_for_review" (Escape .Doer.Name) | Str2html}}
                {{end}}
 
                {{- if eq .Body ""}}
                        {{if eq .ActionName "new"}}
-                               {{.i18n.Tr "mail.issue.action.new" .Doer.Name .Issue.Index | Str2html}}
+                               {{.i18n.Tr "mail.issue.action.new" (Escape .Doer.Name) .Issue.Index | Str2html}}
                        {{end}}
                {{else}}
                        {{.Body | Str2html}}
@@ -72,7 +72,7 @@
                        <ul>
                        {{range .Comment.Commits}}
                                <li>
-                                       <a href="{{AppUrl}}{{$.Comment.Issue.PullRequest.BaseRepo.OwnerName}}/{{$.Comment.Issue.PullRequest.BaseRepo.Name}}/commit/{{.ID}}">
+                                       <a href="{{$.Comment.Issue.PullRequest.BaseRepo.HTMLURL}}/commit/{{.ID}}">
                                                {{ShortSha .ID.String}}
                                        </a>  -  {{.Summary}}
                                </li>
index 4dea9474016db6d8b5a9f48fb1024135cbea927d..6250ff7c20b82a220161fb1a13b11bfa438eacb8 100644 (file)
@@ -5,7 +5,7 @@
        <title>{{.Subject}}</title>
 </head>
 
-{{$url := printf "<a href='%[1]s'>%[2]s</a>" .Link .Repo}}
+{{$url := printf "<a href='%[1]s'>%[2]s</a>" (Escape .Link) (Escape .Repo)}}
 <body>
        <p>{{.Subject}}.
                {{.i18n.Tr "mail.repo.transfer.body" $url | Str2html}}
index fabe4999e30f8b1b4c2a30f5c7cb94e27646c654..813aba556ca465d12eb8ed8528c0cf2649166eb0 100644 (file)
@@ -11,8 +11,8 @@
 
 </head>
 
-{{$release_url := printf "<a href='%s'>%s</a>" .Release.HTMLURL .Release.TagName}}
-{{$repo_url := printf "<a href='%s'>%s</a>" .Release.Repo.HTMLURL .Release.Repo.FullName}}
+{{$release_url := printf "<a href='%s'>%s</a>" (.Release.HTMLURL | Escape) (.Release.TagName | Escape) }}
+{{$repo_url := printf "<a href='%s'>%s</a>" (.Release.Repo.HTMLURL | Escape) (.Release.Repo.FullName | Escape)}}
 <body>
        <p>
                {{.i18n.Tr "mail.release.new.text" .Release.Publisher.Name $release_url $repo_url | Str2html}}
                <br>
                {{.i18n.Tr "mail.release.downloads"}}
                <ul>
-                       {{$tagname := .Release.TagName | EscapePound}}
-                       {{$archive_url := printf "%s%s/%s/archive" AppUrl .Release.Repo.OwnerName .Release.Repo.Name}}
                        <li>
-                               <a href="{{$archive_url}}/{{$tagname}}.zip" rel="nofollow"><strong>{{.i18n.Tr "mail.release.download.zip"}}</strong></a>
+                               <a href="{{.Release.Repo.Link}}/archive/{{.Release.TagName | PathEscapeSegments}}.zip" rel="nofollow"><strong>{{.i18n.Tr "mail.release.download.zip"}}</strong></a>
                        </li>
                        <li>
-                               <a href="{{$archive_url}}/{{$tagname}}.tar.gz" rel="nofollow"><strong>{{.i18n.Tr "mail.release.download.targz"}}</strong></a>
+                               <a href="{{.Release.Repo.Link}}/archive/{{.Release.TagName | PathEscapeSegments}}.tar.gz" rel="nofollow"><strong>{{.i18n.Tr "mail.release.download.targz"}}</strong></a>
                        </li>
                        {{if .Release.Attachments}}
                                {{range .Release.Attachments}}
index 153de30ca31d43d86a61080c55049353180eccf7..868d956011e9888cf0b8fe0b961d48919a6c53dd 100644 (file)
                                        <div class="ui attached table segment teams">
                                                {{range .Teams}}
                                                        <div class="item">
-                                                               <a href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong class="team-name">{{.Name}}</strong></a>
+                                                               <a href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong class="team-name">{{.Name}}</strong></a>
                                                                <p class="text grey">
-                                                                       <a href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong>{{.NumMembers}}</strong> {{$.i18n.Tr "org.lower_members"}}</a> ·
-                                                                       <a href="{{$.OrgLink}}/teams/{{.LowerName}}/repositories"><strong>{{.NumRepos}}</strong> {{$.i18n.Tr "org.lower_repositories"}}</a>
+                                                                       <a href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong>{{.NumMembers}}</strong> {{$.i18n.Tr "org.lower_members"}}</a> ·
+                                                                       <a href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}/repositories"><strong>{{.NumRepos}}</strong> {{$.i18n.Tr "org.lower_repositories"}}</a>
                                                                </p>
                                                        </div>
                                                {{end}}
index f2c89e065364abc19f19007f449cb1a5109666e9..a064ee9b4f7be499dd24280143407e0d43f29261 100644 (file)
@@ -9,7 +9,7 @@
                                {{template "org/team/navbar" .}}
                                {{if .IsOrganizationOwner}}
                                        <div class="ui attached segment">
-                                               <form class="ui form" id="add-member-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/add" method="post">
+                                               <form class="ui form" id="add-member-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/add" method="post">
                                                        {{.CsrfTokenHtml}}
                                                        <input type="hidden" name="uid" value="{{.SignedUser.ID}}">
                                                        <div class="inline field ui left">
@@ -29,7 +29,7 @@
                                                        {{if and $.IsOrganizationOwner (not (eq $.SignedUser.ID .ID))}}
                                                                <form>
                                                                        <button class="ui red button delete-button right" data-modal-id="remove-team-member"
-                                                                               data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/remove" data-datauid="{{.ID}}"
+                                                                               data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/remove" data-datauid="{{.ID}}"
                                                                                data-name="{{.DisplayName}}"
                                                                                data-data-team-name="{{$.Team.Name}}">{{$.i18n.Tr "org.members.remove"}}</button>
                                                                </form>
index b5732ed71b90dbe0141996e9f82e327483af77ba..2dfa244e5f6bd076312a4adbd06a25bbc94c6988 100644 (file)
@@ -1,4 +1,4 @@
 <div class="ui top attached tabular menu">
-       <a class="item{{if .PageIsOrgTeamMembers}} active{{end}}" href="{{.OrgLink}}/teams/{{.Team.LowerName}}">{{svg "octicon-person"}} <strong>{{.Team.NumMembers}}</strong>&nbsp; {{$.i18n.Tr "org.lower_members"}}</a>
-       <a class="item{{if .PageIsOrgTeamRepos}} active{{end}}" href="{{.OrgLink}}/teams/{{.Team.LowerName}}/repositories">{{svg "octicon-repo"}} <strong>{{.Team.NumRepos}}</strong>&nbsp; {{$.i18n.Tr "org.lower_repositories"}}</a>
+       <a class="item{{if .PageIsOrgTeamMembers}} active{{end}}" href="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}">{{svg "octicon-person"}} <strong>{{.Team.NumMembers}}</strong>&nbsp; {{$.i18n.Tr "org.lower_members"}}</a>
+       <a class="item{{if .PageIsOrgTeamRepos}} active{{end}}" href="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/repositories">{{svg "octicon-repo"}} <strong>{{.Team.NumRepos}}</strong>&nbsp; {{$.i18n.Tr "org.lower_repositories"}}</a>
 </div>
index b4c385a2b009b6d12e543065df5b69af4e170e7c..d6a0e41417f2220a8a80b20216e40f8d0053c7b3 100644 (file)
@@ -3,7 +3,7 @@
        {{template "org/header" .}}
        <div class="ui middle very relaxed page grid">
                <div class="column">
-                       <form class="ui form" action="{{if .PageIsOrgTeamsNew}}{{.OrgLink}}/teams/new{{else}}{{.OrgLink}}/teams/{{.Team.LowerName}}/edit{{end}}" data-delete-url="{{.OrgLink}}/teams/{{.Team.LowerName}}/delete" method="post">
+                       <form class="ui form" action="{{if .PageIsOrgTeamsNew}}{{.OrgLink}}/teams/new{{else}}{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/edit{{end}}" data-delete-url="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/delete" method="post">
                                {{.CsrfTokenHtml}}
                                <h3 class="ui top attached header">
                                        {{if .PageIsOrgTeamsNew}}{{.i18n.Tr "org.create_new_team"}}{{else}}{{.i18n.Tr "org.teams.settings"}}{{end}}
                                                {{else}}
                                                        <button class="ui green button">{{.i18n.Tr "org.teams.update_settings"}}</button>
                                                        {{if not (eq .Team.LowerName "owners")}}
-                                                               <button class="ui red button delete-button" data-url="{{.OrgLink}}/teams/{{.team_name}}/delete">{{.i18n.Tr "org.teams.delete_team"}}</button>
+                                                               <button class="ui red button delete-button" data-url="{{.OrgLink}}/teams/{{.team_name | PathEscape}}/delete">{{.i18n.Tr "org.teams.delete_team"}}</button>
                                                        {{end}}
                                                {{end}}
                                        </div>
index 350e8a4628b66ad479984a4e2bec2605d9423c8c..ae747ef2cc85868348bd0c1b947ddbbb52b4865d 100644 (file)
@@ -11,7 +11,7 @@
                                {{if $canAddRemove}}
                                        <div class="ui attached segment" id="repo-top-segment">
                                                <div class="inline ui field left">
-                                                       <form class="ui form" id="add-repo-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/add" method="post">
+                                                       <form class="ui form" id="add-repo-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/add" method="post">
                                                                {{.CsrfTokenHtml}}
                                                                <div class="inline field ui left">
                                                                        <div id="search-repo-box" data-uid="{{.Org.ID}}" class="ui search">
@@ -24,9 +24,9 @@
                                                        </form>
                                                </div>
                                                <div class="inline ui field right">
-                                                       <form class="ui form" id="repo-multiple-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/repositories" method="post">
-                                                               <button class="ui red button delete-button right" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/removeall">{{.i18n.Tr "remove_all"}}</button>
-                                                               <button class="ui green button add-all-button right" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/addall">{{.i18n.Tr "add_all"}}</button>
+                                                       <form class="ui form" id="repo-multiple-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/repositories" method="post">
+                                                               <button class="ui red button delete-button right" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/removeall">{{.i18n.Tr "remove_all"}}</button>
+                                                               <button class="ui green button add-all-button right" data-url="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/addall">{{.i18n.Tr "add_all"}}</button>
                                                        </form>
                                                </div>
                                        </div>
                                        {{range .Team.Repos}}
                                                <div class="item">
                                                        {{if $canAddRemove}}
-                                                               <form method="post" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/remove">
+                                                               <form method="post" action="{{$.OrgLink}}/teams/{{$.Team.LowerName | PathEscape}}/action/repo/remove">
                                                                        {{$.CsrfTokenHtml}}
                                                                        <button type="submit" class="ui red small button right" name="repoid" value="{{.ID}}">{{$.i18n.Tr "remove"}}</button>
                                                                </form>
                                                        {{end}}
-                                                       <a class="member" href="{{AppSubUrl}}/{{$.Org.Name}}/{{.Name}}">
+                                                       <a class="member" href="{{$.Org.HomeLink}}/{{.Name | PathEscape}}">
                                                                {{if .IsPrivate}}
                                                                        {{svg "octicon-lock"}}
                                                                {{else if .IsFork}}
index 84729a08416136a77801c0bc770b3fa8e0420bdf..2e3769de479a15bba1cccc4eae8d4e6877174039 100644 (file)
@@ -5,11 +5,11 @@
                        {{if .Team.IsMember $.SignedUser.ID}}
                                <form>
                                        <button class="ui red tiny button delete-button" data-modal-id="leave-team-sidebar"
-                                               data-url="{{.OrgLink}}/teams/{{.Team.LowerName}}/action/leave" data-datauid="{{$.SignedUser.ID}}"
+                                               data-url="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/action/leave" data-datauid="{{$.SignedUser.ID}}"
                                                data-name="{{.Team.Name}}">{{$.i18n.Tr "org.teams.leave"}}</button>
                                </form>
                        {{else if .IsOrganizationOwner}}
-                               <form method="post" action="{{.OrgLink}}/teams/{{.Team.LowerName}}/action/join">
+                               <form method="post" action="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/action/join">
                                        {{$.CsrfTokenHtml}}
                                        <input type="hidden" name="page" value="team"/>
                                        <button type="submit" class="ui blue tiny button" name="uid" value="{{$.SignedUser.ID}}">{{$.i18n.Tr "org.teams.join"}}</button>
@@ -55,7 +55,7 @@
        </div>
        {{if .IsOrganizationOwner}}
                <div class="ui bottom attached segment">
-                       <a class="ui teal small button" href="{{.OrgLink}}/teams/{{.Team.LowerName}}/edit">{{svg "octicon-gear"}} {{$.i18n.Tr "org.teams.settings"}}</a>
+                       <a class="ui teal small button" href="{{.OrgLink}}/teams/{{.Team.LowerName | PathEscape}}/edit">{{svg "octicon-gear"}} {{$.i18n.Tr "org.teams.settings"}}</a>
                </div>
        {{end}}
 </div>
index 6f4f155072f7110e5e2a865654ee324696da6153..9165a62bcab61c2abd865885630ad8decb969bc4 100644 (file)
                        {{range .Teams}}
                                <div class="column">
                                        <div class="ui top attached header">
-                                               <a class="text black" href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong>{{.Name}}</strong></a>
+                                               <a class="text black" href="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}"><strong>{{.Name}}</strong></a>
                                                <div class="ui right">
                                                        {{if .IsMember $.SignedUser.ID}}
                                                                <form>
                                                                        <button class="ui red tiny button delete-button" data-modal-id="leave-team"
-                                                                               data-url="{{$.OrgLink}}/teams/{{.LowerName}}/action/leave" data-datauid="{{$.SignedUser.ID}}"
+                                                                               data-url="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}/action/leave" data-datauid="{{$.SignedUser.ID}}"
                                                                                data-name="{{.Name}}">{{$.i18n.Tr "org.teams.leave"}}</button>
                                                                </form>
                                                        {{else if $.IsOrganizationOwner}}
-                                                               <form method="post" action="{{$.OrgLink}}/teams/{{.LowerName}}/action/join">
+                                                               <form method="post" action="{{$.OrgLink}}/teams/{{.LowerName | PathEscape}}/action/join">
                                                                        {{$.CsrfTokenHtml}}
                                                                        <button type="submit" class="ui blue small button" name="uid" value="{{$.SignedUser.ID}}">{{$.i18n.Tr "org.teams.join"}}</button>
                                                                </form>
index d4cff880e58294cbaf91ad53903bac1cca967b3a..c67925e4233ca09a3562134d3c86ff1d391ddbf2 100644 (file)
                                                <span class="ui green label">{{$.i18n.Tr "repo.activity.published_release_label"}}</span>
                                                {{.TagName}}
                                                {{if not .IsTag}}
-                                                       <a class="title" href="{{$.RepoLink}}/src/{{.TagName | EscapePound}}">{{.Title | RenderEmoji}}</a>
+                                                       <a class="title" href="{{$.RepoLink}}/src/{{.TagName | PathEscapeSegments}}">{{.Title | RenderEmoji}}</a>
                                                {{end}}
                                                {{TimeSinceUnix .CreatedUnix $.Lang}}
                                        </p>
index c7c497088a9e25dada4fdc0dcdab0ed5fad34d6d..4c04f1f7b8832a00fc7e60c3b48b65e30c6332a8 100644 (file)
                </div>
                <div class="file-header-right file-actions df ac">
                        <div class="ui buttons">
-                               <a class="ui tiny button" href="{{EscapePound $.RawFileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
+                               <a class="ui tiny button" href="{{$.RawFileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
                                {{if not .IsViewCommit}}
-                                       <a class="ui tiny button" href="{{.RepoLink}}/src/commit/{{.CommitID}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_permalink"}}</a>
+                                       <a class="ui tiny button" href="{{.RepoLink}}/src/commit/{{.CommitID | PathEscape}}/{{.TreePath | PathEscapeSegments}}">{{.i18n.Tr "repo.file_permalink"}}</a>
                                {{end}}
-                               <a class="ui tiny button" href="{{.RepoLink}}/src/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.normal_view"}}</a>
-                               <a class="ui tiny button" href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_history"}}</a>
+                               <a class="ui tiny button" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">{{.i18n.Tr "repo.normal_view"}}</a>
+                               <a class="ui tiny button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">{{.i18n.Tr "repo.file_history"}}</a>
                        </div>
                </div>
        </h4>
index cadf91df041c556752c09c061eb50be43dbc8e38..5b95f1be72e08c8bc9eb56ad6af3965094077440 100644 (file)
                                                                {{if .IsProtected}}
                                                                        {{svg "octicon-shield-lock"}}
                                                                {{end}}
-                                                               <a href="{{$.RepoLink}}/src/branch/{{$.DefaultBranch | EscapePound}}">{{$.DefaultBranch}}</a>
-                                                               <p class="info df ac my-2">{{svg "octicon-git-commit" 16 "mr-2"}}<a href="{{$.RepoLink}}/commit/{{.Commit.ID.String}}">{{ShortSha .Commit.ID.String}}</a> · <span class="commit-message">{{RenderCommitMessage .Commit.CommitMessage $.RepoLink $.Repository.ComposeMetas}}</span> · {{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Commit.Committer.When $.i18n.Lang}}</p>
+                                                               <a href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments $.DefaultBranch}}">{{$.DefaultBranch}}</a>
+                                                               <p class="info df ac my-2">{{svg "octicon-git-commit" 16 "mr-2"}}<a href="{{$.RepoLink}}/commit/{{PathEscape .Commit.ID.String}}">{{ShortSha .Commit.ID.String}}</a> · <span class="commit-message">{{RenderCommitMessage .Commit.CommitMessage $.RepoLink $.Repository.ComposeMetas}}</span> · {{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Commit.Committer.When $.i18n.Lang}}</p>
                                                        {{end}}
                                                {{end}}
                                                </td>
                                                <td class="right aligned overflow-visible">
                                                        {{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted)}}
-                                                               <div class="ui basic jump button icon poping up show-create-branch-modal" data-content="{{$.i18n.Tr "repo.branch.new_branch_from" ($.DefaultBranch)}}" data-variation="tiny inverted" data-branch-from="{{EscapePound $.DefaultBranch}}" data-modal="#create-branch-modal" data-position="top right">
+                                                               <div class="ui basic jump button icon poping up show-create-branch-modal" data-content="{{$.i18n.Tr "repo.branch.new_branch_from" ($.DefaultBranch)}}" data-variation="tiny inverted" data-branch-from="{{$.DefaultBranch}}" data-branch-from-urlcomponent="{{PathEscapeSegments $.DefaultBranch}}" data-modal="#create-branch-modal" data-position="top right">
                                                                        {{svg "octicon-git-branch"}}
                                                                </div>
                                                        {{end}}
                                                        <div class="ui basic jump dropdown icon button poping up" data-content="{{$.i18n.Tr "repo.branch.download" ($.DefaultBranch)}}" data-variation="tiny inverted" data-position="top right">
                                                                {{svg "octicon-download"}}
                                                                <div class="menu">
-                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound $.DefaultBranch}}.zip">{{svg "octicon-file-zip"}}&nbsp;ZIP</a>
-                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound $.DefaultBranch}}.tar.gz">{{svg "octicon-file-zip"}}&nbsp;TAR.GZ</a>
+                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{PathEscapeSegments $.DefaultBranch}}.zip">{{svg "octicon-file-zip"}}&nbsp;ZIP</a>
+                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{PathEscapeSegments $.DefaultBranch}}.tar.gz">{{svg "octicon-file-zip"}}&nbsp;TAR.GZ</a>
                                                                </div>
                                                        </div>
                                                </td>
                                                                <tr>
                                                                        <td class="six wide">
                                                                        {{if .IsDeleted}}
-                                                                               <s><a href="{{$.RepoLink}}/src/branch/{{.Name | EscapePound}}">{{.Name}}</a></s>
+                                                                               <s><a href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments .Name}}">{{.Name}}</a></s>
                                                                                <p class="info">{{$.i18n.Tr "repo.branch.deleted_by" .DeletedBranch.DeletedBy.Name}} {{TimeSinceUnix .DeletedBranch.DeletedUnix $.i18n.Lang}}</p>
                                                                        {{else}}
                                                                                {{if .IsProtected}}
                                                                                        {{svg "octicon-shield-lock"}}
                                                                                {{end}}
-                                                                               <a href="{{$.RepoLink}}/src/branch/{{.Name | EscapePound}}">{{.Name}}</a>
-                                                                               <p class="info df ac my-2">{{svg "octicon-git-commit" 16 "mr-2"}}<a href="{{$.RepoLink}}/commit/{{.Commit.ID.String}}">{{ShortSha .Commit.ID.String}}</a> · <span class="commit-message">{{RenderCommitMessage .Commit.CommitMessage $.RepoLink $.Repository.ComposeMetas}}</span> · {{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Commit.Committer.When $.i18n.Lang}}</p>
+                                                                               <a href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments .Name}}">{{.Name}}</a>
+                                                                               <p class="info df ac my-2">{{svg "octicon-git-commit" 16 "mr-2"}}<a href="{{$.RepoLink}}/commit/{{PathEscape .Commit.ID.String}}">{{ShortSha .Commit.ID.String}}</a> · <span class="commit-message">{{RenderCommitMessage .Commit.CommitMessage $.RepoLink $.Repository.ComposeMetas}}</span> · {{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Commit.Committer.When $.i18n.Lang}}</p>
                                                                        {{end}}
                                                                        </td>
                                                                        <td class="three wide ui">
                                                                                                        {{svg "octicon-git-pull-request"}} {{$.i18n.Tr "repo.branch.included"}}
                                                                                                </a>
                                                                                        {{else if and (not .IsDeleted) $.AllowsPulls (gt .CommitsAhead 0)}}
-                                                                                       <a href="{{$.RepoLink}}/compare/{{$.DefaultBranch | EscapePound}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{$.Owner.Name}}:{{end}}{{.Name | EscapePound}}">
+                                                                                       <a href="{{$.RepoLink}}/compare/{{PathEscapeSegments $.DefaultBranch}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{PathEscape $.Owner.Name}}:{{end}}{{PathEscapeSegments .Name}}">
                                                                                                <button id="new-pull-request" class="ui compact basic button mr-0">{{if $.CanPull}}{{$.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{$.i18n.Tr "action.compare_branch"}}{{end}}</button>
                                                                                        </a>
                                                                                        {{end}}
                                                                                {{else if and .LatestPullRequest.HasMerged .MergeMovedOn}}
                                                                                        {{if and (not .IsDeleted) $.AllowsPulls (gt .CommitsAhead 0)}}
-                                                                                       <a href="{{$.RepoLink}}/compare/{{$.DefaultBranch | EscapePound}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{$.Owner.Name}}:{{end}}{{.Name | EscapePound}}">
+                                                                                       <a href="{{$.RepoLink}}/compare/{{PathEscapeSegments $.DefaultBranch}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{$.Owner.Name}}:{{end}}{{.Name | PathEscapeSegments}}">
                                                                                                <button id="new-pull-request" class="ui compact basic button mr-0">{{if $.CanPull}}{{$.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{$.i18n.Tr "action.compare_branch"}}{{end}}</button>
                                                                                        </a>
                                                                                        {{end}}
                                                                        </td>
                                                                        <td class="two wide right aligned overflow-visible">
                                                                                {{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted)}}
-                                                                                       <div class="ui basic jump button icon poping up show-create-branch-modal" data-branch-from="{{EscapePound .Name}}" data-content="{{$.i18n.Tr "repo.branch.new_branch_from" .Name}}" data-variation="tiny inverted" data-position="top right" data-modal="#create-branch-modal" data-name="{{.Name}}">
+                                                                                       <div class="ui basic jump button icon poping up show-create-branch-modal" data-branch-from="{{.Name}}" data-branch-from-urlcomponent="{{PathEscapeSegments .Name}}" data-content="{{$.i18n.Tr "repo.branch.new_branch_from" .Name}}" data-variation="tiny inverted" data-position="top right" data-modal="#create-branch-modal" data-name="{{.Name}}">
                                                                                                {{svg "octicon-git-branch"}}
                                                                                        </div>
                                                                                {{end}}
                                                                                        <div class="ui basic jump dropdown icon button poping up" data-content="{{$.i18n.Tr "repo.branch.download" (.Name)}}" data-variation="tiny inverted" data-position="top right">
                                                                                                {{svg "octicon-download"}}
                                                                                                <div class="menu">
-                                                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound .Name}}.zip">{{svg "octicon-file-zip"}}&nbsp;ZIP</a>
-                                                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound .Name}}.tar.gz">{{svg "octicon-file-zip"}}&nbsp;TAR.GZ</a>
+                                                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{PathEscapeSegments .Name}}.zip">{{svg "octicon-file-zip"}}&nbsp;ZIP</a>
+                                                                                                       <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{PathEscapeSegments .Name}}.tar.gz">{{svg "octicon-file-zip"}}&nbsp;TAR.GZ</a>
                                                                                                </div>
                                                                                        </div>
                                                                                {{end}}
                                                                                {{if and $.IsWriter (not $.IsMirror) (not $.Repository.IsArchived) (not .IsProtected)}}
                                                                                        {{if .IsDeleted}}
-                                                                                               <a class="ui basic jump button icon poping up undo-button" href data-url="{{$.Link}}/restore?branch_id={{.DeletedBranch.ID | urlquery}}&name={{.DeletedBranch.Name | urlquery}}" data-content="{{$.i18n.Tr "repo.branch.restore" (.Name)}}" data-variation="tiny inverted" data-position="top right"><span class="text blue">{{svg "octicon-reply"}}</span></a>
+                                                                                               <a class="ui basic jump button icon poping up undo-button" href data-url="{{$.Link}}/restore?branch_id={{.DeletedBranch.ID}}&name={{PathEscapeSegments .DeletedBranch.Name}}" data-content="{{$.i18n.Tr "repo.branch.restore" (.Name)}}" data-variation="tiny inverted" data-position="top right"><span class="text blue">{{svg "octicon-reply"}}</span></a>
                                                                                        {{else}}
-                                                                                               <a class="ui basic jump button icon poping up delete-button delete-branch-button" href data-url="{{$.Link}}/delete?name={{.Name | urlquery}}" data-content="{{$.i18n.Tr "repo.branch.delete" (.Name)}}" data-variation="tiny inverted" data-position="top right" data-name="{{.Name}}">
+                                                                                               <a class="ui basic jump button icon poping up delete-button delete-branch-button" href data-url="{{$.Link}}/delete?name={{PathEscapeSegments .Name}}" data-content="{{$.i18n.Tr "repo.branch.delete" (.Name)}}" data-variation="tiny inverted" data-position="top right" data-name="{{.Name}}">
                                                                                                        {{svg "octicon-trash"}}
                                                                                                </a>
                                                                                        {{end}}
index 1605fa91a75e0cf833eb4fe010fceb67da658294..a2115729b289816162a6e2af72361ecccd6ffd8c 100644 (file)
                <div class="data" style="display: none" data-mode="{{if .root.IsViewTag}}tags{{else}}branches{{end}}">
                        {{if $showBranchesInDropdown}}
                                {{range .root.Branches}}
-                                       <div class="item branch {{if eq $.root.BranchName .}}selected{{end}}" data-url="{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/branch/{{EscapePound .}}{{if $.root.TreePath}}/{{EscapePound $.root.TreePath}}{{end}}">{{.}}</div>
+                                       <div class="item branch {{if eq $.root.BranchName .}}selected{{end}}" data-url="{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/branch/{{PathEscapeSegments .}}{{if $.root.TreePath}}/{{PathEscapeSegments $.root.TreePath}}{{end}}">{{.}}</div>
                                {{end}}
                        {{end}}
                        {{range .root.Tags}}
                                {{if $release}}
-                                       <div class="item tag {{if eq $release.TagName .}}selected{{end}}" data-url="{{$.root.RepoLink}}/compare/{{EscapePound .}}...{{if $release.IsDraft}}{{EscapePound $release.Target}}{{else}}{{if $release.TagName}}{{EscapePound $release.TagName}}{{else}}{{EscapePound $release.Sha1}}{{end}}{{end}}">{{.}}</div>
+                                       <div class="item tag {{if eq $release.TagName .}}selected{{end}}" data-url="{{$.root.RepoLink}}/compare/{{PathEscapeSegments .}}...{{if $release.IsDraft}}{{PathEscapeSegments $release.Target}}{{else}}{{if $release.TagName}}{{PathEscapeSegments $release.TagName}}{{else}}{{PathEscapeSegments $release.Sha1}}{{end}}{{end}}">{{.}}</div>
                                {{else}}
-                                       <div class="item tag {{if eq $.root.BranchName .}}selected{{end}}" data-url="{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/tag/{{EscapePound .}}{{if $.root.TreePath}}/{{EscapePound $.root.TreePath}}{{end}}">{{.}}</div>
+                                       <div class="item tag {{if eq $.root.BranchName .}}selected{{end}}" data-url="{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/tag/{{PathEscapeSegments .}}{{if $.root.TreePath}}/{{PathEscapeSegments $.root.TreePath}}{{end}}">{{.}}</div>
                                {{end}}
                        {{end}}
                </div>
@@ -71,7 +71,7 @@
                                                        {{end}}
                                                </div>
                                        </a>
-                                       <form ref="newBranchForm" action="{{.root.RepoLink}}/branches/_new/{{EscapePound .root.BranchNameSubURL}}" method="post">
+                                       <form ref="newBranchForm" action="{{.root.RepoLink}}/branches/_new/{{.root.BranchNameSubURL}}" method="post">
                                                {{.root.CsrfTokenHtml}}
                                                <input type="hidden" name="new_branch_name" v-model="searchTerm">
                                                <input type="hidden" name="create_tag" v-model="createTag">
index 01cbd5182dc6632e17ebaf0781851711b0d2d931..b2aadacb7b447f8023c3cee4862177cea36782cb 100644 (file)
@@ -19,7 +19,7 @@
                {{end}}
                <div class="ui top attached info clearing segment {{$class}}">
                        {{if not $.PageIsWiki}}
-                       <a class="ui floated right blue tiny button" href="{{EscapePound .SourcePath}}">
+                       <a class="ui floated right blue tiny button" href="{{.SourcePath}}">
                                {{.i18n.Tr "repo.diff.browse_source"}}
                        </a>
                        {{end}}
@@ -72,9 +72,9 @@
                                                        <div class="item">
                                                                {{range .Parents}}
                                                                        {{if $.PageIsWiki}}
-                                                                               <a class="ui blue sha label" href="{{$.RepoLink}}/wiki/commit/{{.}}">{{ShortSha .}}</a>
+                                                                               <a class="ui blue sha label" href="{{$.RepoLink}}/wiki/commit/{{PathEscape .}}">{{ShortSha .}}</a>
                                                                        {{else}}
-                                                                               <a class="ui blue sha label" href="{{$.RepoLink}}/commit/{{.}}">{{ShortSha .}}</a>
+                                                                               <a class="ui blue sha label" href="{{$.RepoLink}}/commit/{{PathEscape .}}">{{ShortSha .}}</a>
                                                                        {{end}}
                                                                {{end}}
                                                        </div>
index 5282430ec796f727ea8980e80ffff237f36a0380..3a98a3afb23bd6f00a4a3a99e0f4950bdfa073cf 100644 (file)
@@ -17,7 +17,7 @@
                                                                {{if .User.FullName}}
                                                                        {{$userName = .User.FullName}}
                                                                {{end}}
-                                                               {{avatar .User 28 "mr-2"}}<a href="{{AppSubUrl}}/{{.User.Name}}">{{$userName}}</a>
+                                                               {{avatar .User 28 "mr-2"}}<a href="{{.User.HomeLink}}">{{$userName}}</a>
                                                        {{else}}
                                                                {{avatarByEmail .Author.Email .Author.Name 28 "mr-2"}}
                                                                {{$userName}}
@@ -40,9 +40,9 @@
                                                                {{end}}
                                                        {{end}}
                                                        {{if $.PageIsWiki}}
-                                                               <a href="{{AppSubUrl}}/{{$.Username}}/{{$.Reponame}}/wiki/commit/{{.ID}}" rel="nofollow" class="{{$class}}">
+                                                               <a href="{{$.RepoLink}}/wiki/commit/{{.ID}}" rel="nofollow" class="{{$class}}">
                                                        {{else if $.Reponame}}
-                                                               <a href="{{AppSubUrl}}/{{$.Username}}/{{$.Reponame}}/commit/{{.ID}}" rel="nofollow" class="{{$class}}">
+                                                               <a href="{{$.RepoLink}}/commit/{{.ID}}" rel="nofollow" class="{{$class}}">
                                                        {{else}}
                                                                <span class="{{$class}}">
                                                        {{end}}
@@ -61,7 +61,7 @@
                                                        {{if $.PageIsWiki}}
                                                                <span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary | RenderEmoji}}</span>
                                                        {{else }}
-                                                               {{ $commitLink:= printf "%s/%s/%s/commit/%s" AppSubUrl $.Username $.Reponame .ID }}
+                                                               {{ $commitLink:= printf "%s/commit/%s" $.RepoLink (PathEscape .ID.String) }}
                                                                <span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{RenderCommitMessageLinkSubject .Message $.RepoLink $commitLink $.Repository.ComposeMetas}}</span>
                                                        {{end}}
                                                        </span>
index bdbee816cc5802c0f8fb61e663c512bb828e139c..4211eda1af7c80db6539943d154375563454abf4 100644 (file)
@@ -6,7 +6,7 @@
        <div class="singular-commit" id="{{$tag}}">
                <span class="badge badge-commit">{{svg "octicon-git-commit"}}</span>
                {{if .User}}
-                       <a href="{{AppSubUrl}}/{{.User.Name}}">
+                       <a href="{.User.HomeLink}}">
                                {{avatar .User}}
                        </a>
                {{else}}
@@ -31,7 +31,7 @@
                                {{end}}
                        {{end}}
                        {{if $.comment.Issue.PullRequest.BaseRepo.Name}}
-                               <a href="{{AppSubUrl}}/{{$.comment.Issue.PullRequest.BaseRepo.OwnerName}}/{{$.comment.Issue.PullRequest.BaseRepo.Name}}/commit/{{.ID}}" rel="nofollow" class="{{$class}}">
+                               <a href="{{$.comment.Issue.PullRequest.BaseRepo.Link}}/commit/{{PathEscape .ID.String}}" rel="nofollow" class="{{$class}}">
                        {{else}}
                                <span class="{{$class}}">
                        {{end}}
@@ -46,7 +46,7 @@
                        {{end}}
                </span>
 
-               {{ $commitLink:= printf "%s/%s/%s/commit/%s" AppSubUrl  $.comment.Issue.PullRequest.BaseRepo.OwnerName $.comment.Issue.PullRequest.BaseRepo.Name .ID }}
+               {{ $commitLink:= printf "%s/commit/%s" $.comment.Issue.PullRequest.BaseRepo.Link (PathEscape .ID.String) }}
                <span class="mono commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{RenderCommitMessageLinkSubject .Message ($.comment.Issue.PullRequest.BaseRepo.Link|Escape) $commitLink $.comment.Issue.PullRequest.BaseRepo.ComposeMetas}}</span>
                {{if IsMultilineCommitMessage .Message}}
                        <button class="basic compact mini ui icon button commit-button"><i class="ellipsis horizontal icon"></i></button>
index 7bdcb340d9fe8f4c551ee5f6c31897659636c36b..4871b688a70e5fde332ae549d946284e1ed4e723 100644 (file)
@@ -11,7 +11,7 @@
        </div>
        <div class="commits-table-right df ac">
                {{if .PageIsCommits}}
-                       <form class="ignore-dirty" action="{{.RepoLink}}/commits/{{.BranchNameSubURL | EscapePound}}/search">
+                       <form class="ignore-dirty" action="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/search">
                                <div class="ui tiny search input">
                                        <input name="q" placeholder="{{.i18n.Tr "repo.commits.search"}}" value="{{.Keyword}}" autofocus>
                                </div>
@@ -23,9 +23,9 @@
                                <button class="ui primary tiny button mr-0 poping up" data-panel="#add-deploy-key-panel" data-content={{.i18n.Tr "repo.commits.search.tooltip"}}>{{.i18n.Tr "repo.commits.find"}}</button>
                        </form>
                {{else if .IsDiffCompare}}
-                       <a href="{{$.CommitRepoLink}}/commit/{{.BeforeCommitID}}" class="ui green sha label">{{if not .BaseIsCommit}}{{if .BaseIsBranch}}{{svg "octicon-git-branch"}}{{else if .BaseIsTag}}{{svg "octicon-tag"}}{{end}}{{.BaseBranch}}{{else}}{{ShortSha .BaseBranch}}{{end}}</a>
+                       <a href="{{$.CommitRepoLink}}/commit/{{.BeforeCommitID | PathEscape}}" class="ui green sha label">{{if not .BaseIsCommit}}{{if .BaseIsBranch}}{{svg "octicon-git-branch"}}{{else if .BaseIsTag}}{{svg "octicon-tag"}}{{end}}{{.BaseBranch}}{{else}}{{ShortSha .BaseBranch}}{{end}}</a>
                        ...
-                       <a href="{{$.CommitRepoLink}}/commit/{{.AfterCommitID}}" class="ui green sha label">{{if not .HeadIsCommit}}{{if .HeadIsBranch}}{{svg "octicon-git-branch"}}{{else if .HeadIsTag}}{{svg "octicon-tag"}}{{end}}{{.HeadBranch}}{{else}}{{ShortSha .HeadBranch}}{{end}}</a>
+                       <a href="{{$.CommitRepoLink}}/commit/{{.AfterCommitID | PathEscape}}" class="ui green sha label">{{if not .HeadIsCommit}}{{if .HeadIsBranch}}{{svg "octicon-git-branch"}}{{else if .HeadIsTag}}{{svg "octicon-tag"}}{{end}}{{.HeadBranch}}{{else}}{{ShortSha .HeadBranch}}{{end}}</a>
                {{end}}
        </div>
 </h4>
index 6915cf3b4980688b65644fef903724f43d08c340..78493629b31c9db399a4f5366c83964ec0a3184d 100644 (file)
@@ -11,7 +11,7 @@
                                        {{template "base/alert" .}}
 
                                        {{if not $.DisableMigrations}}
-                                               <p class="ui center">{{.i18n.Tr "repo.new_repo_helper" (printf "%s%s" AppSubUrl "/repo/migrate") | Safe}}</p>
+                                               <p class="ui center">{{.i18n.Tr "repo.new_repo_helper" ((printf "%s%s" AppSubUrl "/repo/migrate")|Escape) | Safe}}</p>
                                        {{end}}
 
                                        {{if not .CanCreateRepo}}
index 2543756d44581584e94fbbe83bbe7b236856d61f..792c539ac592d2754e71ab695bf7ffe5d806dd38 100644 (file)
@@ -4,17 +4,17 @@
                {{if eq .GetType 4}}
                        <td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}">
                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
-                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=down" data-anchor="{{$.Anchor}}">
+                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=down" data-anchor="{{$.Anchor}}">
                                                {{svg "octicon-fold-down"}}
                                        </a>
                                {{end}}
                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
-                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=up" data-anchor="{{$.Anchor}}">
+                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=up" data-anchor="{{$.Anchor}}">
                                                {{svg "octicon-fold-up"}}
                                        </a>
                                {{end}}
                                {{if eq $line.GetExpandDirection 2}}
-                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=" data-anchor="{{$.Anchor}}">
+                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=" data-anchor="{{$.Anchor}}">
                                                {{svg "octicon-fold"}}
                                        </a>
                                {{end}}
                {{if eq .GetType 4}}
                        <td colspan="2" class="lines-num">
                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
-                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=down" data-anchor="{{$.Anchor}}">
+                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=down" data-anchor="{{$.Anchor}}">
                                                {{svg "octicon-fold-down"}}
                                        </a>
                                {{end}}
                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
-                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=up" data-anchor="{{$.Anchor}}">
+                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=up" data-anchor="{{$.Anchor}}">
                                                {{svg "octicon-fold-up"}}
                                        </a>
                                {{end}}
                                {{if eq $line.GetExpandDirection 2}}
-                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=" data-anchor="{{$.Anchor}}">
+                                       <a role="button" class="blob-excerpt" data-url="{{$.RepoLink}}/blob_excerpt/{{PathEscape $.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=" data-anchor="{{$.Anchor}}">
                                                {{svg "octicon-fold"}}
                                        </a>
                                {{end}}
index 8aa3242063324f99e49f4433bd4ba846f61aa83b..56d6942baab9a6c2c28b0f819b9a4d0855e350c8 100644 (file)
@@ -96,9 +96,9 @@
                                                        {{end}}
                                                        {{if and (not $file.IsSubmodule) (not $.PageIsWiki)}}
                                                                {{if $file.IsDeleted}}
-                                                                       <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+                                                                       <a class="ui basic tiny button" rel="nofollow" href="{{$.BeforeSourcePath}}/{{PathEscapeSegments .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
                                                                {{else}}
-                                                                       <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+                                                                       <a class="ui basic tiny button" rel="nofollow" href="{{$.SourcePath}}/{{PathEscapeSegments .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
                                                                {{end}}
                                                        {{end}}
                                                </div>
index ce99ccd9e92536429a4701fdb4ed2e848b1f4050..9ec42a8d119b7584876ddc1a4cf6474050e85587 100644 (file)
                                                {{ .OriginalAuthor }}
                                        </span>
                                        <span class="text grey">
-                                               {{$.root.i18n.Tr "repo.issues.commented_at" .HashTag $createdStr | Safe}}
+                                               {{$.root.i18n.Tr "repo.issues.commented_at" (.HashTag|Escape) $createdStr | Safe}}
                                        </span>
                                        <span class="text migrate">
                                                {{if $.root.Repository.OriginalURL}}
-                                                       ({{$.root.i18n.Tr "repo.migrated_from" $.root.Repository.OriginalURL $.root.Repository.GetOriginalURLHostname | Safe }})
+                                                       ({{$.root.i18n.Tr "repo.migrated_from" ($.root.Repository.OriginalURL | Escape) ($.root.Repository.GetOriginalURLHostname | Escape) | Safe }})
                                                {{end}}
                                        </span>
                                {{else}}
@@ -30,7 +30,7 @@
                                                <a {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}>
                                                        {{.Poster.GetDisplayName}}
                                                </a>
-                                               {{$.root.i18n.Tr "repo.issues.commented_at" .HashTag $createdStr | Safe}}
+                                               {{$.root.i18n.Tr "repo.issues.commented_at" (.HashTag|Escape) $createdStr | Safe}}
                                        </span>
                                {{end}}
                        </div>
index 54ea4615874d021af3c87a6eddf0f6a6853356fd..51198f4ebfd84a0e1d3602f80c4a7cfe03975c63 100644 (file)
@@ -33,7 +33,7 @@
                {{- end -}}
        {{- end -}}
        <div class="ui segment choose branch">
-               <a href="{{$.HeadRepo.Link}}/compare/{{EscapePound $.HeadBranch}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{$.BaseName}}/{{$.Repository.Name}}:{{end}}{{EscapePound $.BaseBranch}}" title="{{.i18n.Tr "repo.pulls.switch_head_and_base"}}">{{svg "octicon-git-compare"}}</a>
+               <a href="{{$.HeadRepo.Link}}/compare/{{PathEscapeSegments $.HeadBranch}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{PathEscape $.BaseName}}/{{PathEscape $.Repository.Name}}:{{end}}{{PathEscapeSegments $.BaseBranch}}" title="{{.i18n.Tr "repo.pulls.switch_head_and_base"}}">{{svg "octicon-git-compare"}}</a>
                <div class="ui floating filter dropdown" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}">
                        <div class="ui basic small button">
                                <span class="text">{{if $.PageIsComparePull}}{{.i18n.Tr "repo.pulls.compare_base"}}{{else}}{{.i18n.Tr "repo.compare.compare_base"}}{{end}}: {{$BaseCompareName}}:{{$.BaseBranch}}</span>
                                </div>
                                <div class="scrolling menu reference-list-menu base-branch-list">
                                        {{range .Branches}}
-                                               <div class="item {{if eq $.BaseBranch .}}selected{{end}}" data-url="{{$.RepoLink}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{end}}{{EscapePound $.HeadBranch}}">{{$BaseCompareName}}:{{.}}</div>
+                                               <div class="item {{if eq $.BaseBranch .}}selected{{end}}" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{end}}{{PathEscapeSegments $.HeadBranch}}">{{$BaseCompareName}}:{{.}}</div>
                                        {{end}}
                                        {{if not .PullRequestCtx.SameRepo}}
                                                {{range .HeadBranches}}
-                                                       <div class="item" data-url="{{$.HeadRepo.Link}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{EscapePound $.HeadBranch}}">{{$HeadCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.HeadRepo.Link}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{PathEscapeSegments $.HeadBranch}}">{{$HeadCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .OwnForkRepo}}
                                                {{range .OwnForkRepoBranches}}
-                                                       <div class="item" data-url="{{$.OwnForkRepo.Link}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{EscapePound $.HeadBranch}}">{{$OwnForkCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.OwnForkRepo.Link}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{PathEscapeSegments $.HeadBranch}}">{{$OwnForkCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .RootRepo}}
                                                {{range .RootRepoBranches}}
-                                                       <div class="item" data-url="{{$.RootRepo.Link}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{EscapePound $.HeadBranch}}">{{$RootRepoCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RootRepo.Link}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{PathEscapeSegments $.HeadBranch}}">{{$RootRepoCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                </div>
                                <div class="scrolling menu reference-list-menu base-tag-list" style="display: none">
                                        {{range .Tags}}
-                                               <div class="item {{if eq $.BaseBranch .}}selected{{end}}" data-url="{{$.RepoLink}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{end}}{{EscapePound $.HeadBranch}}">{{$BaseCompareName}}:{{.}}</div>
+                                               <div class="item {{if eq $.BaseBranch .}}selected{{end}}" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{end}}{{PathEscapeSegments $.HeadBranch}}">{{$BaseCompareName}}:{{.}}</div>
                                        {{end}}
                                        {{if not .PullRequestCtx.SameRepo}}
                                                {{range .HeadTags}}
-                                                       <div class="item" data-url="{{$.HeadRepo.Link}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{EscapePound $.HeadBranch}}">{{$HeadCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.HeadRepo.Link}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{PathEscapeSegments $.HeadBranch}}">{{$HeadCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .OwnForkRepo}}
                                                {{range .OwnForkRepoTags}}
-                                                       <div class="item" data-url="{{$.OwnForkRepo.Link}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{EscapePound $.HeadBranch}}">{{$OwnForkCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.OwnForkRepo.Link}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{PathEscapeSegments $.HeadBranch}}">{{$OwnForkCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .RootRepo}}
                                                {{range .RootRepoTags}}
-                                                       <div class="item" data-url="{{$.RootRepo.Link}}/compare/{{EscapePound .}}{{$.CompareSeparator}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{EscapePound $.HeadBranch}}">{{$RootRepoCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RootRepo.Link}}/compare/{{PathEscapeSegments .}}{{$.CompareSeparator}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{PathEscapeSegments $.HeadBranch}}">{{$RootRepoCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                </div>
                        </div>
                </div>
-               <a href="{{.RepoLink}}/compare/{{EscapePound .BaseBranch}}{{.OtherCompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{end}}{{EscapePound $.HeadBranch}}" title="{{.i18n.Tr "repo.pulls.switch_comparison_type"}}">{{.CompareSeparator}}</a>
+               <a href="{{.RepoLink}}/compare/{{PathEscapeSegments .BaseBranch}}{{.OtherCompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{end}}{{PathEscapeSegments $.HeadBranch}}" title="{{.i18n.Tr "repo.pulls.switch_comparison_type"}}">{{.CompareSeparator}}</a>
                <div class="ui floating filter dropdown">
                        <div class="ui basic small button">
                                <span class="text">{{if $.PageIsComparePull}}{{.i18n.Tr "repo.pulls.compare_compare"}}{{else}}{{.i18n.Tr "repo.compare.compare_head"}}{{end}}: {{$HeadCompareName}}:{{$.HeadBranch}}</span>
                                </div>
                                <div class="scrolling menu reference-list-menu head-branch-list">
                                        {{range .HeadBranches}}
-                                               <div class="{{if eq $.HeadBranch .}}selected{{end}} item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{end}}{{EscapePound .}}">{{$HeadCompareName}}:{{.}}</div>
+                                               <div class="{{if eq $.HeadBranch .}}selected{{end}} item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{end}}{{PathEscapeSegments .}}">{{$HeadCompareName}}:{{.}}</div>
                                        {{end}}
                                        {{if not .PullRequestCtx.SameRepo}}
                                                {{range .Branches}}
-                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{$.BaseName}}/{{$.Repository.Name}}:{{EscapePound .}}">{{$BaseCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{PathEscape $.BaseName}}/{{PathEscape $.Repository.Name}}:{{PathEscapeSegments .}}">{{$BaseCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .OwnForkRepo}}
                                                {{range .OwnForkRepoBranches}}
-                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{$.OwnForkRepo.OwnerName}}/{{$.OwnForkRepo.Name}}:{{EscapePound .}}">{{$OwnForkCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{PathEscape $.OwnForkRepo.OwnerName}}/{{PathEscape $.OwnForkRepo.Name}}:{{PathEscapeSegments .}}">{{$OwnForkCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .RootRepo}}
                                                {{range .RootRepoBranches}}
-                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{$.RootRepo.OwnerName}}/{{$.RootRepo.Name}}:{{EscapePound .}}">{{$RootRepoCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{PathEscape $.RootRepo.OwnerName}}/{{PathEscape $.RootRepo.Name}}:{{PathEscapeSegments .}}">{{$RootRepoCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                </div>
                                <div class="scrolling menu reference-list-menu head-tag-list" style="display: none">
                                        {{range .HeadTags}}
-                                               <div class="{{if eq $.HeadBranch .}}selected{{end}} item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{$.HeadUser.Name}}/{{$.HeadRepo.Name}}:{{end}}{{EscapePound .}}">{{$HeadCompareName}}:{{.}}</div>
+                                               <div class="{{if eq $.HeadBranch .}}selected{{end}} item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{PathEscape $.HeadUser.Name}}/{{PathEscape $.HeadRepo.Name}}:{{end}}{{PathEscapeSegments .}}">{{$HeadCompareName}}:{{.}}</div>
                                        {{end}}
                                        {{if not .PullRequestCtx.SameRepo}}
                                                {{range .Tags}}
-                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{$.BaseName}}/{{$.Repository.Name}}:{{EscapePound .}}">{{$BaseCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{PathEscape $.BaseName}}/{{PathEscape $.Repository.Name}}:{{PathEscapeSegments .}}">{{$BaseCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .OwnForkRepo}}
                                                {{range .OwnForkRepoTags}}
-                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{$.OwnForkRepo.OwnerName}}/{{$.OwnForkRepo.Name}}:{{EscapePound .}}">{{$OwnForkCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{PathEscape $.OwnForkRepo.OwnerName}}/{{PathEscape $.OwnForkRepo.Name}}:{{PathEscapeSegments .}}">{{$OwnForkCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                        {{if .RootRepo}}
                                                {{range .RootRepoTags}}
-                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{EscapePound $.BaseBranch}}{{$.CompareSeparator}}{{$.RootRepo.OwnerName}}/{{$.RootRepo.Name}}:{{EscapePound .}}">{{$RootRepoCompareName}}:{{.}}</div>
+                                                       <div class="item" data-url="{{$.RepoLink}}/compare/{{PathEscapeSegments $.BaseBranch}}{{$.CompareSeparator}}{{PathEscape $.RootRepo.OwnerName}}/{{PathEscape $.RootRepo.Name}}:{{PathEscapeSegments .}}">{{$RootRepoCompareName}}:{{.}}</div>
                                                {{end}}
                                        {{end}}
                                </div>
        {{else if and .PageIsComparePull (gt .CommitCount 0)}}
                {{if .HasPullRequest}}
                        <div class="ui segment">
-                               {{.i18n.Tr "repo.pulls.has_pull_request" $.RepoLink $.RepoRelPath .PullRequest.Index | Safe}}
+                               {{.i18n.Tr "repo.pulls.has_pull_request" (Escape $.RepoLink) (Escape $.RepoRelPath) .PullRequest.Index | Safe}}
                        </div>
                {{else}}
                        {{if and $.IsSigned (not .Repository.IsArchived)}}
index 3d100ac9920ca31fbebc169126c823bcf60967a2..63481288c913be6330048818a65df8c281dd796d 100644 (file)
@@ -1,9 +1,7 @@
-{{ $imagePathOld := printf "%s/%s" .root.BeforeRawPath (EscapePound .file.OldName)  }}
-{{ $imagePathNew := printf "%s/%s" .root.RawPath (EscapePound .file.Name)  }}
 {{if or .blobBase .blobHead}}
 <tr>
        <td colspan="2">
-               <div class="image-diff" data-path-before="{{$imagePathOld}}" data-path-after="{{$imagePathNew}}">
+               <div class="image-diff" data-path-before="{{.root.BeforeRawPath}}/{{PathEscapeSegments .file.OldName}}" data-path-after="{{.root.RawPath}}/{{PathEscapeSegments .file.Name}}">
                        <div class="ui secondary pointing tabular top attached borderless menu stackable new-menu">
                                <div class="new-menu-inner">
                                        <a class="item active" data-tab="diff-side-by-side-{{ .file.Index }}">{{.root.i18n.Tr "repo.diff.image.side_by_side"}}</a>
index 92d870ea8a3e3f3bad0fbd86ec474ea8dc9f5062..a6ac49210f64e9b48cfa9b3dd8fff7632144c00c 100644 (file)
@@ -7,11 +7,11 @@
                        <a class="item" href="{{$.RepoLink}}/pulls/{{.Issue.Index}}.patch" download="{{.Issue.Index}}.patch">{{.i18n.Tr "repo.diff.download_patch"}}</a>
                        <a class="item" href="{{$.RepoLink}}/pulls/{{.Issue.Index}}.diff" download="{{.Issue.Index}}.diff">{{.i18n.Tr "repo.diff.download_diff"}}</a>
                {{else if $.PageIsWiki}}
-                       <a class="item" href="{{$.RepoLink}}/wiki/commit/{{.Commit.ID.String}}.patch" download="{{ShortSha .Commit.ID.String}}.patch">{{.i18n.Tr "repo.diff.download_patch"}}</a>
-                       <a class="item" href="{{$.RepoLink}}/wiki/commit/{{.Commit.ID.String}}.diff" download="{{ShortSha .Commit.ID.String}}.diff">{{.i18n.Tr "repo.diff.download_diff"}}</a>
+                       <a class="item" href="{{$.RepoLink}}/wiki/commit/{{PathEscape .Commit.ID.String}}.patch" download="{{ShortSha .Commit.ID.String}}.patch">{{.i18n.Tr "repo.diff.download_patch"}}</a>
+                       <a class="item" href="{{$.RepoLink}}/wiki/commit/{{PathEscape .Commit.ID.String}}.diff" download="{{ShortSha .Commit.ID.String}}.diff">{{.i18n.Tr "repo.diff.download_diff"}}</a>
                {{else if .Commit.ID.String}}
-                       <a class="item" href="{{$.RepoLink}}/commit/{{.Commit.ID.String}}.patch" download="{{ShortSha .Commit.ID.String}}.patch">{{.i18n.Tr "repo.diff.download_patch"}}</a>
-                       <a class="item" href="{{$.RepoLink}}/commit/{{.Commit.ID.String}}.diff" download="{{ShortSha .Commit.ID.String}}.diff">{{.i18n.Tr "repo.diff.download_diff"}}</a>
+                       <a class="item" href="{{$.RepoLink}}/commit/{{PathEscape .Commit.ID.String}}.patch" download="{{ShortSha .Commit.ID.String}}.patch">{{.i18n.Tr "repo.diff.download_patch"}}</a>
+                       <a class="item" href="{{$.RepoLink}}/commit/{{PathEscape .Commit.ID.String}}.diff" download="{{ShortSha .Commit.ID.String}}.diff">{{.i18n.Tr "repo.diff.download_diff"}}</a>
                {{end}}
        </div>
 </div>
index ca070858716c3c5f635f15cbdf9a4e9af84373c9..fb6977e204e6f168ec0608d56dbaf165a4aab51a 100644 (file)
@@ -7,17 +7,17 @@
                                {{if eq .GetType 4}}
                                        <td class="lines-num lines-num-old">
                                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
-                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=down" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
+                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=down" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
                                                                {{svg "octicon-fold-down"}}
                                                        </a>
                                                {{end}}
                                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
-                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=up" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
+                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=up" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
                                                                {{svg "octicon-fold-up"}}
                                                        </a>
                                                {{end}}
                                                {{if eq $line.GetExpandDirection 2}}
-                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
+                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
                                                                {{svg "octicon-fold"}}
                                                        </a>
                                                {{end}}
index e89f1a09f73ce56eb11eb61b8f97e01c33ff39c7..57e8fb9a160353177b0e27c2bd2f11e7a26e0b40 100644 (file)
@@ -6,17 +6,17 @@
                                {{if eq .GetType 4}}
                                        <td colspan="2" class="lines-num">
                                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
-                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=down" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
+                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=down" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
                                                                {{svg "octicon-fold-down"}}
                                                        </a>
                                                {{end}}
                                                {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
-                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=up" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
+                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=up" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
                                                                {{svg "octicon-fold-up"}}
                                                        </a>
                                                {{end}}
                                                {{if eq $line.GetExpandDirection 2}}
-                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
+                                                       <a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}">
                                                                {{svg "octicon-fold"}}
                                                        </a>
                                                {{end}}
index cd417b427fbf3ea9f5130240679c7f876a9bcf38..e42c2a2d8a8662a92ad14e5076d1982ca75f6e5b 100644 (file)
@@ -70,5 +70,5 @@
        <button id="commit-button" type="submit" class="ui green button">
                {{if eq .commit_choice "commit-to-new-branch"}}{{.i18n.Tr "repo.editor.propose_file_change"}}{{else}}{{.i18n.Tr "repo.editor.commit_changes"}}{{end}}
        </button>
-       <a class="ui button red" href="{{EscapePound $.BranchLink}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.editor.cancel"}}</a>
+       <a class="ui button red" href="{{$.BranchLink}}/{{PathEscapeSegments .TreePath}}">{{.i18n.Tr "repo.editor.cancel"}}</a>
 </div>
index b7e1589aa14e0a2c9ccdc2d30f296e231e30a337..a342bb03e09cf36dcea67b4525467eeabcc643ab 100644 (file)
@@ -10,7 +10,7 @@
                        <div class="ui secondary menu">
                                <div class="fitted item treepath">
                                        <div class="ui breadcrumb field {{if .Err_TreePath}}error{{end}}">
-                                               <a class="section" href="{{EscapePound $.BranchLink}}">{{.Repository.Name}}</a>
+                                               <a class="section" href="{{$.BranchLink}}">{{.Repository.Name}}</a>
                                                {{ $n := len .TreeNames}}
                                                {{ $l := Subtract $n 1}}
                                                {{range $i, $v := .TreeNames}}
                                                                <input id="file-name" value="{{$v}}" placeholder="{{$.i18n.Tr "repo.editor.name_your_file"}}" data-editorconfig="{{$.Editorconfig}}" required autofocus>
                                                                <span class="poping up" data-content="{{$.i18n.Tr "repo.editor.filename_help"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-info"}}</span>
                                                        {{else}}
-                                                               <span class="section"><a href="{{EscapePound $.BranchLink}}/{{index $.TreePaths $i | EscapePound}}">{{$v}}</a></span>
+                                                               <span class="section"><a href="{{$.BranchLink}}/{{index $.TreePaths $i | PathEscapeSegments}}">{{$v}}</a></span>
                                                        {{end}}
                                                {{end}}
-                                               <span>{{.i18n.Tr "repo.editor.or"}} <a href="{{EscapePound $.BranchLink}}{{if not .IsNewFile}}/{{EscapePound .TreePath}}{{end}}">{{.i18n.Tr "repo.editor.cancel_lower"}}</a></span>
+                                               <span>{{.i18n.Tr "repo.editor.or"}} <a href="{{$.BranchLink}}{{if not .IsNewFile}}/{{PathEscapeSegments .TreePath}}{{end}}">{{.i18n.Tr "repo.editor.cancel_lower"}}</a></span>
                                                <input type="hidden" id="tree_path" name="tree_path" value="{{.TreePath}}" required>
                                        </div>
                                </div>
@@ -31,8 +31,8 @@
                                <div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
                                        <a class="active item" data-tab="write">{{svg "octicon-code"}} {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a>
                                        {{if not .IsNewFile}}
-                                       <a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}" data-markdown-mode="gfm">{{svg "octicon-eye"}} {{.i18n.Tr "preview"}}</a>
-                                       <a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}">{{svg "octicon-diff"}} {{.i18n.Tr "repo.editor.preview_changes"}}</a>
+                                       <a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL}}" data-preview-file-modes="{{.PreviewableFileModes}}" data-markdown-mode="gfm">{{svg "octicon-eye"}} {{.i18n.Tr "preview"}}</a>
+                                       <a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}" data-context="{{.BranchLink}}">{{svg "octicon-diff"}} {{.i18n.Tr "repo.editor.preview_changes"}}</a>
                                        {{end}}
                                </div>
                                <div class="ui bottom attached active tab segment" data-tab="write">
index fb00615abdb2adc0faedd7f263da79257206a145..5fbb42a446629d3a726617ed3559b0cd7abcf271 100644 (file)
@@ -8,7 +8,7 @@
                        <div class="ui secondary menu">
                                <div class="item fitted treepath">
                                        <div class="ui breadcrumb field {{if .Err_TreePath}}error{{end}}">
-                                               <a class="section" href="{{EscapePound $.BranchLink}}">{{.Repository.Name}}</a>
+                                               <a class="section" href="{{$.BranchLink}}">{{.Repository.Name}}</a>
                                                {{ $n := len .TreeNames}}
                                                {{ $l := Subtract $n 1}}
                                                {{range $i, $v := .TreeNames}}
                                                                <input type="text" id="file-name" value="{{$v}}" placeholder="{{$.i18n.Tr "repo.editor.add_subdir"}}" autofocus>
                                                                <span class="poping up" data-content="{{$.i18n.Tr "repo.editor.filename_help"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-info"}}</span>
                                                        {{else}}
-                                                               <span class="section"><a href="{{EscapePound $.BranchLink}}/{{index $.TreePaths $i | EscapePound}}">{{$v}}</a></span>
+                                                               <span class="section"><a href="{{$.BranchLink}}/{{index $.TreePaths $i | PathEscapeSegments}}">{{$v}}</a></span>
                                                        {{end}}
                                                {{end}}
-                                               <span>{{.i18n.Tr "repo.editor.or"}} <a href="{{EscapePound $.BranchLink}}{{if not .IsNewFile}}/{{EscapePound .TreePath}}{{end}}">{{.i18n.Tr "repo.editor.cancel_lower"}}</a></span>
+                                               <span>{{.i18n.Tr "repo.editor.or"}} <a href="{{$.BranchLink}}{{if not .IsNewFile}}/{{.TreePath | PathEscapeSegments}}{{end}}">{{.i18n.Tr "repo.editor.cancel_lower"}}</a></span>
                                                <input type="hidden" id="tree_path" name="tree_path" value="{{.TreePath}}" required>
                                        </div>
                                </div>
index 192291275f34ac8b4471161037ac810b00bb74ad..ff6e9949d35b7ead671112bcb5f644ef4c7df6f1 100644 (file)
@@ -10,9 +10,9 @@
                                <div class="item">
                                        {{avatar .Owner}}
                                        <div class="link">
-                                               <a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
+                                               <a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a>
                                                /
-                                               <a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">{{.Name}}</a>
+                                               <a href="{{.Link}}">{{.Name}}</a>
                                        </div>
                                </div>
                        {{end}}
index 3427aed58ca7009f8979c7d623af9f6d56a7d3e6..d054462ebcedd25b7088317ea4cff3847b79982b 100644 (file)
@@ -21,7 +21,7 @@
                                                                {{$class = (printf "%s%s" $class " isWarning")}}
                                                        {{end}}
                                                {{end}}
-                                               <a href="{{AppSubUrl}}/{{$.Username}}/{{$.Reponame}}/commit/{{$commit.Rev}}" rel="nofollow" class="{{$class}}">
+                                               <a href="{{$.RepoLink}}/commit/{{$commit.Rev|PathEscape}}" rel="nofollow" class="{{$class}}">
                                                        <span class="shortsha">{{ShortSha $commit.Commit.ID.String}}</span>
                                                        {{- if $commit.Commit.Signature -}}
                                                                <span class="shortsha-pad"></span>{{template "repo/shabox_badge" dict "root" $ "verification" $commit.Verification}}
@@ -44,7 +44,7 @@
                                                                        {{svg "octicon-tag" 16 "mr-2"}}{{.ShortName}}
                                                                </a>
                                                        {{else if eq $refGroup "remotes"}}
-                                                               <a class="ui labelled icon button basic tiny" href="{{$.RepoLink}}/src/commit/{{$commit.Rev}}">
+                                                               <a class="ui labelled icon button basic tiny" href="{{$.RepoLink}}/src/commit/{{$commit.Rev|PathEscape}}">
                                                                        {{svg "octicon-cross-reference" 16 "mr-2"}}{{.ShortName}}
                                                                </a>
                                                        {{else if eq $refGroup "heads"}}
index 49a651e6c5a8699929d3f21f1be9331295bd9e29..765de1a146507e6e13e2425eaa87d96fb89630c0 100644 (file)
@@ -10,7 +10,7 @@
                                        {{else}}
                                                {{template "repo/icon" .}}
                                        {{end}}
-                                       <a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
+                                       <a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a>
                                        <div class="mx-2">/</div>
                                        <a href="{{$.RepoLink}}">{{.Name}}</a>
                                        <div class="labels df ac fw">
@@ -37,8 +37,8 @@
                                        </div>
                                </div>
                                {{if .IsMirror}}<div class="fork-flag">{{$.i18n.Tr "repo.mirror_from"}} <a target="_blank" rel="noopener noreferrer" href="{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{(MirrorRemoteAddress $.Mirror).Address}}{{end}}">{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{(MirrorRemoteAddress $.Mirror).Address}}{{end}}</a></div>{{end}}
-                               {{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{SubStr .BaseRepo.RelLink 1 -1}}</a></div>{{end}}
-                               {{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{SubStr .TemplateRepo.RelLink 1 -1}}</a></div>{{end}}
+                               {{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{.BaseRepo.FullName}}</a></div>{{end}}
+                               {{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{.TemplateRepo.FullName}}</a></div>{{end}}
                        </div>
                        {{if not .IsBeingCreated}}
                                <div class="repo-buttons">
                {{if not .Repository.IsBeingCreated}}
                        <div class="ui tabular stackable menu navbar">
                                {{if .Permission.CanRead $.UnitTypeCode}}
-                               <a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">
+                               <a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}">
                                        {{svg "octicon-code"}} {{.i18n.Tr "repo.code"}}
                                </a>
                                {{end}}
index eb6ee8c0a29b1016405e295655bb2e32828a6500..40e782a6056620086c74ffb293b1b4b2eebf1d9a 100644 (file)
                        {{if eq $n 0}}
                                {{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
                                        <div class="fitted item mx-0">
-                                               <a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}{{if .BaseRepo.IsFork}}/{{.Repository.Name}}{{end}}:{{end}}{{.BranchName | EscapePound}}">
+                                               <a href="{{.BaseRepo.Link}}/compare/{{PathEscapeSegments .BaseRepo.DefaultBranch}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}{{if .BaseRepo.IsFork}}/{{PathEscape .Repository.Name}}{{end}}:{{end}}{{PathEscapeSegments .BranchName}}">
                                                        <button id="new-pull-request" class="ui compact basic button">{{if .PullRequestCtx.Allowed}}{{.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{.i18n.Tr "action.compare_branch"}}{{end}}</button>
                                                </a>
                                        </div>
                                {{end}}
                        {{else}}
-                               <div class="fitted item"><span class="ui breadcrumb repo-path"><a class="section" href="{{.RepoLink}}/src/{{EscapePound .BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{ $p := index $.Paths $i}}<span class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
+                               <div class="fitted item"><span class="ui breadcrumb repo-path"><a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{ $p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
                        {{end}}
                        <div class="right fitted item mr-0" id="file-buttons">
                                <div class="ui tiny primary buttons">
                                        {{if .Repository.CanEnableEditor}}
                                                {{if .CanAddFile}}
-                                                       <a href="{{.RepoLink}}/_new/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
+                                                       <a href="{{.RepoLink}}/_new/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}" class="ui button">
                                                                {{.i18n.Tr "repo.editor.new_file"}}
                                                        </a>
                                                {{end}}
                                                {{if .CanUploadFile}}
-                                                       <a href="{{.RepoLink}}/_upload/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
+                                                       <a href="{{.RepoLink}}/_upload/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}" class="ui button">
                                                                {{.i18n.Tr "repo.editor.upload_file"}}
                                                        </a>
                                                {{end}}
                                        {{end}}
                                        {{if and (ne $n 0) (not .IsViewFile) (not .IsBlame) }}
-                                               <a href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}" class="ui button">
+                                               <a href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}" class="ui button">
                                                        {{.i18n.Tr "repo.file_history"}}
                                                </a>
                                        {{end}}
                                                <button id="download-btn" class="ui basic jump dropdown icon button poping up" data-content="{{.i18n.Tr "repo.download_archive"}}" data-variation="tiny inverted" data-position="top right">
                                                        {{svg "octicon-download"}}
                                                        <div class="menu">
-                                                               <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.zip">{{svg "octicon-file-zip" 16 "mr-3"}}{{.i18n.Tr "repo.download_zip"}}</a>
-                                                               <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.tar.gz">{{svg "octicon-file-zip" 16 "mr-3"}}{{.i18n.Tr "repo.download_tar"}}</a>
-                                                               <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.bundle">{{svg "octicon-package" 16 "mr-3"}}{{.i18n.Tr "repo.download_bundle"}}</a>
+                                                               <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{PathEscapeSegments $.BranchName}}.zip">{{svg "octicon-file-zip" 16 "mr-3"}}{{.i18n.Tr "repo.download_zip"}}</a>
+                                                               <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{PathEscapeSegments $.BranchName}}.tar.gz">{{svg "octicon-file-zip" 16 "mr-3"}}{{.i18n.Tr "repo.download_tar"}}</a>
+                                                               <a class="item archive-link" data-url="{{$.RepoLink}}/archive/{{PathEscapeSegments $.BranchName}}.bundle">{{svg "octicon-package" 16 "mr-3"}}{{.i18n.Tr "repo.download_bundle"}}</a>
                                                                <a class="item" href="vscode://vscode.git/clone?url={{if $.PageIsWiki}}{{$.WikiCloneLink.HTTPS}}{{else}}{{$.CloneLink.HTTPS}}{{end}}">{{svg "gitea-vscode" 16 "mr-3"}}{{.i18n.Tr "repo.clone_in_vsc"}}</a>
                                                        </div>
                                                </button>
index a6d52fe54434fe3fc36b7f02eb224f260912999c..0afe5cb6e7b1ee89a475f4b2c808a02351f32c08 100644 (file)
@@ -1,7 +1,7 @@
 <a
        class="ui label item {{if not .label.IsChecked}}hide{{end}}"
        id="label_{{.label.ID}}"
-       href="{{.root.RepoLink}}/{{if or .root.IsPull .root.Issue.IsPull}}pulls{{else}}issues{{end}}?labels={{.label.ID}}"
+       href="{{.root.RepoLink}}/{{if or .root.IsPull .root.Issue.IsPull}}pulls{{else}}issues{{end}}?labels={{.label.ID}}"{{/* FIXME: use .root.Issue.Link or create .root.Link */}}
        style="color: {{.label.ForegroundColor}}; background-color: {{.label.Color}}"
        title="{{.label.Description | RenderEmojiPlain}}"
 >
index 64b68f145eee34ae55c69086d44f53a882c31a86..63d746f570a184dbc31fe1b2cd4435aa5fb86669 100644 (file)
                                        {{if .PageIsIssueList}}
                                                <a class="ui green button" href="{{.RepoLink}}/issues/new{{if .NewIssueChooseTemplate}}/choose{{end}}">{{.i18n.Tr "repo.issues.new"}}</a>
                                        {{else}}
-                                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.Repository.Link}}/compare/{{.Repository.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | EscapePound}}{{end}}">{{.i18n.Tr "repo.pulls.new"}}</a>
+                                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.Repository.Link}}/compare/{{.Repository.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{.i18n.Tr "repo.pulls.new"}}</a>
                                        {{end}}
                                </div>
                        {{else}}
                                {{if not .PageIsIssueList}}
                                        <div class="column right aligned">
-                                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.PullRequestCtx.BaseRepo.Link}}/compare/{{.PullRequestCtx.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | EscapePound}}{{end}}">{{$.i18n.Tr "action.compare_commits_general"}}</a>
+                                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{if .PullRequestCtx.Allowed}}{{.PullRequestCtx.BaseRepo.Link}}/compare/{{.PullRequestCtx.BaseRepo.DefaultBranch | PathEscapeSegments}}...{{if ne .Repository.Owner.Name .PullRequestCtx.BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}:{{end}}{{.Repository.DefaultBranch | PathEscapeSegments}}{{end}}">{{$.i18n.Tr "action.compare_commits_general"}}</a>
                                        </div>
                                {{end}}
                        {{end}}
index 39d3b77017f3f6dbe787a5dfa6777f02f8bc1bc2..acfd25e7e0248ed69bf7470926a5ddbefeba5afb 100644 (file)
@@ -11,7 +11,7 @@
                                        {{if .PageIsIssueList}}
                                                <a class="ui green button" href="{{.RepoLink}}/issues/new{{if .NewIssueChooseTemplate}}/choose{{end}}">{{.i18n.Tr "repo.issues.new"}}</a>
                                        {{else}}
-                                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a>
+                                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | PathEscapeSegments}}...{{.PullRequestCtx.HeadInfoSubURL}}">{{.i18n.Tr "repo.pulls.new"}}</a>
                                        {{end}}
                                </div>
                        {{end}}
index 29c8626596563220c35c205f3bea904f4fa83401..687f9133b120136477a2e2be21a68a012dd82a3d 100644 (file)
                                                                        {{ .Issue.OriginalAuthor }}
                                                                </span>
                                                                <span class="text grey">
-                                                                       {{ .i18n.Tr "repo.issues.commented_at" .Issue.HashTag $createdStr | Safe }}
+                                                                       {{ .i18n.Tr "repo.issues.commented_at" (.Issue.HashTag|Escape) $createdStr | Safe }}
                                                                </span>
                                                                <span class="text migrate">
-                                                                       {{if .Repository.OriginalURL}} ({{$.i18n.Tr "repo.migrated_from" .Repository.OriginalURL .Repository.GetOriginalURLHostname | Safe }}){{end}}
+                                                                       {{if .Repository.OriginalURL}} ({{$.i18n.Tr "repo.migrated_from" (.Repository.OriginalURL|Escape) (.Repository.GetOriginalURLHostname|Escape) | Safe }}){{end}}
                                                                </span>
                                                        {{else}}
                                                                <span class="text grey">
                                                                        <a class="author"{{if gt .Issue.Poster.ID 0}} href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.GetDisplayName}}</a>
-                                                                       {{.i18n.Tr "repo.issues.commented_at" .Issue.HashTag $createdStr | Safe}}
+                                                                       {{.i18n.Tr "repo.issues.commented_at" (.Issue.HashTag|Escape) $createdStr | Safe}}
                                                                </span>
                                                        {{end}}
                                                </div>
                                        {{end}}
                                {{else}}
                                        <div class="ui warning message">
-                                               {{.i18n.Tr "repo.issues.sign_in_require_desc" .SignInLink | Safe}}
+                                               {{.i18n.Tr "repo.issues.sign_in_require_desc" (.SignInLink|Escape) | Safe}}
                                        </div>
                                {{end}}
                        {{end}}
index 57ec007bed03a69f85f93c40d7a43e6d0c26bd81..9907246d9f403c5d2d89352925b75e35f74f4071 100644 (file)
                                                                {{ .OriginalAuthor }}
                                                        </span>
                                                        <span class="text grey">
-                                                               {{$.i18n.Tr "repo.issues.commented_at" .Issue.HashTag $createdStr | Safe}} {{if $.Repository.OriginalURL}}
+                                                               {{$.i18n.Tr "repo.issues.commented_at" (.Issue.HashTag|Escape) $createdStr | Safe}} {{if $.Repository.OriginalURL}}
                                                        </span>
                                                        <span class="text migrate">
-                                                               ({{$.i18n.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname | Safe }}){{end}}
+                                                               ({{$.i18n.Tr "repo.migrated_from" ($.Repository.OriginalURL|Escape) ($.Repository.GetOriginalURLHostname|Escape) | Safe }}){{end}}
                                                        </span>
                                                {{else}}
                                                        <span class="text grey">
                                                                <a class="author"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>
                                                                        {{.Poster.GetDisplayName}}
                                                                </a>
-                                                               {{$.i18n.Tr "repo.issues.commented_at" .HashTag $createdStr | Safe}}
+                                                               {{$.i18n.Tr "repo.issues.commented_at" (.HashTag|Escape) $createdStr | Safe}}
                                                        </span>
                                                {{end}}
                                        </div>
                        </a>
                        <span class="text grey">
                                <a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a>
-                               {{$link := printf "%s/commit/%s" $.Repository.HTMLURL $.Issue.PullRequest.MergedCommitID}}
+                               {{$link := printf "%s/commit/%s" $.Repository.HTMLURL ($.Issue.PullRequest.MergedCommitID|PathEscape)}}
                                {{if eq $.Issue.PullRequest.Status 3}}
-                                       {{$.i18n.Tr "repo.issues.manually_pull_merged_at" $link (ShortSha $.Issue.PullRequest.MergedCommitID) $.BaseTarget $createdStr | Str2html}}
+                                       {{$.i18n.Tr "repo.issues.manually_pull_merged_at" ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID) ($.BaseTarget|Escape) $createdStr | Str2html}}
                                {{else}}
-                                       {{$.i18n.Tr "repo.issues.pull_merged_at" $link (ShortSha $.Issue.PullRequest.MergedCommitID) $.BaseTarget $createdStr | Str2html}}
+                                       {{$.i18n.Tr "repo.issues.pull_merged_at" ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID) ($.BaseTarget|Escape) $createdStr | Str2html}}
                                {{end}}
                        </span>
                </div>
        {{else if eq .Type 3 5 6}}
                {{ $refFrom:= "" }}
                {{if ne .RefRepoID .Issue.RepoID}}
-                       {{ $refFrom = $.i18n.Tr "repo.issues.ref_from" .RefRepo.FullName }}
+                       {{ $refFrom = $.i18n.Tr "repo.issues.ref_from" (.RefRepo.FullName|Escape) }}
                {{end}}
                {{ $refTr := "repo.issues.ref_issue_from" }}
                {{if .Issue.IsPull}}
                        {{if eq .RefAction 3}}<del>{{end}}
                        <span class="text grey">
                                <a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a>
-                               {{$.i18n.Tr $refTr .EventTag $createdStr .RefCommentHTMLURL $refFrom | Safe}}
+                               {{$.i18n.Tr $refTr (.EventTag|Escape) $createdStr (.RefCommentHTMLURL|Escape) $refFrom | Safe}}
                        </span>
                        {{if eq .RefAction 3}}</del>{{end}}
 
                                                        {{ .OriginalAuthor }}
                                                </span>
                                                <span class="text grey"> {{if $.Repository.OriginalURL}}</span>
-                                               <span class="text migrate">({{$.i18n.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname | Safe }}){{end}}</span>
+                                               <span class="text migrate">({{$.i18n.Tr "repo.migrated_from" ($.Repository.OriginalURL|Escape) ($.Repository.GetOriginalURLHostname|Escape) | Safe }}){{end}}</span>
                                        {{else}}
                                                <a class="author"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>{{.Poster.GetDisplayName}}</a>
                                        {{end}}
                                                                        {{ .OriginalAuthor }}
                                                                </span>
                                                                <span class="text grey"> {{if $.Repository.OriginalURL}}</span>
-                                                               <span class="text migrate">({{$.i18n.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname | Safe }}){{end}}</span>
+                                                               <span class="text migrate">({{$.i18n.Tr "repo.migrated_from" ($.Repository.OriginalURL|Escape) ($.Repository.GetOriginalURLHostname|Escape) | Safe }}){{end}}</span>
                                                        {{else}}
                                                                <a class="author"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>{{.Poster.GetDisplayName}}</a>
                                                        {{end}}
                                                                                                                                                {{ .OriginalAuthor }}
                                                                                                                                        </span>
                                                                                                                                        <span class="text grey"> {{if $.Repository.OriginalURL}}</span>
-                                                                                                                                       <span class="text migrate">({{$.i18n.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname | Safe }}){{end}}</span>
+                                                                                                                                       <span class="text migrate">({{$.i18n.Tr "repo.migrated_from" ($.Repository.OriginalURL|Escape) ($.Repository.GetOriginalURLHostname|Escape) | Safe }}){{end}}</span>
                                                                                                                                {{else}}
                                                                                                                                        <a class="author"{{if gt .Poster.ID 0}} href="{{.Poster.HomeLink}}"{{end}}>{{.Poster.GetDisplayName}}</a>
                                                                                                                                {{end}}
-                                                                                                                               {{$.i18n.Tr "repo.issues.commented_at" .HashTag $createdSubStr | Safe}}
+                                                                                                                               {{$.i18n.Tr "repo.issues.commented_at" (.HashTag|Escape) $createdSubStr | Safe}}
                                                                                                                        </span>
                                                                                                                </div>
                                                                                                                <div class="comment-header-right actions df ac">
                        <span class="text grey">
                                <a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a>
                                {{ if .IsForcePush }}
-                                       {{$.i18n.Tr "repo.issues.force_push_codes" $.Issue.PullRequest.HeadBranch (ShortSha .OldCommit) ($.Issue.Repo.CommitLink .OldCommit)  (ShortSha .NewCommit) ($.Issue.Repo.CommitLink .NewCommit) $createdStr | Safe}}
+                                       {{$.i18n.Tr "repo.issues.force_push_codes" ($.Issue.PullRequest.HeadBranch|Escape) (ShortSha .OldCommit) (($.Issue.Repo.CommitLink .OldCommit)|Escape)  (ShortSha .NewCommit) (($.Issue.Repo.CommitLink .NewCommit)|Escape) $createdStr | Safe}}
                                {{else}}
                                        {{$.i18n.Tr (TrN $.i18n.Lang (len .Commits) "repo.issues.push_commit_1" "repo.issues.push_commits_n") (len .Commits) $createdStr | Safe}}
                                {{end}}
index 71ce03a4cab053d63a3861d17c8695f720f03248..2c2129caacb3bfd1d4d3b4d891717bf7997d29d9 100644 (file)
@@ -6,13 +6,9 @@
        <div class="menu">
                {{ $referenceUrl := "" }}
                {{ if .issue }}
-                       {{ if .ctx.Issue.IsPull}}
-                               {{ $referenceUrl = Printf "%s%s/pulls/%d#%s" AppUrl .ctx.Repository.FullName .ctx.Issue.Index .item.HashTag }}
-                       {{ else }}
-                               {{ $referenceUrl = Printf "%s%s/issues/%d#%s" AppUrl .ctx.Repository.FullName .ctx.Issue.Index .item.HashTag }}
-                       {{ end }}
+                       {{ $referenceUrl = Printf "%s#%s" .ctx.Issue.HTMLURL .item.HashTag }}
                {{ else }}
-                       {{ $referenceUrl = Printf "%s%s/pulls/%d/files#%s" AppUrl .ctx.Repository.FullName .ctx.Issue.Index .item.HashTag }}
+                       {{ $referenceUrl = Printf "%s/files#%s" .ctx.Issue.HTMLURL .item.HashTag }}
                {{ end }}
                <div class="item context" data-clipboard-text="{{$referenceUrl}}">{{.ctx.i18n.Tr "repo.issues.context.copy_link"}}</div>
                <div class="item context quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.ID}}">{{.ctx.i18n.Tr "repo.issues.context.quote_reply"}}</div>
index 706cc0eac754a59efdf0270bcb46315095597e4c..a684edfb3a7b2253c5b6592608ec1bff5f2b4ae1 100644 (file)
@@ -86,7 +86,7 @@
                                        <div class="ui divider"></div>
                                        <div class="review-item">
                                                <div class="review-item-left">
-                                                       <a href="{{$.Repository.OriginalURL}}" class="ui poping up" data-content="{{$.i18n.Tr "repo.migrated_from_fake" $.Repository.GetOriginalURLHostname | Safe }}">
+                                                       <a href="{{$.Repository.OriginalURL}}" class="ui poping up" data-content="{{$.i18n.Tr "repo.migrated_from_fake" ($.Repository.GetOriginalURLHostname|Escape) | Safe }}">
                                                                <span class="text black ">
                                                                        {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
                                                                        {{ .OriginalAuthor }}
                        {{if .Issue.PullRequest.HasMerged}}
                                <div class="item text">
                                        {{if .Issue.PullRequest.MergedCommitID}}
-                                               {{$link := printf "%s/commit/%s" $.Repository.HTMLURL .Issue.PullRequest.MergedCommitID}}
+                                               {{$link := printf "%s/commit/%s" $.Repository.HTMLURL (.Issue.PullRequest.MergedCommitID|PathEscape)}}
                                                {{if eq $.Issue.PullRequest.Status 3}}
-                                                       {{$.i18n.Tr "repo.pulls.manually_merged_as" $link (ShortSha .Issue.PullRequest.MergedCommitID) | Safe}}
+                                                       {{$.i18n.Tr "repo.pulls.manually_merged_as" ($link|Escape) (ShortSha .Issue.PullRequest.MergedCommitID) | Safe}}
                                                {{else}}
-                                                       {{$.i18n.Tr "repo.pulls.merged_as" $link (ShortSha .Issue.PullRequest.MergedCommitID) | Safe}}
+                                                       {{$.i18n.Tr "repo.pulls.merged_as" ($link|Escape) (ShortSha .Issue.PullRequest.MergedCommitID) | Safe}}
                                                {{end}}
                                        {{else}}
                                                {{$.i18n.Tr "repo.pulls.has_merged"}}
                                        {{$.i18n.Tr "repo.pulls.data_broken"}}
                                </div>
                        {{else if .IsPullWorkInProgress}}
-                               <div class="item toggle-wip df ac sb" data-title="{{.Issue.Title}}" data-wip-prefix="{{(.WorkInProgressPrefix|Escape)}}" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title">
+                               <div class="item toggle-wip df ac sb" data-title="{{.Issue.Title}}" data-wip-prefix="{{(.WorkInProgressPrefix|Escape)}}" data-update-url="{{.Issue.Link}}/title">
                                        <div>
                                                <i class="icon icon-octicon">{{svg "octicon-x"}}</i>
                                                {{$.i18n.Tr "repo.pulls.cannot_merge_work_in_progress" }}
index ed700617ea32869ba135dac38a482d66c2f291a7..a72a9216a53e2c65a9b66c0280dcfebb368009c0 100644 (file)
@@ -79,7 +79,7 @@
                                        {{end}}
                                        {{range .OriginalReviews}}
                                                <div class="item" style="margin-bottom: 10px;">
-                                                       <a href="{{$.Repository.OriginalURL}}" class="ui poping up" data-content="{{$.i18n.Tr "repo.migrated_from_fake" $.Repository.GetOriginalURLHostname | Safe }}">
+                                                       <a href="{{$.Repository.OriginalURL}}" class="ui poping up" data-content="{{$.i18n.Tr "repo.migrated_from_fake" ($.Repository.GetOriginalURLHostname|Escape) | Safe }}">
                                                                <span class="text black">
                                                                        {{svg (MigrationIcon $.Repository.GetOriginalURLHostname)}}
                                                                        {{ .OriginalAuthor }}
@@ -97,7 +97,7 @@
                                </div>
                        </div>
                        {{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .HasMerged) (not .Issue.IsClosed) (not .IsPullWorkInProgress)}}
-                               <div class="toggle-wip" data-title="{{.Issue.Title}}" data-wip-prefix="{{(index .PullRequestWorkInProgressPrefixes 0| Escape)}}" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title">
+                               <div class="toggle-wip" data-title="{{.Issue.Title}}" data-wip-prefix="{{(index .PullRequestWorkInProgressPrefixes 0| Escape)}}" data-update-url="{{.Issue.Link}}/title">
                                        <a class="muted">
                                                {{.i18n.Tr "repo.pulls.still_in_progress"}} {{.i18n.Tr "repo.pulls.add_prefix" (index .PullRequestWorkInProgressPrefixes 0| Escape) | Safe}}
                                        </a>
                        <div class="ui watching">
                                <span class="text"><strong>{{.i18n.Tr "notification.notifications"}}</strong></span>
                                <div class="mt-3">
-                                       <form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/watch">
+                                       <form method="POST" action="{{.Issue.Link}}/watch">
                                                <input type="hidden" name="watch" value="{{if $.IssueWatch.IsWatching}}0{{else}}1{{end}}" />
                                                {{$.CsrfTokenHtml}}
                                                <button class="fluid ui button df jc">
                                <div class="ui timetrack">
                                        <span class="text"><strong>{{.i18n.Tr "repo.issues.tracker"}}</strong></span>
                                        <div class="mt-3">
-                                               <form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/times/stopwatch/toggle" id="toggle_stopwatch_form">
+                                               <form method="POST" action="{{.Issue.Link}}/times/stopwatch/toggle" id="toggle_stopwatch_form">
                                                        {{$.CsrfTokenHtml}}
                                                </form>
-                                               <form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/times/stopwatch/cancel" id="cancel_stopwatch_form">
+                                               <form method="POST" action="{{.Issue.Link}}/times/stopwatch/cancel" id="cancel_stopwatch_form">
                                                        {{$.CsrfTokenHtml}}
                                                </form>
                                                {{if  $.IsStopwatchRunning}}
                                                {{else}}
                                                        {{if .HasUserStopwatch}}
                                                                <div class="ui warning message">
-                                                                       {{.i18n.Tr "repo.issues.tracking_already_started" .OtherStopwatchURL | Safe}}
+                                                                       {{.i18n.Tr "repo.issues.tracking_already_started" (.OtherStopwatchURL|Escape) | Safe}}
                                                                </div>
                                                        {{end}}
                                                        <button class="ui fluid button poping up issue-start-time" data-content='{{.i18n.Tr "repo.issues.start_tracking"}}' data-position="top center" data-variation="small inverted">{{.i18n.Tr "repo.issues.start_tracking_short"}}</button>
                                                        <div class="ui mini modal issue-start-time-modal">
                                                                <div class="header">{{.i18n.Tr "repo.issues.add_time"}}</div>
                                                                <div class="content">
-                                                                       <form method="POST" id="add_time_manual_form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/times/add" class="ui action input fluid">
+                                                                       <form method="POST" id="add_time_manual_form" action="{{.Issue.Link}}/times/add" class="ui action input fluid">
                                                                                {{$.CsrfTokenHtml}}
                                                                                <input placeholder='{{.i18n.Tr "repo.issues.add_time_hours"}}' type="number" name="hours">
                                                                                <input placeholder='{{.i18n.Tr "repo.issues.add_time_minutes"}}' type="number" name="minutes" class="ui compact">
 
                        {{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
                                <div {{if ne .Issue.DeadlineUnix 0}} style="display: none;"{{end}} id="deadlineForm">
-                                       <form class="ui fluid action input issue-due-form" action="{{AppSubUrl}}/api/v1/repos/{{.Repository.Owner.Name}}/{{.Repository.Name}}/issues/{{.Issue.Index}}" method="post" id="update-issue-deadline-form">
+                                       <form class="ui fluid action input issue-due-form" action="{{AppSubUrl}}/api/v1/repos/{{PathEscape .Repository.Owner.Name}}/{{PathEscape .Repository.Name}}/issues/{{.Issue.Index}}" method="post" id="update-issue-deadline-form">
                                                {{$.CsrfTokenHtml}}
                                                <input required placeholder="{{.i18n.Tr "repo.issues.due_date_form"}}" {{if gt .Issue.DeadlineUnix 0}}value="{{.Issue.DeadlineUnix.Format "2006-01-02"}}"{{end}} type="date" name="deadlineDate" id="deadlineDate">
                                                <button class="ui green icon button">
                                                {{range .BlockingDependencies}}
                                                        <div class="item dependency{{if .Issue.IsClosed}} is-closed{{end}} df ac sb">
                                                                <div class="item-left df jc fc f1">
-                                                                       <a class="title" href="{{.Repository.Link}}/issues/{{.Issue.Index}}">
+                                                                       <a class="title" href="{{.Issue.Link}}">
                                                                                #{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}
                                                                        </a>
                                                                        <div class="text small">
                                                {{range .BlockedByDependencies}}
                                                        <div class="item dependency{{if .Issue.IsClosed}} is-closed{{end}} df ac sb">
                                                                <div class="item-left df jc fc f1">
-                                                                       <a class="title" href="{{.Repository.Link}}/{{if .Issue.IsPull}}pulls{{else}}issues{{end}}/{{.Issue.Index}}">
+                                                                       <a class="title" href="{{.Issue.Link}}">
                                                                                #{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}
                                                                        </a>
                                                                        <div class="text small">
 
                                {{if and .CanCreateIssueDependencies (not .Repository.IsArchived)}}
                                        <div>
-                                               <form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/dependency/add" id="addDependencyForm">
+                                               <form method="POST" action="{{.Issue.Link}}/dependency/add" id="addDependencyForm">
                                                        {{$.CsrfTokenHtml}}
                                                        <div class="ui fluid action input">
                                                                <div class="ui search selection dropdown" id="new-dependency-drop-list" data-issue-id="{{.Issue.ID}}">
                                                {{.i18n.Tr "repo.issues.dependency.remove_header"}}
                                        </div>
                                        <div class="content">
-                                               <form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/dependency/delete" id="removeDependencyForm">
+                                               <form method="POST" action="{{.Issue.Link}}/dependency/delete" id="removeDependencyForm">
                                                        {{$.CsrfTokenHtml}}
                                                        <input type="hidden" value="" name="removeDependencyID" id="removeDependencyID"/>
                                                        <input type="hidden" value="" name="dependencyType" id="dependencyType"/>
                                                {{end}}
                                        </div>
 
-                                       <form class="ui form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}{{ if .Issue.IsLocked }}/unlock{{else}}/lock{{end}}"
+                                       <form class="ui form" action="{{.Issue.Link}}{{ if .Issue.IsLocked }}/unlock{{else}}/lock{{end}}"
                                                method="post">
                                                {{.CsrfTokenHtml}}
 
index a21e58068c792326088625668428d00b9b1ee8a5..c4b391d97a0d7a6ecb74e57ac27707d8b6e99df4 100644 (file)
@@ -91,9 +91,9 @@
                {{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.Lang }}
                <span class="time-desc">
                        {{if .Issue.OriginalAuthor }}
-                               {{$.i18n.Tr "repo.issues.opened_by_fake" $createdStr .Issue.OriginalAuthor | Safe}}
+                               {{$.i18n.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.OriginalAuthor|Escape) | Safe}}
                        {{else if gt .Issue.Poster.ID 0}}
-                               {{$.i18n.Tr "repo.issues.opened_by" $createdStr .Issue.Poster.HomeLink (.Issue.Poster.GetDisplayName|Escape) | Safe}}
+                               {{$.i18n.Tr "repo.issues.opened_by" $createdStr (.Issue.Poster.HomeLink|Escape) (.Issue.Poster.GetDisplayName|Escape) | Safe}}
                        {{else}}
                                {{$.i18n.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.Poster.GetDisplayName|Escape) | Safe}}
                        {{end}}
index d97a0f594292ccff0c9504137a25c8cfbbbf3474..f7d699d9656573a1ae7260ad73e28e19db66c5c1 100644 (file)
                                                                                {{end}}
                                                                        {{end}}
                                                                </span>
-                                                               <a class="project-board-title vm" href="{{$.RepoLink}}/issues/{{.Index}}">
+                                                               <a class="project-board-title vm" href="{{.Link}}">
                                                                        {{.Title}}
                                                                </a>
                                                        </div>
                                                                        #{{.Index}}
                                                                        {{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.Lang }}
                                                                        {{if .OriginalAuthor }}
-                                                                               {{$.i18n.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor | Safe}}
+                                                                               {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}}
                                                                        {{else if gt .Poster.ID 0}}
-                                                                               {{$.i18n.Tr .GetLastEventLabel $timeStr .Poster.HomeLink (.Poster.GetDisplayName | Escape) | Safe}}
+                                                                               {{$.i18n.Tr .GetLastEventLabel $timeStr (.Poster.HomeLink|Escape) (.Poster.GetDisplayName | Escape) | Safe}}
                                                                        {{else}}
                                                                                {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}}
                                                                        {{end}}
index ecfe09c1ecbfe20a65d72e189ce8c2719a96a099..7152e345c3519c4ef253bbe62e3bcd28ec70c10b 100644 (file)
@@ -5,7 +5,7 @@
                <div class="navbar">
                        {{template "repo/issue/navbar" .}}
                        <div class="ui right">
-                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a>
+                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | PathEscapeSegments}}...{{.PullRequestCtx.HeadInfoSubURL}}">{{.i18n.Tr "repo.pulls.new"}}</a>
                        </div>
                </div>
                <div class="ui divider"></div>
index 60f47408c26d64f9c24724d6a4fb10cff056cf75..7866697629e3e366b9cf5c6eb0d07161b0c25435 100644 (file)
@@ -5,7 +5,7 @@
                <div class="navbar">
                        {{template "repo/issue/navbar" .}}
                        <div class="ui right">
-                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a>
+                               <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | PathEscapeSegments}}...{{.PullRequestCtx.HeadInfoSubURL}}">{{.i18n.Tr "repo.pulls.new"}}</a>
                        </div>
                </div>
                <div class="ui divider"></div>
index bf310e15968c7a1fdc330dc5c4469dc554fa4489..f5ca0e4769e5130d7ee6c85bc53bcb45a6d09657 100644 (file)
@@ -37,7 +37,7 @@
 
                                        <div class="inline field">
                                                <label>{{.i18n.Tr "repo.fork_from"}}</label>
-                                               <a href="{{AppSubUrl}}/{{.ForkFrom}}">{{.ForkFrom}}</a>
+                                               <a href="{{.ForkRepo.Link}}">{{.ForkRepo.FullName}}</a>
                                        </div>
                                        <div class="inline required field {{if .Err_RepoName}}error{{end}}">
                                                <label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
@@ -61,7 +61,7 @@
                                                <button class="ui green button">
                                                        {{.i18n.Tr "repo.fork_repo"}}
                                                </button>
-                                               <a class="ui button" href="{{AppSubUrl}}/{{.ForkFrom}}">{{.i18n.Tr "cancel"}}</a>
+                                               <a class="ui button" href="{{.ForkRepo.Link}}">{{.i18n.Tr "cancel"}}</a>
                                        </div>
                                </div>
                        </form>
index 5a414f7fc23ebcb8cb99d369332eb21f307a8480..ace916e9f5229172d2ced072f69588e171a69ae9 100644 (file)
@@ -1,15 +1,15 @@
 <div class="ui top attached pull tabular stackable menu">
-       <a class="item {{if .PageIsPullConversation}}active{{end}}" href="{{.RepoLink}}/pulls/{{.Issue.Index}}">
+       <a class="item {{if .PageIsPullConversation}}active{{end}}" href="{{.Issue.Link}}">
                {{svg "octicon-comment-discussion"}}
                {{$.i18n.Tr "repo.pulls.tab_conversation"}}
                <span class="ui {{if not .Issue.NumComments}}gray{{else}}blue{{end}} small label">{{.Issue.NumComments}}</span>
        </a>
-       <a class="item {{if .PageIsPullCommits}}active{{end}}" {{if .NumCommits}}href="{{.RepoLink}}/pulls/{{.Issue.Index}}/commits"{{end}}>
+       <a class="item {{if .PageIsPullCommits}}active{{end}}" {{if .NumCommits}}href="{{.Issue.Link}}/commits"{{end}}>
                {{svg "octicon-git-commit"}}
                {{$.i18n.Tr "repo.pulls.tab_commits"}}
                <span class="ui {{if not .NumCommits}}gray{{else}}blue{{end}} small label">{{if .NumCommits}}{{.NumCommits}}{{else}}N/A{{end}}</span>
        </a>
-       <a class="item {{if .PageIsPullFiles}}active{{end}}" {{if .NumFiles}}href="{{.RepoLink}}/pulls/{{.Issue.Index}}/files"{{end}}>
+       <a class="item {{if .PageIsPullFiles}}active{{end}}" {{if .NumFiles}}href="{{.Issue.Link}}/files"{{end}}>
                {{svg "octicon-diff"}}
                {{$.i18n.Tr "repo.pulls.tab_files"}}
                <span class="ui {{if not .NumFiles}}gray{{else}}blue{{end}} small label">{{if .NumFiles}}{{.NumFiles}}{{else}}N/A{{end}}</span>
index 5f06bf45d40988e985e00fe9d1012d88bf2e99e4..b47e7c482cf6126649acc52ab70f4b5cddcbd0a7 100644 (file)
                                                <tr>
                                                        <td class="tag">
                                                                <h3 class="release-tag-name mb-3">
-                                                                       <a class="df ac" href="{{$.RepoLink}}/src/tag/{{.TagName | EscapePound}}" rel="nofollow">{{.TagName}}</a>
+                                                                       <a class="df ac" href="{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}" rel="nofollow">{{.TagName}}</a>
                                                                </h3>
                                                                <div class="download df ac">
                                                                        {{if $.Permission.CanRead $.UnitTypeCode}}
                                                                                <a class="mr-3 mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a>
-                                                                               <a class="archive-link mr-3" data-url="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "mr-2"}}ZIP</a>
-                                                                               <a class="archive-link mr-3" data-url="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.tar.gz">{{svg "octicon-file-zip" 16 "mr-2"}}TAR.GZ</a>
+                                                                               <a class="archive-link mr-3" data-url="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "mr-2"}}ZIP</a>
+                                                                               <a class="archive-link mr-3" data-url="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.tar.gz">{{svg "octicon-file-zip" 16 "mr-2"}}TAR.GZ</a>
                                                                                {{if (and $.CanCreateRelease $release.IsTag)}}
-                                                                                       <a class="mr-3" href="{{$.RepoLink}}/releases/new?tag={{.TagName | EscapePound}}">{{svg "octicon-tag" 16 "mr-2"}}{{$.i18n.Tr "repo.release.new_release"}}</a>
+                                                                                       <a class="mr-3" href="{{$.RepoLink}}/releases/new?tag={{.TagName | PathEscapeSegments}}">{{svg "octicon-tag" 16 "mr-2"}}{{$.i18n.Tr "repo.release.new_release"}}</a>
                                                                                {{end}}
                                                                                {{if (and ($.Permission.CanWrite $.UnitTypeCode) $release.IsTag)}}
                                                                                        <a class="ui red delete-button mr-3" data-url="{{$.RepoLink}}/tags/delete" data-id="{{.ID}}">
@@ -48,7 +48,7 @@
                                                                                        </a>
                                                                                {{end}}
                                                                                {{if (not $release.IsTag)}}
-                                                                                       <a class="mr-3" href="{{$.RepoLink}}/releases/tag/{{.TagName | EscapePound}}">{{svg "octicon-tag" 16 "mr-2"}}{{$.i18n.Tr "repo.release.detail"}}</a>
+                                                                                       <a class="mr-3" href="{{$.RepoLink}}/releases/tag/{{.TagName | PathEscapeSegments}}">{{svg "octicon-tag" 16 "mr-2"}}{{$.i18n.Tr "repo.release.detail"}}</a>
                                                                                {{end}}
                                                                        {{end}}
                                                                </div>
@@ -75,7 +75,7 @@
                                                                <span class="ui green label">{{$.i18n.Tr "repo.release.stable"}}</span>
                                                        {{end}}
                                                        <span class="tag text blue">
-                                                               <a class="df ac je" href="{{if .IsDraft}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | EscapePound}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a>
+                                                               <a class="df ac je" href="{{if .IsDraft}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a>
                                                        </span>
                                                        {{if not .IsDraft}}
                                                                <span class="commit">
                                        <div class="ui twelve wide column detail">
                                                {{if .IsTag}}
                                                        <h4>
-                                                               <a href="{{$.RepoLink}}/src/tag/{{.TagName | EscapePound}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a>
+                                                               <a href="{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a>
                                                        </h4>
                                                        <p class="text grey">
                                                                {{ if gt .Publisher.ID 0 }}
                                                                <span class="author">
                                                                        {{avatar .Publisher 20}}
-                                                                       <a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.Name}}</a>
+                                                                       <a href="{{.Publisher.HomeLink}}">{{.Publisher.Name}}</a>
                                                                </span>
                                                                {{ end }}
-                                                               <span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | EscapePound}}...{{.Target}}">{{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{$.i18n.Tr "repo.release.ahead.target" $.DefaultBranch}}</span>
+                                                               <span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | PathEscapeSegments}}...{{.Target | PathEscapeSegments}}">{{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{$.i18n.Tr "repo.release.ahead.target" $.DefaultBranch}}</span>
                                                        </p>
                                                        <div class="download">
                                                        {{if $.Permission.CanRead $.UnitTypeCode}}
                                                                <a class="mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a>
-                                                               <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.zip" rel="nofollow">{{svg "octicon-file-zip"}}&nbsp;ZIP</a>
-                                                               <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.tar.gz">{{svg "octicon-file-zip"}}&nbsp;TAR.GZ</a>
+                                                               <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.zip" rel="nofollow">{{svg "octicon-file-zip"}}&nbsp;ZIP</a>
+                                                               <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.tar.gz">{{svg "octicon-file-zip"}}&nbsp;TAR.GZ</a>
                                                        {{end}}
                                                        </div>
                                                {{else}}
                                                        <h4 class="release-list-title df ac">
-                                                               <a href="{{$.RepoLink}}/releases/tag/{{.TagName | EscapePound}}">{{.Title}}</a>
+                                                               <a href="{{$.RepoLink}}/releases/tag/{{.TagName | PathEscapeSegments}}">{{.Title}}</a>
                                                                {{if $.CanCreateRelease}}
                                                                        <small class="ml-2">
-                                                                               (<a href="{{$.RepoLink}}/releases/edit/{{.TagName | EscapePound}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>)
+                                                                               (<a href="{{$.RepoLink}}/releases/edit/{{.TagName | PathEscapeSegments}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>)
                                                                        </small>
                                                                {{end}}
                                                        </h4>
                                                                        {{svg "octicon-mark-github" 16 "mr-2"}}{{.OriginalAuthor}}
                                                                {{else if .Publisher}}
                                                                        {{avatar .Publisher 20}}
-                                                                       <a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.GetDisplayName}}</a>
+                                                                       <a href="{{.Publisher.HomeLink}}">{{.Publisher.GetDisplayName}}</a>
                                                                {{else}}
                                                                        Ghost
                                                                {{end}}
                                                                        <span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>
                                                                {{end}}
                                                                {{if not .IsDraft}}
-                                                                       | <span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | EscapePound}}...{{.Target}}">{{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{$.i18n.Tr "repo.release.ahead.target" .Target}}</span>
+                                                                       | <span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | PathEscapeSegments}}...{{.Target | PathEscapeSegments}}">{{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{$.i18n.Tr "repo.release.ahead.target" .Target}}</span>
                                                                {{end}}
                                                        </p>
                                                        <div class="markup desc">
                                                                <ul class="list">
                                                                        {{if and (not .IsDraft) ($.Permission.CanRead $.UnitTypeCode)}}
                                                                                <li>
-                                                                                       <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.zip" rel="nofollow"><strong>{{svg "octicon-file-zip" 16 "mr-2"}}{{$.i18n.Tr "repo.release.source_code"}} (ZIP)</strong></a>
+                                                                                       <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.zip" rel="nofollow"><strong>{{svg "octicon-file-zip" 16 "mr-2"}}{{$.i18n.Tr "repo.release.source_code"}} (ZIP)</strong></a>
                                                                                </li>
                                                                                <li>
-                                                                                       <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.tar.gz"><strong>{{svg "octicon-file-zip" 16 "mr-2"}}{{$.i18n.Tr "repo.release.source_code"}} (TAR.GZ)</strong></a>
+                                                                                       <a class="archive-link" data-url="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.tar.gz"><strong>{{svg "octicon-file-zip" 16 "mr-2"}}{{$.i18n.Tr "repo.release.source_code"}} (TAR.GZ)</strong></a>
                                                                                </li>
                                                                        {{end}}
                                                                        {{if .Attachments}}
index bd70690e061cab51ce7314438777abddca04d5a4..f2c2269af7fe679e045247ceb598d7f7c9e79506 100644 (file)
                </div>
                {{if .Keyword}}
                        <h3>
-                               {{.i18n.Tr "repo.search.results" (.Keyword|Escape) .RepoLink .RepoName | Str2html }}
+                               {{.i18n.Tr "repo.search.results" (.Keyword|Escape) (.RepoLink|Escape) (.RepoName|Escape) | Str2html }}
                        </h3>
                        <div class="df ac fw">
                                {{range $term := .SearchResultLanguages}}
-                               <a class="ui text-label df ac mr-1 my-1 {{if eq $.Language $term.Language}}primary {{end}}basic label" href="{{EscapePound $.SourcePath}}/search?q={{$.Keyword}}{{if ne $.Language $term.Language}}&l={{$term.Language}}{{end}}{{if ne $.queryType ""}}&t={{$.queryType}}{{end}}">
+                               <a class="ui text-label df ac mr-1 my-1 {{if eq $.Language $term.Language}}primary {{end}}basic label" href="{{$.SourcePath}}/search?q={{$.Keyword}}{{if ne $.Language $term.Language}}&l={{$term.Language}}{{end}}{{if ne $.queryType ""}}&t={{$.queryType}}{{end}}">
                                        <i class="color-icon mr-3" style="background-color: {{$term.Color}}"></i>
                                        {{$term.Language}}
                                        <div class="detail">{{$term.Count}}</div>
@@ -36,7 +36,7 @@
                                        <div class="diff-file-box diff-box file-content non-diff-file-content repo-search-result">
                                                <h4 class="ui top attached normal header">
                                                        <span class="file">{{.Filename}}</span>
-                                                       <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.SourcePath}}/src/commit/{{$result.CommitID}}/{{EscapePound .Filename}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+                                                       <a class="ui basic tiny button" rel="nofollow" href="{{$.SourcePath}}/src/commit/{{PathEscape $result.CommitID}}/{{PathEscapeSegments .Filename}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
                                                </h4>
                                                <div class="ui attached table segment">
                                                        <div class="file-body file-code code-view">
@@ -45,7 +45,7 @@
                                                                                <tr>
                                                                                        <td class="lines-num">
                                                                                                {{range .LineNumbers}}
-                                                                                                       <a href="{{EscapePound $.SourcePath}}/src/commit/{{$result.CommitID}}/{{EscapePound $result.Filename}}#L{{.}}"><span>{{.}}</span></a>
+                                                                                                       <a href="{{$.SourcePath}}/src/commit/{{PathEscape $result.CommitID}}/{{PathEscapeSegments $result.Filename}}#L{{.}}"><span>{{.}}</span></a>
                                                                                                {{end}}
                                                                                        </td>
                                                                                        <td class="lines-code chroma"><code class="code-inner">{{.FormattedLines | Safe}}</code></td>
index 89d7c6db77a31b86e6d95f30f02d16af887e964e..5671eca368a50fea8a6e19655d86fc36d2f21284 100644 (file)
@@ -53,7 +53,7 @@
                                                        <div class="default text">{{.i18n.Tr "repo.settings.choose_branch"}}</div>
                                                        <div class="menu transition hidden" tabindex="-1" style="display: block !important;">
                                                                {{range .LeftBranches}}
-                                                                       <a class="item" href="{{$.Repository.Link}}/settings/branches/{{. | EscapePound}}">{{.}}</a>
+                                                                       <a class="item" href="{{$.Repository.Link}}/settings/branches/{{. | PathEscapeSegments}}">{{.}}</a>
                                                                {{end}}
                                                        </div>
                                                </div>
@@ -67,7 +67,7 @@
                                                                {{range .ProtectedBranches}}
                                                                        <tr>
                                                                                <td><div class="ui basic label blue">{{.BranchName}}</div></td>
-                                                                               <td class="right aligned"><a class="rm ui button" href="{{$.Repository.Link}}/settings/branches/{{.BranchName | EscapePound}}">{{$.i18n.Tr "repo.settings.edit_protected_branch"}}</a></td>
+                                                                               <td class="right aligned"><a class="rm ui button" href="{{$.Repository.Link}}/settings/branches/{{.BranchName | PathEscapeSegments}}">{{$.i18n.Tr "repo.settings.edit_protected_branch"}}</a></td>
                                                                        </tr>
                                                                {{else}}
                                                                        <tr class="center aligned"><td>{{.i18n.Tr "repo.settings.no_protected_branch"}}</td></tr>
index 864b2968fc699d9751f64adb6b9040199c1f1605..3b584a559ba239c1837fe4121f30d0601424bd6a 100644 (file)
@@ -12,7 +12,7 @@
                        {{range .Collaborators}}
                                <div class="item ui grid">
                                        <div class="ui five wide column">
-                                               <a href="{{AppSubUrl}}/{{.Name}}">
+                                               <a href="{{.HomeLink}}">
                                                        {{avatar .}}
                                                        {{.DisplayName}}
                                                </a>
@@ -62,7 +62,7 @@
                        {{range $t, $team := .Teams}}
                                <div class="item ui grid">
                                        <div class="ui five wide column">
-                                               <a href="{{AppSubUrl}}/org/{{$.OrgName}}/teams/{{.LowerName}}">
+                                               <a href="{{AppSubUrl}}/org/{{$.OrgName|PathEscape}}/teams/{{.LowerName|PathEscape}}">
                                                        {{.Name}}
                                                </a>
                                        </div>
index 40bc787c8dcd85b7b846f8576d2287498713395a..972d03425c7d395eb10cf81c6d8de91f14b312dd 100644 (file)
@@ -16,7 +16,7 @@
                                        <div class="item">
                                                <span class="text {{if .IsActive}}green{{else}}grey{{end}}">{{svg "octicon-dot-fill"}}</span>
                                                <span>{{.Name}}</span>
-                                               <a class="text blue ui right" href="{{$.RepoLink}}/settings/hooks/git/{{.Name}}">
+                                               <a class="text blue ui right" href="{{$.RepoLink}}/settings/hooks/git/{{.Name|PathEscape}}">
                                                        {{svg "octicon-pencil"}}
                                                </a>
                                        </div>
index 478c034e11074b6ad567c2193adf06cfe6424835..f6510f17db3141255ffa7ab85faca27d91011d16 100644 (file)
                                        {{else if not .IsTextFile}}
                                                <div class="view-raw ui center">
                                                        {{if .IsImageFile}}
-                                                               <img src="{{EscapePound $.RawFileLink}}">
+                                                               <img src="{{$.RawFileLink}}">
                                                        {{else if .IsVideoFile}}
-                                                               <video controls src="{{EscapePound $.RawFileLink}}">
+                                                               <video controls src="{{$.RawFileLink}}">
                                                                        <strong>{{.i18n.Tr "repo.video_not_supported_in_browser"}}</strong>
                                                                </video>
                                                        {{else if .IsAudioFile}}
-                                                               <audio controls src="{{EscapePound $.RawFileLink}}">
+                                                               <audio controls src="{{$.RawFileLink}}">
                                                                        <strong>{{.i18n.Tr "repo.audio_not_supported_in_browser"}}</strong>
                                                                </audio>
                                                        {{else if .IsPDFFile}}
-                                                               <iframe width="100%" height="600px" src="{{AppSubUrl}}/vendor/plugins/pdfjs/web/viewer.html?file={{EscapePound $.RawFileLink}}"></iframe>
+                                                               <iframe width="100%" height="600px" src="{{AppSubUrl}}/vendor/plugins/pdfjs/web/viewer.html?file={{$.RawFileLink}}"></iframe>
                                                        {{else}}
-                                                               <a href="{{EscapePound $.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
+                                                               <a href="{{$.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
                                                        {{end}}
                                                </div>
                                        {{else if .FileSize}}
index 83a2e317d57fcbac3d72685e4c70ffde0af49051..f5a0e0081c52b7057c3ee686390b5995ddf5f23f 100644 (file)
@@ -14,7 +14,7 @@
                                                <tr>
                                                        <td>
                                                                {{svg "octicon-file"}}
-                                                               <a href="{{EscapePound $.RepoLink}}/src/commit/{{.SHA}}/{{EscapePound .Name}}" title="{{.Name}}">{{.Name}}</a>
+                                                               <a href="{{$.RepoLink}}/src/commit/{{.SHA}}/{{PathEscapeSegments .Name}}" title="{{.Name}}">{{.Name}}</a>
                                                        </td>
                                                        <td class="message">
                                                                <span class="truncate">
index 84269dc612bef85f557016aaaecd0b9d896fb5ec..7d6e531bd226e4e0e8069795a29819abe38ca71d 100644 (file)
@@ -24,7 +24,7 @@
                                                        <td>
                                                                {{if index $.Linkable $index}}
                                                                        {{svg "octicon-file"}}
-                                                               <a href="{{EscapePound $.RepoLink}}/src/branch/{{EscapePound $lock.Repo.DefaultBranch}}/{{EscapePound $lock.Path}}" title="{{$lock.Path}}">{{$lock.Path}}</a>
+                                                               <a href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments $lock.Repo.DefaultBranch}}/{{PathEscapeSegments $lock.Path}}" title="{{$lock.Path}}">{{$lock.Path}}</a>
                                                                {{else}}
                                                                        {{svg "octicon-diff"}}
                                                                <span class="poping up" title="{{$.i18n.Tr "repo.settings.lfs_lock_file_no_exist"}}">{{$lock.Path}}</span>
@@ -34,7 +34,7 @@
                                                                {{end}}
                                                        </td>
                                                        <td>
-                                                               <a href="{{AppSubUrl}}/{{$lock.Owner.Name}}">
+                                                               <a href="{{$lock.Owner.HomeLink}}">
                                                                        {{avatar $lock.Owner}}
                                                                        {{$lock.Owner.DisplayName}}
                                                                </a>
index a2c887b1f8f3937a038a2dbef40057971f903693..48c42bdf254c4b0eed10bea4f7666db6697049e3 100644 (file)
                                                                                                        {{$teamIDs := .AllowlistTeamIDs}}
                                                                                                        {{range $.Teams}}
                                                                                                                {{if contain $teamIDs .ID }}
-                                                                                                                       <a class="ui basic image label" href="{{$.Owner.OrganisationLink}}/teams/{{.LowerName}}">{{.Name}}</a>
+                                                                                                                       <a class="ui basic image label" href="{{$.Owner.OrganisationLink}}/teams/{{PathEscape .LowerName}}">{{.Name}}</a>
                                                                                                                {{end}}
                                                                                                        {{end}}
                                                                                                {{end}}
index f00237047e8752d8fb510040e7e87e09e781623e..3b05708c74620a48e87ee7c6b4994050ceefcfbf 100644 (file)
@@ -3,7 +3,7 @@
                <div class="ui two horizontal center link list">
                        {{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo)}}
                                <div class="item{{if .PageIsCommits}} active{{end}}">
-                                       <a class="ui" href="{{.RepoLink}}/commits{{if .IsViewBranch}}/branch{{else if .IsViewTag}}/tag{{else if .IsViewCommit}}/commit{{end}}/{{EscapePound .BranchName}}">{{svg "octicon-history"}} <b>{{.CommitsCount}}</b> {{.i18n.Tr (TrN .i18n.Lang .CommitsCount "repo.commit" "repo.commits") }}</a>
+                                       <a class="ui" href="{{.RepoLink}}/commits{{if .IsViewBranch}}/branch{{else if .IsViewTag}}/tag{{else if .IsViewCommit}}/commit{{end}}/{{PathEscapeSegments .BranchName}}">{{svg "octicon-history"}} <b>{{.CommitsCount}}</b> {{.i18n.Tr (TrN .i18n.Lang .CommitsCount "repo.commit" "repo.commits") }}</a>
                                </div>
                                <div class="item{{if .PageIsBranches}} active{{end}}">
                                        <a class="ui" href="{{.RepoLink}}/branches">{{svg "octicon-git-branch"}} <b>{{.BranchesCount}}</b> {{.i18n.Tr (TrN .i18n.Lang .BranchesCount "repo.branch" "repo.branches") }}</a>
index 2c678beb9073657b73a1fa53e223fcc0d69f8a2b..afe3306a4d5dd43c6f974a8051f06c3c60ff0ef9 100644 (file)
@@ -24,7 +24,7 @@
                                        {{if .LFSLock}}
                                                <div class="file-info-entry ui poping up" data-content="{{.LFSLockHint}}">
                                                        {{svg "octicon-lock" 16 "mr-2"}}
-                                                       <a href="{{AppSubUrl}}/{{.LFSLock.Owner.Name}}">{{.LFSLockOwner}}</a>
+                                                       <a href="{{.LFSLock.Owner.HomeLink}}">{{.LFSLockOwner}}</a>
                                                </div>
                                        {{end}}
                                </div>
                                </div>
                        {{end}}
                        <div class="ui buttons mr-2">
-                               <a class="ui mini basic button" href="{{EscapePound $.RawFileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
+                               <a class="ui mini basic button" href="{{$.RawFileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
                                {{if not .IsViewCommit}}
-                                       <a class="ui mini basic button" href="{{.RepoLink}}/src/commit/{{.CommitID}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_permalink"}}</a>
+                                       <a class="ui mini basic button" href="{{.RepoLink}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{.i18n.Tr "repo.file_permalink"}}</a>
                                {{end}}
                                {{if .IsRepresentableAsText}}
-                                       <a class="ui mini basic button" href="{{.RepoLink}}/blame/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.blame"}}</a>
+                                       <a class="ui mini basic button" href="{{.RepoLink}}/blame/{{.BranchNameSubURL}}/{{PathEscapeSegments .TreePath}}">{{.i18n.Tr "repo.blame"}}</a>
                                {{end}}
-                               <a class="ui mini basic button" href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_history"}}</a>
+                               <a class="ui mini basic button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{PathEscapeSegments .TreePath}}">{{.i18n.Tr "repo.file_history"}}</a>
                        </div>
-                       <a download href="{{EscapePound $.RawFileLink}}"><span class="btn-octicon poping up" data-content="{{.i18n.Tr "repo.download_file"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-download"}}</span></a>
+                       <a download href="{{$.RawFileLink}}"><span class="btn-octicon poping up" data-content="{{.i18n.Tr "repo.download_file"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-download"}}</span></a>
                        {{if .Repository.CanEnableEditor}}
                                {{if .CanEditFile}}
-                                       <a href="{{.RepoLink}}/_edit/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}"><span class="btn-octicon poping up" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil"}}</span></a>
+                                       <a href="{{.RepoLink}}/_edit/{{PathEscapeSegments .BranchName}}/{{PathEscapeSegments .TreePath}}"><span class="btn-octicon poping up" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil"}}</span></a>
                                {{else}}
                                        <span class="btn-octicon poping up disabled" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil"}}</span>
                                {{end}}
                                {{if .CanDeleteFile}}
-                                       <a href="{{.RepoLink}}/_delete/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}"><span class="btn-octicon btn-octicon-danger poping up"  data-content="{{.DeleteFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-trash"}}</span></a>
+                                       <a href="{{.RepoLink}}/_delete/{{PathEscapeSegments .BranchName}}/{{PathEscapeSegments .TreePath}}"><span class="btn-octicon btn-octicon-danger poping up"  data-content="{{.DeleteFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-trash"}}</span></a>
                                {{else}}
                                        <span class="btn-octicon poping up disabled" data-content="{{.DeleteFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-trash"}}</span>
                                {{end}}
                        {{else if not .IsTextSource}}
                                <div class="view-raw ui center">
                                        {{if .IsImageFile}}
-                                               <img src="{{EscapePound $.RawFileLink}}">
+                                               <img src="{{$.RawFileLink}}">
                                        {{else if .IsVideoFile}}
-                                               <video controls src="{{EscapePound $.RawFileLink}}">
+                                               <video controls src="{{$.RawFileLink}}">
                                                        <strong>{{.i18n.Tr "repo.video_not_supported_in_browser"}}</strong>
                                                </video>
                                        {{else if .IsAudioFile}}
-                                               <audio controls src="{{EscapePound $.RawFileLink}}">
+                                               <audio controls src="{{$.RawFileLink}}">
                                                        <strong>{{.i18n.Tr "repo.audio_not_supported_in_browser"}}</strong>
                                                </audio>
                                        {{else if .IsPDFFile}}
-                                               <iframe width="100%" height="600px" src="{{AssetUrlPrefix}}/vendor/plugins/pdfjs/web/viewer.html?file={{EscapePound $.RawFileLink}}"></iframe>
+                                               <iframe width="100%" height="600px" src="{{AssetUrlPrefix}}/vendor/plugins/pdfjs/web/viewer.html?file={{$.RawFileLink}}"></iframe>
                                        {{else}}
-                                               <a href="{{EscapePound $.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
+                                               <a href="{{$.RawFileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
                                        {{end}}
                                </div>
                        {{else if .FileSize}}
                                                <div class="column">
                                                        {{if $.Permission.CanRead $.UnitTypeIssues}}
                                                                <div class="ui link list">
-                                                                       <a class="item ref-in-new-issue" href="{{.RepoLink}}/issues/new?body={{URLJoin AppUrl .RepoLink}}/src/commit/{{.CommitID}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.issues.context.reference_issue"}}</a>
+                                                                       <a class="item ref-in-new-issue" href="{{.RepoLink}}/issues/new?body={{.Repository.HTMLURL}}{{printf "/src/commit/" }}{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{.i18n.Tr "repo.issues.context.reference_issue"}}</a>
                                                                </div>
                                                        {{end}}
                                                        <div class="ui link list">
-                                                               <a data-clipboard-text="{{URLJoin AppUrl .RepoLink}}/src/commit/{{.CommitID}}/{{EscapePound .TreePath}}" class="item copy-line-permalink">{{.i18n.Tr "repo.file_copy_permalink"}}</a>
+                                                               <a data-clipboard-text="{{.Repository.HTMLURL}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}" class="item copy-line-permalink">{{.i18n.Tr "repo.file_copy_permalink"}}</a>
                                                        </div>
                                                </div>
                                        </div>
index 3e7bcbe505a52b75a5bb0f7d95a720e5c4398401..9b28b395d1226797f1f7f5d0019b85c6aaa941bb 100644 (file)
@@ -8,9 +8,9 @@
                                        {{if .LatestCommitUser}}
                                                {{avatar .LatestCommitUser 24}}
                                                {{if .LatestCommitUser.FullName}}
-                                                       <a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
+                                                       <a href="{{.LatestCommitUser.HomeLink}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
                                                {{else}}
-                                                       <a href="{{AppSubUrl}}/{{.LatestCommitUser.Name}}"><strong>{{if .LatestCommit.Author}}{{.LatestCommit.Author.Name}}{{else}}{{.LatestCommitUser.Name}}{{end}}</strong></a>
+                                                       <a href="{{.LatestCommitUser.HomeLink}}"><strong>{{if .LatestCommit.Author}}{{.LatestCommit.Author.Name}}{{else}}{{.LatestCommitUser.Name}}{{end}}</strong></a>
                                                {{end}}
                                        {{else}}
                                                {{if .LatestCommit.Author}}
                                                        <strong>{{.LatestCommit.Author.Name}}</strong>
                                                {{end}}
                                        {{end}}
-                                       <a rel="nofollow" class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}Untrusted{{else}}Unmatched{{end}}{{else if .LatestCommitVerification.Warning}} isWarning{{end}}{{end}}" href="{{.RepoLink}}/commit/{{.LatestCommit.ID}}">
+                                       <a rel="nofollow" class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}Untrusted{{else}}Unmatched{{end}}{{else if .LatestCommitVerification.Warning}} isWarning{{end}}{{end}}" href="{{.RepoLink}}/commit/{{PathEscape .LatestCommit.ID.String}}">
                                                <span class="shortsha">{{ShortSha .LatestCommit.ID.String}}</span>
                                                {{if .LatestCommit.Signature}}
                                                        {{template "repo/shabox_badge" dict "root" $ "verification" .LatestCommitVerification}}
                                                {{end}}
                                        </a>
                                        {{template "repo/commit_statuses" dict "Status" .LatestCommitStatus "Statuses" .LatestCommitStatuses "root" $}}
-                                       {{ $commitLink:= printf "%s/commit/%s" .RepoLink .LatestCommit.ID }}
+                                       {{ $commitLink:= printf "%s/commit/%s" .RepoLink (PathEscape .LatestCommit.ID.String) }}
                                        <span class="grey commit-summary" title="{{.LatestCommit.Summary}}"><span class="message-wrapper">{{RenderCommitMessageLinkSubject .LatestCommit.Message $.RepoLink $commitLink $.Repository.ComposeMetas}}</span>
                                                {{if IsMultilineCommitMessage .LatestCommit.Message}}
                                                        <button class="basic compact mini ui icon button commit-button"><i class="ellipsis horizontal icon"></i></button>
@@ -40,7 +40,7 @@
        <tbody>
                {{if .HasParentPath}}
                        <tr class="has-parent">
-                               <td colspan="3">{{svg "octicon-reply"}}<a href="{{EscapePound .BranchLink}}{{.ParentPath}}">..</a></td>
+                               <td colspan="3">{{svg "octicon-reply"}}<a href="{{.BranchLink}}{{if .ParentPath}}{{PathEscapeSegments .ParentPath}}{{end}}">..</a></td>
                        </tr>
                {{end}}
                {{range $item := .Files}}
@@ -54,7 +54,7 @@
                                                        {{svg "octicon-file-submodule"}}
                                                        {{$refURL := $subModuleFile.RefURL AppUrl $.Repository.FullName $.SSHDomain}}
                                                        {{if $refURL}}
-                                                               <a href="{{$refURL}}">{{$entry.Name}}</a><span class="at">@</span><a href="{{$refURL}}/commit/{{$subModuleFile.RefID}}">{{ShortSha $subModuleFile.RefID}}</a>
+                                                               <a href="{{$refURL}}">{{$entry.Name}}</a><span class="at">@</span><a href="{{$refURL}}/commit/{{PathEscape $subModuleFile.RefID}}">{{ShortSha $subModuleFile.RefID}}</a>
                                                        {{else}}
                                                                {{$entry.Name}}<span class="at">@</span>{{ShortSha $subModuleFile.RefID}}
                                                        {{end}}
@@ -63,7 +63,7 @@
                                                                {{$subJumpablePathName := $entry.GetSubJumpablePathName}}
                                                                {{$subJumpablePath := SubJumpablePath $subJumpablePathName}}
                                                                {{svg "octicon-file-directory"}}
-                                                               <a href="{{EscapePound $.TreeLink}}/{{EscapePound $subJumpablePathName}}" title="{{$subJumpablePathName}}">
+                                                               <a href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
                                                                        {{if eq (len $subJumpablePath) 2}}
                                                                                <span class="jumpable-path">{{index  $subJumpablePath 0}}</span>{{index  $subJumpablePath 1}}
                                                                        {{else}}
@@ -72,7 +72,7 @@
                                                                </a>
                                                        {{else}}
                                                                {{svg (printf "octicon-%s" (EntryIcon $entry))}}
-                                                               <a href="{{EscapePound $.TreeLink}}/{{EscapePound $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
+                                                               <a href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
                                                        {{end}}
                                                {{end}}
                                        </span>
@@ -80,7 +80,7 @@
                                <td class="message nine wide">
                                        <span class="truncate">
                                                {{if $commit}}
-                                                       <a href="{{$.RepoLink}}/commit/{{$commit.ID}}" title="{{$commit.Summary}}">{{$commit.Summary | RenderEmoji}}</a>
+                                                       <a href="{{$.RepoLink}}/commit/{{PathEscape $commit.ID.String}}" title="{{$commit.Summary}}">{{$commit.Summary | RenderEmoji}}</a>
                                                {{else}}
                                                        <div class="ui active tiny slow centered inline">…</div>
                                                {{end}}
index d887d8ffae28095cdc429057605b7573daf5cdb7..6cfa7983743f7f7ca8870e5dcfefd6fb5f2e5734 100644 (file)
@@ -7,7 +7,7 @@
                        {{.i18n.Tr "repo.wiki.new_page"}}
                        {{if .PageIsWikiEdit}}
                                <div class="ui right">
-                                       <a class="ui green small button" href="{{.RepoLink}}/wiki/_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a>
+                                       <a class="ui green small button" href="{{.RepoLink}}/wiki?action=_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a>
                                </div>
                        {{end}}
                </div>
index 3afa7772de609f55196cb916cb2814d47281fd77..43766771bc504573bb4808f64937d3419c29bee7 100644 (file)
@@ -8,7 +8,7 @@
                        </div>
                        <div>
                                {{if and .CanWriteWiki (not .IsRepositoryMirror)}}
-                                       <a class="ui green small button" href="{{.RepoLink}}/wiki/_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a>
+                                       <a class="ui green small button" href="{{.RepoLink}}/wiki?action=_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a>
                                {{end}}
                        </div>
                </h2>
index e9b7ecb6c959c5be0381f19726ea4141c0f7c282..514ac114ad6f62ae63716110ea6775a939d45351 100644 (file)
@@ -7,7 +7,7 @@
                        <h2>{{.i18n.Tr "repo.wiki.welcome"}}</h2>
                        <p>{{.i18n.Tr "repo.wiki.welcome_desc"}}</p>
                        {{if and .CanWriteWiki (not .Repository.IsMirror)}}
-                               <a class="ui green button" href="{{.RepoLink}}/wiki/_new">{{.i18n.Tr "repo.wiki.create_first_page"}}</a>
+                               <a class="ui green button" href="{{.RepoLink}}/wiki?action=_new">{{.i18n.Tr "repo.wiki.create_first_page"}}</a>
                        {{end}}
                </div>
        </div>
index a393fb20a18f0fa7c0b8a0889c3f9b8964b8253d..b71c950e1747561c6cdf9421110a3d465deb7994 100644 (file)
@@ -37,7 +37,7 @@
                <div class="ui dividing header">
                        <div class="ui stackable grid">
                                <div class="eight wide column">
-                                       <a class="file-revisions-btn ui basic button" title="{{.i18n.Tr "repo.wiki.file_revision"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}/_revision" ><span>{{.CommitCount}}</span> {{svg "octicon-history"}}</a>
+                                       <a class="file-revisions-btn ui basic button" title="{{.i18n.Tr "repo.wiki.file_revision"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}?action=_revision" ><span>{{.CommitCount}}</span> {{svg "octicon-history"}}</a>
                                        {{$title}}
                                        <div class="ui sub header">
                                                {{$timeSince := TimeSince .Author.When $.Lang}}
@@ -47,9 +47,9 @@
                                <div class="eight wide right aligned column">
                                        {{if and .CanWriteWiki (not .Repository.IsMirror)}}
                                                <div class="ui right">
-                                                       <a class="ui small button" href="{{.RepoLink}}/wiki/{{.PageURL}}/_edit">{{.i18n.Tr "repo.wiki.edit_page_button"}}</a>
-                                                       <a class="ui green small button" href="{{.RepoLink}}/wiki/_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a>
-                                                       <a class="ui red small button delete-button" href="" data-url="{{.RepoLink}}/wiki/{{.PageURL}}/delete" data-id="{{.PageURL}}">{{.i18n.Tr "repo.wiki.delete_page_button"}}</a>
+                                                       <a class="ui small button" href="{{.RepoLink}}/wiki/{{.PageURL}}?action=_edit">{{.i18n.Tr "repo.wiki.edit_page_button"}}</a>
+                                                       <a class="ui green small button" href="{{.RepoLink}}/wiki?action=_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a>
+                                                       <a class="ui red small button delete-button" href="" data-url="{{.RepoLink}}/wiki/{{.PageURL}}?action=_delete" data-id="{{.PageURL}}">{{.i18n.Tr "repo.wiki.delete_page_button"}}</a>
                                                </div>
                                        {{end}}
                                </div>
@@ -68,7 +68,7 @@
                        <div class="column" style="padding-top: 0;">
                                <div class="ui segment">
                                        {{if and .CanWriteWiki (not .Repository.IsMirror)}}
-                                               <a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Sidebar/_edit" aria-label="{{.i18n.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
+                                               <a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{.i18n.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
                                        {{end}}
                                        {{.sidebarContent | Str2html}}
                                </div>
@@ -78,7 +78,7 @@
                {{if .footerPresent}}
                <div class="ui segment">
                                {{if and .CanWriteWiki (not .Repository.IsMirror)}}
-                                       <a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Footer/_edit" aria-label="{{.i18n.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
+                                       <a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{.i18n.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
                                {{end}}
                        {{.footerContent | Str2html}}
                </div>
index 984ddf44737c5939dbcc9d6ba5e356600ed177ef..80d9fb11724b50215974433496b96033cb54ebae 100644 (file)
                                        </a>
                                        {{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.Lang }}
                                        {{if .OriginalAuthor }}
-                                               {{$.i18n.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor | Safe}}
+                                               {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.OriginalAuthor|Escape) | Safe}}
                                        {{else if gt .Poster.ID 0}}
-                                               {{$.i18n.Tr .GetLastEventLabel $timeStr .Poster.HomeLink (.Poster.GetDisplayName | Escape) | Safe}}
+                                               {{$.i18n.Tr .GetLastEventLabel $timeStr (.Poster.HomeLink|Escape) (.Poster.GetDisplayName | Escape) | Safe}}
                                        {{else}}
                                                {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}}
                                        {{end}}
                                        {{if and .Milestone (ne $.listType "milestone")}}
-                                               <a class="milestone" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/milestone/{{.Milestone.ID}}"{{end}}>
+                                               <a class="milestone" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{.Repo.Link}}/milestone/{{.Milestone.ID}}"{{end}}>
                                                        {{svg "octicon-milestone" 14 "mr-2"}}{{.Milestone.Name}}
                                                </a>
                                        {{end}}
                                        {{if .Ref}}
-                                               <a class="ref" {{if $.RepoLink}}href="{{index $.IssueRefURLs .ID}}"{{else}}href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{index $.IssueRefURLs .ID}}"{{end}}>
+                                               <a class="ref" {{if $.RepoLink}}href="{{index $.IssueRefURLs .ID}}"{{else}}href="{{.Repo.Link}}{{index $.IssueRefURLs .ID}}"{{end}}>
                                                        {{svg "octicon-git-branch" 14 "mr-2"}}{{index $.IssueRefEndNames .ID}}
                                                </a>
                                        {{end}}
index 130c2383e78e29f172308a7e6ea9787ced3601da..2f8dffb52ec075f8a0958207a4cb51bf156437c9 100644 (file)
@@ -9,11 +9,11 @@
                                {{template "base/alert" .}}
                                <p>
                                        <b>{{.i18n.Tr "auth.authorize_application_description"}}</b><br/>
-                                       {{.i18n.Tr "auth.authorize_application_created_by" .ApplicationUserLink | Str2html}}
+                                       {{.i18n.Tr "auth.authorize_application_created_by" (.ApplicationUserLink|Escape) | Str2html}}
                                </p>
                        </div>
                        <div class="ui attached segment">
-                               <p>{{.i18n.Tr "auth.authorize_redirect_notice" .ApplicationRedirectDomainHTML | Str2html}}</p>
+                               <p>{{.i18n.Tr "auth.authorize_redirect_notice" (.ApplicationRedirectDomainHTML|Escape) | Str2html}}</p>
                        </div>
                        <div class="ui attached segment">
                                <form method="post" action="{{AppSubUrl}}/login/oauth/grant">
index 83d064dc9529b3e6b4fd965b8a0b1c8c43bc1694..a2510f43ef4d2cfe2e6ddd87a81549c67afc3687 100644 (file)
@@ -8,80 +8,80 @@
                                <div class="{{if or (eq .GetOpType 5) (eq .GetOpType 18)}}push news{{end}}">
                                        <p>
                                                {{if gt .ActUser.ID 0}}
-                                                       <a href="{{AppSubUrl}}/{{.GetActUserName}}" title="{{.GetDisplayNameTitle}}">{{.GetDisplayName}}</a>
+                                                       <a href="{{AppSubUrl}}/{{.GetActUserName | PathEscape}}" title="{{.GetDisplayNameTitle}}">{{.GetDisplayName}}</a>
                                                {{else}}
                                                        {{.ShortActUserName}}
                                                {{end}}
                                                {{if eq .GetOpType 1}}
-                                                       {{$.i18n.Tr "action.create_repo" .GetRepoLink .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.create_repo" (.GetRepoLink|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 2}}
-                                                       {{$.i18n.Tr "action.rename_repo" .GetContent .GetRepoLink .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.rename_repo" (.GetContent|Escape) (.GetRepoLink|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 5}}
-                                                       {{ $branchLink := .GetBranch | EscapePound | Escape}}
+                                                       {{ $branchLink := .GetBranch | PathEscapeSegments | Escape}}
                                                        {{if .Content}}
-                                                               {{$.i18n.Tr "action.commit_repo" .GetRepoLink $branchLink (Escape .GetBranch) .ShortRepoPath | Str2html}}
+                                                               {{$.i18n.Tr "action.commit_repo" (.GetRepoLink|Escape) $branchLink (Escape .GetBranch) (.ShortRepoPath|Escape) | Str2html}}
                                                        {{else}}
-                                                               {{$.i18n.Tr "action.create_branch" .GetRepoLink $branchLink (Escape .GetBranch) .ShortRepoPath | Str2html}}
+                                                               {{$.i18n.Tr "action.create_branch" (.GetRepoLink|Escape) $branchLink (Escape .GetBranch) (.ShortRepoPath|Escape) | Str2html}}
                                                        {{end}}
                                                {{else if eq .GetOpType 6}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.create_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.create_issue" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 7}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.create_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.create_pull_request" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 8}}
-                                                       {{$.i18n.Tr "action.transfer_repo" .GetContent .GetRepoLink .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.transfer_repo" .GetContent (.GetRepoLink|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 9}}
-                                                       {{ $tagLink := .GetTag | EscapePound | Escape}}
-                                                       {{$.i18n.Tr "action.push_tag" .GetRepoLink $tagLink .ShortRepoPath .GetTag | Str2html}}
+                                                       {{ $tagLink := .GetTag | PathEscapeSegments | Escape}}
+                                                       {{$.i18n.Tr "action.push_tag" (.GetRepoLink|Escape) $tagLink (.ShortRepoPath|Escape) .GetTag | Str2html}}
                                                {{else if eq .GetOpType 10}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.comment_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.comment_issue" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 11}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.merge_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.merge_pull_request" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 12}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.close_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.close_issue" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 13}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.reopen_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.reopen_issue" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 14}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.close_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.close_pull_request" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 15}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.reopen_pull_request" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 16}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.delete_tag" .GetRepoLink (.GetTag|Escape) .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.delete_tag" (.GetRepoLink|Escape) (.GetTag|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 17}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.delete_branch" .GetRepoLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.delete_branch" (.GetRepoLink|Escape) (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 18}}
-                                                       {{ $branchLink := .GetBranch | EscapePound}}
-                                                       {{$.i18n.Tr "action.mirror_sync_push" .GetRepoLink $branchLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
+                                                       {{ $branchLink := .GetBranch | PathEscapeSegments}}
+                                                       {{$.i18n.Tr "action.mirror_sync_push" (.GetRepoLink|Escape) $branchLink (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 19}}
-                                                       {{$.i18n.Tr "action.mirror_sync_create" .GetRepoLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.mirror_sync_create" (.GetRepoLink|Escape) (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 20}}
-                                                       {{$.i18n.Tr "action.mirror_sync_delete" .GetRepoLink (.GetBranch|Escape) .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.mirror_sync_delete" (.GetRepoLink|Escape) (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 21}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.approve_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.approve_pull_request" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 22}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.reject_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.reject_pull_request" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 23}}
                                                        {{ $index := index .GetIssueInfos 0}}
-                                                       {{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoPath | Str2html}}
+                                                       {{$.i18n.Tr "action.comment_pull" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) | Str2html}}
                                                {{else if eq .GetOpType 24}}
-                                                       {{ $branchLink := .GetBranch | EscapePound | Escape}}
+                                                       {{ $branchLink := .GetBranch | PathEscapeSegments | Escape}}
                                                        {{ $linkText := .Content | RenderEmoji }}
-                                                       {{$.i18n.Tr "action.publish_release" .GetRepoLink $branchLink .ShortRepoPath $linkText | Str2html}}
+                                                       {{$.i18n.Tr "action.publish_release" (.GetRepoLink|Escape) $branchLink (.ShortRepoPath|Escape) $linkText | Str2html}}
                                                {{else if eq .GetOpType 25}}
                                                        {{ $index := index .GetIssueInfos 0}}
                                                        {{ $reviewer := index .GetIssueInfos 1}}
-                                                       {{$.i18n.Tr "action.review_dismissed" .GetRepoLink $index .ShortRepoPath $reviewer | Str2html}}
+                                                       {{$.i18n.Tr "action.review_dismissed" (.GetRepoLink|Escape) $index (.ShortRepoPath|Escape) $reviewer | Str2html}}
                                                {{end}}
                                        </p>
                                        {{if or (eq .GetOpType 5) (eq .GetOpType 18)}}
index d2a51fd44a729a725bcd6c09049ba0cd046b196e..aca61f9ae906c529c5df0b38edd1f8b41bc62dbc 100644 (file)
                                        {{range .Repos}}
                                                {{with $Repo := .}}
                                                        <a class="{{range $.RepoIDs}}{{if eq . $Repo.ID}}ui basic blue button{{end}}{{end}} repo name item" href="{{$.Link}}?type={{$.ViewType}}&repos=[
-                                                                       {{with $include := true}}
-                                                                               {{range $.RepoIDs}}
-                                                                                       {{if eq . $Repo.ID}}
+                                                                       {{- with $include := true -}}
+                                                                               {{- range $.RepoIDs -}}
+                                                                                       {{- if eq . $Repo.ID -}}
                                                                                                {{$include = false}}
-                                                                                       {{else}}
+                                                                                       {{- else -}}
                                                                                                {{.}}%2C
-                                                                                       {{end}}
-                                                                               {{end}}
-                                                                               {{if eq $include true}}
+                                                                                       {{- end -}}
+                                                                               {{- end -}}
+                                                                               {{- if eq $include true -}}
                                                                                        {{$Repo.ID}}%2C
-                                                                               {{end}}
-                                                                       {{end}}
+                                                                               {{- end -}}
+                                                                       {{- end -}}
                                                                        ]&sort={{$.SortType}}&state={{$.State}}&q={{$.Keyword}}" title="{{.FullName}}">
                                                                <span class="text truncate">{{$Repo.FullName}}</span>
                                                                <div class="ui {{if $.IsShowClosed}}red{{else}}green{{end}} label">{{CountFmt (index $.Counts $Repo.ID)}}</div>
index c7416e7cd7b94dd8aaa0730378e06f8a66d7d813..3e1ef95d9826001e21afd742725190da06c9a4db 100644 (file)
                                        {{range .Repos}}
                                                {{with $Repo := .}}
                                                        <a class="{{range $.RepoIDs}}{{if eq . $Repo.ID}}ui basic blue button{{end}}{{end}} repo name item" href="{{$.Link}}?repos=[
-                                                               {{with $include := true}}
-                                                                       {{range $.RepoIDs}}
-                                                                               {{if eq . $Repo.ID}}
-                                                                                       {{$include = false}}
-                                                                               {{else}}
-                                                                                       {{.}}%2C
-                                                                               {{end}}
-                                                                       {{end}}
-                                                                       {{if eq $include true}}
-                                                                               {{$Repo.ID}}%2C
-                                                                       {{end}}
-                                                               {{end}}
+                                                               {{- with $include := true -}}
+                                                                               {{- range $.RepoIDs -}}
+                                                                                       {{- if eq . $Repo.ID -}}
+                                                                                               {{$include = false}}
+                                                                                       {{- else -}}
+                                                                                               {{.}}%2C
+                                                                                       {{- end -}}
+                                                                               {{- end -}}
+                                                                               {{- if eq $include true -}}
+                                                                                       {{$Repo.ID}}%2C
+                                                                               {{- end -}}
+                                                                       {{- end -}}
                                                                ]&sort={{$.SortType}}&state={{$.State}}&q={{$.Keyword}}" title="{{.FullName}}">
                                                                <span class="text truncate">{{$Repo.FullName}}</span>
                                                                <div class="ui {{if $.IsShowClosed}}red{{else}}green{{end}} label">{{index $.Counts $Repo.ID}}</div>
index 6f3b4ac51c4e130b8af1d30438626d3c7d138383..740929d46e6262492149a1a33c0c190bb4315f40 100644 (file)
 
        {{if .ContextUser.IsOrganization}}
                <div class="right stackable menu">
-                       <a class="{{if .PageIsNews}}active{{end}} item" style="margin-left: auto" href="{{.ContextUser.DashboardLink}}{{if .Team}}/{{.Team.Name}}{{end}}">
+                       <a class="{{if .PageIsNews}}active{{end}} item" style="margin-left: auto" href="{{.ContextUser.DashboardLink}}{{if .Team}}/{{PathEscape .Team.Name}}{{end}}">
                                {{svg "octicon-rss"}}&nbsp;{{.i18n.Tr "activities"}}
                        </a>
                        {{if not .UnitIssuesGlobalDisabled}}
-                       <a class="{{if .PageIsIssues}}active{{end}} item" href="{{.ContextUser.OrganisationLink}}/issues{{if .Team}}/{{.Team.Name}}{{end}}">
+                       <a class="{{if .PageIsIssues}}active{{end}} item" href="{{.ContextUser.OrganisationLink}}/issues{{if .Team}}/{{PathEscape .Team.Name}}{{end}}">
                                {{svg "octicon-issue-opened"}}&nbsp;{{.i18n.Tr "issues"}}
                        </a>
                        {{end}}
                        {{if not .UnitPullsGlobalDisabled}}
-                       <a class="{{if .PageIsPulls}}active{{end}} item" href="{{.ContextUser.OrganisationLink}}/pulls{{if .Team}}/{{.Team.Name}}{{end}}">
+                       <a class="{{if .PageIsPulls}}active{{end}} item" href="{{.ContextUser.OrganisationLink}}/pulls{{if .Team}}/{{PathEscape.Team.Name}}{{end}}">
                                {{svg "octicon-git-pull-request"}}&nbsp;{{.i18n.Tr "pull_requests"}}
                        </a>
                        {{end}}
                        {{if and .ShowMilestonesDashboardPage (not (and .UnitIssuesGlobalDisabled .UnitPullsGlobalDisabled))}}
-                       <a class="{{if .PageIsMilestonesDashboard}}active{{end}} item" href="{{.ContextUser.OrganisationLink}}/milestones{{if .Team}}/{{.Team.Name}}{{end}}">
+                       <a class="{{if .PageIsMilestonesDashboard}}active{{end}} item" href="{{.ContextUser.OrganisationLink}}/milestones{{if .Team}}/{{PathEscape .Team.Name}}{{end}}">
                                {{svg "octicon-milestone"}}&nbsp;{{.i18n.Tr "milestones"}}
                        </a>
                        {{end}}
index c02cdecd49dc376312c804aea03b1ab4a100140b..83a0f6b3ad53c592909013b378d6bb85189c4a0c 100644 (file)
                        <div v-if="repos.length" class="ui attached table segment rounded-bottom">
                                <ul class="repo-owner-name-list">
                                        <li v-for="repo in repos" :class="{'private': repo.private || repo.internal}">
-                                               <a class="repo-list-link df ac sb" :href="subUrl + '/' + repo.full_name">
+                                               <a class="repo-list-link df ac sb" :href="repo.html_url">
                                                        <div class="text truncate item-name f1">
                                                                <component v-bind:is="repoIcon(repo)" size="16"></component>
                                                                <strong>${repo.full_name}</strong>
                        <div v-if="organizations.length" class="ui attached table segment rounded-bottom">
                                <ul class="repo-owner-name-list">
                                        <li v-for="org in organizations">
-                                               <a class="repo-list-link df ac sb" :href="subUrl + '/' + org.name">
+                                               <a class="repo-list-link df ac sb" :href="subUrl + '/' + encodeURIComponent(org.name)">
                                                        <div class="text truncate item-name f1">
                                                                {{svg "octicon-organization" 16 "mr-2"}}
                                                                <strong>${org.name}</strong>
index 8976e1fda4a00427ec7c28fef67a13d499938f3c..67193169d966994c0dc06ab2b244cdca1d4ca4f9 100644 (file)
@@ -68,8 +68,8 @@
                                                                                {{end}}
                                                                        </a>
                                                                </td>
-                                                               <td data-href="{{AppSubUrl}}/{{$repoOwner.Name}}/{{$repo.Name}}">
-                                                                       <a class="item" href="{{AppSubUrl}}/{{$repoOwner.Name}}/{{$repo.Name}}">
+                                                               <td data-href="{{$repo.Link}}">
+                                                                       <a class="item" href="{{$repo.Link}}">
                                                                                {{$repoOwner.Name}}/{{$repo.Name}}
                                                                        </a>
                                                                </td>
index b82f131b205ae066d2c99480e28a2db54fcdcf08..74f2bc057404464fc059aa49b6b8c5d0a222c56e 100644 (file)
                                                                                {{else}}
                                                                                        <span class="icon">{{svg "octicon-repo"}}</span>
                                                                                {{end}}
-                                                                               <a class="name" href="{{AppSubUrl}}/{{$repo.OwnerName}}/{{$repo.Name}}">{{$repo.OwnerName}}/{{$repo.Name}}</a>
+                                                                               <a class="name" href="{{$repo.Link}}">{{$repo.OwnerName}}/{{$repo.Name}}</a>
                                                                                <span>{{SizeFmt $repo.Size}}</span>
                                                                                {{if $repo.IsFork}}
                                                                                        {{$.i18n.Tr "repo.forked_from"}}
-                                                                                       <span><a href="{{AppSubUrl}}/{{$repo.BaseRepo.OwnerName}}/{{$repo.BaseRepo.Name}}">{{$repo.BaseRepo.OwnerName}}/{{$repo.BaseRepo.Name}}</a></span>
+                                                                                       <span><a href="{{$repo.BaseRepo.Link}}">{{$repo.BaseRepo.OwnerName}}/{{$repo.BaseRepo.Name}}</a></span>
                                                                                {{end}}
                                                                        {{else}}
                                                                                <span class="icon">{{svg "octicon-file-directory"}}</span>
                                                                        {{else}}
                                                                                <span class="iconFloat">{{svg "octicon-repo"}}</span>
                                                                        {{end}}
-                                                                       <a class="name" href="{{AppSubUrl}}/{{.OwnerName}}/{{.Name}}">{{.OwnerName}}/{{.Name}}</a>
+                                                                       <a class="name" href="{{.Link}}">{{.OwnerName}}/{{.Name}}</a>
                                                                        <span>{{SizeFmt .Size}}</span>
                                                                        {{if .IsFork}}
                                                                                {{$.i18n.Tr "repo.forked_from"}}
-                                                                               <span><a href="{{AppSubUrl}}/{{.BaseRepo.OwnerName}}/{{.BaseRepo.Name}}">{{.BaseRepo.OwnerName}}/{{.BaseRepo.Name}}</a></span>
+                                                                               <span><a href="{{.BaseRepo.Link}}">{{.BaseRepo.OwnerName}}/{{.BaseRepo.Name}}</a></span>
                                                                        {{end}}
                                                                </div>
                                                        </div>
index c9119997caef091d7ac74e8e7e71c9c8626f6fe0..4402411bfd5f22175323115825d00eb45584355a 100644 (file)
@@ -1,6 +1,6 @@
 export function initRepoBranchButton() {
   $('.show-create-branch-modal.button').on('click', function () {
-    $('#create-branch-form')[0].action = $('#create-branch-form').data('base-action') + $(this).data('branch-from');
+    $('#create-branch-form')[0].action = $('#create-branch-form').data('base-action') + $(this).data('branch-from-urlcomponent');
     $('#modal-create-branch-from-span').text($(this).data('branch-from'));
     $($(this).data('modal')).modal('show');
   });