@@ -45,6 +45,8 @@ import (
4545 "golang.org/x/crypto/pbkdf2"
4646)
4747
48+ const CookieNameFlash = "gitea_flash"
49+
4850// Render represents a template render
4951type Render interface {
5052 TemplateLookup (tmpl string ) (* template.Template , error )
@@ -60,7 +62,7 @@ type Context struct {
6062 Render Render
6163 translation.Locale
6264 Cache cache.Cache
63- csrf CSRFProtector
65+ Csrf CSRFProtector
6466 Flash * middleware.Flash
6567 Session session.Store
6668
@@ -478,38 +480,26 @@ func (ctx *Context) Redirect(location string, status ...int) {
478480 http .Redirect (ctx .Resp , ctx .Req , location , code )
479481}
480482
481- // SetCookie convenience function to set most cookies consistently
483+ // SetSiteCookie convenience function to set most cookies consistently
482484// CSRF and a few others are the exception here
483- func (ctx * Context ) SetCookie (name , value string , expiry int ) {
484- middleware .SetCookie (ctx .Resp , name , value ,
485- expiry ,
486- setting .AppSubURL ,
487- setting .SessionConfig .Domain ,
488- setting .SessionConfig .Secure ,
489- true ,
490- middleware .SameSite (setting .SessionConfig .SameSite ))
485+ func (ctx * Context ) SetSiteCookie (name , value string , maxAge int ) {
486+ middleware .SetSiteCookie (ctx .Resp , name , value , maxAge )
491487}
492488
493- // DeleteCookie convenience function to delete most cookies consistently
489+ // DeleteSiteCookie convenience function to delete most cookies consistently
494490// CSRF and a few others are the exception here
495- func (ctx * Context ) DeleteCookie (name string ) {
496- middleware .SetCookie (ctx .Resp , name , "" ,
497- - 1 ,
498- setting .AppSubURL ,
499- setting .SessionConfig .Domain ,
500- setting .SessionConfig .Secure ,
501- true ,
502- middleware .SameSite (setting .SessionConfig .SameSite ))
491+ func (ctx * Context ) DeleteSiteCookie (name string ) {
492+ middleware .SetSiteCookie (ctx .Resp , name , "" , - 1 )
503493}
504494
505- // GetCookie returns given cookie value from request header.
506- func (ctx * Context ) GetCookie (name string ) string {
507- return middleware .GetCookie (ctx .Req , name )
495+ // GetSiteCookie returns given cookie value from request header.
496+ func (ctx * Context ) GetSiteCookie (name string ) string {
497+ return middleware .GetSiteCookie (ctx .Req , name )
508498}
509499
510500// GetSuperSecureCookie returns given cookie value from request header with secret string.
511501func (ctx * Context ) GetSuperSecureCookie (secret , name string ) (string , bool ) {
512- val := ctx .GetCookie (name )
502+ val := ctx .GetSiteCookie (name )
513503 return ctx .CookieDecrypt (secret , val )
514504}
515505
@@ -530,10 +520,9 @@ func (ctx *Context) CookieDecrypt(secret, val string) (string, bool) {
530520}
531521
532522// SetSuperSecureCookie sets given cookie value to response header with secret string.
533- func (ctx * Context ) SetSuperSecureCookie (secret , name , value string , expiry int ) {
523+ func (ctx * Context ) SetSuperSecureCookie (secret , name , value string , maxAge int ) {
534524 text := ctx .CookieEncrypt (secret , value )
535-
536- ctx .SetCookie (name , text , expiry )
525+ ctx .SetSiteCookie (name , text , maxAge )
537526}
538527
539528// CookieEncrypt encrypts a given value using the provided secret
@@ -549,19 +538,19 @@ func (ctx *Context) CookieEncrypt(secret, value string) string {
549538
550539// GetCookieInt returns cookie result in int type.
551540func (ctx * Context ) GetCookieInt (name string ) int {
552- r , _ := strconv .Atoi (ctx .GetCookie (name ))
541+ r , _ := strconv .Atoi (ctx .GetSiteCookie (name ))
553542 return r
554543}
555544
556545// GetCookieInt64 returns cookie result in int64 type.
557546func (ctx * Context ) GetCookieInt64 (name string ) int64 {
558- r , _ := strconv .ParseInt (ctx .GetCookie (name ), 10 , 64 )
547+ r , _ := strconv .ParseInt (ctx .GetSiteCookie (name ), 10 , 64 )
559548 return r
560549}
561550
562551// GetCookieFloat64 returns cookie result in float64 type.
563552func (ctx * Context ) GetCookieFloat64 (name string ) float64 {
564- v , _ := strconv .ParseFloat (ctx .GetCookie (name ), 64 )
553+ v , _ := strconv .ParseFloat (ctx .GetSiteCookie (name ), 64 )
565554 return v
566555}
567556
@@ -659,7 +648,10 @@ func WithContext(req *http.Request, ctx *Context) *http.Request {
659648
660649// GetContext retrieves install context from request
661650func GetContext (req * http.Request ) * Context {
662- return req .Context ().Value (contextKey ).(* Context )
651+ if ctx , ok := req .Context ().Value (contextKey ).(* Context ); ok {
652+ return ctx
653+ }
654+ return nil
663655}
664656
665657// GetContextUser returns context user
@@ -726,54 +718,32 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler {
726718 ctx .Data ["Context" ] = & ctx
727719
728720 ctx .Req = WithContext (req , & ctx )
729- ctx .csrf = PrepareCSRFProtector (csrfOpts , & ctx )
721+ ctx .Csrf = PrepareCSRFProtector (csrfOpts , & ctx )
730722
731- // Get flash.
732- flashCookie := ctx . GetCookie ( "macaron_flash" )
733- vals , _ := url .ParseQuery (flashCookie )
734- if len ( vals ) > 0 {
735- f : = & middleware.Flash {
723+ // Get the last flash message from cookie
724+ lastFlashCookie := middleware . GetSiteCookie ( ctx . Req , CookieNameFlash )
725+ if vals , _ := url .ParseQuery (lastFlashCookie ); len ( vals ) > 0 {
726+ // store last Flash message into the template data, to render it
727+ ctx . Data [ "Flash" ] = & middleware.Flash {
736728 DataStore : & ctx ,
737729 Values : vals ,
738730 ErrorMsg : vals .Get ("error" ),
739731 SuccessMsg : vals .Get ("success" ),
740732 InfoMsg : vals .Get ("info" ),
741733 WarningMsg : vals .Get ("warning" ),
742734 }
743- ctx .Data ["Flash" ] = f
744735 }
745736
746- f := & middleware.Flash {
747- DataStore : & ctx ,
748- Values : url.Values {},
749- ErrorMsg : "" ,
750- WarningMsg : "" ,
751- InfoMsg : "" ,
752- SuccessMsg : "" ,
753- }
737+ // prepare an empty Flash message for current request
738+ ctx .Flash = & middleware.Flash {DataStore : & ctx , Values : url.Values {}}
754739 ctx .Resp .Before (func (resp ResponseWriter ) {
755- if flash := f .Encode (); len (flash ) > 0 {
756- middleware .SetCookie (resp , "macaron_flash" , flash , 0 ,
757- setting .SessionConfig .CookiePath ,
758- middleware .Domain (setting .SessionConfig .Domain ),
759- middleware .HTTPOnly (true ),
760- middleware .Secure (setting .SessionConfig .Secure ),
761- middleware .SameSite (setting .SessionConfig .SameSite ),
762- )
763- return
740+ if val := ctx .Flash .Encode (); val != "" {
741+ middleware .SetSiteCookie (ctx .Resp , CookieNameFlash , val , 0 )
742+ } else if lastFlashCookie != "" {
743+ middleware .SetSiteCookie (ctx .Resp , CookieNameFlash , "" , - 1 )
764744 }
765-
766- middleware .SetCookie (ctx .Resp , "macaron_flash" , "" , - 1 ,
767- setting .SessionConfig .CookiePath ,
768- middleware .Domain (setting .SessionConfig .Domain ),
769- middleware .HTTPOnly (true ),
770- middleware .Secure (setting .SessionConfig .Secure ),
771- middleware .SameSite (setting .SessionConfig .SameSite ),
772- )
773745 })
774746
775- ctx .Flash = f
776-
777747 // If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
778748 if ctx .Req .Method == "POST" && strings .Contains (ctx .Req .Header .Get ("Content-Type" ), "multipart/form-data" ) {
779749 if err := ctx .Req .ParseMultipartForm (setting .Attachment .MaxSize << 20 ); err != nil && ! strings .Contains (err .Error (), "EOF" ) { // 32MB max size
@@ -785,7 +755,7 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler {
785755 httpcache .SetCacheControlInHeader (ctx .Resp .Header (), 0 , "no-transform" )
786756 ctx .Resp .Header ().Set (`X-Frame-Options` , setting .CORSConfig .XFrameOptions )
787757
788- ctx .Data ["CsrfToken" ] = ctx .csrf .GetToken ()
758+ ctx .Data ["CsrfToken" ] = ctx .Csrf .GetToken ()
789759 ctx .Data ["CsrfTokenHtml" ] = template .HTML (`<input type="hidden" name="_csrf" value="` + ctx .Data ["CsrfToken" ].(string ) + `">` )
790760
791761 // FIXME: do we really always need these setting? There should be someway to have to avoid having to always set these
0 commit comments