Browse Source

add interface: query public datasets

tags/v1.21.12.1
yuyuanshifu 5 years ago
parent
commit
c80c882d08
38 changed files with 4219 additions and 138 deletions
  1. +3
    -0
      custom/conf/app.ini.sample
  2. +2
    -0
      go.mod
  3. +6
    -0
      go.sum
  4. +9
    -0
      models/attachment.go
  5. +29
    -0
      modules/context/auth.go
  6. +8
    -0
      modules/setting/setting.go
  7. +43
    -1
      routers/repo/attachment.go
  8. +5
    -0
      routers/routes/routes.go
  9. +20
    -0
      vendor/github.com/go-macaron/auth/LICENSE
  10. +68
    -0
      vendor/github.com/go-macaron/auth/README.md
  11. +59
    -0
      vendor/github.com/go-macaron/auth/basic.go
  12. +44
    -0
      vendor/github.com/go-macaron/auth/bearer.go
  13. +14
    -0
      vendor/github.com/go-macaron/auth/util.go
  14. +1
    -0
      vendor/github.com/go-macaron/auth/wercker.yml
  15. +14
    -0
      vendor/github.com/go-macaron/inject/.travis.yml
  16. +191
    -0
      vendor/github.com/go-macaron/inject/LICENSE
  17. +11
    -0
      vendor/github.com/go-macaron/inject/README.md
  18. +262
    -0
      vendor/github.com/go-macaron/inject/inject.go
  19. +3
    -0
      vendor/gopkg.in/macaron.v1/.gitignore
  20. +191
    -0
      vendor/gopkg.in/macaron.v1/LICENSE
  21. +96
    -0
      vendor/gopkg.in/macaron.v1/README.md
  22. +9
    -0
      vendor/gopkg.in/macaron.v1/codecov.yml
  23. +537
    -0
      vendor/gopkg.in/macaron.v1/context.go
  24. +13
    -0
      vendor/gopkg.in/macaron.v1/go.mod
  25. +32
    -0
      vendor/gopkg.in/macaron.v1/go.sum
  26. +73
    -0
      vendor/gopkg.in/macaron.v1/logger.go
  27. +334
    -0
      vendor/gopkg.in/macaron.v1/macaron.go
  28. BIN
      vendor/gopkg.in/macaron.v1/macaronlogo.png
  29. +163
    -0
      vendor/gopkg.in/macaron.v1/recovery.go
  30. +724
    -0
      vendor/gopkg.in/macaron.v1/render.go
  31. +124
    -0
      vendor/gopkg.in/macaron.v1/response_writer.go
  32. +76
    -0
      vendor/gopkg.in/macaron.v1/return_handler.go
  33. +380
    -0
      vendor/gopkg.in/macaron.v1/router.go
  34. +230
    -0
      vendor/gopkg.in/macaron.v1/static.go
  35. +390
    -0
      vendor/gopkg.in/macaron.v1/tree.go
  36. +25
    -0
      vendor/gopkg.in/macaron.v1/util_go17.go
  37. +24
    -0
      vendor/gopkg.in/macaron.v1/util_go18.go
  38. +6
    -137
      vendor/modules.txt

+ 3
- 0
custom/conf/app.ini.sample View File

@@ -1049,6 +1049,9 @@ RESULT_BACKEND = redis://localhost:6379
HOST = http://192.168.204.24 HOST = http://192.168.204.24
USERNAME = USERNAME =
PASSWORD = PASSWORD =
; cloudbrain visit opendata
USER = cW4cMtH24eoWPE7X
PWD = 4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC


[decompress] [decompress]
HOST = http://192.168.207.34:39987 HOST = http://192.168.207.34:39987


+ 2
- 0
go.mod View File

@@ -42,6 +42,7 @@ require (
github.com/go-git/go-billy/v5 v5.0.0 github.com/go-git/go-billy/v5 v5.0.0
github.com/go-git/go-git/v5 v5.0.0 github.com/go-git/go-git/v5 v5.0.0
github.com/go-ini/ini v1.56.0 // indirect github.com/go-ini/ini v1.56.0 // indirect
github.com/go-macaron/auth v0.0.0-20161228062157-884c0e6c9b92
github.com/go-openapi/jsonreference v0.19.3 // indirect github.com/go-openapi/jsonreference v0.19.3 // indirect
github.com/go-redis/redis v6.15.2+incompatible github.com/go-redis/redis v6.15.2+incompatible
github.com/go-resty/resty/v2 v2.3.0 github.com/go-resty/resty/v2 v2.3.0
@@ -121,6 +122,7 @@ require (
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.52.0 gopkg.in/ini.v1 v1.52.0
gopkg.in/ldap.v3 v3.0.2 gopkg.in/ldap.v3 v3.0.2
gopkg.in/macaron.v1 v1.3.9 // indirect
gopkg.in/testfixtures.v2 v2.5.0 gopkg.in/testfixtures.v2 v2.5.0
gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 v2.2.8
mvdan.cc/xurls/v2 v2.1.0 mvdan.cc/xurls/v2 v2.1.0


+ 6
- 0
go.sum View File

@@ -234,6 +234,10 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-macaron/auth v0.0.0-20161228062157-884c0e6c9b92 h1:71YL0o1ch/APk7bmW9jWKBY7ibd9U8NQX2bQ25EJMHI=
github.com/go-macaron/auth v0.0.0-20161228062157-884c0e6c9b92/go.mod h1:saPJfEeea+kiiZJF4GG7TSOao0T/Yrm5rpsqYglss6k=
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI=
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
@@ -1032,6 +1036,8 @@ gopkg.in/ini.v1 v1.52.0 h1:j+Lt/M1oPPejkniCg1TkWE2J3Eh1oZTsHSXzMTzUXn4=
gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ldap.v3 v3.0.2 h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w= gopkg.in/ldap.v3 v3.0.2 h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w=
gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw= gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw=
gopkg.in/macaron.v1 v1.3.9 h1:Dw+DDRYdXgQyEsPlfAfKz+UA5qVUrH3KPD7JhmZ9MFc=
gopkg.in/macaron.v1 v1.3.9/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/testfixtures.v2 v2.5.0 h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw= gopkg.in/testfixtures.v2 v2.5.0 h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw=


+ 9
- 0
models/attachment.go View File

@@ -346,3 +346,12 @@ func getUnDecompressAttachments(e Engine) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10) attachments := make([]*Attachment, 0, 10)
return attachments, e.Where("decompress_state = ? and dataset_id != 0 and name like '%.zip'", DecompressStateInit).Find(&attachments) return attachments, e.Where("decompress_state = ? and dataset_id != 0 and name like '%.zip'", DecompressStateInit).Find(&attachments)
} }

func GetAllPublicAttachments() ([]*Attachment, error) {
return getAllPublicAttachments(x)
}

func getAllPublicAttachments(e Engine) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10)
return attachments, e.Where("is_private = true ").Find(&attachments)
}

+ 29
- 0
modules/context/auth.go View File

@@ -10,9 +10,13 @@ import (
"code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"encoding/base64"
"net/http"


"gitea.com/macaron/csrf" "gitea.com/macaron/csrf"
"gitea.com/macaron/macaron" "gitea.com/macaron/macaron"

marc_auth "github.com/go-macaron/auth"
) )


// ToggleOptions contains required or check options // ToggleOptions contains required or check options
@@ -21,6 +25,7 @@ type ToggleOptions struct {
SignOutRequired bool SignOutRequired bool
AdminRequired bool AdminRequired bool
DisableCSRF bool DisableCSRF bool
BasicAuthRequired bool
} }


// Toggle returns toggle options as middleware // Toggle returns toggle options as middleware
@@ -130,5 +135,29 @@ func Toggle(options *ToggleOptions) macaron.Handler {
} }
ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdmin"] = true
} }

if options.BasicAuthRequired {
if !basicAuth(ctx) {
basicUnauthorized(ctx.Resp)
return
}
}
} }
} }

func basicAuth(ctx *Context) bool {
var siteAuth = base64.StdEncoding.EncodeToString([]byte(setting.CBAuthUser + ":" + setting.CBAuthPassword))
auth := ctx.Req.Header.Get("Authorization")

if !marc_auth.SecureCompare(auth, "Basic " + siteAuth) {
return false
}

return true

}

func basicUnauthorized(res http.ResponseWriter) {
res.Header().Set("WWW-Authenticate", "Basic realm=\"" + marc_auth.BasicRealm + "\"")
http.Error(res, "Not Authorized", http.StatusUnauthorized)
}

+ 8
- 0
modules/setting/setting.go View File

@@ -430,6 +430,10 @@ var (
DecompressAddress string DecompressAddress string
AuthUser string AuthUser string
AuthPassword string AuthPassword string

//cloudbrain config
CBAuthUser string
CBAuthPassword string
) )


// DateLang transforms standard language locale name to corresponding value in datetime plugin. // DateLang transforms standard language locale name to corresponding value in datetime plugin.
@@ -1097,6 +1101,10 @@ func NewContext() {
DecompressAddress = sec.Key("HOST").MustString("http://192.168.207.34:39987") DecompressAddress = sec.Key("HOST").MustString("http://192.168.207.34:39987")
AuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X") AuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X")
AuthPassword = sec.Key("PASSWORD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC") AuthPassword = sec.Key("PASSWORD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC")

sec = Cfg.Section("cloudbrain")
CBAuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X")
CBAuthPassword = sec.Key("PWD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC")
} }


func loadInternalToken(sec *ini.Section) string { func loadInternalToken(sec *ini.Section) string {


+ 43
- 1
routers/repo/attachment.go View File

@@ -6,6 +6,7 @@ package repo


import ( import (
contexExt "context" contexExt "context"
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
@@ -29,6 +30,11 @@ const (
DecompressFailed = "1" DecompressFailed = "1"
) )


type PublicDataset struct {
Name string `json:"name"`
Path string `json:"path"`
}

func RenderAttachmentSettings(ctx *context.Context) { func RenderAttachmentSettings(ctx *context.Context) {
renderAttachmentSettings(ctx) renderAttachmentSettings(ctx)
} }
@@ -374,7 +380,7 @@ func GetSuccessChunks(ctx *context.Context) {


chunks, err = storage.GetPartInfos(fileChunk.UUID, fileChunk.UploadID) chunks, err = storage.GetPartInfos(fileChunk.UUID, fileChunk.UploadID)
if err != nil { if err != nil {
ctx.ServerError("json.Marshal failed", err)
ctx.ServerError("GetPartInfos failed", err)
return return
} }
} }
@@ -601,3 +607,39 @@ func HandleUnDecompressAttachment() {


return return
} }

func QueryAllPublicDataset(ctx *context.Context){
log.Info("QueryAllPublicDataset")

attachs, err := models.GetAllPublicAttachments()
if err != nil {
ctx.JSON(200, map[string]string{
"result_code": "-1",
"data": "",
})
return
}

var publicDatasets []PublicDataset
for _, attch := range attachs {
publicDatasets = append(publicDatasets, PublicDataset{attch.Name,
models.AttachmentRelativePath(attch.UUID)})
}

data,err := json.Marshal(publicDatasets)
if err != nil {
log.Error("json.Marshal failed:", err.Error())
ctx.JSON(200, map[string]string{
"result_code": "-1",
"data": "",
})
return
}

log.Info(string(data))

ctx.JSON(200, map[string]string{
"result_code": "0",
"data": string(data),
})
}

+ 5
- 0
routers/routes/routes.go View File

@@ -245,6 +245,7 @@ func RegisterRoutes(m *macaron.Macaron) {
ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView}) ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView})
ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true}) ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true})
reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true}) reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true})
reqBasicAuth := context.Toggle(&context.ToggleOptions{BasicAuthRequired:true})


bindIgnErr := binding.BindIgnErr bindIgnErr := binding.BindIgnErr
validation.AddBindingRules() validation.AddBindingRules()
@@ -533,6 +534,10 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/decompress_done_notify", repo.UpdateAttachmentDecompressState) m.Post("/decompress_done_notify", repo.UpdateAttachmentDecompressState)
}) })


m.Group("/attachments/public", func() {
m.Get("/query", repo.QueryAllPublicDataset)
}, reqBasicAuth)

m.Group("/:username", func() { m.Group("/:username", func() {
m.Post("/action/:action", user.Action) m.Post("/action/:action", user.Action)
}, reqSignIn) }, reqSignIn)


+ 20
- 0
vendor/github.com/go-macaron/auth/LICENSE View File

@@ -0,0 +1,20 @@
The MIT License (MIT)

Copyright (c) 2013 Jeremy Saenz

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 68
- 0
vendor/github.com/go-macaron/auth/README.md View File

@@ -0,0 +1,68 @@
# auth
Macaron middleware/handler for http basic authentication. Modified from <https://github.com/martini-contrib/auth>

[API Reference](http://godoc.org/github.com/go-macaron/auth)

## Simple Usage

Use `auth.Basic` to authenticate against a pre-defined username and password:

~~~ go
import (
"gopkg.in/macaron.v1"
"github.com/go-macaron/auth"
)

func main() {
m := macaron.Classic()
// authenticate every request
m.Use(auth.Basic("username", "secretpassword"))
m.Run()
}
~~~

## Advanced Usage

Using `auth.BasicFunc` lets you authenticate on a per-user level, by checking
the username and password in the callback function:

~~~ go
import (
"gopkg.in/macaron.v1"
"github.com/go-macaron/auth"
)

func main() {
m := macaron.Classic()
// authenticate every request
m.Use(auth.BasicFunc(func(username, password string) bool {
return username == "admin" && password == "guessme"
}))
m.Run()
}
~~~

Note that checking usernames and passwords with string comparison might be
susceptible to timing attacks. To avoid that, use `auth.SecureCompare` instead:

~~~ go
m.Use(auth.BasicFunc(func(username, password string) bool {
return auth.SecureCompare(username, "admin") && auth.SecureCompare(password, "guessme")
}))
}
~~~

Upon successful authentication, the username is available to all subsequent
handlers via the `auth.User` type:

~~~ go
m.Get("/", func(user auth.User) string {
return "Welcome, " + string(user)
})
}
~~~

## Authors
* [Jeremy Saenz](https://github.com/codegangsta)
* [Brendon Murphy](https://github.com/bemurphy)
* [codeskyblue](https://github.com/codeskyblue)

+ 59
- 0
vendor/github.com/go-macaron/auth/basic.go View File

@@ -0,0 +1,59 @@
package auth

import (
"encoding/base64"
"net/http"
"strings"

"gopkg.in/macaron.v1"
)

// User is the authenticated username that was extracted from the request.
type User string

// BasicRealm is used when setting the WWW-Authenticate response header.
var BasicRealm = "Authorization Required"
var basicPrefix = "Basic "

// Basic returns a Handler that authenticates via Basic Auth. Writes a http.StatusUnauthorized
// if authentication fails.
func Basic(username string, password string) macaron.Handler {
var siteAuth = base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
auth := req.Header.Get("Authorization")
if !SecureCompare(auth, basicPrefix+siteAuth) {
basicUnauthorized(res)
return
}
c.Map(User(username))
}
}

// BasicFunc returns a Handler that authenticates via Basic Auth using the provided function.
// The function should return true for a valid username/password combination.
func BasicFunc(authfn func(string, string) bool) macaron.Handler {
return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
auth := req.Header.Get("Authorization")
n := len(basicPrefix)
if len(auth) < n || auth[:n] != basicPrefix {
basicUnauthorized(res)
return
}
b, err := base64.StdEncoding.DecodeString(auth[n:])
if err != nil {
basicUnauthorized(res)
return
}
tokens := strings.SplitN(string(b), ":", 2)
if len(tokens) != 2 || !authfn(tokens[0], tokens[1]) {
basicUnauthorized(res)
return
}
c.Map(User(tokens[0]))
}
}

func basicUnauthorized(res http.ResponseWriter) {
res.Header().Set("WWW-Authenticate", "Basic realm=\""+BasicRealm+"\"")
http.Error(res, "Not Authorized", http.StatusUnauthorized)
}

+ 44
- 0
vendor/github.com/go-macaron/auth/bearer.go View File

@@ -0,0 +1,44 @@
package auth

import (
"net/http"

"gopkg.in/macaron.v1"
)

var bearerPrefix = "Bearer "

// Bearer returns a Handler that authenticates via Bearer Auth. Writes a http.StatusUnauthorized
// if authentication fails.
func Bearer(token string) macaron.Handler {
return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
auth := req.Header.Get("Authorization")
if !SecureCompare(auth, bearerPrefix+token) {
bearerUnauthorized(res)
return
}
c.Map(User(""))
}
}

// BearerFunc returns a Handler that authenticates via Bearer Auth using the provided function.
// The function should return true for a valid bearer token.
func BearerFunc(authfn func(string) bool) macaron.Handler {
return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
auth := req.Header.Get("Authorization")
n := len(bearerPrefix)
if len(auth) < n || auth[:n] != bearerPrefix {
bearerUnauthorized(res)
return
}
if !authfn(auth[n:]) {
bearerUnauthorized(res)
return
}
c.Map(User(""))
}
}

func bearerUnauthorized(res http.ResponseWriter) {
http.Error(res, "Not Authorized", http.StatusUnauthorized)
}

+ 14
- 0
vendor/github.com/go-macaron/auth/util.go View File

@@ -0,0 +1,14 @@
package auth

import (
"crypto/sha512"
"crypto/subtle"
)

// SecureCompare performs a constant time compare of two strings to limit timing attacks.
func SecureCompare(given string, actual string) bool {
givenSha := sha512.Sum512([]byte(given))
actualSha := sha512.Sum512([]byte(actual))

return subtle.ConstantTimeCompare(givenSha[:], actualSha[:]) == 1
}

+ 1
- 0
vendor/github.com/go-macaron/auth/wercker.yml View File

@@ -0,0 +1 @@
box: wercker/golang@1.1.1

+ 14
- 0
vendor/github.com/go-macaron/inject/.travis.yml View File

@@ -0,0 +1,14 @@
sudo: false
language: go

go:
- 1.3
- 1.4
- 1.5
- tip

script: go test -v -cover -race

notifications:
email:
- u@gogs.io

+ 191
- 0
vendor/github.com/go-macaron/inject/LICENSE View File

@@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.

"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.

2. Grant of Copyright License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.

3. Grant of Patent License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.

4. Redistribution.

You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:

You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.

5. Submission of Contributions.

Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.

6. Trademarks.

This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.

7. Disclaimer of Warranty.

Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.

8. Limitation of Liability.

In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability.

While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work

To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
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]

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.

+ 11
- 0
vendor/github.com/go-macaron/inject/README.md View File

@@ -0,0 +1,11 @@
# inject [![Build Status](https://travis-ci.org/go-macaron/inject.svg?branch=master)](https://travis-ci.org/go-macaron/inject) [![](http://gocover.io/_badge/github.com/go-macaron/inject)](http://gocover.io/github.com/go-macaron/inject)

Package inject provides utilities for mapping and injecting dependencies in various ways.

**This a modified version of [codegangsta/inject](https://github.com/codegangsta/inject) for special purpose of Macaron**

**Please use the original version if you need dependency injection feature**

## License

This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.

+ 262
- 0
vendor/github.com/go-macaron/inject/inject.go View File

@@ -0,0 +1,262 @@
// Copyright 2013 Jeremy Saenz
// Copyright 2015 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 inject provides utilities for mapping and injecting dependencies in various ways.
package inject

import (
"fmt"
"reflect"
)

// Injector represents an interface for mapping and injecting dependencies into structs
// and function arguments.
type Injector interface {
Applicator
Invoker
TypeMapper
// SetParent sets the parent of the injector. If the injector cannot find a
// dependency in its Type map it will check its parent before returning an
// error.
SetParent(Injector)
}

// Applicator represents an interface for mapping dependencies to a struct.
type Applicator interface {
// Maps dependencies in the Type map to each field in the struct
// that is tagged with 'inject'. Returns an error if the injection
// fails.
Apply(interface{}) error
}

// Invoker represents an interface for calling functions via reflection.
type Invoker interface {
// Invoke attempts to call the interface{} provided as a function,
// providing dependencies for function arguments based on Type. Returns
// a slice of reflect.Value representing the returned values of the function.
// Returns an error if the injection fails.
Invoke(interface{}) ([]reflect.Value, error)
}

// FastInvoker represents an interface in order to avoid the calling function via reflection.
//
// example:
// type handlerFuncHandler func(http.ResponseWriter, *http.Request) error
// func (f handlerFuncHandler)Invoke([]interface{}) ([]reflect.Value, error){
// ret := f(p[0].(http.ResponseWriter), p[1].(*http.Request))
// return []reflect.Value{reflect.ValueOf(ret)}, nil
// }
//
// type funcHandler func(int, string)
// func (f funcHandler)Invoke([]interface{}) ([]reflect.Value, error){
// f(p[0].(int), p[1].(string))
// return nil, nil
// }
type FastInvoker interface {
// Invoke attempts to call the ordinary functions. If f is a function
// with the appropriate signature, f.Invoke([]interface{}) is a Call that calls f.
// Returns a slice of reflect.Value representing the returned values of the function.
// Returns an error if the injection fails.
Invoke([]interface{}) ([]reflect.Value, error)
}

// IsFastInvoker check interface is FastInvoker
func IsFastInvoker(h interface{}) bool {
_, ok := h.(FastInvoker)
return ok
}

// TypeMapper represents an interface for mapping interface{} values based on type.
type TypeMapper interface {
// Maps the interface{} value based on its immediate type from reflect.TypeOf.
Map(interface{}) TypeMapper
// Maps the interface{} value based on the pointer of an Interface provided.
// This is really only useful for mapping a value as an interface, as interfaces
// cannot at this time be referenced directly without a pointer.
MapTo(interface{}, interface{}) TypeMapper
// Provides a possibility to directly insert a mapping based on type and value.
// This makes it possible to directly map type arguments not possible to instantiate
// with reflect like unidirectional channels.
Set(reflect.Type, reflect.Value) TypeMapper
// Returns the Value that is mapped to the current type. Returns a zeroed Value if
// the Type has not been mapped.
GetVal(reflect.Type) reflect.Value
}

type injector struct {
values map[reflect.Type]reflect.Value
parent Injector
}

// InterfaceOf dereferences a pointer to an Interface type.
// It panics if value is not an pointer to an interface.
func InterfaceOf(value interface{}) reflect.Type {
t := reflect.TypeOf(value)

for t.Kind() == reflect.Ptr {
t = t.Elem()
}

if t.Kind() != reflect.Interface {
panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
}

return t
}

// New returns a new Injector.
func New() Injector {
return &injector{
values: make(map[reflect.Type]reflect.Value),
}
}

// Invoke attempts to call the interface{} provided as a function,
// providing dependencies for function arguments based on Type.
// Returns a slice of reflect.Value representing the returned values of the function.
// Returns an error if the injection fails.
// It panics if f is not a function
func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
t := reflect.TypeOf(f)
switch v := f.(type) {
case FastInvoker:
return inj.fastInvoke(v, t, t.NumIn())
default:
return inj.callInvoke(f, t, t.NumIn())
}
}

func (inj *injector) fastInvoke(f FastInvoker, t reflect.Type, numIn int) ([]reflect.Value, error) {
var in []interface{}
if numIn > 0 {
in = make([]interface{}, numIn) // Panic if t is not kind of Func
var argType reflect.Type
var val reflect.Value
for i := 0; i < numIn; i++ {
argType = t.In(i)
val = inj.GetVal(argType)
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}

in[i] = val.Interface()
}
}
return f.Invoke(in)
}

// callInvoke reflect.Value.Call
func (inj *injector) callInvoke(f interface{}, t reflect.Type, numIn int) ([]reflect.Value, error) {
var in []reflect.Value
if numIn > 0 {
in = make([]reflect.Value, numIn)
var argType reflect.Type
var val reflect.Value
for i := 0; i < numIn; i++ {
argType = t.In(i)
val = inj.GetVal(argType)
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}

in[i] = val
}
}
return reflect.ValueOf(f).Call(in), nil
}

// Maps dependencies in the Type map to each field in the struct
// that is tagged with 'inject'.
// Returns an error if the injection fails.
func (inj *injector) Apply(val interface{}) error {
v := reflect.ValueOf(val)

for v.Kind() == reflect.Ptr {
v = v.Elem()
}

if v.Kind() != reflect.Struct {
return nil // Should not panic here ?
}

t := v.Type()

for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
structField := t.Field(i)
if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
ft := f.Type()
v := inj.GetVal(ft)
if !v.IsValid() {
return fmt.Errorf("Value not found for type %v", ft)
}

f.Set(v)
}

}

return nil
}

// Maps the concrete value of val to its dynamic type using reflect.TypeOf,
// It returns the TypeMapper registered in.
func (i *injector) Map(val interface{}) TypeMapper {
i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
return i
}

func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
return i
}

// Maps the given reflect.Type to the given reflect.Value and returns
// the Typemapper the mapping has been registered in.
func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
i.values[typ] = val
return i
}

func (i *injector) GetVal(t reflect.Type) reflect.Value {
val := i.values[t]

if val.IsValid() {
return val
}

// no concrete types found, try to find implementors
// if t is an interface
if t.Kind() == reflect.Interface {
for k, v := range i.values {
if k.Implements(t) {
val = v
break
}
}
}

// Still no type found, try to look it up on the parent
if !val.IsValid() && i.parent != nil {
val = i.parent.GetVal(t)
}

return val

}

func (i *injector) SetParent(parent Injector) {
i.parent = parent
}

+ 3
- 0
vendor/gopkg.in/macaron.v1/.gitignore View File

@@ -0,0 +1,3 @@
macaron.sublime-project
macaron.sublime-workspace
.idea

+ 191
- 0
vendor/gopkg.in/macaron.v1/LICENSE View File

@@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.

"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.

2. Grant of Copyright License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.

3. Grant of Patent License.

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.

4. Redistribution.

You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:

You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.

5. Submission of Contributions.

Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.

6. Trademarks.

This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.

7. Disclaimer of Warranty.

Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.

8. Limitation of Liability.

In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability.

While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work

To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "[]" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
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 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.
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.

+ 96
- 0
vendor/gopkg.in/macaron.v1/README.md View File

@@ -0,0 +1,96 @@
# Macaron

[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/go-macaron/macaron/Go?logo=github&style=for-the-badge)](https://github.com/go-macaron/macaron/actions?query=workflow%3AGo)
[![codecov](https://img.shields.io/codecov/c/github/go-macaron/macaron/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-macaron/macaron)
[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/gopkg.in/macaron.v1?tab=doc)
[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-macaron/macaron)

![Macaron Logo](https://raw.githubusercontent.com/go-macaron/macaron/v1/macaronlogo.png)

Package macaron is a high productive and modular web framework in Go.

## Getting Started

The minimum requirement of Go is **1.6**.

To install Macaron:

go get gopkg.in/macaron.v1

The very basic usage of Macaron:

```go
package main

import "gopkg.in/macaron.v1"

func main() {
m := macaron.Classic()
m.Get("/", func() string {
return "Hello world!"
})
m.Run()
}
```

## Features

- Powerful routing with suburl.
- Flexible routes combinations.
- Unlimited nested group routers.
- Directly integrate with existing services.
- Dynamically change template files at runtime.
- Allow to use in-memory template and static files.
- Easy to plugin/unplugin features with modular design.
- Handy dependency injection powered by [inject](https://github.com/codegangsta/inject).
- Better router layer and less reflection make faster speed.

## Middlewares

Middlewares allow you easily plugin/unplugin features for your Macaron applications.

There are already many [middlewares](https://github.com/go-macaron) to simplify your work:

- render - Go template engine
- static - Serves static files
- [gzip](https://github.com/go-macaron/gzip) - Gzip compression to all responses
- [binding](https://github.com/go-macaron/binding) - Request data binding and validation
- [i18n](https://github.com/go-macaron/i18n) - Internationalization and Localization
- [cache](https://github.com/go-macaron/cache) - Cache manager
- [session](https://github.com/go-macaron/session) - Session manager
- [csrf](https://github.com/go-macaron/csrf) - Generates and validates csrf tokens
- [captcha](https://github.com/go-macaron/captcha) - Captcha service
- [pongo2](https://github.com/go-macaron/pongo2) - Pongo2 template engine support
- [sockets](https://github.com/go-macaron/sockets) - WebSockets channels binding
- [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
- [Critical Stack Intel](https://intel.criticalstack.com/): A 100% free intel marketplace from Critical Stack, Inc.

## Getting Help

- [API Reference](https://gowalker.org/gopkg.in/macaron.v1)
- [Documentation](https://go-macaron.com)
- [FAQs](https://go-macaron.com/docs/faqs)

## Credits

- Basic design of [Martini](https://github.com/go-martini/martini).
- Logo is modified by [@insionng](https://github.com/insionng) based on [Tribal Dragon](http://xtremeyamazaki.deviantart.com/art/Tribal-Dragon-27005087).

## License

This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.

+ 9
- 0
vendor/gopkg.in/macaron.v1/codecov.yml View File

@@ -0,0 +1,9 @@
coverage:
range: "60...95"
status:
project:
default:
threshold: 1%

comment:
layout: 'diff, files'

+ 537
- 0
vendor/gopkg.in/macaron.v1/context.go View File

@@ -0,0 +1,537 @@
// 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. 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 (
"crypto/sha256"
"encoding/hex"
"html/template"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"

"github.com/go-macaron/inject"
"github.com/unknwon/com"
"golang.org/x/crypto/pbkdf2"
)

// Locale reprents a localization interface.
type Locale interface {
Language() string
Tr(string, ...interface{}) string
}

// RequestBody represents a request body.
type RequestBody struct {
reader io.ReadCloser
}

// Bytes reads and returns content of request body in bytes.
func (rb *RequestBody) Bytes() ([]byte, error) {
return ioutil.ReadAll(rb.reader)
}

// String reads and returns content of request body in string.
func (rb *RequestBody) String() (string, error) {
data, err := rb.Bytes()
return string(data), err
}

// ReadCloser returns a ReadCloser for request body.
func (rb *RequestBody) ReadCloser() io.ReadCloser {
return rb.reader
}

// Request represents an HTTP request received by a server or to be sent by a client.
type Request struct {
*http.Request
}

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 {
inject.Injector
handlers []Handler
action Handler
index int

*Router
Req Request
Resp ResponseWriter
params Params
Render
Locale
Data map[string]interface{}
}

func (c *Context) handler() Handler {
if c.index < len(c.handlers) {
return c.handlers[c.index]
}
if c.index == len(c.handlers) {
return c.action
}
panic("invalid index for context handler")
}

func (c *Context) Next() {
c.index += 1
c.run()
}

func (c *Context) Written() bool {
return c.Resp.Written()
}

func (c *Context) run() {
for c.index <= len(c.handlers) {
vals, err := c.Invoke(c.handler())
if err != nil {
panic(err)
}
c.index += 1

// if the handler returned something, write it to the http response
if len(vals) > 0 {
ev := c.GetVal(reflect.TypeOf(ReturnHandler(nil)))
handleReturn := ev.Interface().(ReturnHandler)
handleReturn(c, vals)
}

if c.Written() {
return
}
}
}

// RemoteAddr returns more real IP address.
func (ctx *Context) RemoteAddr() string {
addr := ctx.Req.Header.Get("X-Real-IP")
if len(addr) == 0 {
addr = ctx.Req.Header.Get("X-Forwarded-For")
if addr == "" {
addr = ctx.Req.RemoteAddr
if i := strings.LastIndex(addr, ":"); i > -1 {
addr = addr[:i]
}
}
}
return addr
}

func (ctx *Context) renderHTML(status int, setName, tplName string, data ...interface{}) {
if len(data) <= 0 {
ctx.Render.HTMLSet(status, setName, tplName, ctx.Data)
} else if len(data) == 1 {
ctx.Render.HTMLSet(status, setName, tplName, data[0])
} else {
ctx.Render.HTMLSet(status, setName, tplName, data[0], data[1].(HTMLOptions))
}
}

// HTML renders the HTML with default template set.
func (ctx *Context) HTML(status int, name string, data ...interface{}) {
ctx.renderHTML(status, DEFAULT_TPL_SET_NAME, name, data...)
}

// HTMLSet renders the HTML with given template set name.
func (ctx *Context) HTMLSet(status int, setName, tplName string, data ...interface{}) {
ctx.renderHTML(status, setName, tplName, data...)
}

func (ctx *Context) Redirect(location string, status ...int) {
code := http.StatusFound
if len(status) == 1 {
code = status[0]
}

http.Redirect(ctx.Resp, ctx.Req.Request, location, code)
}

// Maximum amount of memory to use when parsing a multipart form.
// Set this to whatever value you prefer; default is 10 MB.
var MaxMemory = int64(1024 * 1024 * 10)

func (ctx *Context) parseForm() {
if ctx.Req.Form != nil {
return
}

contentType := ctx.Req.Header.Get(_CONTENT_TYPE)
if (ctx.Req.Method == "POST" || ctx.Req.Method == "PUT") &&
len(contentType) > 0 && strings.Contains(contentType, "multipart/form-data") {
_ = ctx.Req.ParseMultipartForm(MaxMemory)
} else {
_ = ctx.Req.ParseForm()
}
}

// Query querys form parameter.
func (ctx *Context) Query(name string) string {
ctx.parseForm()
return ctx.Req.Form.Get(name)
}

// QueryTrim querys and trims spaces form parameter.
func (ctx *Context) QueryTrim(name string) string {
return strings.TrimSpace(ctx.Query(name))
}

// QueryStrings returns a list of results by given query name.
func (ctx *Context) QueryStrings(name string) []string {
ctx.parseForm()

vals, ok := ctx.Req.Form[name]
if !ok {
return []string{}
}
return vals
}

// QueryEscape returns escapred query result.
func (ctx *Context) QueryEscape(name string) string {
return template.HTMLEscapeString(ctx.Query(name))
}

// QueryBool returns query result in bool type.
func (ctx *Context) QueryBool(name string) bool {
v, _ := strconv.ParseBool(ctx.Query(name))
return v
}

// QueryInt returns query result in int type.
func (ctx *Context) QueryInt(name string) int {
return com.StrTo(ctx.Query(name)).MustInt()
}

// QueryInt64 returns query result in int64 type.
func (ctx *Context) QueryInt64(name string) int64 {
return com.StrTo(ctx.Query(name)).MustInt64()
}

// QueryFloat64 returns query result in float64 type.
func (ctx *Context) QueryFloat64(name string) float64 {
v, _ := strconv.ParseFloat(ctx.Query(name), 64)
return v
}

// Params returns value of given param name.
// e.g. ctx.Params(":uid") or ctx.Params("uid")
func (ctx *Context) Params(name string) string {
if len(name) == 0 {
return ""
}
if len(name) > 1 && name[0] != ':' {
name = ":" + name
}
return ctx.params[name]
}

// AllParams returns all params.
func (ctx *Context) AllParams() Params {
return ctx.params
}

// SetParams sets value of param with given name.
func (ctx *Context) SetParams(name, val string) {
if name != "*" && !strings.HasPrefix(name, ":") {
name = ":" + name
}
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 {
return template.HTMLEscapeString(ctx.Params(name))
}

// ParamsInt returns params result in int type.
// e.g. ctx.ParamsInt(":uid")
func (ctx *Context) ParamsInt(name string) int {
return com.StrTo(ctx.Params(name)).MustInt()
}

// ParamsInt64 returns params result in int64 type.
// e.g. ctx.ParamsInt64(":uid")
func (ctx *Context) ParamsInt64(name string) int64 {
return com.StrTo(ctx.Params(name)).MustInt64()
}

// ParamsFloat64 returns params result in int64 type.
// e.g. ctx.ParamsFloat64(":uid")
func (ctx *Context) ParamsFloat64(name string) float64 {
v, _ := strconv.ParseFloat(ctx.Params(name), 64)
return v
}

// GetFile returns information about user upload file by given form field name.
func (ctx *Context) GetFile(name string) (multipart.File, *multipart.FileHeader, error) {
return ctx.Req.FormFile(name)
}

// SaveToFile reads a file from request by field name and saves to given path.
func (ctx *Context) SaveToFile(name, savePath string) error {
fr, _, err := ctx.GetFile(name)
if err != nil {
return err
}
defer fr.Close()

fw, err := os.OpenFile(savePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
defer fw.Close()

_, err = io.Copy(fw, fr)
return err
}

// SetCookie sets given cookie value to response header.
// FIXME: IE support? http://golanghome.com/post/620#reply2
func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
cookie := http.Cookie{}
cookie.Name = name
cookie.Value = url.QueryEscape(value)

if len(others) > 0 {
switch v := others[0].(type) {
case int:
cookie.MaxAge = v
case int64:
cookie.MaxAge = int(v)
case int32:
cookie.MaxAge = int(v)
}
}

cookie.Path = "/"
if len(others) > 1 {
if v, ok := others[1].(string); ok && len(v) > 0 {
cookie.Path = v
}
}

if len(others) > 2 {
if v, ok := others[2].(string); ok && len(v) > 0 {
cookie.Domain = v
}
}

if len(others) > 3 {
switch v := others[3].(type) {
case bool:
cookie.Secure = v
default:
if others[3] != nil {
cookie.Secure = true
}
}
}

if len(others) > 4 {
if v, ok := others[4].(bool); ok && v {
cookie.HttpOnly = true
}
}

if len(others) > 5 {
if v, ok := others[5].(time.Time); ok {
cookie.Expires = v
cookie.RawExpires = v.Format(time.UnixDate)
}
}

ctx.Resp.Header().Add("Set-Cookie", cookie.String())
}

// GetCookie returns given cookie value from request header.
func (ctx *Context) GetCookie(name string) string {
cookie, err := ctx.Req.Cookie(name)
if err != nil {
return ""
}
val, _ := url.QueryUnescape(cookie.Value)
return val
}

// GetCookieInt returns cookie result in int type.
func (ctx *Context) GetCookieInt(name string) int {
return com.StrTo(ctx.GetCookie(name)).MustInt()
}

// GetCookieInt64 returns cookie result in int64 type.
func (ctx *Context) GetCookieInt64(name string) int64 {
return com.StrTo(ctx.GetCookie(name)).MustInt64()
}

// GetCookieFloat64 returns cookie result in float64 type.
func (ctx *Context) GetCookieFloat64(name string) float64 {
v, _ := strconv.ParseFloat(ctx.GetCookie(name), 64)
return v
}

var defaultCookieSecret string

// SetDefaultCookieSecret sets global default secure cookie secret.
func (m *Macaron) SetDefaultCookieSecret(secret string) {
defaultCookieSecret = secret
}

// SetSecureCookie sets given cookie value to response header with default secret string.
func (ctx *Context) SetSecureCookie(name, value string, others ...interface{}) {
ctx.SetSuperSecureCookie(defaultCookieSecret, name, value, others...)
}

// GetSecureCookie returns given cookie value from request header with default secret string.
func (ctx *Context) GetSecureCookie(key string) (string, bool) {
return ctx.GetSuperSecureCookie(defaultCookieSecret, key)
}

// SetSuperSecureCookie sets given cookie value to response header with secret string.
func (ctx *Context) SetSuperSecureCookie(secret, name, value string, others ...interface{}) {
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, name string) (string, bool) {
val := ctx.GetCookie(name)
if val == "" {
return "", false
}

text, err := hex.DecodeString(val)
if err != nil {
return "", false
}

key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
text, err = com.AESGCMDecrypt(key, text)
return string(text), err == nil
}

func (ctx *Context) setRawContentHeader() {
ctx.Resp.Header().Set("Content-Description", "Raw content")
ctx.Resp.Header().Set("Content-Type", "text/plain")
ctx.Resp.Header().Set("Expires", "0")
ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
ctx.Resp.Header().Set("Pragma", "public")
}

// ServeContent serves given content to response.
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
modtime := time.Now()
for _, p := range params {
switch v := p.(type) {
case time.Time:
modtime = v
}
}

ctx.setRawContentHeader()
http.ServeContent(ctx.Resp, ctx.Req.Request, name, modtime, r)
}

// ServeFileContent serves given file as content to response.
func (ctx *Context) ServeFileContent(file string, names ...string) {
var name string
if len(names) > 0 {
name = names[0]
} else {
name = path.Base(file)
}

f, err := os.Open(file)
if err != nil {
if Env == PROD {
http.Error(ctx.Resp, "Internal Server Error", 500)
} else {
http.Error(ctx.Resp, err.Error(), 500)
}
return
}
defer f.Close()

ctx.setRawContentHeader()
http.ServeContent(ctx.Resp, ctx.Req.Request, name, time.Now(), f)
}

// ServeFile serves given file to response.
func (ctx *Context) ServeFile(file string, names ...string) {
var name string
if len(names) > 0 {
name = names[0]
} else {
name = path.Base(file)
}
ctx.Resp.Header().Set("Content-Description", "File Transfer")
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
ctx.Resp.Header().Set("Expires", "0")
ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
ctx.Resp.Header().Set("Pragma", "public")
http.ServeFile(ctx.Resp, ctx.Req.Request, file)
}

// ChangeStaticPath changes static path from old to new one.
func (ctx *Context) ChangeStaticPath(oldPath, newPath string) {
if !filepath.IsAbs(oldPath) {
oldPath = filepath.Join(Root, oldPath)
}
dir := statics.Get(oldPath)
if dir != nil {
statics.Delete(oldPath)

if !filepath.IsAbs(newPath) {
newPath = filepath.Join(Root, newPath)
}
*dir = http.Dir(newPath)
statics.Set(dir)
}
}

+ 13
- 0
vendor/gopkg.in/macaron.v1/go.mod View File

@@ -0,0 +1,13 @@
module gopkg.in/macaron.v1

go 1.12

require (
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
gopkg.in/ini.v1 v1.46.0
)

+ 32
- 0
vendor/gopkg.in/macaron.v1/go.sum View File

@@ -0,0 +1,32 @@
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI=
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM=
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag=
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=

+ 73
- 0
vendor/gopkg.in/macaron.v1/logger.go View File

@@ -0,0 +1,73 @@
// Copyright 2013 Martini Authors
// 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. 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 (
"fmt"
"log"
"net/http"
"reflect"
"runtime"
"time"
)

var (
ColorLog = true
LogTimeFormat = "2006-01-02 15:04:05"
)

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) {
start := time.Now()

log.Printf("%s: Started %s %s for %s", time.Now().Format(LogTimeFormat), ctx.Req.Method, ctx.Req.RequestURI, ctx.RemoteAddr())

rw := ctx.Resp.(ResponseWriter)
ctx.Next()

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:
content = fmt.Sprintf("\033[1;32m%s\033[0m", content)
case 301, 302:
content = fmt.Sprintf("\033[1;37m%s\033[0m", content)
case 304:
content = fmt.Sprintf("\033[1;33m%s\033[0m", content)
case 401, 403:
content = fmt.Sprintf("\033[4;31m%s\033[0m", content)
case 404:
content = fmt.Sprintf("\033[1;31m%s\033[0m", content)
case 500:
content = fmt.Sprintf("\033[1;36m%s\033[0m", content)
}
}
log.Println(content)
}
}

+ 334
- 0
vendor/gopkg.in/macaron.v1/macaron.go View File

@@ -0,0 +1,334 @@
// +build go1.3

// 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. 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 is a high productive and modular web framework in Go.
package macaron // import "gopkg.in/macaron.v1"

import (
"io"
"log"
"net/http"
"os"
"reflect"
"strings"
"sync"

"github.com/unknwon/com"
"gopkg.in/ini.v1"

"github.com/go-macaron/inject"
)

const _VERSION = "1.3.4.0805"

func Version() string {
return _VERSION
}

// Handler can be any callable function.
// Macaron attempts to inject services into the handler's argument list,
// and panics if an argument could not be fullfilled via dependency injection.
type Handler interface{}

// 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
}

// 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.
// inject.Injector methods can be invoked to map services on a global level.
type Macaron struct {
inject.Injector
befores []BeforeHandler
handlers []Handler
action Handler

hasURLPrefix bool
urlPrefix string // For suburl support.
*Router

logger *log.Logger
}

// NewWithLogger creates a bare bones Macaron instance.
// Use this method if you want to have full control over the middleware that is used.
// You can specify logger output writer with this function.
func NewWithLogger(out io.Writer) *Macaron {
m := &Macaron{
Injector: inject.New(),
action: func() {},
Router: NewRouter(),
logger: log.New(out, "[Macaron] ", 0),
}
m.Router.m = m
m.Map(m.logger)
m.Map(defaultReturnHandler())
m.NotFound(http.NotFound)
m.InternalServerError(func(rw http.ResponseWriter, err error) {
http.Error(rw, err.Error(), 500)
})
return m
}

// New creates a bare bones Macaron instance.
// Use this method if you want to have full control over the middleware that is used.
func New() *Macaron {
return NewWithLogger(os.Stdout)
}

// Classic creates a classic Macaron with some basic default middleware:
// macaron.Logger, macaron.Recovery and macaron.Static.
func Classic() *Macaron {
m := New()
m.Use(Logger())
m.Use(Recovery())
m.Use(Static("public"))
return m
}

// Handlers sets the entire middleware stack with the given Handlers.
// This will clear any current middleware handlers,
// and panics if any of the handlers is not a callable function
func (m *Macaron) Handlers(handlers ...Handler) {
m.handlers = make([]Handler, 0)
for _, handler := range handlers {
m.Use(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) {
handler = validateAndWrapHandler(handler)
m.action = handler
}

// BeforeHandler represents a handler executes at beginning of every request.
// Macaron stops future process when it returns true.
type BeforeHandler func(rw http.ResponseWriter, req *http.Request) bool

func (m *Macaron) Before(handler BeforeHandler) {
m.befores = append(m.befores, handler)
}

// Use adds a middleware Handler to the stack,
// 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) {
handler = validateAndWrapHandler(handler)
m.handlers = append(m.handlers, handler)
}

func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Context {
c := &Context{
Injector: inject.New(),
handlers: m.handlers,
action: m.action,
index: 0,
Router: m.Router,
Req: Request{req},
Resp: NewResponseWriter(req.Method, rw),
Render: &DummyRender{rw},
Data: make(map[string]interface{}),
}
c.SetParent(m)
c.Map(c)
c.MapTo(c.Resp, (*http.ResponseWriter)(nil))
c.Map(req)
return c
}

// ServeHTTP is the HTTP Entry point for a Macaron instance.
// Useful if you want to control your own HTTP server.
// Be aware that none of middleware will run without registering any router.
func (m *Macaron) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if m.hasURLPrefix {
req.URL.Path = strings.TrimPrefix(req.URL.Path, m.urlPrefix)
}
for _, h := range m.befores {
if h(rw, req) {
return
}
}
m.Router.ServeHTTP(rw, req)
}

func GetDefaultListenInfo() (string, int) {
host := os.Getenv("HOST")
if len(host) == 0 {
host = "0.0.0.0"
}
port := com.StrTo(os.Getenv("PORT")).MustInt()
if port == 0 {
port = 4000
}
return host, port
}

// Run the http server. Listening on os.GetEnv("PORT") or 4000 by default.
func (m *Macaron) Run(args ...interface{}) {
host, port := GetDefaultListenInfo()
if len(args) == 1 {
switch arg := args[0].(type) {
case string:
host = arg
case int:
port = arg
}
} else if len(args) >= 2 {
if arg, ok := args[0].(string); ok {
host = arg
}
if arg, ok := args[1].(int); ok {
port = arg
}
}

addr := host + ":" + com.ToStr(port)
logger := m.GetVal(reflect.TypeOf(m.logger)).Interface().(*log.Logger)
logger.Printf("listening on %s (%s)\n", addr, safeEnv())
logger.Fatalln(http.ListenAndServe(addr, m))
}

// SetURLPrefix sets URL prefix of router layer, so that it support suburl.
func (m *Macaron) SetURLPrefix(prefix string) {
m.urlPrefix = prefix
m.hasURLPrefix = len(m.urlPrefix) > 0
}

// ____ ____ .__ ___. .__
// \ \ / /____ _______|__|____ \_ |__ | | ____ ______
// \ Y /\__ \\_ __ \ \__ \ | __ \| | _/ __ \ / ___/
// \ / / __ \| | \/ |/ __ \| \_\ \ |_\ ___/ \___ \
// \___/ (____ /__| |__(____ /___ /____/\___ >____ >
// \/ \/ \/ \/ \/

const (
DEV = "development"
PROD = "production"
TEST = "test"
)

var (
// Env is the environment that Macaron is executing in.
// The MACARON_ENV is read on initialization to set this variable.
Env = DEV
envLock sync.Mutex

// Path of work directory.
Root string

// Flash applies to current request.
FlashNow bool

// Configuration convention object.
cfg *ini.File
)

func setENV(e string) {
envLock.Lock()
defer envLock.Unlock()

if len(e) > 0 {
Env = e
}
}

func safeEnv() string {
envLock.Lock()
defer envLock.Unlock()

return Env
}

func init() {
setENV(os.Getenv("MACARON_ENV"))

var err error
Root, err = os.Getwd()
if err != nil {
panic("error getting work directory: " + err.Error())
}
}

// SetConfig sets data sources for configuration.
func SetConfig(source interface{}, others ...interface{}) (_ *ini.File, err error) {
cfg, err = ini.Load(source, others...)
return Config(), err
}

// Config returns configuration convention object.
// It returns an empty object if there is no one available.
func Config() *ini.File {
if cfg == nil {
return ini.Empty()
}
return cfg
}

BIN
vendor/gopkg.in/macaron.v1/macaronlogo.png View File

Before After
Width: 300  |  Height: 300  |  Size: 89 kB

+ 163
- 0
vendor/gopkg.in/macaron.v1/recovery.go View File

@@ -0,0 +1,163 @@
// Copyright 2013 Martini Authors
// 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. 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 (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"runtime"

"github.com/go-macaron/inject"
)

const (
panicHtml = `<html>
<head><title>PANIC: %s</title>
<meta charset="utf-8" />
<style type="text/css">
html, body {
font-family: "Roboto", sans-serif;
color: #333333;
background-color: #ea5343;
margin: 0px;
}
h1 {
color: #d04526;
background-color: #ffffff;
padding: 20px;
border-bottom: 1px dashed #2b3848;
}
pre {
margin: 20px;
padding: 20px;
border: 2px solid #2b3848;
background-color: #ffffff;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
</style>
</head><body>
<h1>PANIC</h1>
<pre style="font-weight: bold;">%s</pre>
<pre>%s</pre>
</body>
</html>`
)

var (
dunno = []byte("???")
centerDot = []byte("·")
dot = []byte(".")
slash = []byte("/")
)

// stack returns a nicely formated stack frame, skipping skip frames
func stack(skip int) []byte {
buf := new(bytes.Buffer) // the returned data
// As we loop, we open files and read them. These variables record the currently
// loaded file.
var lines [][]byte
var lastFile string
for i := skip; ; i++ { // Skip the expected number of frames
pc, file, line, ok := runtime.Caller(i)
if !ok {
break
}
// Print this much at least. If we can't find the source, it won't show.
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
if file != lastFile {
data, err := ioutil.ReadFile(file)
if err != nil {
continue
}
lines = bytes.Split(data, []byte{'\n'})
lastFile = file
}
fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
}
return buf.Bytes()
}

// source returns a space-trimmed slice of the n'th line.
func source(lines [][]byte, n int) []byte {
n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
if n < 0 || n >= len(lines) {
return dunno
}
return bytes.TrimSpace(lines[n])
}

// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
fn := runtime.FuncForPC(pc)
if fn == nil {
return dunno
}
name := []byte(fn.Name())
// The name includes the path name to the package, which is unnecessary
// since the file name is already included. Plus, it has center dots.
// That is, we see
// runtime/debug.*T·ptrmethod
// and want
// *T.ptrmethod
// Also the package path might contains dot (e.g. code.google.com/...),
// so first eliminate the path prefix
if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
name = name[lastslash+1:]
}
if period := bytes.Index(name, dot); period >= 0 {
name = name[period+1:]
}
name = bytes.Replace(name, centerDot, dot, -1)
return name
}

// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.
// While Martini is in development mode, Recovery will also output the panic as HTML.
func Recovery() Handler {
return func(c *Context, log *log.Logger) {
defer func() {
if err := recover(); err != nil {
stack := stack(3)
log.Printf("PANIC: %s\n%s", err, stack)

// Lookup the current responsewriter
val := c.GetVal(inject.InterfaceOf((*http.ResponseWriter)(nil)))
res := val.Interface().(http.ResponseWriter)

// respond with panic message while in development mode
var body []byte
if Env == DEV {
res.Header().Set("Content-Type", "text/html")
body = []byte(fmt.Sprintf(panicHtml, err, err, stack))
}

res.WriteHeader(http.StatusInternalServerError)
if nil != body {
_, _ = res.Write(body)
}
}
}()

c.Next()
}
}

+ 724
- 0
vendor/gopkg.in/macaron.v1/render.go View File

@@ -0,0 +1,724 @@
// Copyright 2013 Martini Authors
// 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. 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 (
"bytes"
"encoding/json"
"encoding/xml"
"fmt"
"html/template"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"sync"
"time"

"github.com/unknwon/com"
)

const (
_CONTENT_TYPE = "Content-Type"
_CONTENT_BINARY = "application/octet-stream"
_CONTENT_JSON = "application/json"
_CONTENT_HTML = "text/html"
_CONTENT_PLAIN = "text/plain"
_CONTENT_XHTML = "application/xhtml+xml"
_CONTENT_XML = "text/xml"
_DEFAULT_CHARSET = "UTF-8"
)

var (
// Provides a temporary buffer to execute templates into and catch errors.
bufpool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) },
}

// Included helper functions for use when rendering html
helperFuncs = template.FuncMap{
"yield": func() (string, error) {
return "", fmt.Errorf("yield called with no layout defined")
},
"current": func() (string, error) {
return "", nil
},
}
)

type (
// TemplateFile represents a interface of template file that has name and can be read.
TemplateFile interface {
Name() string
Data() []byte
Ext() string
}
// TemplateFileSystem represents a interface of template file system that able to list all files.
TemplateFileSystem interface {
ListFiles() []TemplateFile
Get(string) (io.Reader, error)
}

// Delims represents a set of Left and Right delimiters for HTML template rendering
Delims struct {
// Left delimiter, defaults to {{
Left string
// Right delimiter, defaults to }}
Right string
}

// RenderOptions represents a struct for specifying configuration options for the Render middleware.
RenderOptions struct {
// Directory to load templates. Default is "templates".
Directory string
// Addtional directories to overwite templates.
AppendDirectories []string
// Layout template name. Will not render a layout if "". Default is to "".
Layout string
// Extensions to parse template files from. Defaults are [".tmpl", ".html"].
Extensions []string
// Funcs is a slice of FuncMaps to apply to the template upon compilation. This is useful for helper functions. Default is [].
Funcs []template.FuncMap
// Delims sets the action delimiters to the specified strings in the Delims struct.
Delims Delims
// Appends the given charset to the Content-Type header. Default is "UTF-8".
Charset string
// Outputs human readable JSON.
IndentJSON bool
// Outputs human readable XML.
IndentXML bool
// Prefixes the JSON output with the given bytes.
PrefixJSON []byte
// Prefixes the XML output with the given bytes.
PrefixXML []byte
// Allows changing of output to XHTML instead of HTML. Default is "text/html"
HTMLContentType string
// TemplateFileSystem is the interface for supporting any implmentation of template file system.
TemplateFileSystem
}

// HTMLOptions is a struct for overriding some rendering Options for specific HTML call
HTMLOptions struct {
// Layout template name. Overrides Options.Layout.
Layout string
}

Render interface {
http.ResponseWriter
SetResponseWriter(http.ResponseWriter)

JSON(int, interface{})
JSONString(interface{}) (string, error)
RawData(int, []byte) // Serve content as binary
PlainText(int, []byte) // Serve content as plain text
HTML(int, string, interface{}, ...HTMLOptions)
HTMLSet(int, string, string, interface{}, ...HTMLOptions)
HTMLSetString(string, string, interface{}, ...HTMLOptions) (string, error)
HTMLString(string, interface{}, ...HTMLOptions) (string, error)
HTMLSetBytes(string, string, interface{}, ...HTMLOptions) ([]byte, error)
HTMLBytes(string, interface{}, ...HTMLOptions) ([]byte, error)
XML(int, interface{})
Error(int, ...string)
Status(int)
SetTemplatePath(string, string)
HasTemplateSet(string) bool
}
)

// TplFile implements TemplateFile interface.
type TplFile struct {
name string
data []byte
ext string
}

// NewTplFile cerates new template file with given name and data.
func NewTplFile(name string, data []byte, ext string) *TplFile {
return &TplFile{name, data, ext}
}

func (f *TplFile) Name() string {
return f.name
}

func (f *TplFile) Data() []byte {
return f.data
}

func (f *TplFile) Ext() string {
return f.ext
}

// TplFileSystem implements TemplateFileSystem interface.
type TplFileSystem struct {
files []TemplateFile
}

// NewTemplateFileSystem creates new template file system with given options.
func NewTemplateFileSystem(opt RenderOptions, omitData bool) TplFileSystem {
fs := TplFileSystem{}
fs.files = make([]TemplateFile, 0, 10)

// Directories are composed in reverse order because later one overwrites previous ones,
// so once found, we can directly jump out of the loop.
dirs := make([]string, 0, len(opt.AppendDirectories)+1)
for i := len(opt.AppendDirectories) - 1; i >= 0; i-- {
dirs = append(dirs, opt.AppendDirectories[i])
}
dirs = append(dirs, opt.Directory)

var err error
for i := range dirs {
// Skip ones that does not exists for symlink test,
// but allow non-symlink ones added after start.
if !com.IsExist(dirs[i]) {
continue
}

dirs[i], err = filepath.EvalSymlinks(dirs[i])
if err != nil {
panic("EvalSymlinks(" + dirs[i] + "): " + err.Error())
}
}
lastDir := dirs[len(dirs)-1]

// We still walk the last (original) directory because it's non-sense we load templates not exist in original directory.
if err = filepath.Walk(lastDir, func(path string, info os.FileInfo, _ error) error {
r, err := filepath.Rel(lastDir, path)
if err != nil {
return err
}

ext := GetExt(r)

for _, extension := range opt.Extensions {
if ext != extension {
continue
}

var data []byte
if !omitData {
// Loop over candidates of directory, break out once found.
// The file always exists because it's inside the walk function,
// and read original file is the worst case.
for i := range dirs {
path = filepath.Join(dirs[i], r)
if !com.IsFile(path) {
continue
}

data, err = ioutil.ReadFile(path)
if err != nil {
return err
}
break
}
}

name := filepath.ToSlash((r[0 : len(r)-len(ext)]))
fs.files = append(fs.files, NewTplFile(name, data, ext))
}

return nil
}); err != nil {
panic("NewTemplateFileSystem: " + err.Error())
}

return fs
}

func (fs TplFileSystem) ListFiles() []TemplateFile {
return fs.files
}

func (fs TplFileSystem) Get(name string) (io.Reader, error) {
for i := range fs.files {
if fs.files[i].Name()+fs.files[i].Ext() == name {
return bytes.NewReader(fs.files[i].Data()), nil
}
}
return nil, fmt.Errorf("file '%s' not found", name)
}

func PrepareCharset(charset string) string {
if len(charset) != 0 {
return "; charset=" + charset
}

return "; charset=" + _DEFAULT_CHARSET
}

func GetExt(s string) string {
index := strings.Index(s, ".")
if index == -1 {
return ""
}
return s[index:]
}

func compile(opt RenderOptions) *template.Template {
t := template.New(opt.Directory)
t.Delims(opt.Delims.Left, opt.Delims.Right)
// Parse an initial template in case we don't have any.
template.Must(t.Parse("Macaron"))

if opt.TemplateFileSystem == nil {
opt.TemplateFileSystem = NewTemplateFileSystem(opt, false)
}

for _, f := range opt.TemplateFileSystem.ListFiles() {
tmpl := t.New(f.Name())
for _, funcs := range opt.Funcs {
tmpl.Funcs(funcs)
}
// Bomb out if parse fails. We don't want any silent server starts.
template.Must(tmpl.Funcs(helperFuncs).Parse(string(f.Data())))
}

return t
}

const (
DEFAULT_TPL_SET_NAME = "DEFAULT"
)

// TemplateSet represents a template set of type *template.Template.
type TemplateSet struct {
lock sync.RWMutex
sets map[string]*template.Template
dirs map[string]string
}

// NewTemplateSet initializes a new empty template set.
func NewTemplateSet() *TemplateSet {
return &TemplateSet{
sets: make(map[string]*template.Template),
dirs: make(map[string]string),
}
}

func (ts *TemplateSet) Set(name string, opt *RenderOptions) *template.Template {
t := compile(*opt)

ts.lock.Lock()
defer ts.lock.Unlock()

ts.sets[name] = t
ts.dirs[name] = opt.Directory
return t
}

func (ts *TemplateSet) Get(name string) *template.Template {
ts.lock.RLock()
defer ts.lock.RUnlock()

return ts.sets[name]
}

func (ts *TemplateSet) GetDir(name string) string {
ts.lock.RLock()
defer ts.lock.RUnlock()

return ts.dirs[name]
}

func prepareRenderOptions(options []RenderOptions) RenderOptions {
var opt RenderOptions
if len(options) > 0 {
opt = options[0]
}

// Defaults.
if len(opt.Directory) == 0 {
opt.Directory = "templates"
}
if len(opt.Extensions) == 0 {
opt.Extensions = []string{".tmpl", ".html"}
}
if len(opt.HTMLContentType) == 0 {
opt.HTMLContentType = _CONTENT_HTML
}

return opt
}

func ParseTplSet(tplSet string) (tplName string, tplDir string) {
tplSet = strings.TrimSpace(tplSet)
if len(tplSet) == 0 {
panic("empty template set argument")
}
infos := strings.Split(tplSet, ":")
if len(infos) == 1 {
tplDir = infos[0]
tplName = path.Base(tplDir)
} else {
tplName = infos[0]
tplDir = infos[1]
}

if !com.IsDir(tplDir) {
panic("template set path does not exist or is not a directory")
}
return tplName, tplDir
}

func renderHandler(opt RenderOptions, tplSets []string) Handler {
cs := PrepareCharset(opt.Charset)
ts := NewTemplateSet()
ts.Set(DEFAULT_TPL_SET_NAME, &opt)

var tmpOpt RenderOptions
for _, tplSet := range tplSets {
tplName, tplDir := ParseTplSet(tplSet)
tmpOpt = opt
tmpOpt.Directory = tplDir
ts.Set(tplName, &tmpOpt)
}

return func(ctx *Context) {
r := &TplRender{
ResponseWriter: ctx.Resp,
TemplateSet: ts,
Opt: &opt,
CompiledCharset: cs,
}
ctx.Data["TmplLoadTimes"] = func() string {
if r.startTime.IsZero() {
return ""
}
return fmt.Sprint(time.Since(r.startTime).Nanoseconds()/1e6) + "ms"
}

ctx.Render = r
ctx.MapTo(r, (*Render)(nil))
}
}

// Renderer is a Middleware that maps a macaron.Render service into the Macaron handler chain.
// An single variadic macaron.RenderOptions struct can be optionally provided to configure
// HTML rendering. The default directory for templates is "templates" and the default
// file extension is ".tmpl" and ".html".
//
// If MACARON_ENV is set to "" or "development" then templates will be recompiled on every request. For more performance, set the
// MACARON_ENV environment variable to "production".
func Renderer(options ...RenderOptions) Handler {
return renderHandler(prepareRenderOptions(options), []string{})
}

func Renderers(options RenderOptions, tplSets ...string) Handler {
return renderHandler(prepareRenderOptions([]RenderOptions{options}), tplSets)
}

type TplRender struct {
http.ResponseWriter
*TemplateSet
Opt *RenderOptions
CompiledCharset string

startTime time.Time
}

func (r *TplRender) SetResponseWriter(rw http.ResponseWriter) {
r.ResponseWriter = rw
}

func (r *TplRender) JSON(status int, v interface{}) {
var (
result []byte
err error
)
if r.Opt.IndentJSON {
result, err = json.MarshalIndent(v, "", " ")
} else {
result, err = json.Marshal(v)
}
if err != nil {
http.Error(r, err.Error(), 500)
return
}

// json rendered fine, write out the result
r.Header().Set(_CONTENT_TYPE, _CONTENT_JSON+r.CompiledCharset)
r.WriteHeader(status)
if len(r.Opt.PrefixJSON) > 0 {
_, _ = r.Write(r.Opt.PrefixJSON)
}
_, _ = r.Write(result)
}

func (r *TplRender) JSONString(v interface{}) (string, error) {
var result []byte
var err error
if r.Opt.IndentJSON {
result, err = json.MarshalIndent(v, "", " ")
} else {
result, err = json.Marshal(v)
}
if err != nil {
return "", err
}
return string(result), nil
}

func (r *TplRender) XML(status int, v interface{}) {
var result []byte
var err error
if r.Opt.IndentXML {
result, err = xml.MarshalIndent(v, "", " ")
} else {
result, err = xml.Marshal(v)
}
if err != nil {
http.Error(r, err.Error(), 500)
return
}

// XML rendered fine, write out the result
r.Header().Set(_CONTENT_TYPE, _CONTENT_XML+r.CompiledCharset)
r.WriteHeader(status)
if len(r.Opt.PrefixXML) > 0 {
_, _ = r.Write(r.Opt.PrefixXML)
}
_, _ = r.Write(result)
}

func (r *TplRender) data(status int, contentType string, v []byte) {
if r.Header().Get(_CONTENT_TYPE) == "" {
r.Header().Set(_CONTENT_TYPE, contentType)
}
r.WriteHeader(status)
_, _ = r.Write(v)
}

func (r *TplRender) RawData(status int, v []byte) {
r.data(status, _CONTENT_BINARY, v)
}

func (r *TplRender) PlainText(status int, v []byte) {
r.data(status, _CONTENT_PLAIN, v)
}

func (r *TplRender) execute(t *template.Template, name string, data interface{}) (*bytes.Buffer, error) {
buf := bufpool.Get().(*bytes.Buffer)
return buf, t.ExecuteTemplate(buf, name, data)
}

func (r *TplRender) addYield(t *template.Template, tplName string, data interface{}) {
funcs := template.FuncMap{
"yield": func() (template.HTML, error) {
buf, err := r.execute(t, tplName, data)
// return safe html here since we are rendering our own template
return template.HTML(buf.String()), err
},
"current": func() (string, error) {
return tplName, nil
},
}
t.Funcs(funcs)
}

func (r *TplRender) renderBytes(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) (*bytes.Buffer, error) {
t := r.TemplateSet.Get(setName)
if Env == DEV {
opt := *r.Opt
opt.Directory = r.TemplateSet.GetDir(setName)
t = r.TemplateSet.Set(setName, &opt)
}
if t == nil {
return nil, fmt.Errorf("html/template: template \"%s\" is undefined", tplName)
}

opt := r.prepareHTMLOptions(htmlOpt)

if len(opt.Layout) > 0 {
r.addYield(t, tplName, data)
tplName = opt.Layout
}

out, err := r.execute(t, tplName, data)
if err != nil {
return nil, err
}

return out, nil
}

func (r *TplRender) renderHTML(status int, setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) {
r.startTime = time.Now()

out, err := r.renderBytes(setName, tplName, data, htmlOpt...)
if err != nil {
http.Error(r, err.Error(), http.StatusInternalServerError)
return
}

r.Header().Set(_CONTENT_TYPE, r.Opt.HTMLContentType+r.CompiledCharset)
r.WriteHeader(status)

if _, err := out.WriteTo(r); err != nil {
out.Reset()
}
bufpool.Put(out)
}

func (r *TplRender) HTML(status int, name string, data interface{}, htmlOpt ...HTMLOptions) {
r.renderHTML(status, DEFAULT_TPL_SET_NAME, name, data, htmlOpt...)
}

func (r *TplRender) HTMLSet(status int, setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) {
r.renderHTML(status, setName, tplName, data, htmlOpt...)
}

func (r *TplRender) HTMLSetBytes(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) ([]byte, error) {
out, err := r.renderBytes(setName, tplName, data, htmlOpt...)
if err != nil {
return []byte(""), err
}
return out.Bytes(), nil
}

func (r *TplRender) HTMLBytes(name string, data interface{}, htmlOpt ...HTMLOptions) ([]byte, error) {
return r.HTMLSetBytes(DEFAULT_TPL_SET_NAME, name, data, htmlOpt...)
}

func (r *TplRender) HTMLSetString(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) (string, error) {
p, err := r.HTMLSetBytes(setName, tplName, data, htmlOpt...)
return string(p), err
}

func (r *TplRender) HTMLString(name string, data interface{}, htmlOpt ...HTMLOptions) (string, error) {
p, err := r.HTMLBytes(name, data, htmlOpt...)
return string(p), err
}

// Error writes the given HTTP status to the current ResponseWriter
func (r *TplRender) Error(status int, message ...string) {
r.WriteHeader(status)
if len(message) > 0 {
_, _ = r.Write([]byte(message[0]))
}
}

func (r *TplRender) Status(status int) {
r.WriteHeader(status)
}

func (r *TplRender) prepareHTMLOptions(htmlOpt []HTMLOptions) HTMLOptions {
if len(htmlOpt) > 0 {
return htmlOpt[0]
}

return HTMLOptions{
Layout: r.Opt.Layout,
}
}

func (r *TplRender) SetTemplatePath(setName, dir string) {
if len(setName) == 0 {
setName = DEFAULT_TPL_SET_NAME
}
opt := *r.Opt
opt.Directory = dir
r.TemplateSet.Set(setName, &opt)
}

func (r *TplRender) HasTemplateSet(name string) bool {
return r.TemplateSet.Get(name) != nil
}

// DummyRender is used when user does not choose any real render to use.
// This way, we can print out friendly message which asks them to register one,
// instead of ugly and confusing 'nil pointer' panic.
type DummyRender struct {
http.ResponseWriter
}

func renderNotRegistered() {
panic("middleware render hasn't been registered")
}

func (r *DummyRender) SetResponseWriter(http.ResponseWriter) {
renderNotRegistered()
}

func (r *DummyRender) JSON(int, interface{}) {
renderNotRegistered()
}

func (r *DummyRender) JSONString(interface{}) (string, error) {
renderNotRegistered()
return "", nil
}

func (r *DummyRender) RawData(int, []byte) {
renderNotRegistered()
}

func (r *DummyRender) PlainText(int, []byte) {
renderNotRegistered()
}

func (r *DummyRender) HTML(int, string, interface{}, ...HTMLOptions) {
renderNotRegistered()
}

func (r *DummyRender) HTMLSet(int, string, string, interface{}, ...HTMLOptions) {
renderNotRegistered()
}

func (r *DummyRender) HTMLSetString(string, string, interface{}, ...HTMLOptions) (string, error) {
renderNotRegistered()
return "", nil
}

func (r *DummyRender) HTMLString(string, interface{}, ...HTMLOptions) (string, error) {
renderNotRegistered()
return "", nil
}

func (r *DummyRender) HTMLSetBytes(string, string, interface{}, ...HTMLOptions) ([]byte, error) {
renderNotRegistered()
return nil, nil
}

func (r *DummyRender) HTMLBytes(string, interface{}, ...HTMLOptions) ([]byte, error) {
renderNotRegistered()
return nil, nil
}

func (r *DummyRender) XML(int, interface{}) {
renderNotRegistered()
}

func (r *DummyRender) Error(int, ...string) {
renderNotRegistered()
}

func (r *DummyRender) Status(int) {
renderNotRegistered()
}

func (r *DummyRender) SetTemplatePath(string, string) {
renderNotRegistered()
}

func (r *DummyRender) HasTemplateSet(string) bool {
renderNotRegistered()
return false
}

+ 124
- 0
vendor/gopkg.in/macaron.v1/response_writer.go View File

@@ -0,0 +1,124 @@
// Copyright 2013 Martini 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 (
"bufio"
"errors"
"net"
"net/http"
)

// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
// if the functionality calls for it.
type ResponseWriter interface {
http.ResponseWriter
http.Flusher
http.Pusher
// Status returns the status code of the response or 0 if the response has not been written.
Status() int
// Written returns whether or not the ResponseWriter has been written.
Written() bool
// Size returns the size of the response body.
Size() int
// Before allows for a function to be called before the ResponseWriter has been written to. This is
// useful for setting headers or any other operations that must happen before a response has been written.
Before(BeforeFunc)
}

// BeforeFunc is a function that is called before the ResponseWriter has been written to.
type BeforeFunc func(ResponseWriter)

// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
func NewResponseWriter(method string, rw http.ResponseWriter) ResponseWriter {
return &responseWriter{method, rw, 0, 0, nil}
}

type responseWriter struct {
method string
http.ResponseWriter
status int
size int
beforeFuncs []BeforeFunc
}

func (rw *responseWriter) WriteHeader(s int) {
rw.callBefore()
rw.ResponseWriter.WriteHeader(s)
rw.status = s
}

func (rw *responseWriter) Write(b []byte) (size int, err error) {
if !rw.Written() {
// The status will be StatusOK if WriteHeader has not been called yet
rw.WriteHeader(http.StatusOK)
}
if rw.method != "HEAD" {
size, err = rw.ResponseWriter.Write(b)
rw.size += size
}
return size, err
}

func (rw *responseWriter) Status() int {
return rw.status
}

func (rw *responseWriter) Size() int {
return rw.size
}

func (rw *responseWriter) Written() bool {
return rw.status != 0
}

func (rw *responseWriter) Before(before BeforeFunc) {
rw.beforeFuncs = append(rw.beforeFuncs, before)
}

func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hijacker, ok := rw.ResponseWriter.(http.Hijacker)
if !ok {
return nil, nil, errors.New("the ResponseWriter doesn't support the Hijacker interface")
}
return hijacker.Hijack()
}

//nolint
func (rw *responseWriter) CloseNotify() <-chan bool {
return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
}

func (rw *responseWriter) callBefore() {
for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
rw.beforeFuncs[i](rw)
}
}

func (rw *responseWriter) Flush() {
flusher, ok := rw.ResponseWriter.(http.Flusher)
if ok {
flusher.Flush()
}
}

func (rw *responseWriter) Push(target string, opts *http.PushOptions) error {
pusher, ok := rw.ResponseWriter.(http.Pusher)
if !ok {
return errors.New("the ResponseWriter doesn't support the Pusher interface")
}
return pusher.Push(target, opts)
}

+ 76
- 0
vendor/gopkg.in/macaron.v1/return_handler.go View File

@@ -0,0 +1,76 @@
// Copyright 2013 Martini Authors
// 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. 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/http"
"reflect"

"github.com/go-macaron/inject"
)

// ReturnHandler is a service that Martini provides that is called
// when a route handler returns something. The ReturnHandler is
// responsible for writing to the ResponseWriter based on the values
// that are passed into this function.
type ReturnHandler func(*Context, []reflect.Value)

func canDeref(val reflect.Value) bool {
return val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr
}

func isError(val reflect.Value) bool {
_, ok := val.Interface().(error)
return ok
}

func isByteSlice(val reflect.Value) bool {
return val.Kind() == reflect.Slice && val.Type().Elem().Kind() == reflect.Uint8
}

func defaultReturnHandler() ReturnHandler {
return func(ctx *Context, vals []reflect.Value) {
rv := ctx.GetVal(inject.InterfaceOf((*http.ResponseWriter)(nil)))
resp := rv.Interface().(http.ResponseWriter)
var respVal reflect.Value
if len(vals) > 1 && vals[0].Kind() == reflect.Int {
resp.WriteHeader(int(vals[0].Int()))
respVal = vals[1]
} else if len(vals) > 0 {
respVal = vals[0]

if isError(respVal) {
err := respVal.Interface().(error)
if err != nil {
ctx.internalServerError(ctx, err)
}
return
} else if canDeref(respVal) {
if respVal.IsNil() {
return // Ignore nil error
}
}
}
if canDeref(respVal) {
respVal = respVal.Elem()
}
if isByteSlice(respVal) {
_, _ = resp.Write(respVal.Bytes())
} else {
_, _ = resp.Write([]byte(respVal.String()))
}
}
}

+ 380
- 0
vendor/gopkg.in/macaron.v1/router.go View File

@@ -0,0 +1,380 @@
// 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. 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/http"
"strings"
"sync"
)

var (
// Known HTTP methods.
_HTTP_METHODS = map[string]bool{
"GET": true,
"POST": true,
"PUT": true,
"DELETE": true,
"PATCH": true,
"OPTIONS": true,
"HEAD": true,
}
)

// routeMap represents a thread-safe map for route tree.
type routeMap struct {
lock sync.RWMutex
routes map[string]map[string]*Leaf
}

// NewRouteMap initializes and returns a new routeMap.
func NewRouteMap() *routeMap {
rm := &routeMap{
routes: make(map[string]map[string]*Leaf),
}
for m := range _HTTP_METHODS {
rm.routes[m] = make(map[string]*Leaf)
}
return rm
}

// getLeaf returns Leaf object if a route has been registered.
func (rm *routeMap) getLeaf(method, pattern string) *Leaf {
rm.lock.RLock()
defer rm.lock.RUnlock()

return rm.routes[method][pattern]
}

// add adds new route to route tree map.
func (rm *routeMap) add(method, pattern string, leaf *Leaf) {
rm.lock.Lock()
defer rm.lock.Unlock()

rm.routes[method][pattern] = leaf
}

type group struct {
pattern string
handlers []Handler
}

// Router represents a Macaron router layer.
type Router struct {
m *Macaron
autoHead bool
routers map[string]*Tree
*routeMap
namedRoutes map[string]*Leaf

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 {
return &Router{
routers: make(map[string]*Tree),
routeMap: NewRouteMap(),
namedRoutes: make(map[string]*Leaf),
}
}

// SetAutoHead sets the value who determines whether add HEAD method automatically
// when GET method is added.
func (r *Router) SetAutoHead(v bool) {
r.autoHead = v
}

type Params map[string]string

// Handle is a function that can be registered to a route to handle HTTP requests.
// Like http.HandlerFunc, but has a third parameter for the values of wildcards (variables).
type Handle func(http.ResponseWriter, *http.Request, Params)

// Route represents a wrapper of leaf route and upper level router.
type Route struct {
router *Router
leaf *Leaf
}

// Name sets name of route.
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: " + name)
}
r.router.namedRoutes[name] = r.leaf
}

// handle adds new route to the router tree.
func (r *Router) handle(method, pattern string, handle Handle) *Route {
method = strings.ToUpper(method)

var leaf *Leaf
// Prevent duplicate routes.
if leaf = r.getLeaf(method, pattern); leaf != nil {
return &Route{r, leaf}
}

// Validate HTTP methods.
if !_HTTP_METHODS[method] && method != "*" {
panic("unknown HTTP method: " + method)
}

// Generate methods need register.
methods := make(map[string]bool)
if method == "*" {
for m := range _HTTP_METHODS {
methods[m] = true
}
} else {
methods[method] = true
}

// Add to router tree.
for m := range methods {
if t, ok := r.routers[m]; ok {
leaf = t.Add(pattern, handle)
} else {
t := NewTree()
leaf = t.Add(pattern, handle)
r.routers[m] = t
}
r.add(m, pattern, leaf)
}
return &Route{r, leaf}
}

// Handle registers a new request handle with the given pattern, method and handlers.
func (r *Router) Handle(method string, pattern string, handlers []Handler) *Route {
if len(r.groups) > 0 {
groupPattern := ""
h := make([]Handler, 0)
for _, g := range r.groups {
groupPattern += g.pattern
h = append(h, g.handlers...)
}

pattern = groupPattern + pattern
h = append(h, handlers...)
handlers = h
}
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)
c.params = params
c.handlers = make([]Handler, 0, len(r.m.handlers)+len(handlers))
c.handlers = append(c.handlers, r.m.handlers...)
c.handlers = append(c.handlers, handlers...)
c.run()
})
}

func (r *Router) Group(pattern string, fn func(), h ...Handler) {
r.groups = append(r.groups, group{pattern, h})
fn()
r.groups = r.groups[:len(r.groups)-1]
}

// Get is a shortcut for r.Handle("GET", pattern, handlers)
func (r *Router) Get(pattern string, h ...Handler) (leaf *Route) {
leaf = r.Handle("GET", pattern, h)
if r.autoHead {
r.Head(pattern, h...)
}
return leaf
}

// Patch is a shortcut for r.Handle("PATCH", pattern, handlers)
func (r *Router) Patch(pattern string, h ...Handler) *Route {
return r.Handle("PATCH", pattern, h)
}

// Post is a shortcut for r.Handle("POST", pattern, handlers)
func (r *Router) Post(pattern string, h ...Handler) *Route {
return r.Handle("POST", pattern, h)
}

// Put is a shortcut for r.Handle("PUT", pattern, handlers)
func (r *Router) Put(pattern string, h ...Handler) *Route {
return r.Handle("PUT", pattern, h)
}

// Delete is a shortcut for r.Handle("DELETE", pattern, handlers)
func (r *Router) Delete(pattern string, h ...Handler) *Route {
return r.Handle("DELETE", pattern, h)
}

// Options is a shortcut for r.Handle("OPTIONS", pattern, handlers)
func (r *Router) Options(pattern string, h ...Handler) *Route {
return r.Handle("OPTIONS", pattern, h)
}

// Head is a shortcut for r.Handle("HEAD", pattern, handlers)
func (r *Router) Head(pattern string, h ...Handler) *Route {
return r.Handle("HEAD", pattern, h)
}

// Any is a shortcut for r.Handle("*", pattern, handlers)
func (r *Router) Any(pattern string, h ...Handler) *Route {
return r.Handle("*", pattern, h)
}

// Route is a shortcut for same handlers but different HTTP methods.
//
// Example:
// m.Route("/", "GET,POST", h)
func (r *Router) Route(pattern, methods string, h ...Handler) (route *Route) {
for _, m := range strings.Split(methods, ",") {
route = r.Handle(strings.TrimSpace(m), pattern, h)
}
return route
}

// Combo returns a combo router.
func (r *Router) Combo(pattern string, h ...Handler) *ComboRouter {
return &ComboRouter{r, pattern, h, map[string]bool{}, nil}
}

// 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) {
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))
c.handlers = append(c.handlers, r.m.handlers...)
c.handlers = append(c.handlers, handlers...)
c.run()
}
}

// 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) {
handlers = validateAndWrapHandlers(handlers)
r.internalServerError = func(c *Context, err error) {
c.index = 0
c.handlers = handlers
c.Map(err)
c.run()
}
}

// 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 {
// 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.
}
h(rw, req, p)
return
}
}

r.notFound(rw, req)
}

// URLFor builds path part of URL by given pair values.
func (r *Router) URLFor(name string, pairs ...string) string {
leaf, ok := r.namedRoutes[name]
if !ok {
panic("route with given name does not exists: " + name)
}
return leaf.URLPath(pairs...)
}

// ComboRouter represents a combo router.
type ComboRouter struct {
router *Router
pattern string
handlers []Handler
methods map[string]bool // Registered methods.

lastRoute *Route
}

func (cr *ComboRouter) checkMethod(name string) {
if cr.methods[name] {
panic("method '" + name + "' has already been registered")
}
cr.methods[name] = true
}

func (cr *ComboRouter) route(fn func(string, ...Handler) *Route, method string, h ...Handler) *ComboRouter {
cr.checkMethod(method)
cr.lastRoute = fn(cr.pattern, append(cr.handlers, h...)...)
return cr
}

func (cr *ComboRouter) Get(h ...Handler) *ComboRouter {
if cr.router.autoHead {
cr.Head(h...)
}
return cr.route(cr.router.Get, "GET", h...)
}

func (cr *ComboRouter) Patch(h ...Handler) *ComboRouter {
return cr.route(cr.router.Patch, "PATCH", h...)
}

func (cr *ComboRouter) Post(h ...Handler) *ComboRouter {
return cr.route(cr.router.Post, "POST", h...)
}

func (cr *ComboRouter) Put(h ...Handler) *ComboRouter {
return cr.route(cr.router.Put, "PUT", h...)
}

func (cr *ComboRouter) Delete(h ...Handler) *ComboRouter {
return cr.route(cr.router.Delete, "DELETE", h...)
}

func (cr *ComboRouter) Options(h ...Handler) *ComboRouter {
return cr.route(cr.router.Options, "OPTIONS", h...)
}

func (cr *ComboRouter) Head(h ...Handler) *ComboRouter {
return cr.route(cr.router.Head, "HEAD", h...)
}

// Name sets name of ComboRouter route.
func (cr *ComboRouter) Name(name string) {
if cr.lastRoute == nil {
panic("no corresponding route to be named")
}
cr.lastRoute.Name(name)
}

+ 230
- 0
vendor/gopkg.in/macaron.v1/static.go View File

@@ -0,0 +1,230 @@
// Copyright 2013 Martini Authors
// 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. 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 (
"encoding/base64"
"log"
"net/http"
"path"
"path/filepath"
"strings"
"sync"
)

// StaticOptions is a struct for specifying configuration options for the macaron.Static middleware.
type StaticOptions struct {
// Prefix is the optional prefix used to serve the static directory content
Prefix string
// SkipLogging will disable [Static] log messages when a static file is served.
SkipLogging bool
// IndexFile defines which file to serve as index if it exists.
IndexFile string
// Expires defines which user-defined function to use for producing a HTTP Expires Header
// https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
Expires func() string
// ETag defines if we should add an ETag header
// https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#validating-cached-responses-with-etags
ETag bool
// FileSystem is the interface for supporting any implmentation of file system.
FileSystem http.FileSystem
}

// FIXME: to be deleted.
type staticMap struct {
lock sync.RWMutex
data map[string]*http.Dir
}

func (sm *staticMap) Set(dir *http.Dir) {
sm.lock.Lock()
defer sm.lock.Unlock()

sm.data[string(*dir)] = dir
}

func (sm *staticMap) Get(name string) *http.Dir {
sm.lock.RLock()
defer sm.lock.RUnlock()

return sm.data[name]
}

func (sm *staticMap) Delete(name string) {
sm.lock.Lock()
defer sm.lock.Unlock()

delete(sm.data, name)
}

var statics = staticMap{sync.RWMutex{}, map[string]*http.Dir{}}

// staticFileSystem implements http.FileSystem interface.
type staticFileSystem struct {
dir *http.Dir
}

func newStaticFileSystem(directory string) staticFileSystem {
if !filepath.IsAbs(directory) {
directory = filepath.Join(Root, directory)
}
dir := http.Dir(directory)
statics.Set(&dir)
return staticFileSystem{&dir}
}

func (fs staticFileSystem) Open(name string) (http.File, error) {
return fs.dir.Open(name)
}

func prepareStaticOption(dir string, opt StaticOptions) StaticOptions {
// Defaults
if len(opt.IndexFile) == 0 {
opt.IndexFile = "index.html"
}
// Normalize the prefix if provided
if opt.Prefix != "" {
// Ensure we have a leading '/'
if opt.Prefix[0] != '/' {
opt.Prefix = "/" + opt.Prefix
}
// Remove any trailing '/'
opt.Prefix = strings.TrimRight(opt.Prefix, "/")
}
if opt.FileSystem == nil {
opt.FileSystem = newStaticFileSystem(dir)
}
return opt
}

func prepareStaticOptions(dir string, options []StaticOptions) StaticOptions {
var opt StaticOptions
if len(options) > 0 {
opt = options[0]
}
return prepareStaticOption(dir, opt)
}

func staticHandler(ctx *Context, log *log.Logger, opt StaticOptions) bool {
if ctx.Req.Method != "GET" && ctx.Req.Method != "HEAD" {
return false
}

file := ctx.Req.URL.Path
// if we have a prefix, filter requests by stripping the prefix
if opt.Prefix != "" {
if !strings.HasPrefix(file, opt.Prefix) {
return false
}
file = file[len(opt.Prefix):]
if file != "" && file[0] != '/' {
return false
}
}

f, err := opt.FileSystem.Open(file)
if err != nil {
return false
}
defer f.Close()

fi, err := f.Stat()
if err != nil {
return true // File exists but fail to open.
}

// Try to serve index file
if fi.IsDir() {
redirPath := path.Clean(ctx.Req.URL.Path)
// path.Clean removes the trailing slash, so we need to add it back when
// the original path has it.
if strings.HasSuffix(ctx.Req.URL.Path, "/") {
redirPath = redirPath + "/"
}
// Redirect if missing trailing slash.
if !strings.HasSuffix(redirPath, "/") {
http.Redirect(ctx.Resp, ctx.Req.Request, redirPath+"/", http.StatusFound)
return true
}

file = path.Join(file, opt.IndexFile)
f, err = opt.FileSystem.Open(file)
if err != nil {
return false // Discard error.
}
defer f.Close()

fi, err = f.Stat()
if err != nil || fi.IsDir() {
return true
}
}

if !opt.SkipLogging {
log.Println("[Static] Serving " + file)
}

// Add an Expires header to the static content
if opt.Expires != nil {
ctx.Resp.Header().Set("Expires", opt.Expires())
}

if opt.ETag {
tag := `"` + GenerateETag(string(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat)) + `"`
ctx.Resp.Header().Set("ETag", tag)
if ctx.Req.Header.Get("If-None-Match") == tag {
ctx.Resp.WriteHeader(http.StatusNotModified)
return true
}
}

http.ServeContent(ctx.Resp, ctx.Req.Request, file, fi.ModTime(), f)
return true
}

// GenerateETag generates an ETag based on size, filename and file modification time
func GenerateETag(fileSize, fileName, modTime string) string {
etag := fileSize + fileName + modTime
return base64.StdEncoding.EncodeToString([]byte(etag))
}

// Static returns a middleware handler that serves static files in the given directory.
func Static(directory string, staticOpt ...StaticOptions) Handler {
opt := prepareStaticOptions(directory, staticOpt)

return func(ctx *Context, log *log.Logger) {
staticHandler(ctx, log, opt)
}
}

// Statics registers multiple static middleware handlers all at once.
func Statics(opt StaticOptions, dirs ...string) Handler {
if len(dirs) == 0 {
panic("no static directory is given")
}
opts := make([]StaticOptions, len(dirs))
for i := range dirs {
opts[i] = prepareStaticOption(dirs[i], opt)
}

return func(ctx *Context, log *log.Logger) {
for i := range opts {
if staticHandler(ctx, log, opts[i]) {
return
}
}
}
}

+ 390
- 0
vendor/gopkg.in/macaron.v1/tree.go View File

@@ -0,0 +1,390 @@
// Copyright 2015 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 (
"regexp"
"strings"

"github.com/unknwon/com"
)

type patternType int8

const (
_PATTERN_STATIC patternType = iota // /home
_PATTERN_REGEXP // /:id([0-9]+)
_PATTERN_PATH_EXT // /*.*
_PATTERN_HOLDER // /:user
_PATTERN_MATCH_ALL // /*
)

// Leaf represents a leaf route information.
type Leaf struct {
parent *Tree

typ patternType
pattern string
rawPattern string // Contains wildcard instead of regexp
wildcards []string
reg *regexp.Regexp
optional bool

handle Handle
}

var wildcardPattern = regexp.MustCompile(`:[a-zA-Z0-9]+`)

func isSpecialRegexp(pattern, regStr string, pos []int) bool {
return len(pattern) >= pos[1]+len(regStr) && pattern[pos[1]:pos[1]+len(regStr)] == regStr
}

// getNextWildcard tries to find next wildcard and update pattern with corresponding regexp.
func getNextWildcard(pattern string) (wildcard, _ string) {
pos := wildcardPattern.FindStringIndex(pattern)
if pos == nil {
return "", pattern
}
wildcard = pattern[pos[0]:pos[1]]

// Reach last character or no regexp is given.
if len(pattern) == pos[1] {
return wildcard, strings.Replace(pattern, wildcard, `(.+)`, 1)
} else if pattern[pos[1]] != '(' {
switch {
case isSpecialRegexp(pattern, ":int", pos):
pattern = strings.Replace(pattern, ":int", "([0-9]+)", 1)
case isSpecialRegexp(pattern, ":string", pos):
pattern = strings.Replace(pattern, ":string", "([\\w]+)", 1)
default:
return wildcard, strings.Replace(pattern, wildcard, `(.+)`, 1)
}
}

// Cut out placeholder directly.
return wildcard, pattern[:pos[0]] + pattern[pos[1]:]
}

func getWildcards(pattern string) (string, []string) {
wildcards := make([]string, 0, 2)

// Keep getting next wildcard until nothing is left.
var wildcard string
for {
wildcard, pattern = getNextWildcard(pattern)
if len(wildcard) > 0 {
wildcards = append(wildcards, wildcard)
} else {
break
}
}

return pattern, wildcards
}

// getRawPattern removes all regexp but keeps wildcards for building URL path.
func getRawPattern(rawPattern string) string {
rawPattern = strings.Replace(rawPattern, ":int", "", -1)
rawPattern = strings.Replace(rawPattern, ":string", "", -1)

for {
startIdx := strings.Index(rawPattern, "(")
if startIdx == -1 {
break
}

closeIdx := strings.Index(rawPattern, ")")
if closeIdx > -1 {
rawPattern = rawPattern[:startIdx] + rawPattern[closeIdx+1:]
}
}
return rawPattern
}

func checkPattern(pattern string) (typ patternType, rawPattern string, wildcards []string, reg *regexp.Regexp) {
pattern = strings.TrimLeft(pattern, "?")
rawPattern = getRawPattern(pattern)

if pattern == "*" {
typ = _PATTERN_MATCH_ALL
} else if pattern == "*.*" {
typ = _PATTERN_PATH_EXT
} else if strings.Contains(pattern, ":") {
typ = _PATTERN_REGEXP
pattern, wildcards = getWildcards(pattern)
if pattern == "(.+)" {
typ = _PATTERN_HOLDER
} else {
reg = regexp.MustCompile(pattern)
}
}
return typ, rawPattern, wildcards, reg
}

func NewLeaf(parent *Tree, pattern string, handle Handle) *Leaf {
typ, rawPattern, wildcards, reg := checkPattern(pattern)
optional := false
if len(pattern) > 0 && pattern[0] == '?' {
optional = true
}
return &Leaf{parent, typ, pattern, rawPattern, wildcards, reg, optional, handle}
}

// URLPath build path part of URL by given pair values.
func (l *Leaf) URLPath(pairs ...string) string {
if len(pairs)%2 != 0 {
panic("number of pairs does not match")
}

urlPath := l.rawPattern
parent := l.parent
for parent != nil {
urlPath = parent.rawPattern + "/" + urlPath
parent = parent.parent
}
for i := 0; i < len(pairs); i += 2 {
if len(pairs[i]) == 0 {
panic("pair value cannot be empty: " + com.ToStr(i))
} else if pairs[i][0] != ':' && pairs[i] != "*" && pairs[i] != "*.*" {
pairs[i] = ":" + pairs[i]
}
urlPath = strings.Replace(urlPath, pairs[i], pairs[i+1], 1)
}
return urlPath
}

// Tree represents a router tree in Macaron.
type Tree struct {
parent *Tree

typ patternType
pattern string
rawPattern string
wildcards []string
reg *regexp.Regexp

subtrees []*Tree
leaves []*Leaf
}

func NewSubtree(parent *Tree, pattern string) *Tree {
typ, rawPattern, wildcards, reg := checkPattern(pattern)
return &Tree{parent, typ, pattern, rawPattern, wildcards, reg, make([]*Tree, 0, 5), make([]*Leaf, 0, 5)}
}

func NewTree() *Tree {
return NewSubtree(nil, "")
}

func (t *Tree) addLeaf(pattern string, handle Handle) *Leaf {
for i := 0; i < len(t.leaves); i++ {
if t.leaves[i].pattern == pattern {
return t.leaves[i]
}
}

leaf := NewLeaf(t, pattern, handle)

// Add exact same leaf to grandparent/parent level without optional.
if leaf.optional {
parent := leaf.parent
if parent.parent != nil {
parent.parent.addLeaf(parent.pattern, handle)
} else {
parent.addLeaf("", handle) // Root tree can add as empty pattern.
}
}

i := 0
for ; i < len(t.leaves); i++ {
if leaf.typ < t.leaves[i].typ {
break
}
}

if i == len(t.leaves) {
t.leaves = append(t.leaves, leaf)
} else {
t.leaves = append(t.leaves[:i], append([]*Leaf{leaf}, t.leaves[i:]...)...)
}
return leaf
}

func (t *Tree) addSubtree(segment, pattern string, handle Handle) *Leaf {
for i := 0; i < len(t.subtrees); i++ {
if t.subtrees[i].pattern == segment {
return t.subtrees[i].addNextSegment(pattern, handle)
}
}

subtree := NewSubtree(t, segment)
i := 0
for ; i < len(t.subtrees); i++ {
if subtree.typ < t.subtrees[i].typ {
break
}
}

if i == len(t.subtrees) {
t.subtrees = append(t.subtrees, subtree)
} else {
t.subtrees = append(t.subtrees[:i], append([]*Tree{subtree}, t.subtrees[i:]...)...)
}
return subtree.addNextSegment(pattern, handle)
}

func (t *Tree) addNextSegment(pattern string, handle Handle) *Leaf {
pattern = strings.TrimPrefix(pattern, "/")

i := strings.Index(pattern, "/")
if i == -1 {
return t.addLeaf(pattern, handle)
}
return t.addSubtree(pattern[:i], pattern[i+1:], handle)
}

func (t *Tree) Add(pattern string, handle Handle) *Leaf {
pattern = strings.TrimSuffix(pattern, "/")
return t.addNextSegment(pattern, handle)
}

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:
if t.leaves[i].pattern == url {
return t.leaves[i].handle, true
}
case _PATTERN_REGEXP:
results := t.leaves[i].reg.FindStringSubmatch(url)
// Number of results and wildcasrd should be exact same.
if len(results)-1 != len(t.leaves[i].wildcards) {
break
}

for j := 0; j < len(t.leaves[i].wildcards); j++ {
params[t.leaves[i].wildcards[j]] = results[j+1]
}
return t.leaves[i].handle, true
case _PATTERN_PATH_EXT:
j := strings.LastIndex(url, ".")
if j > -1 {
params[":path"] = url[:j]
params[":ext"] = url[j+1:]
} else {
params[":path"] = url
}
return t.leaves[i].handle, true
case _PATTERN_HOLDER:
params[t.leaves[i].wildcards[0]] = url
return t.leaves[i].handle, true
case _PATTERN_MATCH_ALL:
params["*"] = url
params["*"+com.ToStr(globLevel)] = url
return t.leaves[i].handle, true
}
}
return nil, false
}

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 == unescapedSegment {
if handle, ok := t.subtrees[i].matchNextSegment(globLevel, url, params); ok {
return handle, true
}
}
case _PATTERN_REGEXP:
results := t.subtrees[i].reg.FindStringSubmatch(unescapedSegment)
if len(results)-1 != len(t.subtrees[i].wildcards) {
break
}

for j := 0; j < len(t.subtrees[i].wildcards); j++ {
params[t.subtrees[i].wildcards[j]] = results[j+1]
}
if handle, ok := t.subtrees[i].matchNextSegment(globLevel, url, params); ok {
return handle, true
}
case _PATTERN_HOLDER:
if handle, ok := t.subtrees[i].matchNextSegment(globLevel+1, url, params); ok {
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)] = unescapedSegment
return handle, true
}
}
}

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 {
j := strings.LastIndex(unescapedURL, ".")
if j > -1 {
params[":path"] = unescapedURL[:j]
params[":ext"] = unescapedURL[j+1:]
} else {
params[":path"] = unescapedURL
}
return leaf.handle, true
} else if leaf.typ == _PATTERN_MATCH_ALL {
params["*"] = unescapedURL
params["*"+com.ToStr(globLevel)] = unescapedURL
return leaf.handle, true
}
}
return nil, false
}

func (t *Tree) matchNextSegment(globLevel int, url string, params Params) (Handle, bool) {
i := strings.Index(url, "/")
if i == -1 {
return t.matchLeaf(globLevel, url, params)
}
return t.matchSubtree(globLevel, url[:i], url[i+1:], params)
}

func (t *Tree) Match(url string) (Handle, Params, bool) {
url = strings.TrimPrefix(url, "/")
url = strings.TrimSuffix(url, "/")
params := make(Params)
handle, ok := t.matchNextSegment(0, url, params)
return handle, params, ok
}

// MatchTest returns true if given URL is matched by given pattern.
func MatchTest(pattern, url string) bool {
t := NewTree()
t.Add(pattern, nil)
_, _, ok := t.Match(url)
return ok
}

+ 25
- 0
vendor/gopkg.in/macaron.v1/util_go17.go 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
- 0
vendor/gopkg.in/macaron.v1/util_go18.go 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)
}

+ 6
- 137
vendor/modules.txt View File

@@ -1,5 +1,4 @@
# cloud.google.com/go v0.45.0 # cloud.google.com/go v0.45.0
## explicit
cloud.google.com/go/compute/metadata cloud.google.com/go/compute/metadata
cloud.google.com/go/iam cloud.google.com/go/iam
cloud.google.com/go/internal/optional cloud.google.com/go/internal/optional
@@ -8,43 +7,31 @@ cloud.google.com/go/pubsub
cloud.google.com/go/pubsub/apiv1 cloud.google.com/go/pubsub/apiv1
cloud.google.com/go/pubsub/internal/distribution cloud.google.com/go/pubsub/internal/distribution
# gitea.com/jolheiser/gitea-vet v0.1.0 # gitea.com/jolheiser/gitea-vet v0.1.0
## explicit
gitea.com/jolheiser/gitea-vet gitea.com/jolheiser/gitea-vet
gitea.com/jolheiser/gitea-vet/checks gitea.com/jolheiser/gitea-vet/checks
# gitea.com/lunny/levelqueue v0.3.0 # gitea.com/lunny/levelqueue v0.3.0
## explicit
gitea.com/lunny/levelqueue gitea.com/lunny/levelqueue
# gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b # gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b
## explicit
gitea.com/macaron/binding gitea.com/macaron/binding
# gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76 # gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76
## explicit
gitea.com/macaron/cache gitea.com/macaron/cache
gitea.com/macaron/cache/memcache gitea.com/macaron/cache/memcache
gitea.com/macaron/cache/redis gitea.com/macaron/cache/redis
# gitea.com/macaron/captcha v0.0.0-20190822015246-daa973478bae # gitea.com/macaron/captcha v0.0.0-20190822015246-daa973478bae
## explicit
gitea.com/macaron/captcha gitea.com/macaron/captcha
# gitea.com/macaron/cors v0.0.0-20190826180238-95aec09ea8b4 # gitea.com/macaron/cors v0.0.0-20190826180238-95aec09ea8b4
## explicit
gitea.com/macaron/cors gitea.com/macaron/cors
# gitea.com/macaron/csrf v0.0.0-20190822024205-3dc5a4474439 # gitea.com/macaron/csrf v0.0.0-20190822024205-3dc5a4474439
## explicit
gitea.com/macaron/csrf gitea.com/macaron/csrf
# gitea.com/macaron/gzip v0.0.0-20191118041502-506895b47aae # gitea.com/macaron/gzip v0.0.0-20191118041502-506895b47aae
## explicit
gitea.com/macaron/gzip gitea.com/macaron/gzip
# gitea.com/macaron/i18n v0.0.0-20190822004228-474e714e2223 # gitea.com/macaron/i18n v0.0.0-20190822004228-474e714e2223
## explicit
gitea.com/macaron/i18n gitea.com/macaron/i18n
# gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a # gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a
## explicit
gitea.com/macaron/inject gitea.com/macaron/inject
# gitea.com/macaron/macaron v1.4.0 # gitea.com/macaron/macaron v1.4.0
## explicit
gitea.com/macaron/macaron gitea.com/macaron/macaron
# gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d # gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d
## explicit
gitea.com/macaron/session gitea.com/macaron/session
gitea.com/macaron/session/couchbase gitea.com/macaron/session/couchbase
gitea.com/macaron/session/memcache gitea.com/macaron/session/memcache
@@ -53,13 +40,10 @@ gitea.com/macaron/session/nodb
gitea.com/macaron/session/postgres gitea.com/macaron/session/postgres
gitea.com/macaron/session/redis gitea.com/macaron/session/redis
# gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 # gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7
## explicit
gitea.com/macaron/toolbox gitea.com/macaron/toolbox
# github.com/BurntSushi/toml v0.3.1 # github.com/BurntSushi/toml v0.3.1
## explicit
github.com/BurntSushi/toml github.com/BurntSushi/toml
# github.com/PuerkitoBio/goquery v1.5.0 # github.com/PuerkitoBio/goquery v1.5.0
## explicit
github.com/PuerkitoBio/goquery github.com/PuerkitoBio/goquery
# github.com/PuerkitoBio/purell v1.1.1 # github.com/PuerkitoBio/purell v1.1.1
github.com/PuerkitoBio/purell github.com/PuerkitoBio/purell
@@ -68,7 +52,6 @@ github.com/PuerkitoBio/urlesc
# github.com/RichardKnop/logging v0.0.0-20181101035820-b1d5d44c82d6 # github.com/RichardKnop/logging v0.0.0-20181101035820-b1d5d44c82d6
github.com/RichardKnop/logging github.com/RichardKnop/logging
# github.com/RichardKnop/machinery v1.6.9 # github.com/RichardKnop/machinery v1.6.9
## explicit
github.com/RichardKnop/machinery/v1 github.com/RichardKnop/machinery/v1
github.com/RichardKnop/machinery/v1/backends/amqp github.com/RichardKnop/machinery/v1/backends/amqp
github.com/RichardKnop/machinery/v1/backends/dynamodb github.com/RichardKnop/machinery/v1/backends/dynamodb
@@ -95,7 +78,6 @@ github.com/RichardKnop/machinery/v1/tracing
# github.com/RichardKnop/redsync v1.2.0 # github.com/RichardKnop/redsync v1.2.0
github.com/RichardKnop/redsync github.com/RichardKnop/redsync
# github.com/RoaringBitmap/roaring v0.4.23 # github.com/RoaringBitmap/roaring v0.4.23
## explicit
github.com/RoaringBitmap/roaring github.com/RoaringBitmap/roaring
# github.com/andybalholm/cascadia v1.0.0 # github.com/andybalholm/cascadia v1.0.0
github.com/andybalholm/cascadia github.com/andybalholm/cascadia
@@ -147,10 +129,7 @@ github.com/aws/aws-sdk-go/service/sts/stsiface
github.com/aymerick/douceur/css github.com/aymerick/douceur/css
# github.com/beorn7/perks v1.0.1 # github.com/beorn7/perks v1.0.1
github.com/beorn7/perks/quantile github.com/beorn7/perks/quantile
# github.com/bgentry/speakeasy v0.1.0
## explicit
# github.com/blevesearch/bleve v1.0.7 # github.com/blevesearch/bleve v1.0.7
## explicit
github.com/blevesearch/bleve github.com/blevesearch/bleve
github.com/blevesearch/bleve/analysis github.com/blevesearch/bleve/analysis
github.com/blevesearch/bleve/analysis/analyzer/custom github.com/blevesearch/bleve/analysis/analyzer/custom
@@ -212,7 +191,6 @@ github.com/bradfitz/gomemcache/memcache
# github.com/chris-ramon/douceur v0.2.0 # github.com/chris-ramon/douceur v0.2.0
github.com/chris-ramon/douceur/parser github.com/chris-ramon/douceur/parser
# github.com/couchbase/gomemcached v0.0.0-20191004160342-7b5da2ec40b2 # github.com/couchbase/gomemcached v0.0.0-20191004160342-7b5da2ec40b2
## explicit
github.com/couchbase/gomemcached github.com/couchbase/gomemcached
github.com/couchbase/gomemcached/client github.com/couchbase/gomemcached/client
# github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85 # github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85
@@ -227,31 +205,20 @@ github.com/couchbase/vellum/utf8
github.com/couchbaselabs/go-couchbase github.com/couchbaselabs/go-couchbase
# github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d # github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d
github.com/cpuguy83/go-md2man/v2/md2man github.com/cpuguy83/go-md2man/v2/md2man
# github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d
## explicit
# github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548
## explicit
# github.com/cznic/strutil v0.0.0-20181122101858-275e90344537
## explicit
# github.com/davecgh/go-spew v1.1.1 # github.com/davecgh/go-spew v1.1.1
github.com/davecgh/go-spew/spew github.com/davecgh/go-spew/spew
# github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc # github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
## explicit
github.com/denisenkom/go-mssqldb github.com/denisenkom/go-mssqldb
github.com/denisenkom/go-mssqldb/internal/cp github.com/denisenkom/go-mssqldb/internal/cp
github.com/denisenkom/go-mssqldb/internal/decimal github.com/denisenkom/go-mssqldb/internal/decimal
github.com/denisenkom/go-mssqldb/internal/querytext github.com/denisenkom/go-mssqldb/internal/querytext
# github.com/dgrijalva/jwt-go v3.2.0+incompatible # github.com/dgrijalva/jwt-go v3.2.0+incompatible
## explicit
github.com/dgrijalva/jwt-go github.com/dgrijalva/jwt-go
# github.com/dustin/go-humanize v1.0.0 # github.com/dustin/go-humanize v1.0.0
## explicit
github.com/dustin/go-humanize github.com/dustin/go-humanize
# github.com/editorconfig/editorconfig-core-go/v2 v2.1.1 # github.com/editorconfig/editorconfig-core-go/v2 v2.1.1
## explicit
github.com/editorconfig/editorconfig-core-go/v2 github.com/editorconfig/editorconfig-core-go/v2
# github.com/emirpasic/gods v1.12.0 # github.com/emirpasic/gods v1.12.0
## explicit
github.com/emirpasic/gods/containers github.com/emirpasic/gods/containers
github.com/emirpasic/gods/lists github.com/emirpasic/gods/lists
github.com/emirpasic/gods/lists/arraylist github.com/emirpasic/gods/lists/arraylist
@@ -259,14 +226,7 @@ github.com/emirpasic/gods/trees
github.com/emirpasic/gods/trees/binaryheap github.com/emirpasic/gods/trees/binaryheap
github.com/emirpasic/gods/utils github.com/emirpasic/gods/utils
# github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a # github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a
## explicit
github.com/ethantkoenig/rupture github.com/ethantkoenig/rupture
# github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51
## explicit
# github.com/facebookgo/stack v0.0.0-20160209184415-751773369052
## explicit
# github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870
## explicit
# github.com/fatih/color v1.9.0 # github.com/fatih/color v1.9.0
github.com/fatih/color github.com/fatih/color
# github.com/fatih/structtag v1.2.0 # github.com/fatih/structtag v1.2.0
@@ -274,13 +234,10 @@ github.com/fatih/structtag
# github.com/fsnotify/fsnotify v1.4.7 # github.com/fsnotify/fsnotify v1.4.7
github.com/fsnotify/fsnotify github.com/fsnotify/fsnotify
# github.com/gliderlabs/ssh v0.2.2 # github.com/gliderlabs/ssh v0.2.2
## explicit
github.com/gliderlabs/ssh github.com/gliderlabs/ssh
# github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a # github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a
## explicit
github.com/glycerine/go-unsnap-stream github.com/glycerine/go-unsnap-stream
# github.com/go-enry/go-enry/v2 v2.3.0 # github.com/go-enry/go-enry/v2 v2.3.0
## explicit
github.com/go-enry/go-enry/v2 github.com/go-enry/go-enry/v2
github.com/go-enry/go-enry/v2/data github.com/go-enry/go-enry/v2/data
github.com/go-enry/go-enry/v2/data/rule github.com/go-enry/go-enry/v2/data/rule
@@ -295,14 +252,12 @@ github.com/go-git/gcfg/scanner
github.com/go-git/gcfg/token github.com/go-git/gcfg/token
github.com/go-git/gcfg/types github.com/go-git/gcfg/types
# github.com/go-git/go-billy/v5 v5.0.0 # github.com/go-git/go-billy/v5 v5.0.0
## explicit
github.com/go-git/go-billy/v5 github.com/go-git/go-billy/v5
github.com/go-git/go-billy/v5/helper/chroot github.com/go-git/go-billy/v5/helper/chroot
github.com/go-git/go-billy/v5/helper/polyfill github.com/go-git/go-billy/v5/helper/polyfill
github.com/go-git/go-billy/v5/osfs github.com/go-git/go-billy/v5/osfs
github.com/go-git/go-billy/v5/util github.com/go-git/go-billy/v5/util
# github.com/go-git/go-git/v5 v5.0.0 # github.com/go-git/go-git/v5 v5.0.0
## explicit
github.com/go-git/go-git/v5 github.com/go-git/go-git/v5
github.com/go-git/go-git/v5/config github.com/go-git/go-git/v5/config
github.com/go-git/go-git/v5/internal/revision github.com/go-git/go-git/v5/internal/revision
@@ -347,8 +302,11 @@ github.com/go-git/go-git/v5/utils/merkletrie/index
github.com/go-git/go-git/v5/utils/merkletrie/internal/frame github.com/go-git/go-git/v5/utils/merkletrie/internal/frame
github.com/go-git/go-git/v5/utils/merkletrie/noder github.com/go-git/go-git/v5/utils/merkletrie/noder
# github.com/go-ini/ini v1.56.0 # github.com/go-ini/ini v1.56.0
## explicit
github.com/go-ini/ini github.com/go-ini/ini
# github.com/go-macaron/auth v0.0.0-20161228062157-884c0e6c9b92
github.com/go-macaron/auth
# github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191
github.com/go-macaron/inject
# github.com/go-openapi/analysis v0.19.5 # github.com/go-openapi/analysis v0.19.5
github.com/go-openapi/analysis github.com/go-openapi/analysis
github.com/go-openapi/analysis/internal github.com/go-openapi/analysis/internal
@@ -359,7 +317,6 @@ github.com/go-openapi/inflect
# github.com/go-openapi/jsonpointer v0.19.3 # github.com/go-openapi/jsonpointer v0.19.3
github.com/go-openapi/jsonpointer github.com/go-openapi/jsonpointer
# github.com/go-openapi/jsonreference v0.19.3 # github.com/go-openapi/jsonreference v0.19.3
## explicit
github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference
# github.com/go-openapi/loads v0.19.3 # github.com/go-openapi/loads v0.19.3
github.com/go-openapi/loads github.com/go-openapi/loads
@@ -381,7 +338,6 @@ github.com/go-openapi/swag
# github.com/go-openapi/validate v0.19.3 # github.com/go-openapi/validate v0.19.3
github.com/go-openapi/validate github.com/go-openapi/validate
# github.com/go-redis/redis v6.15.2+incompatible # github.com/go-redis/redis v6.15.2+incompatible
## explicit
github.com/go-redis/redis github.com/go-redis/redis
github.com/go-redis/redis/internal github.com/go-redis/redis/internal
github.com/go-redis/redis/internal/consistenthash github.com/go-redis/redis/internal/consistenthash
@@ -390,15 +346,12 @@ github.com/go-redis/redis/internal/pool
github.com/go-redis/redis/internal/proto github.com/go-redis/redis/internal/proto
github.com/go-redis/redis/internal/util github.com/go-redis/redis/internal/util
# github.com/go-resty/resty/v2 v2.3.0 # github.com/go-resty/resty/v2 v2.3.0
## explicit
github.com/go-resty/resty/v2 github.com/go-resty/resty/v2
# github.com/go-sql-driver/mysql v1.4.1 # github.com/go-sql-driver/mysql v1.4.1
## explicit
github.com/go-sql-driver/mysql github.com/go-sql-driver/mysql
# github.com/go-stack/stack v1.8.0 # github.com/go-stack/stack v1.8.0
github.com/go-stack/stack github.com/go-stack/stack
# github.com/go-swagger/go-swagger v0.21.0 # github.com/go-swagger/go-swagger v0.21.0
## explicit
github.com/go-swagger/go-swagger/cmd/swagger github.com/go-swagger/go-swagger/cmd/swagger
github.com/go-swagger/go-swagger/cmd/swagger/commands github.com/go-swagger/go-swagger/cmd/swagger/commands
github.com/go-swagger/go-swagger/cmd/swagger/commands/diff github.com/go-swagger/go-swagger/cmd/swagger/commands/diff
@@ -408,7 +361,6 @@ github.com/go-swagger/go-swagger/codescan
github.com/go-swagger/go-swagger/generator github.com/go-swagger/go-swagger/generator
github.com/go-swagger/go-swagger/scan github.com/go-swagger/go-swagger/scan
# github.com/gobwas/glob v0.2.3 # github.com/gobwas/glob v0.2.3
## explicit
github.com/gobwas/glob github.com/gobwas/glob
github.com/gobwas/glob/compiler github.com/gobwas/glob/compiler
github.com/gobwas/glob/match github.com/gobwas/glob/match
@@ -418,17 +370,14 @@ github.com/gobwas/glob/syntax/lexer
github.com/gobwas/glob/util/runes github.com/gobwas/glob/util/runes
github.com/gobwas/glob/util/strings github.com/gobwas/glob/util/strings
# github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28 # github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
## explicit
github.com/gogs/chardet github.com/gogs/chardet
# github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 # github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
## explicit
github.com/gogs/cron github.com/gogs/cron
# github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe # github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
github.com/golang-sql/civil github.com/golang-sql/civil
# github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 # github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6
github.com/golang/groupcache/lru github.com/golang/groupcache/lru
# github.com/golang/protobuf v1.4.1 # github.com/golang/protobuf v1.4.1
## explicit
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
github.com/golang/protobuf/protoc-gen-go/descriptor github.com/golang/protobuf/protoc-gen-go/descriptor
github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes
@@ -442,7 +391,6 @@ github.com/golang/snappy
github.com/gomodule/redigo/internal github.com/gomodule/redigo/internal
github.com/gomodule/redigo/redis github.com/gomodule/redigo/redis
# github.com/google/go-github/v24 v24.0.1 # github.com/google/go-github/v24 v24.0.1
## explicit
github.com/google/go-github/v24/github github.com/google/go-github/v24/github
# github.com/google/go-querystring v1.0.0 # github.com/google/go-querystring v1.0.0
github.com/google/go-querystring/query github.com/google/go-querystring/query
@@ -451,7 +399,6 @@ github.com/google/uuid
# github.com/googleapis/gax-go/v2 v2.0.5 # github.com/googleapis/gax-go/v2 v2.0.5
github.com/googleapis/gax-go/v2 github.com/googleapis/gax-go/v2
# github.com/gorilla/context v1.1.1 # github.com/gorilla/context v1.1.1
## explicit
github.com/gorilla/context github.com/gorilla/context
# github.com/gorilla/css v1.0.0 # github.com/gorilla/css v1.0.0
github.com/gorilla/css/scanner github.com/gorilla/css/scanner
@@ -466,7 +413,6 @@ github.com/gorilla/sessions
# github.com/hashicorp/go-cleanhttp v0.5.1 # github.com/hashicorp/go-cleanhttp v0.5.1
github.com/hashicorp/go-cleanhttp github.com/hashicorp/go-cleanhttp
# github.com/hashicorp/go-retryablehttp v0.6.6 # github.com/hashicorp/go-retryablehttp v0.6.6
## explicit
github.com/hashicorp/go-retryablehttp github.com/hashicorp/go-retryablehttp
# github.com/hashicorp/hcl v1.0.0 # github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/hcl github.com/hashicorp/hcl
@@ -480,15 +426,10 @@ github.com/hashicorp/hcl/json/parser
github.com/hashicorp/hcl/json/scanner github.com/hashicorp/hcl/json/scanner
github.com/hashicorp/hcl/json/token github.com/hashicorp/hcl/json/token
# github.com/huandu/xstrings v1.3.0 # github.com/huandu/xstrings v1.3.0
## explicit
github.com/huandu/xstrings github.com/huandu/xstrings
# github.com/issue9/assert v1.3.2
## explicit
# github.com/issue9/identicon v1.0.1 # github.com/issue9/identicon v1.0.1
## explicit
github.com/issue9/identicon github.com/issue9/identicon
# github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d # github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d
## explicit
github.com/jaytaylor/html2text github.com/jaytaylor/html2text
# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 # github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
github.com/jbenet/go-context/io github.com/jbenet/go-context/io
@@ -496,21 +437,15 @@ github.com/jbenet/go-context/io
github.com/jessevdk/go-flags github.com/jessevdk/go-flags
# github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af # github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
github.com/jmespath/go-jmespath github.com/jmespath/go-jmespath
# github.com/jmhodges/levigo v1.0.0
## explicit
# github.com/joho/godotenv v1.3.0
## explicit
# github.com/json-iterator/go v1.1.9 # github.com/json-iterator/go v1.1.9
github.com/json-iterator/go github.com/json-iterator/go
# github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657 # github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657
## explicit
github.com/kballard/go-shellquote github.com/kballard/go-shellquote
# github.com/kelseyhightower/envconfig v1.3.0 # github.com/kelseyhightower/envconfig v1.3.0
github.com/kelseyhightower/envconfig github.com/kelseyhightower/envconfig
# github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd # github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd
github.com/kevinburke/ssh_config github.com/kevinburke/ssh_config
# github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 # github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
## explicit
github.com/keybase/go-crypto/brainpool github.com/keybase/go-crypto/brainpool
github.com/keybase/go-crypto/cast5 github.com/keybase/go-crypto/cast5
github.com/keybase/go-crypto/curve25519 github.com/keybase/go-crypto/curve25519
@@ -525,7 +460,6 @@ github.com/keybase/go-crypto/openpgp/packet
github.com/keybase/go-crypto/openpgp/s2k github.com/keybase/go-crypto/openpgp/s2k
github.com/keybase/go-crypto/rsa github.com/keybase/go-crypto/rsa
# github.com/klauspost/compress v1.10.2 # github.com/klauspost/compress v1.10.2
## explicit
github.com/klauspost/compress/flate github.com/klauspost/compress/flate
github.com/klauspost/compress/gzip github.com/klauspost/compress/gzip
# github.com/klauspost/cpuid v1.2.3 # github.com/klauspost/cpuid v1.2.3
@@ -535,16 +469,13 @@ github.com/kr/pretty
# github.com/kr/text v0.2.0 # github.com/kr/text v0.2.0
github.com/kr/text github.com/kr/text
# github.com/lafriks/xormstore v1.3.2 # github.com/lafriks/xormstore v1.3.2
## explicit
github.com/lafriks/xormstore github.com/lafriks/xormstore
github.com/lafriks/xormstore/util github.com/lafriks/xormstore/util
# github.com/lib/pq v1.2.0 # github.com/lib/pq v1.2.0
## explicit
github.com/lib/pq github.com/lib/pq
github.com/lib/pq/oid github.com/lib/pq/oid
github.com/lib/pq/scram github.com/lib/pq/scram
# github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 # github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
## explicit
github.com/lunny/dingtalk_webhook github.com/lunny/dingtalk_webhook
# github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de # github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de
github.com/lunny/log github.com/lunny/log
@@ -557,13 +488,11 @@ github.com/lunny/nodb/store/goleveldb
# github.com/magiconair/properties v1.8.1 # github.com/magiconair/properties v1.8.1
github.com/magiconair/properties github.com/magiconair/properties
# github.com/mailru/easyjson v0.7.0 # github.com/mailru/easyjson v0.7.0
## explicit
github.com/mailru/easyjson github.com/mailru/easyjson
github.com/mailru/easyjson/buffer github.com/mailru/easyjson/buffer
github.com/mailru/easyjson/jlexer github.com/mailru/easyjson/jlexer
github.com/mailru/easyjson/jwriter github.com/mailru/easyjson/jwriter
# github.com/markbates/goth v1.61.2 # github.com/markbates/goth v1.61.2
## explicit
github.com/markbates/goth github.com/markbates/goth
github.com/markbates/goth/gothic github.com/markbates/goth/gothic
github.com/markbates/goth/providers/bitbucket github.com/markbates/goth/providers/bitbucket
@@ -581,35 +510,26 @@ github.com/markbates/goth/providers/yandex
# github.com/mattn/go-colorable v0.1.4 # github.com/mattn/go-colorable v0.1.4
github.com/mattn/go-colorable github.com/mattn/go-colorable
# github.com/mattn/go-isatty v0.0.11 # github.com/mattn/go-isatty v0.0.11
## explicit
github.com/mattn/go-isatty github.com/mattn/go-isatty
# github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d
## explicit
# github.com/mattn/go-runewidth v0.0.7 # github.com/mattn/go-runewidth v0.0.7
github.com/mattn/go-runewidth github.com/mattn/go-runewidth
# github.com/mattn/go-sqlite3 v1.11.0 # github.com/mattn/go-sqlite3 v1.11.0
## explicit
github.com/mattn/go-sqlite3 github.com/mattn/go-sqlite3
# github.com/matttproud/golang_protobuf_extensions v1.0.1 # github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/matttproud/golang_protobuf_extensions/pbutil github.com/matttproud/golang_protobuf_extensions/pbutil
# github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 # github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75
## explicit
github.com/mcuadros/go-version github.com/mcuadros/go-version
# github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 # github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81
## explicit
github.com/mgechev/dots github.com/mgechev/dots
# github.com/mgechev/revive v1.0.2 # github.com/mgechev/revive v1.0.2
## explicit
github.com/mgechev/revive/formatter github.com/mgechev/revive/formatter
github.com/mgechev/revive/lint github.com/mgechev/revive/lint
github.com/mgechev/revive/rule github.com/mgechev/revive/rule
# github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912 # github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912
## explicit
github.com/microcosm-cc/bluemonday github.com/microcosm-cc/bluemonday
# github.com/minio/md5-simd v1.1.0 # github.com/minio/md5-simd v1.1.0
github.com/minio/md5-simd github.com/minio/md5-simd
# github.com/minio/minio-go v6.0.14+incompatible # github.com/minio/minio-go v6.0.14+incompatible
## explicit
github.com/minio/minio-go github.com/minio/minio-go
github.com/minio/minio-go/pkg/credentials github.com/minio/minio-go/pkg/credentials
github.com/minio/minio-go/pkg/encrypt github.com/minio/minio-go/pkg/encrypt
@@ -617,7 +537,6 @@ github.com/minio/minio-go/pkg/s3signer
github.com/minio/minio-go/pkg/s3utils github.com/minio/minio-go/pkg/s3utils
github.com/minio/minio-go/pkg/set github.com/minio/minio-go/pkg/set
# github.com/minio/minio-go/v6 v6.0.57 # github.com/minio/minio-go/v6 v6.0.57
## explicit
github.com/minio/minio-go/v6 github.com/minio/minio-go/v6
github.com/minio/minio-go/v6/pkg/credentials github.com/minio/minio-go/v6/pkg/credentials
github.com/minio/minio-go/v6/pkg/encrypt github.com/minio/minio-go/v6/pkg/encrypt
@@ -628,7 +547,6 @@ github.com/minio/minio-go/v6/pkg/tags
# github.com/minio/sha256-simd v0.1.1 # github.com/minio/sha256-simd v0.1.1
github.com/minio/sha256-simd github.com/minio/sha256-simd
# github.com/mitchellh/go-homedir v1.1.0 # github.com/mitchellh/go-homedir v1.1.0
## explicit
github.com/mitchellh/go-homedir github.com/mitchellh/go-homedir
# github.com/mitchellh/mapstructure v1.1.2 # github.com/mitchellh/mapstructure v1.1.2
github.com/mitchellh/mapstructure github.com/mitchellh/mapstructure
@@ -641,21 +559,16 @@ github.com/mrjones/oauth
# github.com/mschoch/smat v0.2.0 # github.com/mschoch/smat v0.2.0
github.com/mschoch/smat github.com/mschoch/smat
# github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc # github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
## explicit
github.com/msteinert/pam github.com/msteinert/pam
# github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 # github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
## explicit
github.com/nfnt/resize github.com/nfnt/resize
# github.com/niklasfasching/go-org v0.1.9 # github.com/niklasfasching/go-org v0.1.9
## explicit
github.com/niklasfasching/go-org/org github.com/niklasfasching/go-org/org
# github.com/olekukonko/tablewriter v0.0.4 # github.com/olekukonko/tablewriter v0.0.4
github.com/olekukonko/tablewriter github.com/olekukonko/tablewriter
# github.com/oliamb/cutter v0.2.2 # github.com/oliamb/cutter v0.2.2
## explicit
github.com/oliamb/cutter github.com/oliamb/cutter
# github.com/olivere/elastic/v7 v7.0.9 # github.com/olivere/elastic/v7 v7.0.9
## explicit
github.com/olivere/elastic/v7 github.com/olivere/elastic/v7
github.com/olivere/elastic/v7/config github.com/olivere/elastic/v7/config
github.com/olivere/elastic/v7/uritemplates github.com/olivere/elastic/v7/uritemplates
@@ -668,53 +581,41 @@ github.com/pelletier/go-toml
# github.com/philhofer/fwd v1.0.0 # github.com/philhofer/fwd v1.0.0
github.com/philhofer/fwd github.com/philhofer/fwd
# github.com/pkg/errors v0.9.1 # github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0 # github.com/pmezard/go-difflib v1.0.0
github.com/pmezard/go-difflib/difflib github.com/pmezard/go-difflib/difflib
# github.com/pquerna/otp v1.2.0 # github.com/pquerna/otp v1.2.0
## explicit
github.com/pquerna/otp github.com/pquerna/otp
github.com/pquerna/otp/hotp github.com/pquerna/otp/hotp
github.com/pquerna/otp/totp github.com/pquerna/otp/totp
# github.com/prometheus/client_golang v1.1.0 # github.com/prometheus/client_golang v1.1.0
## explicit
github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus
github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/internal
github.com/prometheus/client_golang/prometheus/promhttp github.com/prometheus/client_golang/prometheus/promhttp
# github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 # github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4
## explicit
github.com/prometheus/client_model/go github.com/prometheus/client_model/go
# github.com/prometheus/common v0.6.0 # github.com/prometheus/common v0.6.0
github.com/prometheus/common/expfmt github.com/prometheus/common/expfmt
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
github.com/prometheus/common/model github.com/prometheus/common/model
# github.com/prometheus/procfs v0.0.4 # github.com/prometheus/procfs v0.0.4
## explicit
github.com/prometheus/procfs github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/fs
github.com/prometheus/procfs/internal/util github.com/prometheus/procfs/internal/util
# github.com/quasoft/websspi v1.0.0 # github.com/quasoft/websspi v1.0.0
## explicit
github.com/quasoft/websspi github.com/quasoft/websspi
github.com/quasoft/websspi/secctx github.com/quasoft/websspi/secctx
# github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001
## explicit
# github.com/russross/blackfriday/v2 v2.0.1 # github.com/russross/blackfriday/v2 v2.0.1
github.com/russross/blackfriday/v2 github.com/russross/blackfriday/v2
# github.com/satori/go.uuid v1.2.0 # github.com/satori/go.uuid v1.2.0
## explicit
github.com/satori/go.uuid github.com/satori/go.uuid
# github.com/sergi/go-diff v1.1.0 # github.com/sergi/go-diff v1.1.0
## explicit
github.com/sergi/go-diff/diffmatchpatch github.com/sergi/go-diff/diffmatchpatch
# github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b # github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b
## explicit
github.com/shurcooL/httpfs/vfsutil github.com/shurcooL/httpfs/vfsutil
# github.com/shurcooL/sanitized_anchor_name v1.0.0 # github.com/shurcooL/sanitized_anchor_name v1.0.0
github.com/shurcooL/sanitized_anchor_name github.com/shurcooL/sanitized_anchor_name
# github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd # github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
## explicit
github.com/shurcooL/vfsgen github.com/shurcooL/vfsgen
# github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d # github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d
github.com/siddontang/go-snappy/snappy github.com/siddontang/go-snappy/snappy
@@ -734,7 +635,6 @@ github.com/steveyen/gtreap
# github.com/streadway/amqp v0.0.0-20190214183023-884228600bc9 # github.com/streadway/amqp v0.0.0-20190214183023-884228600bc9
github.com/streadway/amqp github.com/streadway/amqp
# github.com/stretchr/testify v1.4.0 # github.com/stretchr/testify v1.4.0
## explicit
github.com/stretchr/testify/assert github.com/stretchr/testify/assert
github.com/stretchr/testify/require github.com/stretchr/testify/require
# github.com/syndtr/goleveldb v1.0.0 # github.com/syndtr/goleveldb v1.0.0
@@ -750,38 +650,28 @@ github.com/syndtr/goleveldb/leveldb/opt
github.com/syndtr/goleveldb/leveldb/storage github.com/syndtr/goleveldb/leveldb/storage
github.com/syndtr/goleveldb/leveldb/table github.com/syndtr/goleveldb/leveldb/table
github.com/syndtr/goleveldb/leveldb/util github.com/syndtr/goleveldb/leveldb/util
# github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481
## explicit
# github.com/tinylib/msgp v1.1.2 # github.com/tinylib/msgp v1.1.2
## explicit
github.com/tinylib/msgp/msgp github.com/tinylib/msgp/msgp
# github.com/toqueteos/trie v1.0.0 # github.com/toqueteos/trie v1.0.0
github.com/toqueteos/trie github.com/toqueteos/trie
# github.com/toqueteos/webbrowser v1.2.0 # github.com/toqueteos/webbrowser v1.2.0
github.com/toqueteos/webbrowser github.com/toqueteos/webbrowser
# github.com/tstranex/u2f v1.0.0 # github.com/tstranex/u2f v1.0.0
## explicit
github.com/tstranex/u2f github.com/tstranex/u2f
# github.com/unknwon/cae v1.0.0 # github.com/unknwon/cae v1.0.0
## explicit
github.com/unknwon/cae github.com/unknwon/cae
github.com/unknwon/cae/zip github.com/unknwon/cae/zip
# github.com/unknwon/com v1.0.1 # github.com/unknwon/com v1.0.1
## explicit
github.com/unknwon/com github.com/unknwon/com
# github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6 # github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6
## explicit
github.com/unknwon/i18n github.com/unknwon/i18n
# github.com/unknwon/paginater v0.0.0-20151104151617-7748a72e0141 # github.com/unknwon/paginater v0.0.0-20151104151617-7748a72e0141
## explicit
github.com/unknwon/paginater github.com/unknwon/paginater
# github.com/urfave/cli v1.22.1 # github.com/urfave/cli v1.22.1
## explicit
github.com/urfave/cli github.com/urfave/cli
# github.com/willf/bitset v1.1.10 # github.com/willf/bitset v1.1.10
github.com/willf/bitset github.com/willf/bitset
# github.com/xanzy/go-gitlab v0.31.0 # github.com/xanzy/go-gitlab v0.31.0
## explicit
github.com/xanzy/go-gitlab github.com/xanzy/go-gitlab
# github.com/xanzy/ssh-agent v0.2.1 # github.com/xanzy/ssh-agent v0.2.1
github.com/xanzy/ssh-agent github.com/xanzy/ssh-agent
@@ -790,10 +680,8 @@ github.com/xdg/scram
# github.com/xdg/stringprep v1.0.0 # github.com/xdg/stringprep v1.0.0
github.com/xdg/stringprep github.com/xdg/stringprep
# github.com/yohcop/openid-go v1.0.0 # github.com/yohcop/openid-go v1.0.0
## explicit
github.com/yohcop/openid-go github.com/yohcop/openid-go
# github.com/yuin/goldmark v1.1.27 # github.com/yuin/goldmark v1.1.27
## explicit
github.com/yuin/goldmark github.com/yuin/goldmark
github.com/yuin/goldmark/ast github.com/yuin/goldmark/ast
github.com/yuin/goldmark/extension github.com/yuin/goldmark/extension
@@ -804,7 +692,6 @@ github.com/yuin/goldmark/renderer/html
github.com/yuin/goldmark/text github.com/yuin/goldmark/text
github.com/yuin/goldmark/util github.com/yuin/goldmark/util
# github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60 # github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60
## explicit
github.com/yuin/goldmark-meta github.com/yuin/goldmark-meta
# go.etcd.io/bbolt v1.3.4 # go.etcd.io/bbolt v1.3.4
go.etcd.io/bbolt go.etcd.io/bbolt
@@ -856,7 +743,6 @@ go.opencensus.io/trace/internal
go.opencensus.io/trace/propagation go.opencensus.io/trace/propagation
go.opencensus.io/trace/tracestate go.opencensus.io/trace/tracestate
# golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 # golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
## explicit
golang.org/x/crypto/acme golang.org/x/crypto/acme
golang.org/x/crypto/acme/autocert golang.org/x/crypto/acme/autocert
golang.org/x/crypto/argon2 golang.org/x/crypto/argon2
@@ -884,11 +770,9 @@ golang.org/x/crypto/ssh/agent
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/knownhosts golang.org/x/crypto/ssh/knownhosts
# golang.org/x/mod v0.3.0 # golang.org/x/mod v0.3.0
## explicit
golang.org/x/mod/module golang.org/x/mod/module
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.0.0-20200513185701-a91f0712d120 # golang.org/x/net v0.0.0-20200513185701-a91f0712d120
## explicit
golang.org/x/net/context golang.org/x/net/context
golang.org/x/net/context/ctxhttp golang.org/x/net/context/ctxhttp
golang.org/x/net/html golang.org/x/net/html
@@ -904,7 +788,6 @@ golang.org/x/net/proxy
golang.org/x/net/publicsuffix golang.org/x/net/publicsuffix
golang.org/x/net/trace golang.org/x/net/trace
# golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d # golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
## explicit
golang.org/x/oauth2 golang.org/x/oauth2
golang.org/x/oauth2/google golang.org/x/oauth2/google
golang.org/x/oauth2/internal golang.org/x/oauth2/internal
@@ -914,7 +797,6 @@ golang.org/x/oauth2/jwt
golang.org/x/sync/errgroup golang.org/x/sync/errgroup
golang.org/x/sync/semaphore golang.org/x/sync/semaphore
# golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f # golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f
## explicit
golang.org/x/sys/cpu golang.org/x/sys/cpu
golang.org/x/sys/internal/unsafeheader golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix golang.org/x/sys/unix
@@ -922,7 +804,6 @@ golang.org/x/sys/windows
golang.org/x/sys/windows/svc golang.org/x/sys/windows/svc
golang.org/x/sys/windows/svc/debug golang.org/x/sys/windows/svc/debug
# golang.org/x/text v0.3.2 # golang.org/x/text v0.3.2
## explicit
golang.org/x/text/encoding golang.org/x/text/encoding
golang.org/x/text/encoding/charmap golang.org/x/text/encoding/charmap
golang.org/x/text/encoding/htmlindex golang.org/x/text/encoding/htmlindex
@@ -945,10 +826,8 @@ golang.org/x/text/unicode/bidi
golang.org/x/text/unicode/norm golang.org/x/text/unicode/norm
golang.org/x/text/width golang.org/x/text/width
# golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 # golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
## explicit
golang.org/x/time/rate golang.org/x/time/rate
# golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53 # golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53
## explicit
golang.org/x/tools/cover golang.org/x/tools/cover
golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis
golang.org/x/tools/go/analysis/internal/analysisflags golang.org/x/tools/go/analysis/internal/analysisflags
@@ -988,7 +867,6 @@ google.golang.org/api/transport/grpc
google.golang.org/api/transport/http google.golang.org/api/transport/http
google.golang.org/api/transport/http/internal/propagation google.golang.org/api/transport/http/internal/propagation
# google.golang.org/appengine v1.6.5 # google.golang.org/appengine v1.6.5
## explicit
google.golang.org/appengine google.golang.org/appengine
google.golang.org/appengine/cloudsql google.golang.org/appengine/cloudsql
google.golang.org/appengine/internal google.golang.org/appengine/internal
@@ -1087,41 +965,32 @@ google.golang.org/protobuf/types/known/durationpb
google.golang.org/protobuf/types/known/emptypb google.golang.org/protobuf/types/known/emptypb
google.golang.org/protobuf/types/known/timestamppb google.golang.org/protobuf/types/known/timestamppb
# gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc # gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc
## explicit
gopkg.in/alexcesaro/quotedprintable.v3 gopkg.in/alexcesaro/quotedprintable.v3
# gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 # gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175
## explicit
gopkg.in/asn1-ber.v1 gopkg.in/asn1-ber.v1
# gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df # gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
## explicit
gopkg.in/gomail.v2 gopkg.in/gomail.v2
# gopkg.in/ini.v1 v1.52.0 # gopkg.in/ini.v1 v1.52.0
## explicit
gopkg.in/ini.v1 gopkg.in/ini.v1
# gopkg.in/ldap.v3 v3.0.2 # gopkg.in/ldap.v3 v3.0.2
## explicit
gopkg.in/ldap.v3 gopkg.in/ldap.v3
# gopkg.in/macaron.v1 v1.3.9
gopkg.in/macaron.v1
# gopkg.in/testfixtures.v2 v2.5.0 # gopkg.in/testfixtures.v2 v2.5.0
## explicit
gopkg.in/testfixtures.v2 gopkg.in/testfixtures.v2
# gopkg.in/toqueteos/substring.v1 v1.0.2 # gopkg.in/toqueteos/substring.v1 v1.0.2
gopkg.in/toqueteos/substring.v1 gopkg.in/toqueteos/substring.v1
# gopkg.in/warnings.v0 v0.1.2 # gopkg.in/warnings.v0 v0.1.2
gopkg.in/warnings.v0 gopkg.in/warnings.v0
# gopkg.in/yaml.v2 v2.2.8 # gopkg.in/yaml.v2 v2.2.8
## explicit
gopkg.in/yaml.v2 gopkg.in/yaml.v2
# mvdan.cc/xurls/v2 v2.1.0 # mvdan.cc/xurls/v2 v2.1.0
## explicit
mvdan.cc/xurls/v2 mvdan.cc/xurls/v2
# strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 # strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
## explicit
strk.kbt.io/projects/go/libravatar strk.kbt.io/projects/go/libravatar
# xorm.io/builder v0.3.7 # xorm.io/builder v0.3.7
## explicit
xorm.io/builder xorm.io/builder
# xorm.io/xorm v1.0.1 # xorm.io/xorm v1.0.1
## explicit
xorm.io/xorm xorm.io/xorm
xorm.io/xorm/caches xorm.io/xorm/caches
xorm.io/xorm/contexts xorm.io/xorm/contexts


Loading…
Cancel
Save