mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Various wiki bug fixes (#2996)
* Update macaron * Various wiki bug fixes
This commit is contained in:
10
vendor/github.com/Unknwon/com/convert.go
generated
vendored
10
vendor/github.com/Unknwon/com/convert.go
generated
vendored
@@ -41,6 +41,11 @@ func (f StrTo) Int64() (int64, error) {
|
||||
return int64(v), err
|
||||
}
|
||||
|
||||
func (f StrTo) Float64() (float64, error) {
|
||||
v, err := strconv.ParseFloat(f.String(), 64)
|
||||
return float64(v), err
|
||||
}
|
||||
|
||||
func (f StrTo) MustUint8() uint8 {
|
||||
v, _ := f.Uint8()
|
||||
return v
|
||||
@@ -56,6 +61,11 @@ func (f StrTo) MustInt64() int64 {
|
||||
return v
|
||||
}
|
||||
|
||||
func (f StrTo) MustFloat64() float64 {
|
||||
v, _ := f.Float64()
|
||||
return v
|
||||
}
|
||||
|
||||
func (f StrTo) String() string {
|
||||
if f.Exist() {
|
||||
return string(f)
|
||||
|
54
vendor/github.com/Unknwon/com/string.go
generated
vendored
54
vendor/github.com/Unknwon/com/string.go
generated
vendored
@@ -19,9 +19,7 @@ import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
r "math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -30,41 +28,53 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// AESEncrypt encrypts text and given key with AES.
|
||||
func AESEncrypt(key, text []byte) ([]byte, error) {
|
||||
// AESGCMEncrypt encrypts plaintext with the given key using AES in GCM mode.
|
||||
func AESGCMEncrypt(key, plaintext []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := base64.StdEncoding.EncodeToString(text)
|
||||
ciphertext := make([]byte, aes.BlockSize+len(b))
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfb := cipher.NewCFBEncrypter(block, iv)
|
||||
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
|
||||
return ciphertext, nil
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
if _, err := rand.Read(nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext := gcm.Seal(nil, nonce, plaintext, nil)
|
||||
return append(nonce, ciphertext...), nil
|
||||
}
|
||||
|
||||
// AESDecrypt decrypts text and given key with AES.
|
||||
func AESDecrypt(key, text []byte) ([]byte, error) {
|
||||
// AESGCMDecrypt decrypts ciphertext with the given key using AES in GCM mode.
|
||||
func AESGCMDecrypt(key, ciphertext []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(text) < aes.BlockSize {
|
||||
return nil, errors.New("ciphertext too short")
|
||||
}
|
||||
iv := text[:aes.BlockSize]
|
||||
text = text[aes.BlockSize:]
|
||||
cfb := cipher.NewCFBDecrypter(block, iv)
|
||||
cfb.XORKeyStream(text, text)
|
||||
data, err := base64.StdEncoding.DecodeString(string(text))
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
|
||||
size := gcm.NonceSize()
|
||||
if len(ciphertext)-size <= 0 {
|
||||
return nil, errors.New("Ciphertext is empty")
|
||||
}
|
||||
|
||||
nonce := ciphertext[:size]
|
||||
ciphertext = ciphertext[size:]
|
||||
|
||||
plainText, err := gcm.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plainText, nil
|
||||
}
|
||||
|
||||
// IsLetter returns true if the 'l' is an English letter.
|
||||
|
2
vendor/gopkg.in/macaron.v1/LICENSE
generated
vendored
2
vendor/gopkg.in/macaron.v1/LICENSE
generated
vendored
@@ -176,7 +176,7 @@ recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright 2014 The Macaron Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
7
vendor/gopkg.in/macaron.v1/README.md
generated
vendored
7
vendor/gopkg.in/macaron.v1/README.md
generated
vendored
@@ -1,4 +1,4 @@
|
||||
Macaron [](https://travis-ci.org/go-macaron/macaron) [](http://gocover.io/github.com/go-macaron/macaron)
|
||||
Macaron [](https://travis-ci.org/go-macaron/macaron)
|
||||
=======================
|
||||
|
||||

|
||||
@@ -61,18 +61,20 @@ There are already many [middlewares](https://github.com/go-macaron) to simplify
|
||||
- [bindata](https://github.com/go-macaron/bindata) - Embed binary data as static and template files
|
||||
- [toolbox](https://github.com/go-macaron/toolbox) - Health check, pprof, profile and statistic services
|
||||
- [oauth2](https://github.com/go-macaron/oauth2) - OAuth 2.0 backend
|
||||
- [authz](https://github.com/go-macaron/authz) - ACL/RBAC/ABAC authorization based on Casbin
|
||||
- [switcher](https://github.com/go-macaron/switcher) - Multiple-site support
|
||||
- [method](https://github.com/go-macaron/method) - HTTP method override
|
||||
- [permissions2](https://github.com/xyproto/permissions2) - Cookies, users and permissions
|
||||
- [renders](https://github.com/go-macaron/renders) - Beego-like render engine(Macaron has built-in template engine, this is another option)
|
||||
- [piwik](https://github.com/veecue/piwik-middleware) - Server-side piwik analytics
|
||||
|
||||
## Use Cases
|
||||
|
||||
- [Gogs](https://gogs.io): A painless self-hosted Git Service
|
||||
- [Grafana](http://grafana.org/): The open platform for beautiful analytics and monitoring
|
||||
- [Peach](https://peachdocs.org): A modern web documentation server
|
||||
- [Go Walker](https://gowalker.org): Go online API documentation
|
||||
- [Switch](https://gopm.io): Gopm registry
|
||||
- [YouGam](http://yougam.com): Online Forum
|
||||
- [Critical Stack Intel](https://intel.criticalstack.com/): A 100% free intel marketplace from Critical Stack, Inc.
|
||||
|
||||
## Getting Help
|
||||
@@ -80,7 +82,6 @@ There are already many [middlewares](https://github.com/go-macaron) to simplify
|
||||
- [API Reference](https://gowalker.org/gopkg.in/macaron.v1)
|
||||
- [Documentation](https://go-macaron.com)
|
||||
- [FAQs](https://go-macaron.com/docs/faqs)
|
||||
- [](https://gitter.im/go-macaron/macaron?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
## Credits
|
||||
|
||||
|
34
vendor/gopkg.in/macaron.v1/context.go
generated
vendored
34
vendor/gopkg.in/macaron.v1/context.go
generated
vendored
@@ -15,7 +15,7 @@
|
||||
package macaron
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"html/template"
|
||||
"io"
|
||||
@@ -32,8 +32,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
|
||||
"github.com/go-macaron/inject"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
// Locale reprents a localization interface.
|
||||
@@ -72,6 +72,14 @@ func (r *Request) Body() *RequestBody {
|
||||
return &RequestBody{r.Request.Body}
|
||||
}
|
||||
|
||||
// ContextInvoker is an inject.FastInvoker wrapper of func(ctx *Context).
|
||||
type ContextInvoker func(ctx *Context)
|
||||
|
||||
func (invoke ContextInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
|
||||
invoke(params[0].(*Context))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Context represents the runtime context of current request of Macaron instance.
|
||||
// It is the integration of most frequently used middlewares and helper methods.
|
||||
type Context struct {
|
||||
@@ -260,6 +268,11 @@ func (ctx *Context) SetParams(name, val string) {
|
||||
ctx.params[name] = val
|
||||
}
|
||||
|
||||
// ReplaceAllParams replace all current params with given params
|
||||
func (ctx *Context) ReplaceAllParams(params Params) {
|
||||
ctx.params = params;
|
||||
}
|
||||
|
||||
// ParamsEscape returns escapred params result.
|
||||
// e.g. ctx.ParamsEscape(":uname")
|
||||
func (ctx *Context) ParamsEscape(name string) string {
|
||||
@@ -411,30 +424,29 @@ func (ctx *Context) GetSecureCookie(key string) (string, bool) {
|
||||
|
||||
// SetSuperSecureCookie sets given cookie value to response header with secret string.
|
||||
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))
|
||||
key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
|
||||
text, err := com.AESGCMEncrypt(key, []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.
|
||||
func (ctx *Context) GetSuperSecureCookie(secret, key string) (string, bool) {
|
||||
val := ctx.GetCookie(key)
|
||||
func (ctx *Context) GetSuperSecureCookie(secret, name string) (string, bool) {
|
||||
val := ctx.GetCookie(name)
|
||||
if val == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
data, err := hex.DecodeString(val)
|
||||
text, err := hex.DecodeString(val)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
m := md5.Sum([]byte(secret))
|
||||
secret = hex.EncodeToString(m[:])
|
||||
text, err := com.AESDecrypt([]byte(secret), data)
|
||||
key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
|
||||
text, err = com.AESGCMDecrypt(key, text)
|
||||
return string(text), err == nil
|
||||
}
|
||||
|
||||
|
11
vendor/gopkg.in/macaron.v1/logger.go
generated
vendored
11
vendor/gopkg.in/macaron.v1/logger.go
generated
vendored
@@ -19,6 +19,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
@@ -32,6 +33,14 @@ func init() {
|
||||
ColorLog = runtime.GOOS != "windows"
|
||||
}
|
||||
|
||||
// LoggerInvoker is an inject.FastInvoker wrapper of func(ctx *Context, log *log.Logger).
|
||||
type LoggerInvoker func(ctx *Context, log *log.Logger)
|
||||
|
||||
func (invoke LoggerInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
|
||||
invoke(params[0].(*Context), params[1].(*log.Logger))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
|
||||
func Logger() Handler {
|
||||
return func(ctx *Context, log *log.Logger) {
|
||||
@@ -42,7 +51,7 @@ func Logger() Handler {
|
||||
rw := ctx.Resp.(ResponseWriter)
|
||||
ctx.Next()
|
||||
|
||||
content := fmt.Sprintf("%s: Completed %s %v %s in %v", time.Now().Format(LogTimeFormat), ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))
|
||||
content := fmt.Sprintf("%s: Completed %s %s %v %s in %v", time.Now().Format(LogTimeFormat), ctx.Req.Method, ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))
|
||||
if ColorLog {
|
||||
switch rw.Status() {
|
||||
case 200, 201, 202:
|
||||
|
67
vendor/gopkg.in/macaron.v1/macaron.go
generated
vendored
67
vendor/gopkg.in/macaron.v1/macaron.go
generated
vendored
@@ -32,7 +32,7 @@ import (
|
||||
"github.com/go-macaron/inject"
|
||||
)
|
||||
|
||||
const _VERSION = "1.1.12.0122"
|
||||
const _VERSION = "1.2.4.1123"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
@@ -43,20 +43,63 @@ func Version() string {
|
||||
// and panics if an argument could not be fullfilled via dependency injection.
|
||||
type Handler interface{}
|
||||
|
||||
// validateHandler makes sure a handler is a callable function,
|
||||
// and panics if it is not.
|
||||
func validateHandler(h Handler) {
|
||||
// handlerFuncInvoker is an inject.FastInvoker wrapper of func(http.ResponseWriter, *http.Request).
|
||||
type handlerFuncInvoker func(http.ResponseWriter, *http.Request)
|
||||
|
||||
func (invoke handlerFuncInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
|
||||
invoke(params[0].(http.ResponseWriter), params[1].(*http.Request))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// internalServerErrorInvoker is an inject.FastInvoker wrapper of func(rw http.ResponseWriter, err error).
|
||||
type internalServerErrorInvoker func(rw http.ResponseWriter, err error)
|
||||
|
||||
func (invoke internalServerErrorInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
|
||||
invoke(params[0].(http.ResponseWriter), params[1].(error))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// validateAndWrapHandler makes sure a handler is a callable function, it panics if not.
|
||||
// When the handler is also potential to be any built-in inject.FastInvoker,
|
||||
// it wraps the handler automatically to have some performance gain.
|
||||
func validateAndWrapHandler(h Handler) Handler {
|
||||
if reflect.TypeOf(h).Kind() != reflect.Func {
|
||||
panic("Macaron handler must be a callable function")
|
||||
}
|
||||
|
||||
if !inject.IsFastInvoker(h) {
|
||||
switch v := h.(type) {
|
||||
case func(*Context):
|
||||
return ContextInvoker(v)
|
||||
case func(*Context, *log.Logger):
|
||||
return LoggerInvoker(v)
|
||||
case func(http.ResponseWriter, *http.Request):
|
||||
return handlerFuncInvoker(v)
|
||||
case func(http.ResponseWriter, error):
|
||||
return internalServerErrorInvoker(v)
|
||||
}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// validateHandlers makes sure handlers are callable functions,
|
||||
// and panics if any of them is not.
|
||||
func validateHandlers(handlers []Handler) {
|
||||
for _, h := range handlers {
|
||||
validateHandler(h)
|
||||
// validateAndWrapHandlers preforms validation and wrapping for each input handler.
|
||||
// It accepts an optional wrapper function to perform custom wrapping on handlers.
|
||||
func validateAndWrapHandlers(handlers []Handler, wrappers ...func(Handler) Handler) []Handler {
|
||||
var wrapper func(Handler) Handler
|
||||
if len(wrappers) > 0 {
|
||||
wrapper = wrappers[0]
|
||||
}
|
||||
|
||||
wrappedHandlers := make([]Handler, len(handlers))
|
||||
for i, h := range handlers {
|
||||
h = validateAndWrapHandler(h)
|
||||
if wrapper != nil && !inject.IsFastInvoker(h) {
|
||||
h = wrapper(h)
|
||||
}
|
||||
wrappedHandlers[i] = h
|
||||
}
|
||||
|
||||
return wrappedHandlers
|
||||
}
|
||||
|
||||
// Macaron represents the top level web application.
|
||||
@@ -101,7 +144,7 @@ func New() *Macaron {
|
||||
}
|
||||
|
||||
// Classic creates a classic Macaron with some basic default middleware:
|
||||
// mocaron.Logger, mocaron.Recovery and mocaron.Static.
|
||||
// macaron.Logger, macaron.Recovery and macaron.Static.
|
||||
func Classic() *Macaron {
|
||||
m := New()
|
||||
m.Use(Logger())
|
||||
@@ -123,7 +166,7 @@ func (m *Macaron) Handlers(handlers ...Handler) {
|
||||
// Action sets the handler that will be called after all the middleware has been invoked.
|
||||
// This is set to macaron.Router in a macaron.Classic().
|
||||
func (m *Macaron) Action(handler Handler) {
|
||||
validateHandler(handler)
|
||||
handler = validateAndWrapHandler(handler)
|
||||
m.action = handler
|
||||
}
|
||||
|
||||
@@ -139,7 +182,7 @@ func (m *Macaron) Before(handler BeforeHandler) {
|
||||
// and panics if the handler is not a callable func.
|
||||
// Middleware Handlers are invoked in the order that they are added.
|
||||
func (m *Macaron) Use(handler Handler) {
|
||||
validateHandler(handler)
|
||||
handler = validateAndWrapHandler(handler)
|
||||
m.handlers = append(m.handlers, handler)
|
||||
}
|
||||
|
||||
|
29
vendor/gopkg.in/macaron.v1/router.go
generated
vendored
29
vendor/gopkg.in/macaron.v1/router.go
generated
vendored
@@ -82,6 +82,9 @@ type Router struct {
|
||||
groups []group
|
||||
notFound http.HandlerFunc
|
||||
internalServerError func(*Context, error)
|
||||
|
||||
// handlerWrapper is used to wrap arbitrary function from Handler to inject.FastInvoker.
|
||||
handlerWrapper func(Handler) Handler
|
||||
}
|
||||
|
||||
func NewRouter() *Router {
|
||||
@@ -115,7 +118,7 @@ func (r *Route) Name(name string) {
|
||||
if len(name) == 0 {
|
||||
panic("route name cannot be empty")
|
||||
} else if r.router.namedRoutes[name] != nil {
|
||||
panic("route with given name already exists")
|
||||
panic("route with given name already exists: " + name)
|
||||
}
|
||||
r.router.namedRoutes[name] = r.leaf
|
||||
}
|
||||
@@ -173,7 +176,7 @@ func (r *Router) Handle(method string, pattern string, handlers []Handler) *Rout
|
||||
h = append(h, handlers...)
|
||||
handlers = h
|
||||
}
|
||||
validateHandlers(handlers)
|
||||
handlers = validateAndWrapHandlers(handlers, r.handlerWrapper)
|
||||
|
||||
return r.handle(method, pattern, func(resp http.ResponseWriter, req *http.Request, params Params) {
|
||||
c := r.m.createContext(resp, req)
|
||||
@@ -251,11 +254,11 @@ func (r *Router) Combo(pattern string, h ...Handler) *ComboRouter {
|
||||
return &ComboRouter{r, pattern, h, map[string]bool{}, nil}
|
||||
}
|
||||
|
||||
// Configurable http.HandlerFunc which is called when no matching route is
|
||||
// NotFound configurates http.HandlerFunc which is called when no matching route is
|
||||
// found. If it is not set, http.NotFound is used.
|
||||
// Be sure to set 404 response code in your handler.
|
||||
func (r *Router) NotFound(handlers ...Handler) {
|
||||
validateHandlers(handlers)
|
||||
handlers = validateAndWrapHandlers(handlers)
|
||||
r.notFound = func(rw http.ResponseWriter, req *http.Request) {
|
||||
c := r.m.createContext(rw, req)
|
||||
c.handlers = make([]Handler, 0, len(r.m.handlers)+len(handlers))
|
||||
@@ -265,11 +268,11 @@ func (r *Router) NotFound(handlers ...Handler) {
|
||||
}
|
||||
}
|
||||
|
||||
// Configurable handler which is called when route handler returns
|
||||
// InternalServerError configurates handler which is called when route handler returns
|
||||
// error. If it is not set, default handler is used.
|
||||
// Be sure to set 500 response code in your handler.
|
||||
func (r *Router) InternalServerError(handlers ...Handler) {
|
||||
validateHandlers(handlers)
|
||||
handlers = validateAndWrapHandlers(handlers)
|
||||
r.internalServerError = func(c *Context, err error) {
|
||||
c.index = 0
|
||||
c.handlers = handlers
|
||||
@@ -278,9 +281,21 @@ func (r *Router) InternalServerError(handlers ...Handler) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetHandlerWrapper sets handlerWrapper for the router.
|
||||
func (r *Router) SetHandlerWrapper(f func(Handler) Handler) {
|
||||
r.handlerWrapper = f
|
||||
}
|
||||
|
||||
func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if t, ok := r.routers[req.Method]; ok {
|
||||
h, p, ok := t.Match(req.URL.Path)
|
||||
// Fast match for static routes
|
||||
leaf := r.getLeaf(req.Method, req.URL.Path)
|
||||
if leaf != nil {
|
||||
leaf.handle(rw, req, nil)
|
||||
return
|
||||
}
|
||||
|
||||
h, p, ok := t.Match(req.URL.EscapedPath())
|
||||
if ok {
|
||||
if splat, ok := p["*0"]; ok {
|
||||
p["*"] = splat // Easy name.
|
||||
|
33
vendor/gopkg.in/macaron.v1/tree.go
generated
vendored
33
vendor/gopkg.in/macaron.v1/tree.go
generated
vendored
@@ -261,6 +261,10 @@ func (t *Tree) Add(pattern string, handle Handle) *Leaf {
|
||||
}
|
||||
|
||||
func (t *Tree) matchLeaf(globLevel int, url string, params Params) (Handle, bool) {
|
||||
url, err := PathUnescape(url)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
for i := 0; i < len(t.leaves); i++ {
|
||||
switch t.leaves[i].typ {
|
||||
case _PATTERN_STATIC:
|
||||
@@ -300,16 +304,20 @@ func (t *Tree) matchLeaf(globLevel int, url string, params Params) (Handle, bool
|
||||
}
|
||||
|
||||
func (t *Tree) matchSubtree(globLevel int, segment, url string, params Params) (Handle, bool) {
|
||||
unescapedSegment, err := PathUnescape(segment)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
for i := 0; i < len(t.subtrees); i++ {
|
||||
switch t.subtrees[i].typ {
|
||||
case _PATTERN_STATIC:
|
||||
if t.subtrees[i].pattern == segment {
|
||||
if t.subtrees[i].pattern == unescapedSegment {
|
||||
if handle, ok := t.subtrees[i].matchNextSegment(globLevel, url, params); ok {
|
||||
return handle, true
|
||||
}
|
||||
}
|
||||
case _PATTERN_REGEXP:
|
||||
results := t.subtrees[i].reg.FindStringSubmatch(segment)
|
||||
results := t.subtrees[i].reg.FindStringSubmatch(unescapedSegment)
|
||||
if len(results)-1 != len(t.subtrees[i].wildcards) {
|
||||
break
|
||||
}
|
||||
@@ -322,12 +330,12 @@ func (t *Tree) matchSubtree(globLevel int, segment, url string, params Params) (
|
||||
}
|
||||
case _PATTERN_HOLDER:
|
||||
if handle, ok := t.subtrees[i].matchNextSegment(globLevel+1, url, params); ok {
|
||||
params[t.subtrees[i].wildcards[0]] = segment
|
||||
params[t.subtrees[i].wildcards[0]] = unescapedSegment
|
||||
return handle, true
|
||||
}
|
||||
case _PATTERN_MATCH_ALL:
|
||||
if handle, ok := t.subtrees[i].matchNextSegment(globLevel+1, url, params); ok {
|
||||
params["*"+com.ToStr(globLevel)] = segment
|
||||
params["*"+com.ToStr(globLevel)] = unescapedSegment
|
||||
return handle, true
|
||||
}
|
||||
}
|
||||
@@ -335,19 +343,22 @@ func (t *Tree) matchSubtree(globLevel int, segment, url string, params Params) (
|
||||
|
||||
if len(t.leaves) > 0 {
|
||||
leaf := t.leaves[len(t.leaves)-1]
|
||||
unescapedURL, err := PathUnescape(segment + "/" + url)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
if leaf.typ == _PATTERN_PATH_EXT {
|
||||
url = segment + "/" + url
|
||||
j := strings.LastIndex(url, ".")
|
||||
j := strings.LastIndex(unescapedURL, ".")
|
||||
if j > -1 {
|
||||
params[":path"] = url[:j]
|
||||
params[":ext"] = url[j+1:]
|
||||
params[":path"] = unescapedURL[:j]
|
||||
params[":ext"] = unescapedURL[j+1:]
|
||||
} else {
|
||||
params[":path"] = url
|
||||
params[":path"] = unescapedURL
|
||||
}
|
||||
return leaf.handle, true
|
||||
} else if leaf.typ == _PATTERN_MATCH_ALL {
|
||||
params["*"] = segment + "/" + url
|
||||
params["*"+com.ToStr(globLevel)] = segment + "/" + url
|
||||
params["*"] = unescapedURL
|
||||
params["*"+com.ToStr(globLevel)] = unescapedURL
|
||||
return leaf.handle, true
|
||||
}
|
||||
}
|
||||
|
25
vendor/gopkg.in/macaron.v1/util_go17.go
generated
vendored
Normal file
25
vendor/gopkg.in/macaron.v1/util_go17.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// +build !go1.8
|
||||
|
||||
// Copyright 2017 The Macaron Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package macaron
|
||||
|
||||
import "net/url"
|
||||
|
||||
// PathUnescape unescapes a path. Ideally, this function would use
|
||||
// url.PathUnescape(..), but the function was not introduced until go1.8.
|
||||
func PathUnescape(s string) (string, error) {
|
||||
return url.QueryUnescape(s)
|
||||
}
|
24
vendor/gopkg.in/macaron.v1/util_go18.go
generated
vendored
Normal file
24
vendor/gopkg.in/macaron.v1/util_go18.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// +build go1.8
|
||||
|
||||
// Copyright 2017 The Macaron Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package macaron
|
||||
|
||||
import "net/url"
|
||||
|
||||
// PathUnescape unescapes a path.
|
||||
func PathUnescape(s string) (string, error) {
|
||||
return url.PathUnescape(s)
|
||||
}
|
12
vendor/vendor.json
vendored
12
vendor/vendor.json
vendored
@@ -33,10 +33,10 @@
|
||||
"revisionTime": "2016-07-15T03:28:08Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ly9VLPE9GKo2U7mnbZyjb2LDQ3w=",
|
||||
"checksumSHA1": "IrtvVIFBTQmk0+vM7g2xtka5SFg=",
|
||||
"path": "github.com/Unknwon/com",
|
||||
"revision": "28b053d5a2923b87ce8c5a08f3af779894a72758",
|
||||
"revisionTime": "2015-10-08T13:54:07Z"
|
||||
"revision": "7677a1d7c1137cd3dd5ba7a076d0c898a1ef4520",
|
||||
"revisionTime": "2017-08-19T22:39:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "GwPkXd1UL3D7F3IuHHM+V0r4MB4=",
|
||||
@@ -1508,10 +1508,10 @@
|
||||
"revisionTime": "2016-08-08T14:54:09Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "u1dW5zfo2SWot04r5cL8dTbmtcc=",
|
||||
"checksumSHA1": "VJKlO1AEWQivq2S4DvdmAJU2Fvs=",
|
||||
"path": "gopkg.in/macaron.v1",
|
||||
"revision": "aa6b7ee41a182898a33d798c655df1cac9d2230b",
|
||||
"revisionTime": "2017-01-22T14:42:53Z"
|
||||
"revision": "75f2e9b42e99652f0d82b28ccb73648f44615faa",
|
||||
"revisionTime": "2017-11-24T00:20:17Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "6QPjE+qflEBHg+JPJd9e4iQuRAk=",
|
||||
|
Reference in New Issue
Block a user