diff options
Diffstat (limited to 'routers/web/repo')
-rw-r--r-- | routers/web/repo/blame.go | 10 | ||||
-rw-r--r-- | routers/web/repo/commit.go | 4 | ||||
-rw-r--r-- | routers/web/repo/compare.go | 33 | ||||
-rw-r--r-- | routers/web/repo/editor.go | 12 | ||||
-rw-r--r-- | routers/web/repo/issue.go | 25 | ||||
-rw-r--r-- | routers/web/repo/issue_stopwatch.go | 2 | ||||
-rw-r--r-- | routers/web/repo/lfs.go | 3 | ||||
-rw-r--r-- | routers/web/repo/migrate.go | 3 | ||||
-rw-r--r-- | routers/web/repo/milestone.go | 3 | ||||
-rw-r--r-- | routers/web/repo/projects.go | 3 | ||||
-rw-r--r-- | routers/web/repo/pull.go | 72 | ||||
-rw-r--r-- | routers/web/repo/release.go | 3 | ||||
-rw-r--r-- | routers/web/repo/repo.go | 4 | ||||
-rw-r--r-- | routers/web/repo/setting.go | 16 | ||||
-rw-r--r-- | routers/web/repo/setting_protected_branch.go | 7 | ||||
-rw-r--r-- | routers/web/repo/tag.go | 2 | ||||
-rw-r--r-- | routers/web/repo/view.go | 16 | ||||
-rw-r--r-- | routers/web/repo/webhook.go | 11 | ||||
-rw-r--r-- | routers/web/repo/wiki.go | 65 | ||||
-rw-r--r-- | routers/web/repo/wiki_test.go | 22 |
20 files changed, 192 insertions, 124 deletions
diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index 3632d1846e..110ec037e1 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -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 } diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index 4c0f94f15d..06cce92417 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -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 diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 86ecc2bab1..01c324e9e9 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -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 } diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index d9f8c20092..088edbfd29 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -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 { diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index d9e15a784f..95363258e9 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -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, diff --git a/routers/web/repo/issue_stopwatch.go b/routers/web/repo/issue_stopwatch.go index b8efb3b841..0e9405fde4 100644 --- a/routers/web/repo/issue_stopwatch.go +++ b/routers/web/repo/issue_stopwatch.go @@ -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 diff --git a/routers/web/repo/lfs.go b/routers/web/repo/lfs.go index 5e24cfa3c0..b15c7628db 100644 --- a/routers/web/repo/lfs.go +++ b/routers/web/repo/lfs.go @@ -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() { diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go index d5e0a7696b..f91c344e94 100644 --- a/routers/web/repo/migrate.go +++ b/routers/web/repo/migrate.go @@ -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 } diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go index 21e1fb2eab..eadc89333f 100644 --- a/routers/web/repo/milestone.go +++ b/routers/web/repo/milestone.go @@ -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 diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 08b285df0a..437da14d45 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -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 diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 0ac05a7609..4337278214 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -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{}{ diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 20f6ddd2a5..3f12ee72bc 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -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 } diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index c70dec6481..46cef7664a 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -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 } } diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index cecd1da07c..641052316c 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -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 diff --git a/routers/web/repo/setting_protected_branch.go b/routers/web/repo/setting_protected_branch.go index 876ff9ba46..32105b1d43 100644 --- a/routers/web/repo/setting_protected_branch.go +++ b/routers/web/repo/setting_protected_branch.go @@ -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 { diff --git a/routers/web/repo/tag.go b/routers/web/repo/tag.go index a180399c9e..b4d268759c 100644 --- a/routers/web/repo/tag.go +++ b/routers/web/repo/tag.go @@ -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 diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index cecd8437b6..12b3aef505 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -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 diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index f47f8d651d..4f6660926e 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -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, diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index 16927de2e9..82f56a8c4a 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -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" } diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go index cf49f19afe..87f2779c1a 100644 --- a/routers/web/repo/wiki_test.go +++ b/routers/web/repo/wiki_test.go @@ -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) |