|
@@ -15,19 +15,17 @@
|
|
|
package macaron
|
|
package macaron
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
- "crypto/hmac"
|
|
|
|
|
- "crypto/sha1"
|
|
|
|
|
- "encoding/base64"
|
|
|
|
|
- "fmt"
|
|
|
|
|
|
|
+ "crypto/md5"
|
|
|
|
|
+ "encoding/hex"
|
|
|
"html/template"
|
|
"html/template"
|
|
|
"io"
|
|
"io"
|
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
|
"mime/multipart"
|
|
"mime/multipart"
|
|
|
"net/http"
|
|
"net/http"
|
|
|
|
|
+ "net/url"
|
|
|
"path"
|
|
"path"
|
|
|
"path/filepath"
|
|
"path/filepath"
|
|
|
"reflect"
|
|
"reflect"
|
|
|
- "strconv"
|
|
|
|
|
"strings"
|
|
"strings"
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
|
@@ -42,25 +40,28 @@ type Locale interface {
|
|
|
Tr(string, ...interface{}) string
|
|
Tr(string, ...interface{}) string
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Body is the request's body.
|
|
|
|
|
|
|
+// RequestBody represents a request body.
|
|
|
type RequestBody struct {
|
|
type RequestBody struct {
|
|
|
reader io.ReadCloser
|
|
reader io.ReadCloser
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// Bytes reads and returns content of request body in bytes.
|
|
|
func (rb *RequestBody) Bytes() ([]byte, error) {
|
|
func (rb *RequestBody) Bytes() ([]byte, error) {
|
|
|
return ioutil.ReadAll(rb.reader)
|
|
return ioutil.ReadAll(rb.reader)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// String reads and returns content of request body in string.
|
|
|
func (rb *RequestBody) String() (string, error) {
|
|
func (rb *RequestBody) String() (string, error) {
|
|
|
data, err := rb.Bytes()
|
|
data, err := rb.Bytes()
|
|
|
return string(data), err
|
|
return string(data), err
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// ReadCloser returns a ReadCloser for request body.
|
|
|
func (rb *RequestBody) ReadCloser() io.ReadCloser {
|
|
func (rb *RequestBody) ReadCloser() io.ReadCloser {
|
|
|
return rb.reader
|
|
return rb.reader
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// A Request represents an HTTP request received by a server or to be sent by a client.
|
|
|
|
|
|
|
+// Request represents an HTTP request received by a server or to be sent by a client.
|
|
|
type Request struct {
|
|
type Request struct {
|
|
|
*http.Request
|
|
*http.Request
|
|
|
}
|
|
}
|
|
@@ -239,7 +240,7 @@ func (ctx *Context) GetFile(name string) (multipart.File, *multipart.FileHeader,
|
|
|
func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
|
|
func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
|
|
|
cookie := http.Cookie{}
|
|
cookie := http.Cookie{}
|
|
|
cookie.Name = name
|
|
cookie.Name = name
|
|
|
- cookie.Value = value
|
|
|
|
|
|
|
+ cookie.Value = url.QueryEscape(value)
|
|
|
|
|
|
|
|
if len(others) > 0 {
|
|
if len(others) > 0 {
|
|
|
switch v := others[0].(type) {
|
|
switch v := others[0].(type) {
|
|
@@ -296,7 +297,8 @@ func (ctx *Context) GetCookie(name string) string {
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return ""
|
|
return ""
|
|
|
}
|
|
}
|
|
|
- return cookie.Value
|
|
|
|
|
|
|
+ val, _ := url.QueryUnescape(cookie.Value)
|
|
|
|
|
+ return val
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// GetCookieInt returns cookie result in int type.
|
|
// GetCookieInt returns cookie result in int type.
|
|
@@ -327,41 +329,32 @@ func (ctx *Context) GetSecureCookie(key string) (string, bool) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// SetSuperSecureCookie sets given cookie value to response header with secret string.
|
|
// SetSuperSecureCookie sets given cookie value to response header with secret string.
|
|
|
-func (ctx *Context) SetSuperSecureCookie(Secret, name, value string, others ...interface{}) {
|
|
|
|
|
- vs := base64.URLEncoding.EncodeToString([]byte(value))
|
|
|
|
|
- timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
|
|
|
|
|
- h := hmac.New(sha1.New, []byte(Secret))
|
|
|
|
|
- fmt.Fprintf(h, "%s%s", vs, timestamp)
|
|
|
|
|
- sig := fmt.Sprintf("%02x", h.Sum(nil))
|
|
|
|
|
- cookie := strings.Join([]string{vs, timestamp, sig}, "|")
|
|
|
|
|
- ctx.SetCookie(name, cookie, others...)
|
|
|
|
|
|
|
+func (ctx *Context) SetSuperSecureCookie(secret, name, value string, others ...interface{}) {
|
|
|
|
|
+ m := md5.Sum([]byte(secret))
|
|
|
|
|
+ secret = hex.EncodeToString(m[:])
|
|
|
|
|
+ text, err := com.AESEncrypt([]byte(secret), []byte(value))
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ panic("error encrypting cookie: " + err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+ ctx.SetCookie(name, hex.EncodeToString(text), others...)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// GetSuperSecureCookie returns given cookie value from request header with secret string.
|
|
// GetSuperSecureCookie returns given cookie value from request header with secret string.
|
|
|
-func (ctx *Context) GetSuperSecureCookie(Secret, key string) (string, bool) {
|
|
|
|
|
|
|
+func (ctx *Context) GetSuperSecureCookie(secret, key string) (string, bool) {
|
|
|
val := ctx.GetCookie(key)
|
|
val := ctx.GetCookie(key)
|
|
|
if val == "" {
|
|
if val == "" {
|
|
|
return "", false
|
|
return "", false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- parts := strings.SplitN(val, "|", 3)
|
|
|
|
|
-
|
|
|
|
|
- if len(parts) != 3 {
|
|
|
|
|
|
|
+ data, err := hex.DecodeString(val)
|
|
|
|
|
+ if err != nil {
|
|
|
return "", false
|
|
return "", false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- vs := parts[0]
|
|
|
|
|
- timestamp := parts[1]
|
|
|
|
|
- sig := parts[2]
|
|
|
|
|
-
|
|
|
|
|
- h := hmac.New(sha1.New, []byte(Secret))
|
|
|
|
|
- fmt.Fprintf(h, "%s%s", vs, timestamp)
|
|
|
|
|
-
|
|
|
|
|
- if fmt.Sprintf("%02x", h.Sum(nil)) != sig {
|
|
|
|
|
- return "", false
|
|
|
|
|
- }
|
|
|
|
|
- res, _ := base64.URLEncoding.DecodeString(vs)
|
|
|
|
|
- return string(res), true
|
|
|
|
|
|
|
+ m := md5.Sum([]byte(secret))
|
|
|
|
|
+ secret = hex.EncodeToString(m[:])
|
|
|
|
|
+ text, err := com.AESDecrypt([]byte(secret), data)
|
|
|
|
|
+ return string(text), err == nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ServeContent serves given content to response.
|
|
// ServeContent serves given content to response.
|