You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package middleware
  5. import (
  6. "fmt"
  7. "html/template"
  8. "io"
  9. "net/http"
  10. "strings"
  11. "time"
  12. "github.com/Unknwon/macaron"
  13. "github.com/macaron-contrib/cache"
  14. "github.com/macaron-contrib/csrf"
  15. "github.com/macaron-contrib/i18n"
  16. "github.com/macaron-contrib/session"
  17. "github.com/gogits/gogs/models"
  18. "github.com/gogits/gogs/modules/auth"
  19. "github.com/gogits/gogs/modules/base"
  20. "github.com/gogits/gogs/modules/git"
  21. "github.com/gogits/gogs/modules/log"
  22. "github.com/gogits/gogs/modules/setting"
  23. )
  24. // Context represents context of a request.
  25. type Context struct {
  26. *macaron.Context
  27. Cache cache.Cache
  28. csrf csrf.CSRF
  29. Flash *session.Flash
  30. Session session.Store
  31. User *models.User
  32. IsSigned bool
  33. Repo struct {
  34. IsOwner bool
  35. IsTrueOwner bool
  36. IsWatching bool
  37. IsBranch bool
  38. IsTag bool
  39. IsCommit bool
  40. IsAdmin bool // Current user is admin level.
  41. HasAccess bool
  42. Repository *models.Repository
  43. Owner *models.User
  44. Commit *git.Commit
  45. Tag *git.Tag
  46. GitRepo *git.Repository
  47. BranchName string
  48. TagName string
  49. CommitId string
  50. RepoLink string
  51. CloneLink struct {
  52. SSH string
  53. HTTPS string
  54. Git string
  55. }
  56. CommitsCount int
  57. Mirror *models.Mirror
  58. }
  59. Org struct {
  60. IsOwner bool
  61. IsMember bool
  62. IsAdminTeam bool // In owner team or team that has admin permission level.
  63. Organization *models.User
  64. OrgLink string
  65. Team *models.Team
  66. }
  67. }
  68. // Query querys form parameter.
  69. func (ctx *Context) Query(name string) string {
  70. ctx.Req.ParseForm()
  71. return ctx.Req.Form.Get(name)
  72. }
  73. // HasError returns true if error occurs in form validation.
  74. func (ctx *Context) HasApiError() bool {
  75. hasErr, ok := ctx.Data["HasError"]
  76. if !ok {
  77. return false
  78. }
  79. return hasErr.(bool)
  80. }
  81. func (ctx *Context) GetErrMsg() string {
  82. return ctx.Data["ErrorMsg"].(string)
  83. }
  84. // HasError returns true if error occurs in form validation.
  85. func (ctx *Context) HasError() bool {
  86. hasErr, ok := ctx.Data["HasError"]
  87. if !ok {
  88. return false
  89. }
  90. ctx.Flash.ErrorMsg = ctx.Data["ErrorMsg"].(string)
  91. ctx.Data["Flash"] = ctx.Flash
  92. return hasErr.(bool)
  93. }
  94. // HTML calls Context.HTML and converts template name to string.
  95. func (ctx *Context) HTML(status int, name base.TplName) {
  96. ctx.Context.HTML(status, string(name))
  97. }
  98. // RenderWithErr used for page has form validation but need to prompt error to users.
  99. func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
  100. if form != nil {
  101. auth.AssignForm(form, ctx.Data)
  102. }
  103. ctx.Flash.ErrorMsg = msg
  104. ctx.Data["Flash"] = ctx.Flash
  105. ctx.HTML(200, tpl)
  106. }
  107. // Handle handles and logs error by given status.
  108. func (ctx *Context) Handle(status int, title string, err error) {
  109. if err != nil {
  110. log.Error(4, "%s: %v", title, err)
  111. if macaron.Env != macaron.PROD {
  112. ctx.Data["ErrorMsg"] = err
  113. }
  114. }
  115. switch status {
  116. case 404:
  117. ctx.Data["Title"] = "Page Not Found"
  118. case 500:
  119. ctx.Data["Title"] = "Internal Server Error"
  120. }
  121. ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
  122. }
  123. func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
  124. modtime := time.Now()
  125. for _, p := range params {
  126. switch v := p.(type) {
  127. case time.Time:
  128. modtime = v
  129. }
  130. }
  131. ctx.Resp.Header().Set("Content-Description", "File Transfer")
  132. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  133. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
  134. ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
  135. ctx.Resp.Header().Set("Expires", "0")
  136. ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
  137. ctx.Resp.Header().Set("Pragma", "public")
  138. http.ServeContent(ctx.Resp, ctx.Req, name, modtime, r)
  139. }
  140. // Contexter initializes a classic context for a request.
  141. func Contexter() macaron.Handler {
  142. return func(c *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
  143. ctx := &Context{
  144. Context: c,
  145. Cache: cache,
  146. csrf: x,
  147. Flash: f,
  148. Session: sess,
  149. }
  150. // Compute current URL for real-time change language.
  151. link := setting.AppSubUrl + ctx.Req.RequestURI
  152. i := strings.Index(link, "?")
  153. if i > -1 {
  154. link = link[:i]
  155. }
  156. ctx.Data["Link"] = link
  157. ctx.Data["PageStartTime"] = time.Now()
  158. // Get user from session if logined.
  159. ctx.User = auth.SignedInUser(ctx.Req.Header, ctx.Session)
  160. if ctx.User != nil {
  161. ctx.IsSigned = true
  162. ctx.Data["IsSigned"] = ctx.IsSigned
  163. ctx.Data["SignedUser"] = ctx.User
  164. ctx.Data["IsAdmin"] = ctx.User.IsAdmin
  165. }
  166. // If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
  167. if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
  168. if err := ctx.Req.ParseMultipartForm(setting.AttachmentMaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
  169. ctx.Handle(500, "ParseMultipartForm", err)
  170. return
  171. }
  172. }
  173. ctx.Data["CsrfToken"] = x.GetToken()
  174. ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + x.GetToken() + `">`)
  175. c.Map(ctx)
  176. }
  177. }