1
1
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:
Ethan Koenig
2017-11-28 01:43:51 -08:00
committed by Lunny Xiao
parent 6a58e3f9fc
commit b7ebaf6d20
40 changed files with 1087 additions and 381 deletions

View File

@@ -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)

View File

@@ -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
View File

@@ -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.

View File

@@ -1,4 +1,4 @@
Macaron [![Build Status](https://travis-ci.org/go-macaron/macaron.svg?branch=v1)](https://travis-ci.org/go-macaron/macaron) [![](http://gocover.io/_badge/github.com/go-macaron/macaron)](http://gocover.io/github.com/go-macaron/macaron)
Macaron [![Build Status](https://travis-ci.org/go-macaron/macaron.svg?branch=v1)](https://travis-ci.org/go-macaron/macaron)
=======================
![Macaron Logo](https://raw.githubusercontent.com/go-macaron/macaron/v1/macaronlogo.png)
@@ -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)
- [![Join the chat at https://gitter.im/Unknwon/macaron](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-macaron/macaron?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Credits

View File

@@ -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
View File

@@ -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:

View File

@@ -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
View File

@@ -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
View File

@@ -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
View 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
View 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
View File

@@ -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=",