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

context.go 5.7 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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 context
  5. import (
  6. "fmt"
  7. "html/template"
  8. "io"
  9. "net/http"
  10. "strings"
  11. "time"
  12. "github.com/go-macaron/cache"
  13. "github.com/go-macaron/csrf"
  14. "github.com/go-macaron/i18n"
  15. "github.com/go-macaron/session"
  16. "gopkg.in/macaron.v1"
  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/log"
  21. "github.com/gogits/gogs/modules/setting"
  22. )
  23. // Context represents context of a request.
  24. type Context struct {
  25. *macaron.Context
  26. Cache cache.Cache
  27. csrf csrf.CSRF
  28. Flash *session.Flash
  29. Session session.Store
  30. User *models.User
  31. IsSigned bool
  32. IsBasicAuth bool
  33. Repo *Repository
  34. Org *Organization
  35. }
  36. // HasError returns true if error occurs in form validation.
  37. func (ctx *Context) HasApiError() bool {
  38. hasErr, ok := ctx.Data["HasError"]
  39. if !ok {
  40. return false
  41. }
  42. return hasErr.(bool)
  43. }
  44. func (ctx *Context) GetErrMsg() string {
  45. return ctx.Data["ErrorMsg"].(string)
  46. }
  47. // HasError returns true if error occurs in form validation.
  48. func (ctx *Context) HasError() bool {
  49. hasErr, ok := ctx.Data["HasError"]
  50. if !ok {
  51. return false
  52. }
  53. ctx.Flash.ErrorMsg = ctx.Data["ErrorMsg"].(string)
  54. ctx.Data["Flash"] = ctx.Flash
  55. return hasErr.(bool)
  56. }
  57. // HasValue returns true if value of given name exists.
  58. func (ctx *Context) HasValue(name string) bool {
  59. _, ok := ctx.Data[name]
  60. return ok
  61. }
  62. // HTML calls Context.HTML and converts template name to string.
  63. func (ctx *Context) HTML(status int, name base.TplName) {
  64. log.Debug("Template: %s", name)
  65. ctx.Context.HTML(status, string(name))
  66. }
  67. // RenderWithErr used for page has form validation but need to prompt error to users.
  68. func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
  69. if form != nil {
  70. auth.AssignForm(form, ctx.Data)
  71. }
  72. ctx.Flash.ErrorMsg = msg
  73. ctx.Data["Flash"] = ctx.Flash
  74. ctx.HTML(200, tpl)
  75. }
  76. // Handle handles and logs error by given status.
  77. func (ctx *Context) Handle(status int, title string, err error) {
  78. if err != nil {
  79. log.Error(4, "%s: %v", title, err)
  80. if macaron.Env != macaron.PROD {
  81. ctx.Data["ErrorMsg"] = err
  82. }
  83. }
  84. switch status {
  85. case 404:
  86. ctx.Data["Title"] = "Page Not Found"
  87. case 500:
  88. ctx.Data["Title"] = "Internal Server Error"
  89. }
  90. ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
  91. }
  92. func (ctx *Context) HandleText(status int, title string) {
  93. if (status/100 == 4) || (status/100 == 5) {
  94. log.Error(4, "%s", title)
  95. }
  96. ctx.PlainText(status, []byte(title))
  97. }
  98. // APIError logs error with title if status is 500.
  99. func (ctx *Context) APIError(status int, title string, obj interface{}) {
  100. var message string
  101. if err, ok := obj.(error); ok {
  102. message = err.Error()
  103. } else {
  104. message = obj.(string)
  105. }
  106. if status == 500 {
  107. log.Error(4, "%s: %s", title, message)
  108. }
  109. ctx.JSON(status, map[string]string{
  110. "message": message,
  111. "url": base.DOC_URL,
  112. })
  113. }
  114. func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
  115. modtime := time.Now()
  116. for _, p := range params {
  117. switch v := p.(type) {
  118. case time.Time:
  119. modtime = v
  120. }
  121. }
  122. ctx.Resp.Header().Set("Content-Description", "File Transfer")
  123. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  124. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
  125. ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
  126. ctx.Resp.Header().Set("Expires", "0")
  127. ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
  128. ctx.Resp.Header().Set("Pragma", "public")
  129. http.ServeContent(ctx.Resp, ctx.Req.Request, name, modtime, r)
  130. }
  131. // Contexter initializes a classic context for a request.
  132. func Contexter() macaron.Handler {
  133. return func(c *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
  134. ctx := &Context{
  135. Context: c,
  136. Cache: cache,
  137. csrf: x,
  138. Flash: f,
  139. Session: sess,
  140. Repo: &Repository{
  141. PullRequest: &PullRequest{},
  142. },
  143. Org: &Organization{},
  144. }
  145. // Compute current URL for real-time change language.
  146. ctx.Data["Link"] = setting.AppSubUrl + strings.TrimSuffix(ctx.Req.URL.Path, "/")
  147. ctx.Data["PageStartTime"] = time.Now()
  148. // Get user from session if logined.
  149. ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Context, ctx.Session)
  150. if ctx.User != nil {
  151. ctx.IsSigned = true
  152. ctx.Data["IsSigned"] = ctx.IsSigned
  153. ctx.Data["SignedUser"] = ctx.User
  154. ctx.Data["SignedUserID"] = ctx.User.Id
  155. ctx.Data["SignedUserName"] = ctx.User.Name
  156. ctx.Data["IsAdmin"] = ctx.User.IsAdmin
  157. } else {
  158. ctx.Data["SignedUserID"] = 0
  159. ctx.Data["SignedUserName"] = ""
  160. }
  161. // If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
  162. if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
  163. if err := ctx.Req.ParseMultipartForm(setting.AttachmentMaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
  164. ctx.Handle(500, "ParseMultipartForm", err)
  165. return
  166. }
  167. }
  168. ctx.Data["CsrfToken"] = x.GetToken()
  169. ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + x.GetToken() + `">`)
  170. log.Debug("Session ID: %s", sess.ID())
  171. log.Debug("CSRF Token: %v", ctx.Data["CsrfToken"])
  172. ctx.Data["ShowRegistrationButton"] = setting.Service.ShowRegistrationButton
  173. ctx.Data["ShowFooterBranding"] = setting.ShowFooterBranding
  174. ctx.Data["ShowFooterVersion"] = setting.ShowFooterVersion
  175. c.Map(ctx)
  176. }
  177. }