forked from forgejo/forgejo
Use gitea forked macaron (#7933)
Signed-off-by: Tamal Saha <tamal@appscode.com>
This commit is contained in:
parent
ca6fb004ac
commit
171b359877
408 changed files with 14882 additions and 13217 deletions
24
vendor/gitea.com/macaron/binding/.drone.yml
generated
vendored
Normal file
24
vendor/gitea.com/macaron/binding/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
kind: pipeline
|
||||
name: go1-1-1
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: go1-1-2
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
1
vendor/gitea.com/macaron/binding/.gitignore
generated
vendored
Normal file
1
vendor/gitea.com/macaron/binding/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.idea
|
191
vendor/gitea.com/macaron/binding/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/binding/LICENSE
generated
vendored
Normal 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.
|
20
vendor/gitea.com/macaron/binding/README.md
generated
vendored
Normal file
20
vendor/gitea.com/macaron/binding/README.md
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
# binding [](https://travis-ci.org/go-macaron/binding) [](https://sourcegraph.com/github.com/go-macaron/binding?badge)
|
||||
|
||||
Middleware binding provides request data binding and validation for [Macaron](https://github.com/go-macaron/macaron).
|
||||
|
||||
### Installation
|
||||
|
||||
go get github.com/go-macaron/binding
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/github.com/go-macaron/binding)
|
||||
- [Documentation](http://go-macaron.com/docs/middlewares/binding)
|
||||
|
||||
## Credits
|
||||
|
||||
This package is a modified version of [martini-contrib/binding](https://github.com/martini-contrib/binding).
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
761
vendor/gitea.com/macaron/binding/binding.go
generated
vendored
Normal file
761
vendor/gitea.com/macaron/binding/binding.go
generated
vendored
Normal file
|
@ -0,0 +1,761 @@
|
|||
// Copyright 2014 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 binding is a middleware that provides request data binding and validation for Macaron.
|
||||
package binding
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"gitea.com/macaron/macaron"
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
const _VERSION = "0.6.0"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
}
|
||||
|
||||
func bind(ctx *macaron.Context, obj interface{}, ifacePtr ...interface{}) {
|
||||
contentType := ctx.Req.Header.Get("Content-Type")
|
||||
if ctx.Req.Method == "POST" || ctx.Req.Method == "PUT" || len(contentType) > 0 {
|
||||
switch {
|
||||
case strings.Contains(contentType, "form-urlencoded"):
|
||||
ctx.Invoke(Form(obj, ifacePtr...))
|
||||
case strings.Contains(contentType, "multipart/form-data"):
|
||||
ctx.Invoke(MultipartForm(obj, ifacePtr...))
|
||||
case strings.Contains(contentType, "json"):
|
||||
ctx.Invoke(Json(obj, ifacePtr...))
|
||||
default:
|
||||
var errors Errors
|
||||
if contentType == "" {
|
||||
errors.Add([]string{}, ERR_CONTENT_TYPE, "Empty Content-Type")
|
||||
} else {
|
||||
errors.Add([]string{}, ERR_CONTENT_TYPE, "Unsupported Content-Type")
|
||||
}
|
||||
ctx.Map(errors)
|
||||
ctx.Map(obj) // Map a fake struct so handler won't panic.
|
||||
}
|
||||
} else {
|
||||
ctx.Invoke(Form(obj, ifacePtr...))
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
_JSON_CONTENT_TYPE = "application/json; charset=utf-8"
|
||||
STATUS_UNPROCESSABLE_ENTITY = 422
|
||||
)
|
||||
|
||||
// errorHandler simply counts the number of errors in the
|
||||
// context and, if more than 0, writes a response with an
|
||||
// error code and a JSON payload describing the errors.
|
||||
// The response will have a JSON content-type.
|
||||
// Middleware remaining on the stack will not even see the request
|
||||
// if, by this point, there are any errors.
|
||||
// This is a "default" handler, of sorts, and you are
|
||||
// welcome to use your own instead. The Bind middleware
|
||||
// invokes this automatically for convenience.
|
||||
func errorHandler(errs Errors, rw http.ResponseWriter) {
|
||||
if len(errs) > 0 {
|
||||
rw.Header().Set("Content-Type", _JSON_CONTENT_TYPE)
|
||||
if errs.Has(ERR_DESERIALIZATION) {
|
||||
rw.WriteHeader(http.StatusBadRequest)
|
||||
} else if errs.Has(ERR_CONTENT_TYPE) {
|
||||
rw.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
} else {
|
||||
rw.WriteHeader(STATUS_UNPROCESSABLE_ENTITY)
|
||||
}
|
||||
errOutput, _ := json.Marshal(errs)
|
||||
rw.Write(errOutput)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Bind wraps up the functionality of the Form and Json middleware
|
||||
// according to the Content-Type and verb of the request.
|
||||
// A Content-Type is required for POST and PUT requests.
|
||||
// Bind invokes the ErrorHandler middleware to bail out if errors
|
||||
// occurred. If you want to perform your own error handling, use
|
||||
// Form or Json middleware directly. An interface pointer can
|
||||
// be added as a second argument in order to map the struct to
|
||||
// a specific interface.
|
||||
func Bind(obj interface{}, ifacePtr ...interface{}) macaron.Handler {
|
||||
return func(ctx *macaron.Context) {
|
||||
bind(ctx, obj, ifacePtr...)
|
||||
if handler, ok := obj.(ErrorHandler); ok {
|
||||
ctx.Invoke(handler.Error)
|
||||
} else {
|
||||
ctx.Invoke(errorHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BindIgnErr will do the exactly same thing as Bind but without any
|
||||
// error handling, which user has freedom to deal with them.
|
||||
// This allows user take advantages of validation.
|
||||
func BindIgnErr(obj interface{}, ifacePtr ...interface{}) macaron.Handler {
|
||||
return func(ctx *macaron.Context) {
|
||||
bind(ctx, obj, ifacePtr...)
|
||||
}
|
||||
}
|
||||
|
||||
// Form is middleware to deserialize form-urlencoded data from the request.
|
||||
// It gets data from the form-urlencoded body, if present, or from the
|
||||
// query string. It uses the http.Request.ParseForm() method
|
||||
// to perform deserialization, then reflection is used to map each field
|
||||
// into the struct with the proper type. Structs with primitive slice types
|
||||
// (bool, float, int, string) can support deserialization of repeated form
|
||||
// keys, for example: key=val1&key=val2&key=val3
|
||||
// An interface pointer can be added as a second argument in order
|
||||
// to map the struct to a specific interface.
|
||||
func Form(formStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
|
||||
return func(ctx *macaron.Context) {
|
||||
var errors Errors
|
||||
|
||||
ensureNotPointer(formStruct)
|
||||
formStruct := reflect.New(reflect.TypeOf(formStruct))
|
||||
parseErr := ctx.Req.ParseForm()
|
||||
|
||||
// Format validation of the request body or the URL would add considerable overhead,
|
||||
// and ParseForm does not complain when URL encoding is off.
|
||||
// Because an empty request body or url can also mean absence of all needed values,
|
||||
// it is not in all cases a bad request, so let's return 422.
|
||||
if parseErr != nil {
|
||||
errors.Add([]string{}, ERR_DESERIALIZATION, parseErr.Error())
|
||||
}
|
||||
errors = mapForm(formStruct, ctx.Req.Form, nil, errors)
|
||||
validateAndMap(formStruct, ctx, errors, ifacePtr...)
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// MultipartForm works much like Form, except it can parse multipart forms
|
||||
// and handle file uploads. Like the other deserialization middleware handlers,
|
||||
// you can pass in an interface to make the interface available for injection
|
||||
// into other handlers later.
|
||||
func MultipartForm(formStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
|
||||
return func(ctx *macaron.Context) {
|
||||
var errors Errors
|
||||
ensureNotPointer(formStruct)
|
||||
formStruct := reflect.New(reflect.TypeOf(formStruct))
|
||||
// This if check is necessary due to https://github.com/martini-contrib/csrf/issues/6
|
||||
if ctx.Req.MultipartForm == nil {
|
||||
// Workaround for multipart forms returning nil instead of an error
|
||||
// when content is not multipart; see https://code.google.com/p/go/issues/detail?id=6334
|
||||
if multipartReader, err := ctx.Req.MultipartReader(); err != nil {
|
||||
errors.Add([]string{}, ERR_DESERIALIZATION, err.Error())
|
||||
} else {
|
||||
form, parseErr := multipartReader.ReadForm(MaxMemory)
|
||||
if parseErr != nil {
|
||||
errors.Add([]string{}, ERR_DESERIALIZATION, parseErr.Error())
|
||||
}
|
||||
|
||||
if ctx.Req.Form == nil {
|
||||
ctx.Req.ParseForm()
|
||||
}
|
||||
for k, v := range form.Value {
|
||||
ctx.Req.Form[k] = append(ctx.Req.Form[k], v...)
|
||||
}
|
||||
|
||||
ctx.Req.MultipartForm = form
|
||||
}
|
||||
}
|
||||
errors = mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors)
|
||||
validateAndMap(formStruct, ctx, errors, ifacePtr...)
|
||||
}
|
||||
}
|
||||
|
||||
// Json is middleware to deserialize a JSON payload from the request
|
||||
// into the struct that is passed in. The resulting struct is then
|
||||
// validated, but no error handling is actually performed here.
|
||||
// An interface pointer can be added as a second argument in order
|
||||
// to map the struct to a specific interface.
|
||||
func Json(jsonStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
|
||||
return func(ctx *macaron.Context) {
|
||||
var errors Errors
|
||||
ensureNotPointer(jsonStruct)
|
||||
jsonStruct := reflect.New(reflect.TypeOf(jsonStruct))
|
||||
if ctx.Req.Request.Body != nil {
|
||||
defer ctx.Req.Request.Body.Close()
|
||||
err := json.NewDecoder(ctx.Req.Request.Body).Decode(jsonStruct.Interface())
|
||||
if err != nil && err != io.EOF {
|
||||
errors.Add([]string{}, ERR_DESERIALIZATION, err.Error())
|
||||
}
|
||||
}
|
||||
validateAndMap(jsonStruct, ctx, errors, ifacePtr...)
|
||||
}
|
||||
}
|
||||
|
||||
// RawValidate is same as Validate but does not require a HTTP context,
|
||||
// and can be used independently just for validation.
|
||||
// This function does not support Validator interface.
|
||||
func RawValidate(obj interface{}) Errors {
|
||||
var errs Errors
|
||||
v := reflect.ValueOf(obj)
|
||||
k := v.Kind()
|
||||
if k == reflect.Interface || k == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
k = v.Kind()
|
||||
}
|
||||
if k == reflect.Slice || k == reflect.Array {
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
e := v.Index(i).Interface()
|
||||
errs = validateStruct(errs, e)
|
||||
}
|
||||
} else {
|
||||
errs = validateStruct(errs, obj)
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// Validate is middleware to enforce required fields. If the struct
|
||||
// passed in implements Validator, then the user-defined Validate method
|
||||
// is executed, and its errors are mapped to the context. This middleware
|
||||
// performs no error handling: it merely detects errors and maps them.
|
||||
func Validate(obj interface{}) macaron.Handler {
|
||||
return func(ctx *macaron.Context) {
|
||||
var errs Errors
|
||||
v := reflect.ValueOf(obj)
|
||||
k := v.Kind()
|
||||
if k == reflect.Interface || k == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
k = v.Kind()
|
||||
}
|
||||
if k == reflect.Slice || k == reflect.Array {
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
e := v.Index(i).Interface()
|
||||
errs = validateStruct(errs, e)
|
||||
if validator, ok := e.(Validator); ok {
|
||||
errs = validator.Validate(ctx, errs)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errs = validateStruct(errs, obj)
|
||||
if validator, ok := obj.(Validator); ok {
|
||||
errs = validator.Validate(ctx, errs)
|
||||
}
|
||||
}
|
||||
ctx.Map(errs)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
AlphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
|
||||
AlphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]")
|
||||
EmailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
|
||||
)
|
||||
|
||||
// Copied from github.com/asaskevich/govalidator.
|
||||
const _MAX_URL_RUNE_COUNT = 2083
|
||||
const _MIN_URL_RUNE_COUNT = 3
|
||||
|
||||
var (
|
||||
urlSchemaRx = `((ftp|tcp|udp|wss?|https?):\/\/)`
|
||||
urlUsernameRx = `(\S+(:\S*)?@)`
|
||||
urlIPRx = `([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))`
|
||||
ipRx = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
|
||||
urlSubdomainRx = `((www\.)|([a-zA-Z0-9]([-\.][-\._a-zA-Z0-9]+)*))`
|
||||
urlPortRx = `(:(\d{1,5}))`
|
||||
urlPathRx = `((\/|\?|#)[^\s]*)`
|
||||
URLPattern = regexp.MustCompile(`^` + urlSchemaRx + `?` + urlUsernameRx + `?` + `((` + urlIPRx + `|(\[` + ipRx + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + urlSubdomainRx + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + urlPortRx + `?` + urlPathRx + `?$`)
|
||||
)
|
||||
|
||||
// IsURL check if the string is an URL.
|
||||
func isURL(str string) bool {
|
||||
if str == "" || utf8.RuneCountInString(str) >= _MAX_URL_RUNE_COUNT || len(str) <= _MIN_URL_RUNE_COUNT || strings.HasPrefix(str, ".") {
|
||||
return false
|
||||
}
|
||||
u, err := url.Parse(str)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if strings.HasPrefix(u.Host, ".") {
|
||||
return false
|
||||
}
|
||||
if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
|
||||
return false
|
||||
}
|
||||
return URLPattern.MatchString(str)
|
||||
|
||||
}
|
||||
|
||||
type (
|
||||
// Rule represents a validation rule.
|
||||
Rule struct {
|
||||
// IsMatch checks if rule matches.
|
||||
IsMatch func(string) bool
|
||||
// IsValid applies validation rule to condition.
|
||||
IsValid func(Errors, string, interface{}) (bool, Errors)
|
||||
}
|
||||
|
||||
// ParamRule does same thing as Rule but passes rule itself to IsValid method.
|
||||
ParamRule struct {
|
||||
// IsMatch checks if rule matches.
|
||||
IsMatch func(string) bool
|
||||
// IsValid applies validation rule to condition.
|
||||
IsValid func(Errors, string, string, interface{}) (bool, Errors)
|
||||
}
|
||||
|
||||
// RuleMapper and ParamRuleMapper represent validation rule mappers,
|
||||
// it allwos users to add custom validation rules.
|
||||
RuleMapper []*Rule
|
||||
ParamRuleMapper []*ParamRule
|
||||
)
|
||||
|
||||
var ruleMapper RuleMapper
|
||||
var paramRuleMapper ParamRuleMapper
|
||||
|
||||
// AddRule adds new validation rule.
|
||||
func AddRule(r *Rule) {
|
||||
ruleMapper = append(ruleMapper, r)
|
||||
}
|
||||
|
||||
// AddParamRule adds new validation rule.
|
||||
func AddParamRule(r *ParamRule) {
|
||||
paramRuleMapper = append(paramRuleMapper, r)
|
||||
}
|
||||
|
||||
func in(fieldValue interface{}, arr string) bool {
|
||||
val := fmt.Sprintf("%v", fieldValue)
|
||||
vals := strings.Split(arr, ",")
|
||||
isIn := false
|
||||
for _, v := range vals {
|
||||
if v == val {
|
||||
isIn = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return isIn
|
||||
}
|
||||
|
||||
func parseFormName(raw, actual string) string {
|
||||
if len(actual) > 0 {
|
||||
return actual
|
||||
}
|
||||
return nameMapper(raw)
|
||||
}
|
||||
|
||||
// Performs required field checking on a struct
|
||||
func validateStruct(errors Errors, obj interface{}) Errors {
|
||||
typ := reflect.TypeOf(obj)
|
||||
val := reflect.ValueOf(obj)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
|
||||
// Allow ignored fields in the struct
|
||||
if field.Tag.Get("form") == "-" || !val.Field(i).CanInterface() {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldVal := val.Field(i)
|
||||
fieldValue := fieldVal.Interface()
|
||||
zero := reflect.Zero(field.Type).Interface()
|
||||
|
||||
// Validate nested and embedded structs (if pointer, only do so if not nil)
|
||||
if field.Type.Kind() == reflect.Struct ||
|
||||
(field.Type.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, fieldValue) &&
|
||||
field.Type.Elem().Kind() == reflect.Struct) {
|
||||
errors = validateStruct(errors, fieldValue)
|
||||
}
|
||||
errors = validateField(errors, zero, field, fieldVal, fieldValue)
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
func validateField(errors Errors, zero interface{}, field reflect.StructField, fieldVal reflect.Value, fieldValue interface{}) Errors {
|
||||
if fieldVal.Kind() == reflect.Slice {
|
||||
for i := 0; i < fieldVal.Len(); i++ {
|
||||
sliceVal := fieldVal.Index(i)
|
||||
if sliceVal.Kind() == reflect.Ptr {
|
||||
sliceVal = sliceVal.Elem()
|
||||
}
|
||||
|
||||
sliceValue := sliceVal.Interface()
|
||||
zero := reflect.Zero(sliceVal.Type()).Interface()
|
||||
if sliceVal.Kind() == reflect.Struct ||
|
||||
(sliceVal.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, sliceValue) &&
|
||||
sliceVal.Elem().Kind() == reflect.Struct) {
|
||||
errors = validateStruct(errors, sliceValue)
|
||||
}
|
||||
/* Apply validation rules to each item in a slice. ISSUE #3
|
||||
else {
|
||||
errors = validateField(errors, zero, field, sliceVal, sliceValue)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
VALIDATE_RULES:
|
||||
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
|
||||
if len(rule) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case rule == "OmitEmpty":
|
||||
if reflect.DeepEqual(zero, fieldValue) {
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "Required":
|
||||
v := reflect.ValueOf(fieldValue)
|
||||
if v.Kind() == reflect.Slice {
|
||||
if v.Len() == 0 {
|
||||
errors.Add([]string{field.Name}, ERR_REQUIRED, "Required")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(zero, fieldValue) {
|
||||
errors.Add([]string{field.Name}, ERR_REQUIRED, "Required")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "AlphaDash":
|
||||
if AlphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
errors.Add([]string{field.Name}, ERR_ALPHA_DASH, "AlphaDash")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "AlphaDashDot":
|
||||
if AlphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
errors.Add([]string{field.Name}, ERR_ALPHA_DASH_DOT, "AlphaDashDot")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "Size("):
|
||||
size, _ := strconv.Atoi(rule[5 : len(rule)-1])
|
||||
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) != size {
|
||||
errors.Add([]string{field.Name}, ERR_SIZE, "Size")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
v := reflect.ValueOf(fieldValue)
|
||||
if v.Kind() == reflect.Slice && v.Len() != size {
|
||||
errors.Add([]string{field.Name}, ERR_SIZE, "Size")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "MinSize("):
|
||||
min, _ := strconv.Atoi(rule[8 : len(rule)-1])
|
||||
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) < min {
|
||||
errors.Add([]string{field.Name}, ERR_MIN_SIZE, "MinSize")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
v := reflect.ValueOf(fieldValue)
|
||||
if v.Kind() == reflect.Slice && v.Len() < min {
|
||||
errors.Add([]string{field.Name}, ERR_MIN_SIZE, "MinSize")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "MaxSize("):
|
||||
max, _ := strconv.Atoi(rule[8 : len(rule)-1])
|
||||
if str, ok := fieldValue.(string); ok && utf8.RuneCountInString(str) > max {
|
||||
errors.Add([]string{field.Name}, ERR_MAX_SIZE, "MaxSize")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
v := reflect.ValueOf(fieldValue)
|
||||
if v.Kind() == reflect.Slice && v.Len() > max {
|
||||
errors.Add([]string{field.Name}, ERR_MAX_SIZE, "MaxSize")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "Range("):
|
||||
nums := strings.Split(rule[6:len(rule)-1], ",")
|
||||
if len(nums) != 2 {
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
val := com.StrTo(fmt.Sprintf("%v", fieldValue)).MustInt()
|
||||
if val < com.StrTo(nums[0]).MustInt() || val > com.StrTo(nums[1]).MustInt() {
|
||||
errors.Add([]string{field.Name}, ERR_RANGE, "Range")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "Email":
|
||||
if !EmailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
errors.Add([]string{field.Name}, ERR_EMAIL, "Email")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "Url":
|
||||
str := fmt.Sprintf("%v", fieldValue)
|
||||
if len(str) == 0 {
|
||||
continue
|
||||
} else if !isURL(str) {
|
||||
errors.Add([]string{field.Name}, ERR_URL, "Url")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "In("):
|
||||
if !in(fieldValue, rule[3:len(rule)-1]) {
|
||||
errors.Add([]string{field.Name}, ERR_IN, "In")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "NotIn("):
|
||||
if in(fieldValue, rule[6:len(rule)-1]) {
|
||||
errors.Add([]string{field.Name}, ERR_NOT_INT, "NotIn")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "Include("):
|
||||
if !strings.Contains(fmt.Sprintf("%v", fieldValue), rule[8:len(rule)-1]) {
|
||||
errors.Add([]string{field.Name}, ERR_INCLUDE, "Include")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "Exclude("):
|
||||
if strings.Contains(fmt.Sprintf("%v", fieldValue), rule[8:len(rule)-1]) {
|
||||
errors.Add([]string{field.Name}, ERR_EXCLUDE, "Exclude")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case strings.HasPrefix(rule, "Default("):
|
||||
if reflect.DeepEqual(zero, fieldValue) {
|
||||
if fieldVal.CanAddr() {
|
||||
errors = setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors)
|
||||
} else {
|
||||
errors.Add([]string{field.Name}, ERR_EXCLUDE, "Default")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Apply custom validation rules
|
||||
var isValid bool
|
||||
for i := range ruleMapper {
|
||||
if ruleMapper[i].IsMatch(rule) {
|
||||
isValid, errors = ruleMapper[i].IsValid(errors, field.Name, fieldValue)
|
||||
if !isValid {
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := range paramRuleMapper {
|
||||
if paramRuleMapper[i].IsMatch(rule) {
|
||||
isValid, errors = paramRuleMapper[i].IsValid(errors, rule, field.Name, fieldValue)
|
||||
if !isValid {
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
// NameMapper represents a form tag name mapper.
|
||||
type NameMapper func(string) string
|
||||
|
||||
var (
|
||||
nameMapper = func(field string) string {
|
||||
newstr := make([]rune, 0, len(field))
|
||||
for i, chr := range field {
|
||||
if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
|
||||
if i > 0 {
|
||||
newstr = append(newstr, '_')
|
||||
}
|
||||
chr -= ('A' - 'a')
|
||||
}
|
||||
newstr = append(newstr, chr)
|
||||
}
|
||||
return string(newstr)
|
||||
}
|
||||
)
|
||||
|
||||
// SetNameMapper sets name mapper.
|
||||
func SetNameMapper(nm NameMapper) {
|
||||
nameMapper = nm
|
||||
}
|
||||
|
||||
// Takes values from the form data and puts them into a struct
|
||||
func mapForm(formStruct reflect.Value, form map[string][]string,
|
||||
formfile map[string][]*multipart.FileHeader, errors Errors) Errors {
|
||||
|
||||
if formStruct.Kind() == reflect.Ptr {
|
||||
formStruct = formStruct.Elem()
|
||||
}
|
||||
typ := formStruct.Type()
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
typeField := typ.Field(i)
|
||||
structField := formStruct.Field(i)
|
||||
|
||||
if typeField.Type.Kind() == reflect.Ptr && typeField.Anonymous {
|
||||
structField.Set(reflect.New(typeField.Type.Elem()))
|
||||
errors = mapForm(structField.Elem(), form, formfile, errors)
|
||||
if reflect.DeepEqual(structField.Elem().Interface(), reflect.Zero(structField.Elem().Type()).Interface()) {
|
||||
structField.Set(reflect.Zero(structField.Type()))
|
||||
}
|
||||
} else if typeField.Type.Kind() == reflect.Struct {
|
||||
errors = mapForm(structField, form, formfile, errors)
|
||||
}
|
||||
|
||||
inputFieldName := parseFormName(typeField.Name, typeField.Tag.Get("form"))
|
||||
if len(inputFieldName) == 0 || !structField.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
inputValue, exists := form[inputFieldName]
|
||||
if exists {
|
||||
numElems := len(inputValue)
|
||||
if structField.Kind() == reflect.Slice && numElems > 0 {
|
||||
sliceOf := structField.Type().Elem().Kind()
|
||||
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
|
||||
for i := 0; i < numElems; i++ {
|
||||
errors = setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
|
||||
}
|
||||
formStruct.Field(i).Set(slice)
|
||||
} else {
|
||||
errors = setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
inputFile, exists := formfile[inputFieldName]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
fhType := reflect.TypeOf((*multipart.FileHeader)(nil))
|
||||
numElems := len(inputFile)
|
||||
if structField.Kind() == reflect.Slice && numElems > 0 && structField.Type().Elem() == fhType {
|
||||
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
|
||||
for i := 0; i < numElems; i++ {
|
||||
slice.Index(i).Set(reflect.ValueOf(inputFile[i]))
|
||||
}
|
||||
structField.Set(slice)
|
||||
} else if structField.Type() == fhType {
|
||||
structField.Set(reflect.ValueOf(inputFile[0]))
|
||||
}
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
// This sets the value in a struct of an indeterminate type to the
|
||||
// matching value from the request (via Form middleware) in the
|
||||
// same type, so that not all deserialized values have to be strings.
|
||||
// Supported types are string, int, float, and bool.
|
||||
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) Errors {
|
||||
switch valueKind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if val == "" {
|
||||
val = "0"
|
||||
}
|
||||
intVal, err := strconv.ParseInt(val, 10, 64)
|
||||
if err != nil {
|
||||
errors.Add([]string{nameInTag}, ERR_INTERGER_TYPE, "Value could not be parsed as integer")
|
||||
} else {
|
||||
structField.SetInt(intVal)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
if val == "" {
|
||||
val = "0"
|
||||
}
|
||||
uintVal, err := strconv.ParseUint(val, 10, 64)
|
||||
if err != nil {
|
||||
errors.Add([]string{nameInTag}, ERR_INTERGER_TYPE, "Value could not be parsed as unsigned integer")
|
||||
} else {
|
||||
structField.SetUint(uintVal)
|
||||
}
|
||||
case reflect.Bool:
|
||||
if val == "on" {
|
||||
structField.SetBool(true)
|
||||
break
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
val = "false"
|
||||
}
|
||||
boolVal, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
errors.Add([]string{nameInTag}, ERR_BOOLEAN_TYPE, "Value could not be parsed as boolean")
|
||||
} else if boolVal {
|
||||
structField.SetBool(true)
|
||||
}
|
||||
case reflect.Float32:
|
||||
if val == "" {
|
||||
val = "0.0"
|
||||
}
|
||||
floatVal, err := strconv.ParseFloat(val, 32)
|
||||
if err != nil {
|
||||
errors.Add([]string{nameInTag}, ERR_FLOAT_TYPE, "Value could not be parsed as 32-bit float")
|
||||
} else {
|
||||
structField.SetFloat(floatVal)
|
||||
}
|
||||
case reflect.Float64:
|
||||
if val == "" {
|
||||
val = "0.0"
|
||||
}
|
||||
floatVal, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
errors.Add([]string{nameInTag}, ERR_FLOAT_TYPE, "Value could not be parsed as 64-bit float")
|
||||
} else {
|
||||
structField.SetFloat(floatVal)
|
||||
}
|
||||
case reflect.String:
|
||||
structField.SetString(val)
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
// Don't pass in pointers to bind to. Can lead to bugs.
|
||||
func ensureNotPointer(obj interface{}) {
|
||||
if reflect.TypeOf(obj).Kind() == reflect.Ptr {
|
||||
panic("Pointers are not accepted as binding models")
|
||||
}
|
||||
}
|
||||
|
||||
// Performs validation and combines errors from validation
|
||||
// with errors from deserialization, then maps both the
|
||||
// resulting struct and the errors to the context.
|
||||
func validateAndMap(obj reflect.Value, ctx *macaron.Context, errors Errors, ifacePtr ...interface{}) {
|
||||
ctx.Invoke(Validate(obj.Interface()))
|
||||
errors = append(errors, getErrors(ctx)...)
|
||||
ctx.Map(errors)
|
||||
ctx.Map(obj.Elem().Interface())
|
||||
if len(ifacePtr) > 0 {
|
||||
ctx.MapTo(obj.Elem().Interface(), ifacePtr[0])
|
||||
}
|
||||
}
|
||||
|
||||
// getErrors simply gets the errors from the context (it's kind of a chore)
|
||||
func getErrors(ctx *macaron.Context) Errors {
|
||||
return ctx.GetVal(reflect.TypeOf(Errors{})).Interface().(Errors)
|
||||
}
|
||||
|
||||
type (
|
||||
// ErrorHandler is the interface that has custom error handling process.
|
||||
ErrorHandler interface {
|
||||
// Error handles validation errors with custom process.
|
||||
Error(*macaron.Context, Errors)
|
||||
}
|
||||
|
||||
// Validator is the interface that handles some rudimentary
|
||||
// request validation logic so your application doesn't have to.
|
||||
Validator interface {
|
||||
// Validate validates that the request is OK. It is recommended
|
||||
// that validation be limited to checking values for syntax and
|
||||
// semantics, enough to know that you can make sense of the request
|
||||
// in your application. For example, you might verify that a credit
|
||||
// card number matches a valid pattern, but you probably wouldn't
|
||||
// perform an actual credit card authorization here.
|
||||
Validate(*macaron.Context, Errors) Errors
|
||||
}
|
||||
)
|
159
vendor/gitea.com/macaron/binding/errors.go
generated
vendored
Normal file
159
vendor/gitea.com/macaron/binding/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
// Copyright 2014 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 binding
|
||||
|
||||
const (
|
||||
// Type mismatch errors.
|
||||
ERR_CONTENT_TYPE = "ContentTypeError"
|
||||
ERR_DESERIALIZATION = "DeserializationError"
|
||||
ERR_INTERGER_TYPE = "IntegerTypeError"
|
||||
ERR_BOOLEAN_TYPE = "BooleanTypeError"
|
||||
ERR_FLOAT_TYPE = "FloatTypeError"
|
||||
|
||||
// Validation errors.
|
||||
ERR_REQUIRED = "RequiredError"
|
||||
ERR_ALPHA_DASH = "AlphaDashError"
|
||||
ERR_ALPHA_DASH_DOT = "AlphaDashDotError"
|
||||
ERR_SIZE = "SizeError"
|
||||
ERR_MIN_SIZE = "MinSizeError"
|
||||
ERR_MAX_SIZE = "MaxSizeError"
|
||||
ERR_RANGE = "RangeError"
|
||||
ERR_EMAIL = "EmailError"
|
||||
ERR_URL = "UrlError"
|
||||
ERR_IN = "InError"
|
||||
ERR_NOT_INT = "NotInError"
|
||||
ERR_INCLUDE = "IncludeError"
|
||||
ERR_EXCLUDE = "ExcludeError"
|
||||
ERR_DEFAULT = "DefaultError"
|
||||
)
|
||||
|
||||
type (
|
||||
// Errors may be generated during deserialization, binding,
|
||||
// or validation. This type is mapped to the context so you
|
||||
// can inject it into your own handlers and use it in your
|
||||
// application if you want all your errors to look the same.
|
||||
Errors []Error
|
||||
|
||||
Error struct {
|
||||
// An error supports zero or more field names, because an
|
||||
// error can morph three ways: (1) it can indicate something
|
||||
// wrong with the request as a whole, (2) it can point to a
|
||||
// specific problem with a particular input field, or (3) it
|
||||
// can span multiple related input fields.
|
||||
FieldNames []string `json:"fieldNames,omitempty"`
|
||||
|
||||
// The classification is like an error code, convenient to
|
||||
// use when processing or categorizing an error programmatically.
|
||||
// It may also be called the "kind" of error.
|
||||
Classification string `json:"classification,omitempty"`
|
||||
|
||||
// Message should be human-readable and detailed enough to
|
||||
// pinpoint and resolve the problem, but it should be brief. For
|
||||
// example, a payload of 100 objects in a JSON array might have
|
||||
// an error in the 41st object. The message should help the
|
||||
// end user find and fix the error with their request.
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// Add adds an error associated with the fields indicated
|
||||
// by fieldNames, with the given classification and message.
|
||||
func (e *Errors) Add(fieldNames []string, classification, message string) {
|
||||
*e = append(*e, Error{
|
||||
FieldNames: fieldNames,
|
||||
Classification: classification,
|
||||
Message: message,
|
||||
})
|
||||
}
|
||||
|
||||
// Len returns the number of errors.
|
||||
func (e *Errors) Len() int {
|
||||
return len(*e)
|
||||
}
|
||||
|
||||
// Has determines whether an Errors slice has an Error with
|
||||
// a given classification in it; it does not search on messages
|
||||
// or field names.
|
||||
func (e *Errors) Has(class string) bool {
|
||||
for _, err := range *e {
|
||||
if err.Kind() == class {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
// WithClass gets a copy of errors that are classified by the
|
||||
// the given classification.
|
||||
func (e *Errors) WithClass(classification string) Errors {
|
||||
var errs Errors
|
||||
for _, err := range *e {
|
||||
if err.Kind() == classification {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// ForField gets a copy of errors that are associated with the
|
||||
// field by the given name.
|
||||
func (e *Errors) ForField(name string) Errors {
|
||||
var errs Errors
|
||||
for _, err := range *e {
|
||||
for _, fieldName := range err.Fields() {
|
||||
if fieldName == name {
|
||||
errs = append(errs, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// Get gets errors of a particular class for the specified
|
||||
// field name.
|
||||
func (e *Errors) Get(class, fieldName string) Errors {
|
||||
var errs Errors
|
||||
for _, err := range *e {
|
||||
if err.Kind() == class {
|
||||
for _, nameOfField := range err.Fields() {
|
||||
if nameOfField == fieldName {
|
||||
errs = append(errs, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
*/
|
||||
|
||||
// Fields returns the list of field names this error is
|
||||
// associated with.
|
||||
func (e Error) Fields() []string {
|
||||
return e.FieldNames
|
||||
}
|
||||
|
||||
// Kind returns this error's classification.
|
||||
func (e Error) Kind() string {
|
||||
return e.Classification
|
||||
}
|
||||
|
||||
// Error returns this error's message.
|
||||
func (e Error) Error() string {
|
||||
return e.Message
|
||||
}
|
9
vendor/gitea.com/macaron/binding/go.mod
generated
vendored
Normal file
9
vendor/gitea.com/macaron/binding/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
module gitea.com/macaron/binding
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e
|
||||
)
|
30
vendor/gitea.com/macaron/binding/go.sum
generated
vendored
Normal file
30
vendor/gitea.com/macaron/binding/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
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/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 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
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.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
24
vendor/gitea.com/macaron/cache/.drone.yml
generated
vendored
Normal file
24
vendor/gitea.com/macaron/cache/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
kind: pipeline
|
||||
name: go1-1-1
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: go1-1-2
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
5
vendor/gitea.com/macaron/cache/.gitignore
generated
vendored
Normal file
5
vendor/gitea.com/macaron/cache/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
nodb/cache
|
||||
ledis/tmp.db/
|
||||
nodb/tmp.db/
|
||||
/vendor
|
||||
/.idea
|
191
vendor/gitea.com/macaron/cache/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/cache/LICENSE
generated
vendored
Normal 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.
|
20
vendor/gitea.com/macaron/cache/README.md
generated
vendored
Normal file
20
vendor/gitea.com/macaron/cache/README.md
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
# cache
|
||||
|
||||
Middleware cache provides cache management for [Macaron](https://github.com/go-macaron/macaron). It can use many cache adapters, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Ledis and Nodb.
|
||||
|
||||
### Installation
|
||||
|
||||
go get gitea.com/macaron/cache
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/gitea.com/macaron/cache)
|
||||
- [Documentation](http://go-macaron.com/docs/middlewares/cache)
|
||||
|
||||
## Credits
|
||||
|
||||
This package is a modified version of [go-macaron/cache](github.com/go-macaron/cache).
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
122
vendor/gitea.com/macaron/cache/cache.go
generated
vendored
Normal file
122
vendor/gitea.com/macaron/cache/cache.go
generated
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
// Copyright 2013 Beego 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 cache is a middleware that provides the cache management of Macaron.
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitea.com/macaron/macaron"
|
||||
)
|
||||
|
||||
const _VERSION = "0.3.0"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
}
|
||||
|
||||
// Cache is the interface that operates the cache data.
|
||||
type Cache interface {
|
||||
// Put puts value into cache with key and expire time.
|
||||
Put(key string, val interface{}, timeout int64) error
|
||||
// Get gets cached value by given key.
|
||||
Get(key string) interface{}
|
||||
// Delete deletes cached value by given key.
|
||||
Delete(key string) error
|
||||
// Incr increases cached int-type value by given key as a counter.
|
||||
Incr(key string) error
|
||||
// Decr decreases cached int-type value by given key as a counter.
|
||||
Decr(key string) error
|
||||
// IsExist returns true if cached value exists.
|
||||
IsExist(key string) bool
|
||||
// Flush deletes all cached data.
|
||||
Flush() error
|
||||
// StartAndGC starts GC routine based on config string settings.
|
||||
StartAndGC(opt Options) error
|
||||
}
|
||||
|
||||
// Options represents a struct for specifying configuration options for the cache middleware.
|
||||
type Options struct {
|
||||
// Name of adapter. Default is "memory".
|
||||
Adapter string
|
||||
// Adapter configuration, it's corresponding to adapter.
|
||||
AdapterConfig string
|
||||
// GC interval time in seconds. Default is 60.
|
||||
Interval int
|
||||
// Occupy entire database. Default is false.
|
||||
OccupyMode bool
|
||||
// Configuration section name. Default is "cache".
|
||||
Section string
|
||||
}
|
||||
|
||||
func prepareOptions(options []Options) Options {
|
||||
var opt Options
|
||||
if len(options) > 0 {
|
||||
opt = options[0]
|
||||
}
|
||||
if len(opt.Section) == 0 {
|
||||
opt.Section = "cache"
|
||||
}
|
||||
sec := macaron.Config().Section(opt.Section)
|
||||
|
||||
if len(opt.Adapter) == 0 {
|
||||
opt.Adapter = sec.Key("ADAPTER").MustString("memory")
|
||||
}
|
||||
if opt.Interval == 0 {
|
||||
opt.Interval = sec.Key("INTERVAL").MustInt(60)
|
||||
}
|
||||
if len(opt.AdapterConfig) == 0 {
|
||||
opt.AdapterConfig = sec.Key("ADAPTER_CONFIG").MustString("data/caches")
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
// NewCacher creates and returns a new cacher by given adapter name and configuration.
|
||||
// It panics when given adapter isn't registered and starts GC automatically.
|
||||
func NewCacher(name string, opt Options) (Cache, error) {
|
||||
adapter, ok := adapters[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cache: unknown adapter '%s'(forgot to import?)", name)
|
||||
}
|
||||
return adapter, adapter.StartAndGC(opt)
|
||||
}
|
||||
|
||||
// Cacher is a middleware that maps a cache.Cache service into the Macaron handler chain.
|
||||
// An single variadic cache.Options struct can be optionally provided to configure.
|
||||
func Cacher(options ...Options) macaron.Handler {
|
||||
opt := prepareOptions(options)
|
||||
cache, err := NewCacher(opt.Adapter, opt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return func(ctx *macaron.Context) {
|
||||
ctx.Map(cache)
|
||||
}
|
||||
}
|
||||
|
||||
var adapters = make(map[string]Cache)
|
||||
|
||||
// Register registers a adapter.
|
||||
func Register(name string, adapter Cache) {
|
||||
if adapter == nil {
|
||||
panic("cache: cannot register adapter with nil value")
|
||||
}
|
||||
if _, dup := adapters[name]; dup {
|
||||
panic(fmt.Errorf("cache: cannot register adapter '%s' twice", name))
|
||||
}
|
||||
adapters[name] = adapter
|
||||
}
|
208
vendor/gitea.com/macaron/cache/file.go
generated
vendored
Normal file
208
vendor/gitea.com/macaron/cache/file.go
generated
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
// Copyright 2013 Beego 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 cache
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.com/macaron/macaron"
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
// Item represents a cache item.
|
||||
type Item struct {
|
||||
Val interface{}
|
||||
Created int64
|
||||
Expire int64
|
||||
}
|
||||
|
||||
func (item *Item) hasExpired() bool {
|
||||
return item.Expire > 0 &&
|
||||
(time.Now().Unix()-item.Created) >= item.Expire
|
||||
}
|
||||
|
||||
// FileCacher represents a file cache adapter implementation.
|
||||
type FileCacher struct {
|
||||
lock sync.Mutex
|
||||
rootPath string
|
||||
interval int // GC interval.
|
||||
}
|
||||
|
||||
// NewFileCacher creates and returns a new file cacher.
|
||||
func NewFileCacher() *FileCacher {
|
||||
return &FileCacher{}
|
||||
}
|
||||
|
||||
func (c *FileCacher) filepath(key string) string {
|
||||
m := md5.Sum([]byte(key))
|
||||
hash := hex.EncodeToString(m[:])
|
||||
return filepath.Join(c.rootPath, string(hash[0]), string(hash[1]), hash)
|
||||
}
|
||||
|
||||
// Put puts value into cache with key and expire time.
|
||||
// If expired is 0, it will be deleted by next GC operation.
|
||||
func (c *FileCacher) Put(key string, val interface{}, expire int64) error {
|
||||
filename := c.filepath(key)
|
||||
item := &Item{val, time.Now().Unix(), expire}
|
||||
data, err := EncodeGob(item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
os.MkdirAll(filepath.Dir(filename), os.ModePerm)
|
||||
return ioutil.WriteFile(filename, data, os.ModePerm)
|
||||
}
|
||||
|
||||
func (c *FileCacher) read(key string) (*Item, error) {
|
||||
filename := c.filepath(key)
|
||||
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
item := new(Item)
|
||||
return item, DecodeGob(data, item)
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *FileCacher) Get(key string) interface{} {
|
||||
item, err := c.read(key)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if item.hasExpired() {
|
||||
os.Remove(c.filepath(key))
|
||||
return nil
|
||||
}
|
||||
return item.Val
|
||||
}
|
||||
|
||||
// Delete deletes cached value by given key.
|
||||
func (c *FileCacher) Delete(key string) error {
|
||||
return os.Remove(c.filepath(key))
|
||||
}
|
||||
|
||||
// Incr increases cached int-type value by given key as a counter.
|
||||
func (c *FileCacher) Incr(key string) error {
|
||||
item, err := c.read(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
item.Val, err = Incr(item.Val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Put(key, item.Val, item.Expire)
|
||||
}
|
||||
|
||||
// Decrease cached int value.
|
||||
func (c *FileCacher) Decr(key string) error {
|
||||
item, err := c.read(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
item.Val, err = Decr(item.Val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Put(key, item.Val, item.Expire)
|
||||
}
|
||||
|
||||
// IsExist returns true if cached value exists.
|
||||
func (c *FileCacher) IsExist(key string) bool {
|
||||
return com.IsExist(c.filepath(key))
|
||||
}
|
||||
|
||||
// Flush deletes all cached data.
|
||||
func (c *FileCacher) Flush() error {
|
||||
return os.RemoveAll(c.rootPath)
|
||||
}
|
||||
|
||||
func (c *FileCacher) startGC() {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
if c.interval < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
if err := filepath.Walk(c.rootPath, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("Walk: %v", err)
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
fmt.Errorf("ReadFile: %v", err)
|
||||
}
|
||||
|
||||
item := new(Item)
|
||||
if err = DecodeGob(data, item); err != nil {
|
||||
return err
|
||||
}
|
||||
if item.hasExpired() {
|
||||
if err = os.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("Remove: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Printf("error garbage collecting cache files: %v", err)
|
||||
}
|
||||
|
||||
time.AfterFunc(time.Duration(c.interval)*time.Second, func() { c.startGC() })
|
||||
}
|
||||
|
||||
// StartAndGC starts GC routine based on config string settings.
|
||||
func (c *FileCacher) StartAndGC(opt Options) error {
|
||||
c.lock.Lock()
|
||||
c.rootPath = opt.AdapterConfig
|
||||
c.interval = opt.Interval
|
||||
|
||||
if !filepath.IsAbs(c.rootPath) {
|
||||
c.rootPath = filepath.Join(macaron.Root, c.rootPath)
|
||||
}
|
||||
c.lock.Unlock()
|
||||
|
||||
if err := os.MkdirAll(c.rootPath, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go c.startGC()
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("file", NewFileCacher())
|
||||
}
|
30
vendor/gitea.com/macaron/cache/go.mod
generated
vendored
Normal file
30
vendor/gitea.com/macaron/cache/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
module gitea.com/macaron/cache
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/go-redis/redis v6.15.2+incompatible
|
||||
github.com/go-sql-driver/mysql v1.4.1
|
||||
github.com/lib/pq v1.2.0
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de // indirect
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af
|
||||
github.com/mattn/go-sqlite3 v1.11.0 // indirect
|
||||
github.com/onsi/ginkgo v1.8.0 // indirect
|
||||
github.com/onsi/gomega v1.5.0 // indirect
|
||||
github.com/pelletier/go-toml v1.4.0 // indirect
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 // indirect
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d // indirect
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d // indirect
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect
|
||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365 // indirect
|
||||
google.golang.org/appengine v1.6.1 // indirect
|
||||
gopkg.in/ini.v1 v1.44.2
|
||||
)
|
106
vendor/gitea.com/macaron/cache/go.sum
generated
vendored
Normal file
106
vendor/gitea.com/macaron/cache/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 h1:Lgdd/Qp96Qj8jqLpq2cI1I1X7BJnu06efS+XkhRoLUQ=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
|
||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
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/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk=
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ=
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
|
||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
|
||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d h1:qQWKKOvHN7Q9c6GdmUteCef2F9ubxMpxY1IKwpIKz68=
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY=
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92 h1:qvsJwGToa8rxb42cDRhkbKeX2H5N8BH+s2aUikGt8mI=
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d h1:NVwnfyR3rENtlz62bcrkXME3INVUa4lcdGt+opvxExs=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
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/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/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
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-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365 h1:SaXEMXhWzMJThc05vu6uh61Q245r4KaWMrsTedk0FDc=
|
||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.44.2 h1:N6kNUPqiIyxP+s/aINPzRvNpcTVV30qLC0t6ZjZFlUU=
|
||||
gopkg.in/ini.v1 v1.44.2/go.mod h1:M3Cogqpuv0QCi3ExAY5V4uOt4qb/R3xZubo9m8lK5wg=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
92
vendor/gitea.com/macaron/cache/memcache/memcache.go
generated
vendored
Normal file
92
vendor/gitea.com/macaron/cache/memcache/memcache.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
// Copyright 2013 Beego 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 cache
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/bradfitz/gomemcache/memcache"
|
||||
"github.com/unknwon/com"
|
||||
|
||||
"gitea.com/macaron/cache"
|
||||
)
|
||||
|
||||
// MemcacheCacher represents a memcache cache adapter implementation.
|
||||
type MemcacheCacher struct {
|
||||
c *memcache.Client
|
||||
}
|
||||
|
||||
func NewItem(key string, data []byte, expire int32) *memcache.Item {
|
||||
return &memcache.Item{
|
||||
Key: key,
|
||||
Value: data,
|
||||
Expiration: expire,
|
||||
}
|
||||
}
|
||||
|
||||
// Put puts value into cache with key and expire time.
|
||||
// If expired is 0, it lives forever.
|
||||
func (c *MemcacheCacher) Put(key string, val interface{}, expire int64) error {
|
||||
return c.c.Set(NewItem(key, []byte(com.ToStr(val)), int32(expire)))
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *MemcacheCacher) Get(key string) interface{} {
|
||||
item, err := c.c.Get(key)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return string(item.Value)
|
||||
}
|
||||
|
||||
// Delete deletes cached value by given key.
|
||||
func (c *MemcacheCacher) Delete(key string) error {
|
||||
return c.c.Delete(key)
|
||||
}
|
||||
|
||||
// Incr increases cached int-type value by given key as a counter.
|
||||
func (c *MemcacheCacher) Incr(key string) error {
|
||||
_, err := c.c.Increment(key, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
// Decr decreases cached int-type value by given key as a counter.
|
||||
func (c *MemcacheCacher) Decr(key string) error {
|
||||
_, err := c.c.Decrement(key, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsExist returns true if cached value exists.
|
||||
func (c *MemcacheCacher) IsExist(key string) bool {
|
||||
_, err := c.c.Get(key)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Flush deletes all cached data.
|
||||
func (c *MemcacheCacher) Flush() error {
|
||||
return c.c.FlushAll()
|
||||
}
|
||||
|
||||
// StartAndGC starts GC routine based on config string settings.
|
||||
// AdapterConfig: 127.0.0.1:9090;127.0.0.1:9091
|
||||
func (c *MemcacheCacher) StartAndGC(opt cache.Options) error {
|
||||
c.c = memcache.New(strings.Split(opt.AdapterConfig, ";")...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cache.Register("memcache", &MemcacheCacher{})
|
||||
}
|
1
vendor/gitea.com/macaron/cache/memcache/memcache.goconvey
generated
vendored
Normal file
1
vendor/gitea.com/macaron/cache/memcache/memcache.goconvey
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ignore
|
179
vendor/gitea.com/macaron/cache/memory.go
generated
vendored
Normal file
179
vendor/gitea.com/macaron/cache/memory.go
generated
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
// Copyright 2013 Beego 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 cache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MemoryItem represents a memory cache item.
|
||||
type MemoryItem struct {
|
||||
val interface{}
|
||||
created int64
|
||||
expire int64
|
||||
}
|
||||
|
||||
func (item *MemoryItem) hasExpired() bool {
|
||||
return item.expire > 0 &&
|
||||
(time.Now().Unix()-item.created) >= item.expire
|
||||
}
|
||||
|
||||
// MemoryCacher represents a memory cache adapter implementation.
|
||||
type MemoryCacher struct {
|
||||
lock sync.RWMutex
|
||||
items map[string]*MemoryItem
|
||||
interval int // GC interval.
|
||||
}
|
||||
|
||||
// NewMemoryCacher creates and returns a new memory cacher.
|
||||
func NewMemoryCacher() *MemoryCacher {
|
||||
return &MemoryCacher{items: make(map[string]*MemoryItem)}
|
||||
}
|
||||
|
||||
// Put puts value into cache with key and expire time.
|
||||
// If expired is 0, it will be deleted by next GC operation.
|
||||
func (c *MemoryCacher) Put(key string, val interface{}, expire int64) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
c.items[key] = &MemoryItem{
|
||||
val: val,
|
||||
created: time.Now().Unix(),
|
||||
expire: expire,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *MemoryCacher) Get(key string) interface{} {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
item, ok := c.items[key]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if item.hasExpired() {
|
||||
go c.Delete(key)
|
||||
return nil
|
||||
}
|
||||
return item.val
|
||||
}
|
||||
|
||||
// Delete deletes cached value by given key.
|
||||
func (c *MemoryCacher) Delete(key string) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
delete(c.items, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Incr increases cached int-type value by given key as a counter.
|
||||
func (c *MemoryCacher) Incr(key string) (err error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
item, ok := c.items[key]
|
||||
if !ok {
|
||||
return errors.New("key not exist")
|
||||
}
|
||||
item.val, err = Incr(item.val)
|
||||
return err
|
||||
}
|
||||
|
||||
// Decr decreases cached int-type value by given key as a counter.
|
||||
func (c *MemoryCacher) Decr(key string) (err error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
item, ok := c.items[key]
|
||||
if !ok {
|
||||
return errors.New("key not exist")
|
||||
}
|
||||
|
||||
item.val, err = Decr(item.val)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsExist returns true if cached value exists.
|
||||
func (c *MemoryCacher) IsExist(key string) bool {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
_, ok := c.items[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Flush deletes all cached data.
|
||||
func (c *MemoryCacher) Flush() error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
c.items = make(map[string]*MemoryItem)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *MemoryCacher) checkRawExpiration(key string) {
|
||||
item, ok := c.items[key]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if item.hasExpired() {
|
||||
delete(c.items, key)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *MemoryCacher) checkExpiration(key string) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
c.checkRawExpiration(key)
|
||||
}
|
||||
|
||||
func (c *MemoryCacher) startGC() {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
if c.interval < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
if c.items != nil {
|
||||
for key, _ := range c.items {
|
||||
c.checkRawExpiration(key)
|
||||
}
|
||||
}
|
||||
|
||||
time.AfterFunc(time.Duration(c.interval)*time.Second, func() { c.startGC() })
|
||||
}
|
||||
|
||||
// StartAndGC starts GC routine based on config string settings.
|
||||
func (c *MemoryCacher) StartAndGC(opt Options) error {
|
||||
c.lock.Lock()
|
||||
c.interval = opt.Interval
|
||||
c.lock.Unlock()
|
||||
|
||||
go c.startGC()
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("memory", NewMemoryCacher())
|
||||
}
|
178
vendor/gitea.com/macaron/cache/redis/redis.go
generated
vendored
Normal file
178
vendor/gitea.com/macaron/cache/redis/redis.go
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Copyright 2013 Beego 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 cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/unknwon/com"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"gitea.com/macaron/cache"
|
||||
)
|
||||
|
||||
// RedisCacher represents a redis cache adapter implementation.
|
||||
type RedisCacher struct {
|
||||
c *redis.Client
|
||||
prefix string
|
||||
hsetName string
|
||||
occupyMode bool
|
||||
}
|
||||
|
||||
// Put puts value into cache with key and expire time.
|
||||
// If expired is 0, it lives forever.
|
||||
func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
|
||||
key = c.prefix + key
|
||||
if expire == 0 {
|
||||
if err := c.c.Set(key, com.ToStr(val), 0).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
dur, err := time.ParseDuration(com.ToStr(expire) + "s")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = c.c.Set(key, com.ToStr(val), dur).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.occupyMode {
|
||||
return nil
|
||||
}
|
||||
return c.c.HSet(c.hsetName, key, "0").Err()
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *RedisCacher) Get(key string) interface{} {
|
||||
val, err := c.c.Get(c.prefix + key).Result()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// Delete deletes cached value by given key.
|
||||
func (c *RedisCacher) Delete(key string) error {
|
||||
key = c.prefix + key
|
||||
if err := c.c.Del(key).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.occupyMode {
|
||||
return nil
|
||||
}
|
||||
return c.c.HDel(c.hsetName, key).Err()
|
||||
}
|
||||
|
||||
// Incr increases cached int-type value by given key as a counter.
|
||||
func (c *RedisCacher) Incr(key string) error {
|
||||
if !c.IsExist(key) {
|
||||
return fmt.Errorf("key '%s' not exist", key)
|
||||
}
|
||||
return c.c.Incr(c.prefix + key).Err()
|
||||
}
|
||||
|
||||
// Decr decreases cached int-type value by given key as a counter.
|
||||
func (c *RedisCacher) Decr(key string) error {
|
||||
if !c.IsExist(key) {
|
||||
return fmt.Errorf("key '%s' not exist", key)
|
||||
}
|
||||
return c.c.Decr(c.prefix + key).Err()
|
||||
}
|
||||
|
||||
// IsExist returns true if cached value exists.
|
||||
func (c *RedisCacher) IsExist(key string) bool {
|
||||
if c.c.Exists(c.prefix+key).Val() == 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
if !c.occupyMode {
|
||||
c.c.HDel(c.hsetName, c.prefix+key)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Flush deletes all cached data.
|
||||
func (c *RedisCacher) Flush() error {
|
||||
if c.occupyMode {
|
||||
return c.c.FlushDb().Err()
|
||||
}
|
||||
|
||||
keys, err := c.c.HKeys(c.hsetName).Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = c.c.Del(keys...).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.c.Del(c.hsetName).Err()
|
||||
}
|
||||
|
||||
// StartAndGC starts GC routine based on config string settings.
|
||||
// AdapterConfig: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180,hset_name=MacaronCache,prefix=cache:
|
||||
func (c *RedisCacher) StartAndGC(opts cache.Options) error {
|
||||
c.hsetName = "MacaronCache"
|
||||
c.occupyMode = opts.OccupyMode
|
||||
|
||||
cfg, err := ini.Load([]byte(strings.Replace(opts.AdapterConfig, ",", "\n", -1)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opt := &redis.Options{
|
||||
Network: "tcp",
|
||||
}
|
||||
for k, v := range cfg.Section("").KeysHash() {
|
||||
switch k {
|
||||
case "network":
|
||||
opt.Network = v
|
||||
case "addr":
|
||||
opt.Addr = v
|
||||
case "password":
|
||||
opt.Password = v
|
||||
case "db":
|
||||
opt.DB = com.StrTo(v).MustInt()
|
||||
case "pool_size":
|
||||
opt.PoolSize = com.StrTo(v).MustInt()
|
||||
case "idle_timeout":
|
||||
opt.IdleTimeout, err = time.ParseDuration(v + "s")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing idle timeout: %v", err)
|
||||
}
|
||||
case "hset_name":
|
||||
c.hsetName = v
|
||||
case "prefix":
|
||||
c.prefix = v
|
||||
default:
|
||||
return fmt.Errorf("session/redis: unsupported option '%s'", k)
|
||||
}
|
||||
}
|
||||
|
||||
c.c = redis.NewClient(opt)
|
||||
if err = c.c.Ping().Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cache.Register("redis", &RedisCacher{})
|
||||
}
|
1
vendor/gitea.com/macaron/cache/redis/redis.goconvey
generated
vendored
Normal file
1
vendor/gitea.com/macaron/cache/redis/redis.goconvey
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ignore
|
84
vendor/gitea.com/macaron/cache/utils.go
generated
vendored
Normal file
84
vendor/gitea.com/macaron/cache/utils.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
// 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 cache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
)
|
||||
|
||||
func EncodeGob(item *Item) ([]byte, error) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
err := gob.NewEncoder(buf).Encode(item)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func DecodeGob(data []byte, out *Item) error {
|
||||
buf := bytes.NewBuffer(data)
|
||||
return gob.NewDecoder(buf).Decode(&out)
|
||||
}
|
||||
|
||||
func Incr(val interface{}) (interface{}, error) {
|
||||
switch val.(type) {
|
||||
case int:
|
||||
val = val.(int) + 1
|
||||
case int32:
|
||||
val = val.(int32) + 1
|
||||
case int64:
|
||||
val = val.(int64) + 1
|
||||
case uint:
|
||||
val = val.(uint) + 1
|
||||
case uint32:
|
||||
val = val.(uint32) + 1
|
||||
case uint64:
|
||||
val = val.(uint64) + 1
|
||||
default:
|
||||
return val, errors.New("item value is not int-type")
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func Decr(val interface{}) (interface{}, error) {
|
||||
switch val.(type) {
|
||||
case int:
|
||||
val = val.(int) - 1
|
||||
case int32:
|
||||
val = val.(int32) - 1
|
||||
case int64:
|
||||
val = val.(int64) - 1
|
||||
case uint:
|
||||
if val.(uint) > 0 {
|
||||
val = val.(uint) - 1
|
||||
} else {
|
||||
return val, errors.New("item value is less than 0")
|
||||
}
|
||||
case uint32:
|
||||
if val.(uint32) > 0 {
|
||||
val = val.(uint32) - 1
|
||||
} else {
|
||||
return val, errors.New("item value is less than 0")
|
||||
}
|
||||
case uint64:
|
||||
if val.(uint64) > 0 {
|
||||
val = val.(uint64) - 1
|
||||
} else {
|
||||
return val, errors.New("item value is less than 0")
|
||||
}
|
||||
default:
|
||||
return val, errors.New("item value is not int-type")
|
||||
}
|
||||
return val, nil
|
||||
}
|
24
vendor/gitea.com/macaron/captcha/.drone.yml
generated
vendored
Normal file
24
vendor/gitea.com/macaron/captcha/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
kind: pipeline
|
||||
name: go1-1-1
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: go1-1-2
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
191
vendor/gitea.com/macaron/captcha/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/captcha/LICENSE
generated
vendored
Normal 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.
|
16
vendor/gitea.com/macaron/captcha/README.md
generated
vendored
Normal file
16
vendor/gitea.com/macaron/captcha/README.md
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# captcha [](https://drone.gitea.com/macaron/captcha)
|
||||
|
||||
Middleware captcha provides captcha service for [Macaron](https://gitea.com/macaron/macaron).
|
||||
|
||||
### Installation
|
||||
|
||||
go get gitea.com/macaron/captcha
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/gitea.com/macaron/captcha)
|
||||
- [Documentation](http://go-macaron.com/docs/middlewares/captcha)
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
253
vendor/gitea.com/macaron/captcha/captcha.go
generated
vendored
Normal file
253
vendor/gitea.com/macaron/captcha/captcha.go
generated
vendored
Normal file
|
@ -0,0 +1,253 @@
|
|||
// Copyright 2013 Beego 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 captcha a middleware that provides captcha service for Macaron.
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"image/color"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"gitea.com/macaron/cache"
|
||||
"gitea.com/macaron/macaron"
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
const _VERSION = "0.1.0"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
}
|
||||
|
||||
var (
|
||||
defaultChars = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
)
|
||||
|
||||
// Captcha represents a captcha service.
|
||||
type Captcha struct {
|
||||
store cache.Cache
|
||||
SubURL string
|
||||
URLPrefix string
|
||||
FieldIdName string
|
||||
FieldCaptchaName string
|
||||
StdWidth int
|
||||
StdHeight int
|
||||
ChallengeNums int
|
||||
Expiration int64
|
||||
CachePrefix string
|
||||
ColorPalette color.Palette
|
||||
}
|
||||
|
||||
// generate key string
|
||||
func (c *Captcha) key(id string) string {
|
||||
return c.CachePrefix + id
|
||||
}
|
||||
|
||||
// generate rand chars with default chars
|
||||
func (c *Captcha) genRandChars() string {
|
||||
return string(com.RandomCreateBytes(c.ChallengeNums, defaultChars...))
|
||||
}
|
||||
|
||||
// CreateHTML outputs HTML for display and fetch new captcha images.
|
||||
func (c *Captcha) CreateHTML() template.HTML {
|
||||
value, err := c.CreateCaptcha()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("fail to create captcha: %v", err))
|
||||
}
|
||||
return template.HTML(fmt.Sprintf(`<input type="hidden" name="%[1]s" value="%[2]s">
|
||||
<a class="captcha" href="javascript:" tabindex="-1">
|
||||
<img onclick="this.src=('%[3]s%[4]s%[2]s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%[3]s%[4]s%[2]s.png">
|
||||
</a>`, c.FieldIdName, value, c.SubURL, c.URLPrefix))
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (c *Captcha) CreateHtml() template.HTML {
|
||||
return c.CreateHTML()
|
||||
}
|
||||
|
||||
// create a new captcha id
|
||||
func (c *Captcha) CreateCaptcha() (string, error) {
|
||||
id := string(com.RandomCreateBytes(15))
|
||||
if err := c.store.Put(c.key(id), c.genRandChars(), c.Expiration); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// verify from a request
|
||||
func (c *Captcha) VerifyReq(req macaron.Request) bool {
|
||||
req.ParseForm()
|
||||
return c.Verify(req.Form.Get(c.FieldIdName), req.Form.Get(c.FieldCaptchaName))
|
||||
}
|
||||
|
||||
// direct verify id and challenge string
|
||||
func (c *Captcha) Verify(id string, challenge string) bool {
|
||||
if len(challenge) == 0 || len(id) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var chars string
|
||||
|
||||
key := c.key(id)
|
||||
|
||||
if v, ok := c.store.Get(key).(string); ok {
|
||||
chars = v
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
||||
defer c.store.Delete(key)
|
||||
|
||||
if len(chars) != len(challenge) {
|
||||
return false
|
||||
}
|
||||
|
||||
// verify challenge
|
||||
for i, c := range []byte(chars) {
|
||||
if c != challenge[i]-48 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
// Suburl path. Default is empty.
|
||||
SubURL string
|
||||
// URL prefix of getting captcha pictures. Default is "/captcha/".
|
||||
URLPrefix string
|
||||
// Hidden input element ID. Default is "captcha_id".
|
||||
FieldIdName string
|
||||
// User input value element name in request form. Default is "captcha".
|
||||
FieldCaptchaName string
|
||||
// Challenge number. Default is 6.
|
||||
ChallengeNums int
|
||||
// Captcha image width. Default is 240.
|
||||
Width int
|
||||
// Captcha image height. Default is 80.
|
||||
Height int
|
||||
// Captcha expiration time in seconds. Default is 600.
|
||||
Expiration int64
|
||||
// Cache key prefix captcha characters. Default is "captcha_".
|
||||
CachePrefix string
|
||||
// ColorPalette holds a collection of primary colors used for
|
||||
// the captcha's text. If not defined, a random color will be generated.
|
||||
ColorPalette color.Palette
|
||||
}
|
||||
|
||||
func prepareOptions(options []Options) Options {
|
||||
var opt Options
|
||||
if len(options) > 0 {
|
||||
opt = options[0]
|
||||
}
|
||||
|
||||
opt.SubURL = strings.TrimSuffix(opt.SubURL, "/")
|
||||
|
||||
// Defaults.
|
||||
if len(opt.URLPrefix) == 0 {
|
||||
opt.URLPrefix = "/captcha/"
|
||||
} else if opt.URLPrefix[len(opt.URLPrefix)-1] != '/' {
|
||||
opt.URLPrefix += "/"
|
||||
}
|
||||
if len(opt.FieldIdName) == 0 {
|
||||
opt.FieldIdName = "captcha_id"
|
||||
}
|
||||
if len(opt.FieldCaptchaName) == 0 {
|
||||
opt.FieldCaptchaName = "captcha"
|
||||
}
|
||||
if opt.ChallengeNums == 0 {
|
||||
opt.ChallengeNums = 6
|
||||
}
|
||||
if opt.Width == 0 {
|
||||
opt.Width = stdWidth
|
||||
}
|
||||
if opt.Height == 0 {
|
||||
opt.Height = stdHeight
|
||||
}
|
||||
if opt.Expiration == 0 {
|
||||
opt.Expiration = 600
|
||||
}
|
||||
if len(opt.CachePrefix) == 0 {
|
||||
opt.CachePrefix = "captcha_"
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
// NewCaptcha initializes and returns a captcha with given options.
|
||||
func NewCaptcha(opt Options) *Captcha {
|
||||
return &Captcha{
|
||||
SubURL: opt.SubURL,
|
||||
URLPrefix: opt.URLPrefix,
|
||||
FieldIdName: opt.FieldIdName,
|
||||
FieldCaptchaName: opt.FieldCaptchaName,
|
||||
StdWidth: opt.Width,
|
||||
StdHeight: opt.Height,
|
||||
ChallengeNums: opt.ChallengeNums,
|
||||
Expiration: opt.Expiration,
|
||||
CachePrefix: opt.CachePrefix,
|
||||
ColorPalette: opt.ColorPalette,
|
||||
}
|
||||
}
|
||||
|
||||
// Captchaer is a middleware that maps a captcha.Captcha service into the Macaron handler chain.
|
||||
// An single variadic captcha.Options struct can be optionally provided to configure.
|
||||
// This should be register after cache.Cacher.
|
||||
func Captchaer(options ...Options) macaron.Handler {
|
||||
return func(ctx *macaron.Context, cache cache.Cache) {
|
||||
cpt := NewCaptcha(prepareOptions(options))
|
||||
cpt.store = cache
|
||||
|
||||
if strings.HasPrefix(ctx.Req.URL.Path, cpt.URLPrefix) {
|
||||
var chars string
|
||||
id := path.Base(ctx.Req.URL.Path)
|
||||
if i := strings.Index(id, "."); i > -1 {
|
||||
id = id[:i]
|
||||
}
|
||||
key := cpt.key(id)
|
||||
|
||||
// Reload captcha.
|
||||
if len(ctx.Query("reload")) > 0 {
|
||||
chars = cpt.genRandChars()
|
||||
if err := cpt.store.Put(key, chars, cpt.Expiration); err != nil {
|
||||
ctx.Status(500)
|
||||
ctx.Write([]byte("captcha reload error"))
|
||||
panic(fmt.Errorf("reload captcha: %v", err))
|
||||
}
|
||||
} else {
|
||||
if v, ok := cpt.store.Get(key).(string); ok {
|
||||
chars = v
|
||||
} else {
|
||||
ctx.Status(404)
|
||||
ctx.Write([]byte("captcha not found"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := NewImage([]byte(chars), cpt.StdWidth, cpt.StdHeight, cpt.ColorPalette).WriteTo(ctx.Resp); err != nil {
|
||||
panic(fmt.Errorf("write captcha: %v", err))
|
||||
}
|
||||
ctx.Status(200)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Captcha"] = cpt
|
||||
ctx.Map(cpt)
|
||||
}
|
||||
}
|
10
vendor/gitea.com/macaron/captcha/go.mod
generated
vendored
Normal file
10
vendor/gitea.com/macaron/captcha/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
module gitea.com/macaron/captcha
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e
|
||||
)
|
78
vendor/gitea.com/macaron/captcha/go.sum
generated
vendored
Normal file
78
vendor/gitea.com/macaron/captcha/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76 h1:mMsMEg90c5KXQgRWsH8D6GHXfZIW1RAe5S9VYIb12lM=
|
||||
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76/go.mod h1:NFHb9Of+LUnU86bU20CiXXg6ZlgCJ4XytP14UsHOXFs=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
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/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY=
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
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/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/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
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-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.44.2 h1:N6kNUPqiIyxP+s/aINPzRvNpcTVV30qLC0t6ZjZFlUU=
|
||||
gopkg.in/ini.v1 v1.44.2/go.mod h1:M3Cogqpuv0QCi3ExAY5V4uOt4qb/R3xZubo9m8lK5wg=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
505
vendor/gitea.com/macaron/captcha/image.go
generated
vendored
Normal file
505
vendor/gitea.com/macaron/captcha/image.go
generated
vendored
Normal file
|
@ -0,0 +1,505 @@
|
|||
// Copyright 2013 Beego 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 captcha
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"io"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
fontWidth = 11
|
||||
fontHeight = 18
|
||||
blackChar = 1
|
||||
|
||||
// Standard width and height of a captcha image.
|
||||
stdWidth = 240
|
||||
stdHeight = 80
|
||||
|
||||
// Maximum absolute skew factor of a single digit.
|
||||
maxSkew = 0.7
|
||||
// Number of background circles.
|
||||
circleCount = 20
|
||||
)
|
||||
|
||||
var font = [][]byte{
|
||||
{ // 0
|
||||
0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
},
|
||||
{ // 1
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
},
|
||||
{ // 2
|
||||
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
},
|
||||
{ // 3
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
},
|
||||
{ // 4
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
},
|
||||
{ // 5
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
},
|
||||
{ // 6
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0,
|
||||
1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0,
|
||||
1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
},
|
||||
{ // 7
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
{ // 8
|
||||
0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
|
||||
1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
},
|
||||
{ // 9
|
||||
0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
|
||||
0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
},
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
*image.Paletted
|
||||
numWidth int
|
||||
numHeight int
|
||||
dotSize int
|
||||
}
|
||||
|
||||
var prng = &siprng{}
|
||||
|
||||
// randIntn returns a pseudorandom non-negative int in range [0, n).
|
||||
func randIntn(n int) int {
|
||||
return prng.Intn(n)
|
||||
}
|
||||
|
||||
// randInt returns a pseudorandom int in range [from, to].
|
||||
func randInt(from, to int) int {
|
||||
return prng.Intn(to+1-from) + from
|
||||
}
|
||||
|
||||
// randFloat returns a pseudorandom float64 in range [from, to].
|
||||
func randFloat(from, to float64) float64 {
|
||||
return (to-from)*prng.Float64() + from
|
||||
}
|
||||
|
||||
func randomPalette(primary color.Palette) color.Palette {
|
||||
p := make([]color.Color, circleCount+1)
|
||||
// Transparent color.
|
||||
p[0] = color.RGBA{0xFF, 0xFF, 0xFF, 0x00}
|
||||
// Primary color.
|
||||
var prim color.RGBA
|
||||
if len(primary) == 0 {
|
||||
prim = color.RGBA{
|
||||
uint8(randIntn(129)),
|
||||
uint8(randIntn(129)),
|
||||
uint8(randIntn(129)),
|
||||
0xFF,
|
||||
}
|
||||
} else {
|
||||
r, g, b, a := primary[randIntn(len(primary)-1)].RGBA()
|
||||
prim = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
|
||||
}
|
||||
p[1] = prim
|
||||
// Circle colors.
|
||||
for i := 2; i <= circleCount; i++ {
|
||||
p[i] = randomBrightness(prim, 255)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// NewImage returns a new captcha image of the given width and height with the
|
||||
// given digits, where each digit must be in range 0-9. The digit's color is
|
||||
// chosen by random from the colorPalette.
|
||||
func NewImage(digits []byte, width, height int, colorPalette color.Palette) *Image {
|
||||
m := new(Image)
|
||||
m.Paletted = image.NewPaletted(image.Rect(0, 0, width, height), randomPalette(colorPalette))
|
||||
m.calculateSizes(width, height, len(digits))
|
||||
// Randomly position captcha inside the image.
|
||||
maxx := width - (m.numWidth+m.dotSize)*len(digits) - m.dotSize
|
||||
maxy := height - m.numHeight - m.dotSize*2
|
||||
var border int
|
||||
if width > height {
|
||||
border = height / 5
|
||||
} else {
|
||||
border = width / 5
|
||||
}
|
||||
x := randInt(border, maxx-border)
|
||||
y := randInt(border, maxy-border)
|
||||
// Draw digits.
|
||||
for _, n := range digits {
|
||||
m.drawDigit(font[n], x, y)
|
||||
x += m.numWidth + m.dotSize
|
||||
}
|
||||
// Draw strike-through line.
|
||||
m.strikeThrough()
|
||||
// Apply wave distortion.
|
||||
m.distort(randFloat(5, 10), randFloat(100, 200))
|
||||
// Fill image with random circles.
|
||||
m.fillWithCircles(circleCount, m.dotSize)
|
||||
return m
|
||||
}
|
||||
|
||||
// encodedPNG encodes an image to PNG and returns
|
||||
// the result as a byte slice.
|
||||
func (m *Image) encodedPNG() []byte {
|
||||
var buf bytes.Buffer
|
||||
if err := png.Encode(&buf, m.Paletted); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// WriteTo writes captcha image in PNG format into the given writer.
|
||||
func (m *Image) WriteTo(w io.Writer) (int64, error) {
|
||||
n, err := w.Write(m.encodedPNG())
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
func (m *Image) calculateSizes(width, height, ncount int) {
|
||||
// Goal: fit all digits inside the image.
|
||||
var border int
|
||||
if width > height {
|
||||
border = height / 4
|
||||
} else {
|
||||
border = width / 4
|
||||
}
|
||||
// Convert everything to floats for calculations.
|
||||
w := float64(width - border*2)
|
||||
h := float64(height - border*2)
|
||||
// fw takes into account 1-dot spacing between digits.
|
||||
fw := float64(fontWidth + 1)
|
||||
fh := float64(fontHeight)
|
||||
nc := float64(ncount)
|
||||
// Calculate the width of a single digit taking into account only the
|
||||
// width of the image.
|
||||
nw := w / nc
|
||||
// Calculate the height of a digit from this width.
|
||||
nh := nw * fh / fw
|
||||
// Digit too high?
|
||||
if nh > h {
|
||||
// Fit digits based on height.
|
||||
nh = h
|
||||
nw = fw / fh * nh
|
||||
}
|
||||
// Calculate dot size.
|
||||
m.dotSize = int(nh / fh)
|
||||
// Save everything, making the actual width smaller by 1 dot to account
|
||||
// for spacing between digits.
|
||||
m.numWidth = int(nw) - m.dotSize
|
||||
m.numHeight = int(nh)
|
||||
}
|
||||
|
||||
func (m *Image) drawHorizLine(fromX, toX, y int, colorIdx uint8) {
|
||||
for x := fromX; x <= toX; x++ {
|
||||
m.SetColorIndex(x, y, colorIdx)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Image) drawCircle(x, y, radius int, colorIdx uint8) {
|
||||
f := 1 - radius
|
||||
dfx := 1
|
||||
dfy := -2 * radius
|
||||
xo := 0
|
||||
yo := radius
|
||||
|
||||
m.SetColorIndex(x, y+radius, colorIdx)
|
||||
m.SetColorIndex(x, y-radius, colorIdx)
|
||||
m.drawHorizLine(x-radius, x+radius, y, colorIdx)
|
||||
|
||||
for xo < yo {
|
||||
if f >= 0 {
|
||||
yo--
|
||||
dfy += 2
|
||||
f += dfy
|
||||
}
|
||||
xo++
|
||||
dfx += 2
|
||||
f += dfx
|
||||
m.drawHorizLine(x-xo, x+xo, y+yo, colorIdx)
|
||||
m.drawHorizLine(x-xo, x+xo, y-yo, colorIdx)
|
||||
m.drawHorizLine(x-yo, x+yo, y+xo, colorIdx)
|
||||
m.drawHorizLine(x-yo, x+yo, y-xo, colorIdx)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Image) fillWithCircles(n, maxradius int) {
|
||||
maxx := m.Bounds().Max.X
|
||||
maxy := m.Bounds().Max.Y
|
||||
for i := 0; i < n; i++ {
|
||||
colorIdx := uint8(randInt(1, circleCount-1))
|
||||
r := randInt(1, maxradius)
|
||||
m.drawCircle(randInt(r, maxx-r), randInt(r, maxy-r), r, colorIdx)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Image) strikeThrough() {
|
||||
maxx := m.Bounds().Max.X
|
||||
maxy := m.Bounds().Max.Y
|
||||
y := randInt(maxy/3, maxy-maxy/3)
|
||||
amplitude := randFloat(5, 20)
|
||||
period := randFloat(80, 180)
|
||||
dx := 2.0 * math.Pi / period
|
||||
for x := 0; x < maxx; x++ {
|
||||
xo := amplitude * math.Cos(float64(y)*dx)
|
||||
yo := amplitude * math.Sin(float64(x)*dx)
|
||||
for yn := 0; yn < m.dotSize; yn++ {
|
||||
r := randInt(0, m.dotSize)
|
||||
m.drawCircle(x+int(xo), y+int(yo)+(yn*m.dotSize), r/2, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Image) drawDigit(digit []byte, x, y int) {
|
||||
skf := randFloat(-maxSkew, maxSkew)
|
||||
xs := float64(x)
|
||||
r := m.dotSize / 2
|
||||
y += randInt(-r, r)
|
||||
for yo := 0; yo < fontHeight; yo++ {
|
||||
for xo := 0; xo < fontWidth; xo++ {
|
||||
if digit[yo*fontWidth+xo] != blackChar {
|
||||
continue
|
||||
}
|
||||
m.drawCircle(x+xo*m.dotSize, y+yo*m.dotSize, r, 1)
|
||||
}
|
||||
xs += skf
|
||||
x = int(xs)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Image) distort(amplude float64, period float64) {
|
||||
w := m.Bounds().Max.X
|
||||
h := m.Bounds().Max.Y
|
||||
|
||||
oldm := m.Paletted
|
||||
newm := image.NewPaletted(image.Rect(0, 0, w, h), oldm.Palette)
|
||||
|
||||
dx := 2.0 * math.Pi / period
|
||||
for x := 0; x < w; x++ {
|
||||
for y := 0; y < h; y++ {
|
||||
xo := amplude * math.Sin(float64(y)*dx)
|
||||
yo := amplude * math.Cos(float64(x)*dx)
|
||||
newm.SetColorIndex(x, y, oldm.ColorIndexAt(x+int(xo), y+int(yo)))
|
||||
}
|
||||
}
|
||||
m.Paletted = newm
|
||||
}
|
||||
|
||||
func randomBrightness(c color.RGBA, max uint8) color.RGBA {
|
||||
minc := min3(c.R, c.G, c.B)
|
||||
maxc := max3(c.R, c.G, c.B)
|
||||
if maxc > max {
|
||||
return c
|
||||
}
|
||||
n := randIntn(int(max-maxc)) - int(minc)
|
||||
return color.RGBA{
|
||||
uint8(int(c.R) + n),
|
||||
uint8(int(c.G) + n),
|
||||
uint8(int(c.B) + n),
|
||||
uint8(c.A),
|
||||
}
|
||||
}
|
||||
|
||||
func min3(x, y, z uint8) (m uint8) {
|
||||
m = x
|
||||
if y < m {
|
||||
m = y
|
||||
}
|
||||
if z < m {
|
||||
m = z
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func max3(x, y, z uint8) (m uint8) {
|
||||
m = x
|
||||
if y > m {
|
||||
m = y
|
||||
}
|
||||
if z > m {
|
||||
m = z
|
||||
}
|
||||
return
|
||||
}
|
277
vendor/gitea.com/macaron/captcha/siprng.go
generated
vendored
Normal file
277
vendor/gitea.com/macaron/captcha/siprng.go
generated
vendored
Normal file
|
@ -0,0 +1,277 @@
|
|||
// Copyright 2013 Beego 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 captcha
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// siprng is PRNG based on SipHash-2-4.
|
||||
type siprng struct {
|
||||
mu sync.Mutex
|
||||
k0, k1, ctr uint64
|
||||
}
|
||||
|
||||
// siphash implements SipHash-2-4, accepting a uint64 as a message.
|
||||
func siphash(k0, k1, m uint64) uint64 {
|
||||
// Initialization.
|
||||
v0 := k0 ^ 0x736f6d6570736575
|
||||
v1 := k1 ^ 0x646f72616e646f6d
|
||||
v2 := k0 ^ 0x6c7967656e657261
|
||||
v3 := k1 ^ 0x7465646279746573
|
||||
t := uint64(8) << 56
|
||||
|
||||
// Compression.
|
||||
v3 ^= m
|
||||
|
||||
// Round 1.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
// Round 2.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
v0 ^= m
|
||||
|
||||
// Compress last block.
|
||||
v3 ^= t
|
||||
|
||||
// Round 1.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
// Round 2.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
v0 ^= t
|
||||
|
||||
// Finalization.
|
||||
v2 ^= 0xff
|
||||
|
||||
// Round 1.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
// Round 2.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
// Round 3.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
// Round 4.
|
||||
v0 += v1
|
||||
v1 = v1<<13 | v1>>(64-13)
|
||||
v1 ^= v0
|
||||
v0 = v0<<32 | v0>>(64-32)
|
||||
|
||||
v2 += v3
|
||||
v3 = v3<<16 | v3>>(64-16)
|
||||
v3 ^= v2
|
||||
|
||||
v0 += v3
|
||||
v3 = v3<<21 | v3>>(64-21)
|
||||
v3 ^= v0
|
||||
|
||||
v2 += v1
|
||||
v1 = v1<<17 | v1>>(64-17)
|
||||
v1 ^= v2
|
||||
v2 = v2<<32 | v2>>(64-32)
|
||||
|
||||
return v0 ^ v1 ^ v2 ^ v3
|
||||
}
|
||||
|
||||
// rekey sets a new PRNG key, which is read from crypto/rand.
|
||||
func (p *siprng) rekey() {
|
||||
var k [16]byte
|
||||
if _, err := io.ReadFull(rand.Reader, k[:]); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
p.k0 = binary.LittleEndian.Uint64(k[0:8])
|
||||
p.k1 = binary.LittleEndian.Uint64(k[8:16])
|
||||
p.ctr = 1
|
||||
}
|
||||
|
||||
// Uint64 returns a new pseudorandom uint64.
|
||||
// It rekeys PRNG on the first call and every 64 MB of generated data.
|
||||
func (p *siprng) Uint64() uint64 {
|
||||
p.mu.Lock()
|
||||
if p.ctr == 0 || p.ctr > 8*1024*1024 {
|
||||
p.rekey()
|
||||
}
|
||||
v := siphash(p.k0, p.k1, p.ctr)
|
||||
p.ctr++
|
||||
p.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
|
||||
func (p *siprng) Int63() int64 {
|
||||
return int64(p.Uint64() & 0x7fffffffffffffff)
|
||||
}
|
||||
|
||||
func (p *siprng) Uint32() uint32 {
|
||||
return uint32(p.Uint64())
|
||||
}
|
||||
|
||||
func (p *siprng) Int31() int32 {
|
||||
return int32(p.Uint32() & 0x7fffffff)
|
||||
}
|
||||
|
||||
func (p *siprng) Intn(n int) int {
|
||||
if n <= 0 {
|
||||
panic("invalid argument to Intn")
|
||||
}
|
||||
if n <= 1<<31-1 {
|
||||
return int(p.Int31n(int32(n)))
|
||||
}
|
||||
return int(p.Int63n(int64(n)))
|
||||
}
|
||||
|
||||
func (p *siprng) Int63n(n int64) int64 {
|
||||
if n <= 0 {
|
||||
panic("invalid argument to Int63n")
|
||||
}
|
||||
max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
|
||||
v := p.Int63()
|
||||
for v > max {
|
||||
v = p.Int63()
|
||||
}
|
||||
return v % n
|
||||
}
|
||||
|
||||
func (p *siprng) Int31n(n int32) int32 {
|
||||
if n <= 0 {
|
||||
panic("invalid argument to Int31n")
|
||||
}
|
||||
max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
|
||||
v := p.Int31()
|
||||
for v > max {
|
||||
v = p.Int31()
|
||||
}
|
||||
return v % n
|
||||
}
|
||||
|
||||
func (p *siprng) Float64() float64 { return float64(p.Int63()) / (1 << 63) }
|
9
vendor/gitea.com/macaron/cors/.drone.yml
generated
vendored
Normal file
9
vendor/gitea.com/macaron/cors/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
12
vendor/gitea.com/macaron/cors/.gitignore
generated
vendored
Normal file
12
vendor/gitea.com/macaron/cors/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
201
vendor/gitea.com/macaron/cors/LICENSE
generated
vendored
Normal file
201
vendor/gitea.com/macaron/cors/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
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:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) 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
|
||||
|
||||
(d) 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.
|
5
vendor/gitea.com/macaron/cors/README.md
generated
vendored
Normal file
5
vendor/gitea.com/macaron/cors/README.md
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# cors
|
||||
|
||||
[](https://drone.gitea.com/macaron/cors)
|
||||
|
||||
Package cors is a middleware that handles CORS requests & headers for Macaron.
|
168
vendor/gitea.com/macaron/cors/cors.go
generated
vendored
Normal file
168
vendor/gitea.com/macaron/cors/cors.go
generated
vendored
Normal file
|
@ -0,0 +1,168 @@
|
|||
package cors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
macaron "gitea.com/macaron/macaron"
|
||||
)
|
||||
|
||||
const version = "0.1.1"
|
||||
|
||||
const anyDomain = "!*"
|
||||
|
||||
// Version returns the version of this module
|
||||
func Version() string {
|
||||
return version
|
||||
}
|
||||
|
||||
/*
|
||||
Options to configure the CORS middleware read from the [cors] section of the ini configuration file.
|
||||
|
||||
SCHEME may be http or https as accepted schemes or the '*' wildcard to accept any scheme.
|
||||
|
||||
ALLOW_DOMAIN may be a comma separated list of domains that are allowed to run CORS requests
|
||||
Special values are the a single '*' wildcard that will allow any domain to send requests without
|
||||
credentials and the special '!*' wildcard which will reply with requesting domain in the 'access-control-allow-origin'
|
||||
header and hence allow requess from any domain *with* credentials.
|
||||
|
||||
ALLOW_SUBDOMAIN set to true accepts requests from any subdomain of ALLOW_DOMAIN.
|
||||
|
||||
METHODS may be a comma separated list of HTTP-methods to be accepted.
|
||||
|
||||
MAX_AGE_SECONDS may be the duration in secs for which the response is cached (default 600).
|
||||
ref: https://stackoverflow.com/questions/54300997/is-it-possible-to-cache-http-options-response?noredirect=1#comment95790277_54300997
|
||||
ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
|
||||
|
||||
ALLOW_CREDENTIALS set to false rejects any request with credentials.
|
||||
*/
|
||||
type Options struct {
|
||||
Section string
|
||||
Scheme string
|
||||
AllowDomain []string
|
||||
AllowSubdomain bool
|
||||
Methods []string
|
||||
MaxAgeSeconds int
|
||||
AllowCredentials bool
|
||||
}
|
||||
|
||||
func prepareOptions(options []Options) Options {
|
||||
var opt Options
|
||||
if len(options) > 0 {
|
||||
opt = options[0]
|
||||
}
|
||||
|
||||
if len(opt.Section) == 0 {
|
||||
opt.Section = "cors"
|
||||
}
|
||||
sec := macaron.Config().Section(opt.Section)
|
||||
|
||||
if len(opt.Scheme) == 0 {
|
||||
opt.Scheme = sec.Key("SCHEME").MustString("http")
|
||||
}
|
||||
if len(opt.AllowDomain) == 0 {
|
||||
opt.AllowDomain = sec.Key("ALLOW_DOMAIN").Strings(",")
|
||||
if len(opt.AllowDomain) == 0 {
|
||||
opt.AllowDomain = []string{"*"}
|
||||
}
|
||||
}
|
||||
if !opt.AllowSubdomain {
|
||||
opt.AllowSubdomain = sec.Key("ALLOW_SUBDOMAIN").MustBool(false)
|
||||
}
|
||||
if len(opt.Methods) == 0 {
|
||||
opt.Methods = sec.Key("METHODS").Strings(",")
|
||||
if len(opt.Methods) == 0 {
|
||||
opt.Methods = []string{
|
||||
http.MethodGet,
|
||||
http.MethodHead,
|
||||
http.MethodPost,
|
||||
http.MethodPut,
|
||||
http.MethodPatch,
|
||||
http.MethodDelete,
|
||||
http.MethodOptions,
|
||||
}
|
||||
}
|
||||
}
|
||||
if opt.MaxAgeSeconds <= 0 {
|
||||
opt.MaxAgeSeconds = sec.Key("MAX_AGE_SECONDS").MustInt(600)
|
||||
}
|
||||
if !opt.AllowCredentials {
|
||||
opt.AllowCredentials = sec.Key("ALLOW_CREDENTIALS").MustBool(true)
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
// CORS responds to preflight requests with adequat access-control-* respond headers
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
|
||||
// https://fetch.spec.whatwg.org/#cors-protocol-and-credentials
|
||||
func CORS(options ...Options) macaron.Handler {
|
||||
opt := prepareOptions(options)
|
||||
return func(ctx *macaron.Context, log *log.Logger) {
|
||||
reqOptions := ctx.Req.Method == http.MethodOptions
|
||||
|
||||
headers := map[string]string{
|
||||
"access-control-allow-methods": strings.Join(opt.Methods, ","),
|
||||
"access-control-allow-headers": ctx.Req.Header.Get("access-control-request-headers"),
|
||||
"access-control-max-age": strconv.Itoa(opt.MaxAgeSeconds),
|
||||
}
|
||||
if opt.AllowDomain[0] == "*" {
|
||||
headers["access-control-allow-origin"] = "*"
|
||||
} else {
|
||||
origin := ctx.Req.Header.Get("Origin")
|
||||
if reqOptions && origin == "" {
|
||||
respErrorf(ctx, log, http.StatusBadRequest, "missing origin header in CORS request")
|
||||
return
|
||||
}
|
||||
|
||||
u, err := url.Parse(origin)
|
||||
if err != nil {
|
||||
respErrorf(ctx, log, http.StatusBadRequest, "Failed to parse CORS origin header. Reason: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
ok := false
|
||||
for _, d := range opt.AllowDomain {
|
||||
if u.Hostname() == d || (opt.AllowSubdomain && strings.HasSuffix(u.Hostname(), "."+d)) || d == anyDomain {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
if opt.Scheme != "*" {
|
||||
u.Scheme = opt.Scheme
|
||||
}
|
||||
headers["access-control-allow-origin"] = u.String()
|
||||
headers["access-control-allow-credentials"] = strconv.FormatBool(opt.AllowCredentials)
|
||||
headers["vary"] = "Origin"
|
||||
}
|
||||
if reqOptions && !ok {
|
||||
respErrorf(ctx, log, http.StatusBadRequest, "CORS request from prohibited domain %v", origin)
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.Resp.Before(func(w macaron.ResponseWriter) {
|
||||
for k, v := range headers {
|
||||
w.Header().Set(k, v)
|
||||
}
|
||||
})
|
||||
if reqOptions {
|
||||
ctx.Status(200) // return response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func respErrorf(ctx *macaron.Context, log *log.Logger, statusCode int, format string, a ...interface{}) {
|
||||
msg := fmt.Sprintf(format, a...)
|
||||
log.Println(msg)
|
||||
ctx.WriteHeader(statusCode)
|
||||
_, err := ctx.Write([]byte(msg))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
5
vendor/gitea.com/macaron/cors/go.mod
generated
vendored
Normal file
5
vendor/gitea.com/macaron/cors/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitea.com/macaron/cors
|
||||
|
||||
go 1.11
|
||||
|
||||
require gitea.com/macaron/macaron v1.3.3-0.20190803174002-53e005ff4827
|
31
vendor/gitea.com/macaron/cors/go.sum
generated
vendored
Normal file
31
vendor/gitea.com/macaron/cors/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190803174002-53e005ff4827 h1:/rT4MEFjhdViy2BFWKUwbC0JSNSziEbBCM7q4/B9qgo=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190803174002-53e005ff4827/go.mod h1:/rvxMjIkOq4BM8uPUb+VHuU02ZfAO6R4+wD//tiCiRw=
|
||||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755 h1:1B7wb36fHLSwZfHg6ngZhhtIEHQjiC5H4p7qQGBEffg=
|
||||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755/go.mod h1:voKvFVpXBJxdIPeqjoJuLK+UVcRlo/JLjeToGxPYu68=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/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/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=
|
||||
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.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
24
vendor/gitea.com/macaron/csrf/.drone.yml
generated
vendored
Normal file
24
vendor/gitea.com/macaron/csrf/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
kind: pipeline
|
||||
name: go1-1-1
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: go1-1-2
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
191
vendor/gitea.com/macaron/csrf/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/csrf/LICENSE
generated
vendored
Normal 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.
|
18
vendor/gitea.com/macaron/csrf/README.md
generated
vendored
Normal file
18
vendor/gitea.com/macaron/csrf/README.md
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# csrf [](https://drone.gitea.com/macaron/csrf)
|
||||
|
||||
Middleware csrf generates and validates CSRF tokens for [Macaron](https://gitea.com/macaron/macaron).
|
||||
|
||||
[API Reference](https://gowalker.org/gitea.com/macaron/csrf)
|
||||
|
||||
### Installation
|
||||
|
||||
go get gitea.com/macaron/csrf
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/gitea.com/macaron/csrf)
|
||||
- [Documentation](http://go-macaron.com/docs/middlewares/csrf)
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
267
vendor/gitea.com/macaron/csrf/csrf.go
generated
vendored
Normal file
267
vendor/gitea.com/macaron/csrf/csrf.go
generated
vendored
Normal file
|
@ -0,0 +1,267 @@
|
|||
// 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 csrf is a middleware that generates and validates CSRF tokens for Macaron.
|
||||
package csrf
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gitea.com/macaron/macaron"
|
||||
"gitea.com/macaron/session"
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
const _VERSION = "0.1.1"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
}
|
||||
|
||||
// CSRF represents a CSRF service and is used to get the current token and validate a suspect token.
|
||||
type CSRF interface {
|
||||
// Return HTTP header to search for token.
|
||||
GetHeaderName() string
|
||||
// Return form value to search for token.
|
||||
GetFormName() string
|
||||
// Return cookie name to search for token.
|
||||
GetCookieName() string
|
||||
// Return cookie path
|
||||
GetCookiePath() string
|
||||
// Return the flag value used for the csrf token.
|
||||
GetCookieHttpOnly() bool
|
||||
// Return the token.
|
||||
GetToken() string
|
||||
// Validate by token.
|
||||
ValidToken(t string) bool
|
||||
// Error replies to the request with a custom function when ValidToken fails.
|
||||
Error(w http.ResponseWriter)
|
||||
}
|
||||
|
||||
type csrf struct {
|
||||
// Header name value for setting and getting csrf token.
|
||||
Header string
|
||||
// Form name value for setting and getting csrf token.
|
||||
Form string
|
||||
// Cookie name value for setting and getting csrf token.
|
||||
Cookie string
|
||||
//Cookie domain
|
||||
CookieDomain string
|
||||
//Cookie path
|
||||
CookiePath string
|
||||
// Cookie HttpOnly flag value used for the csrf token.
|
||||
CookieHttpOnly bool
|
||||
// Token generated to pass via header, cookie, or hidden form value.
|
||||
Token string
|
||||
// This value must be unique per user.
|
||||
ID string
|
||||
// Secret used along with the unique id above to generate the Token.
|
||||
Secret string
|
||||
// ErrorFunc is the custom function that replies to the request when ValidToken fails.
|
||||
ErrorFunc func(w http.ResponseWriter)
|
||||
}
|
||||
|
||||
// GetHeaderName returns the name of the HTTP header for csrf token.
|
||||
func (c *csrf) GetHeaderName() string {
|
||||
return c.Header
|
||||
}
|
||||
|
||||
// GetFormName returns the name of the form value for csrf token.
|
||||
func (c *csrf) GetFormName() string {
|
||||
return c.Form
|
||||
}
|
||||
|
||||
// GetCookieName returns the name of the cookie for csrf token.
|
||||
func (c *csrf) GetCookieName() string {
|
||||
return c.Cookie
|
||||
}
|
||||
|
||||
// GetCookiePath returns the path of the cookie for csrf token.
|
||||
func (c *csrf) GetCookiePath() string {
|
||||
return c.CookiePath
|
||||
}
|
||||
|
||||
// GetCookieHttpOnly returns the flag value used for the csrf token.
|
||||
func (c *csrf) GetCookieHttpOnly() bool {
|
||||
return c.CookieHttpOnly
|
||||
}
|
||||
|
||||
// GetToken returns the current token. This is typically used
|
||||
// to populate a hidden form in an HTML template.
|
||||
func (c *csrf) GetToken() string {
|
||||
return c.Token
|
||||
}
|
||||
|
||||
// ValidToken validates the passed token against the existing Secret and ID.
|
||||
func (c *csrf) ValidToken(t string) bool {
|
||||
return ValidToken(t, c.Secret, c.ID, "POST")
|
||||
}
|
||||
|
||||
// Error replies to the request when ValidToken fails.
|
||||
func (c *csrf) Error(w http.ResponseWriter) {
|
||||
c.ErrorFunc(w)
|
||||
}
|
||||
|
||||
// Options maintains options to manage behavior of Generate.
|
||||
type Options struct {
|
||||
// The global secret value used to generate Tokens.
|
||||
Secret string
|
||||
// HTTP header used to set and get token.
|
||||
Header string
|
||||
// Form value used to set and get token.
|
||||
Form string
|
||||
// Cookie value used to set and get token.
|
||||
Cookie string
|
||||
// Cookie domain.
|
||||
CookieDomain string
|
||||
// Cookie path.
|
||||
CookiePath string
|
||||
CookieHttpOnly bool
|
||||
// Key used for getting the unique ID per user.
|
||||
SessionKey string
|
||||
// oldSeesionKey saves old value corresponding to SessionKey.
|
||||
oldSeesionKey string
|
||||
// If true, send token via X-CSRFToken header.
|
||||
SetHeader bool
|
||||
// If true, send token via _csrf cookie.
|
||||
SetCookie bool
|
||||
// Set the Secure flag to true on the cookie.
|
||||
Secure bool
|
||||
// Disallow Origin appear in request header.
|
||||
Origin bool
|
||||
// The function called when Validate fails.
|
||||
ErrorFunc func(w http.ResponseWriter)
|
||||
}
|
||||
|
||||
func prepareOptions(options []Options) Options {
|
||||
var opt Options
|
||||
if len(options) > 0 {
|
||||
opt = options[0]
|
||||
}
|
||||
|
||||
// Defaults.
|
||||
if len(opt.Secret) == 0 {
|
||||
opt.Secret = string(com.RandomCreateBytes(10))
|
||||
}
|
||||
if len(opt.Header) == 0 {
|
||||
opt.Header = "X-CSRFToken"
|
||||
}
|
||||
if len(opt.Form) == 0 {
|
||||
opt.Form = "_csrf"
|
||||
}
|
||||
if len(opt.Cookie) == 0 {
|
||||
opt.Cookie = "_csrf"
|
||||
}
|
||||
if len(opt.CookiePath) == 0 {
|
||||
opt.CookiePath = "/"
|
||||
}
|
||||
if len(opt.SessionKey) == 0 {
|
||||
opt.SessionKey = "uid"
|
||||
}
|
||||
opt.oldSeesionKey = "_old_" + opt.SessionKey
|
||||
if opt.ErrorFunc == nil {
|
||||
opt.ErrorFunc = func(w http.ResponseWriter) {
|
||||
http.Error(w, "Invalid csrf token.", http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
// Generate maps CSRF to each request. If this request is a Get request, it will generate a new token.
|
||||
// Additionally, depending on options set, generated tokens will be sent via Header and/or Cookie.
|
||||
func Generate(options ...Options) macaron.Handler {
|
||||
opt := prepareOptions(options)
|
||||
return func(ctx *macaron.Context, sess session.Store) {
|
||||
x := &csrf{
|
||||
Secret: opt.Secret,
|
||||
Header: opt.Header,
|
||||
Form: opt.Form,
|
||||
Cookie: opt.Cookie,
|
||||
CookieDomain: opt.CookieDomain,
|
||||
CookiePath: opt.CookiePath,
|
||||
CookieHttpOnly: opt.CookieHttpOnly,
|
||||
ErrorFunc: opt.ErrorFunc,
|
||||
}
|
||||
ctx.MapTo(x, (*CSRF)(nil))
|
||||
|
||||
if opt.Origin && len(ctx.Req.Header.Get("Origin")) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
x.ID = "0"
|
||||
uid := sess.Get(opt.SessionKey)
|
||||
if uid != nil {
|
||||
x.ID = com.ToStr(uid)
|
||||
}
|
||||
|
||||
needsNew := false
|
||||
oldUid := sess.Get(opt.oldSeesionKey)
|
||||
if oldUid == nil || oldUid.(string) != x.ID {
|
||||
needsNew = true
|
||||
sess.Set(opt.oldSeesionKey, x.ID)
|
||||
} else {
|
||||
// If cookie present, map existing token, else generate a new one.
|
||||
if val := ctx.GetCookie(opt.Cookie); len(val) > 0 {
|
||||
// FIXME: test coverage.
|
||||
x.Token = val
|
||||
} else {
|
||||
needsNew = true
|
||||
}
|
||||
}
|
||||
|
||||
if needsNew {
|
||||
// FIXME: actionId.
|
||||
x.Token = GenerateToken(x.Secret, x.ID, "POST")
|
||||
if opt.SetCookie {
|
||||
ctx.SetCookie(opt.Cookie, x.Token, 0, opt.CookiePath, opt.CookieDomain, opt.Secure, opt.CookieHttpOnly, time.Now().AddDate(0, 0, 1))
|
||||
}
|
||||
}
|
||||
|
||||
if opt.SetHeader {
|
||||
ctx.Resp.Header().Add(opt.Header, x.Token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Csrfer maps CSRF to each request. If this request is a Get request, it will generate a new token.
|
||||
// Additionally, depending on options set, generated tokens will be sent via Header and/or Cookie.
|
||||
func Csrfer(options ...Options) macaron.Handler {
|
||||
return Generate(options...)
|
||||
}
|
||||
|
||||
// Validate should be used as a per route middleware. It attempts to get a token from a "X-CSRFToken"
|
||||
// HTTP header and then a "_csrf" form value. If one of these is found, the token will be validated
|
||||
// using ValidToken. If this validation fails, custom Error is sent in the reply.
|
||||
// If neither a header or form value is found, http.StatusBadRequest is sent.
|
||||
func Validate(ctx *macaron.Context, x CSRF) {
|
||||
if token := ctx.Req.Header.Get(x.GetHeaderName()); len(token) > 0 {
|
||||
if !x.ValidToken(token) {
|
||||
ctx.SetCookie(x.GetCookieName(), "", -1, x.GetCookiePath())
|
||||
x.Error(ctx.Resp)
|
||||
}
|
||||
return
|
||||
}
|
||||
if token := ctx.Req.FormValue(x.GetFormName()); len(token) > 0 {
|
||||
if !x.ValidToken(token) {
|
||||
ctx.SetCookie(x.GetCookieName(), "", -1, x.GetCookiePath())
|
||||
x.Error(ctx.Resp)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(ctx.Resp, "Bad Request: no CSRF token present", http.StatusBadRequest)
|
||||
}
|
12
vendor/gitea.com/macaron/csrf/go.mod
generated
vendored
Normal file
12
vendor/gitea.com/macaron/csrf/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
module gitea.com/macaron/csrf
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb
|
||||
gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705
|
||||
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
|
||||
)
|
83
vendor/gitea.com/macaron/csrf/go.sum
generated
vendored
Normal file
83
vendor/gitea.com/macaron/csrf/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs=
|
||||
gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705 h1:mvkQGAlON1Z6Y8pqa/+FpYIskk54mazuECUfZK5oTg0=
|
||||
gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705/go.mod h1:1ujH0jD6Ca4iK9NL0Q2a7fG2chvXx5hVa7hBfABwpkA=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
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/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY=
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
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/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
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-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
97
vendor/gitea.com/macaron/csrf/xsrf.go
generated
vendored
Normal file
97
vendor/gitea.com/macaron/csrf/xsrf.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||
// 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 csrf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// The duration that XSRF tokens are valid.
|
||||
// It is exported so clients may set cookie timeouts that match generated tokens.
|
||||
const TIMEOUT = 24 * time.Hour
|
||||
|
||||
// clean sanitizes a string for inclusion in a token by replacing all ":"s.
|
||||
func clean(s string) string {
|
||||
return strings.Replace(s, ":", "_", -1)
|
||||
}
|
||||
|
||||
// GenerateToken returns a URL-safe secure XSRF token that expires in 24 hours.
|
||||
//
|
||||
// key is a secret key for your application.
|
||||
// userID is a unique identifier for the user.
|
||||
// actionID is the action the user is taking (e.g. POSTing to a particular path).
|
||||
func GenerateToken(key, userID, actionID string) string {
|
||||
return generateTokenAtTime(key, userID, actionID, time.Now())
|
||||
}
|
||||
|
||||
// generateTokenAtTime is like Generate, but returns a token that expires 24 hours from now.
|
||||
func generateTokenAtTime(key, userID, actionID string, now time.Time) string {
|
||||
h := hmac.New(sha1.New, []byte(key))
|
||||
fmt.Fprintf(h, "%s:%s:%d", clean(userID), clean(actionID), now.UnixNano())
|
||||
tok := fmt.Sprintf("%s:%d", h.Sum(nil), now.UnixNano())
|
||||
return base64.RawURLEncoding.EncodeToString([]byte(tok))
|
||||
}
|
||||
|
||||
// Valid returns true if token is a valid, unexpired token returned by Generate.
|
||||
func ValidToken(token, key, userID, actionID string) bool {
|
||||
return validTokenAtTime(token, key, userID, actionID, time.Now())
|
||||
}
|
||||
|
||||
// validTokenAtTime is like Valid, but it uses now to check if the token is expired.
|
||||
func validTokenAtTime(token, key, userID, actionID string, now time.Time) bool {
|
||||
// Decode the token.
|
||||
data, err := base64.RawURLEncoding.DecodeString(token)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Extract the issue time of the token.
|
||||
sep := bytes.LastIndex(data, []byte{':'})
|
||||
if sep < 0 {
|
||||
return false
|
||||
}
|
||||
nanos, err := strconv.ParseInt(string(data[sep+1:]), 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
issueTime := time.Unix(0, nanos)
|
||||
|
||||
// Check that the token is not expired.
|
||||
if now.Sub(issueTime) >= TIMEOUT {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check that the token is not from the future.
|
||||
// Allow 1 minute grace period in case the token is being verified on a
|
||||
// machine whose clock is behind the machine that issued the token.
|
||||
if issueTime.After(now.Add(1 * time.Minute)) {
|
||||
return false
|
||||
}
|
||||
|
||||
expected := generateTokenAtTime(key, userID, actionID, issueTime)
|
||||
|
||||
// Check that the token matches the expected value.
|
||||
// Use constant time comparison to avoid timing attacks.
|
||||
return subtle.ConstantTimeCompare([]byte(token), []byte(expected)) == 1
|
||||
}
|
24
vendor/gitea.com/macaron/i18n/.drone.yml
generated
vendored
Normal file
24
vendor/gitea.com/macaron/i18n/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
kind: pipeline
|
||||
name: golang-1-1
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: golang-1-2
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
191
vendor/gitea.com/macaron/i18n/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/i18n/LICENSE
generated
vendored
Normal 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.
|
16
vendor/gitea.com/macaron/i18n/README.md
generated
vendored
Normal file
16
vendor/gitea.com/macaron/i18n/README.md
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# i18n [](https://drone.gitea.com/macaron/i18n) [](http://gocover.io/github.com/go-macaron/i18n)
|
||||
|
||||
Middleware i18n provides app Internationalization and Localization for [Macaron](https://gitea.com/macaron/macaron).
|
||||
|
||||
### Installation
|
||||
|
||||
go get gitea.com/macaron/i18n
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/gitea.com/macaron/i18n)
|
||||
- [Documentation](http://go-macaron.com/docs/middlewares/i18n)
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
11
vendor/gitea.com/macaron/i18n/go.mod
generated
vendored
Normal file
11
vendor/gitea.com/macaron/i18n/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
module gitea.com/macaron/i18n
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e
|
||||
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6
|
||||
golang.org/x/text v0.3.2
|
||||
)
|
35
vendor/gitea.com/macaron/i18n/go.sum
generated
vendored
Normal file
35
vendor/gitea.com/macaron/i18n/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
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/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=
|
||||
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6 h1:sRrkJEHtNoaSvyXMbRgofEOX4/3gMiraevQKJdIBhYE=
|
||||
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6/go.mod h1:+5rDk6sDGpl3azws3O+f+GpFSyN9GVr0K8cvQLQM2ZQ=
|
||||
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/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag=
|
||||
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
227
vendor/gitea.com/macaron/i18n/i18n.go
generated
vendored
Normal file
227
vendor/gitea.com/macaron/i18n/i18n.go
generated
vendored
Normal file
|
@ -0,0 +1,227 @@
|
|||
// 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 i18n is a middleware that provides app Internationalization and Localization of Macaron.
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"gitea.com/macaron/macaron"
|
||||
"github.com/unknwon/com"
|
||||
"github.com/unknwon/i18n"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
const _VERSION = "0.4.0"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
}
|
||||
|
||||
// initLocales initializes language type list and Accept-Language header matcher.
|
||||
func initLocales(opt Options) language.Matcher {
|
||||
tags := make([]language.Tag, len(opt.Langs))
|
||||
for i, lang := range opt.Langs {
|
||||
tags[i] = language.Raw.Make(lang)
|
||||
fname := fmt.Sprintf(opt.Format, lang)
|
||||
// Append custom locale file.
|
||||
custom := []interface{}{}
|
||||
customPath := path.Join(opt.CustomDirectory, fname)
|
||||
if com.IsFile(customPath) {
|
||||
custom = append(custom, customPath)
|
||||
}
|
||||
|
||||
var locale interface{}
|
||||
if data, ok := opt.Files[fname]; ok {
|
||||
locale = data
|
||||
} else {
|
||||
locale = path.Join(opt.Directory, fname)
|
||||
}
|
||||
|
||||
err := i18n.SetMessageWithDesc(lang, opt.Names[i], locale, custom...)
|
||||
if err != nil && err != i18n.ErrLangAlreadyExist {
|
||||
panic(fmt.Errorf("fail to set message file(%s): %v", lang, err))
|
||||
}
|
||||
}
|
||||
return language.NewMatcher(tags)
|
||||
}
|
||||
|
||||
// A Locale describles the information of localization.
|
||||
type Locale struct {
|
||||
i18n.Locale
|
||||
}
|
||||
|
||||
// Language returns language current locale represents.
|
||||
func (l Locale) Language() string {
|
||||
return l.Lang
|
||||
}
|
||||
|
||||
// Options represents a struct for specifying configuration options for the i18n middleware.
|
||||
type Options struct {
|
||||
// Suburl of path. Default is empty.
|
||||
SubURL string
|
||||
// Directory to load locale files. Default is "conf/locale"
|
||||
Directory string
|
||||
// File stores actual data of locale files. Used for in-memory purpose.
|
||||
Files map[string][]byte
|
||||
// Custom directory to overload locale files. Default is "custom/conf/locale"
|
||||
CustomDirectory string
|
||||
// Langauges that will be supported, order is meaningful.
|
||||
Langs []string
|
||||
// Human friendly names corresponding to Langs list.
|
||||
Names []string
|
||||
// Default language locale, leave empty to remain unset.
|
||||
DefaultLang string
|
||||
// Locale file naming style. Default is "locale_%s.ini".
|
||||
Format string
|
||||
// Name of language parameter name in URL. Default is "lang".
|
||||
Parameter string
|
||||
// Redirect when user uses get parameter to specify language.
|
||||
Redirect bool
|
||||
// Name that maps into template variable. Default is "i18n".
|
||||
TmplName string
|
||||
// Configuration section name. Default is "i18n".
|
||||
Section string
|
||||
// Domain used for `lang` cookie. Default is ""
|
||||
CookieDomain string
|
||||
}
|
||||
|
||||
func prepareOptions(options []Options) Options {
|
||||
var opt Options
|
||||
if len(options) > 0 {
|
||||
opt = options[0]
|
||||
}
|
||||
|
||||
if len(opt.Section) == 0 {
|
||||
opt.Section = "i18n"
|
||||
}
|
||||
sec := macaron.Config().Section(opt.Section)
|
||||
|
||||
opt.SubURL = strings.TrimSuffix(opt.SubURL, "/")
|
||||
|
||||
if len(opt.Langs) == 0 {
|
||||
opt.Langs = sec.Key("LANGS").Strings(",")
|
||||
}
|
||||
if len(opt.Names) == 0 {
|
||||
opt.Names = sec.Key("NAMES").Strings(",")
|
||||
}
|
||||
if len(opt.Langs) == 0 {
|
||||
panic("no language is specified")
|
||||
} else if len(opt.Langs) != len(opt.Names) {
|
||||
panic("length of langs is not same as length of names")
|
||||
}
|
||||
i18n.SetDefaultLang(opt.DefaultLang)
|
||||
|
||||
if len(opt.Directory) == 0 {
|
||||
opt.Directory = sec.Key("DIRECTORY").MustString("conf/locale")
|
||||
}
|
||||
if len(opt.CustomDirectory) == 0 {
|
||||
opt.CustomDirectory = sec.Key("CUSTOM_DIRECTORY").MustString("custom/conf/locale")
|
||||
}
|
||||
if len(opt.Format) == 0 {
|
||||
opt.Format = sec.Key("FORMAT").MustString("locale_%s.ini")
|
||||
}
|
||||
if len(opt.Parameter) == 0 {
|
||||
opt.Parameter = sec.Key("PARAMETER").MustString("lang")
|
||||
}
|
||||
if !opt.Redirect {
|
||||
opt.Redirect = sec.Key("REDIRECT").MustBool()
|
||||
}
|
||||
if len(opt.TmplName) == 0 {
|
||||
opt.TmplName = sec.Key("TMPL_NAME").MustString("i18n")
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
type LangType struct {
|
||||
Lang, Name string
|
||||
}
|
||||
|
||||
// I18n is a middleware provides localization layer for your application.
|
||||
// Paramenter langs must be in the form of "en-US", "zh-CN", etc.
|
||||
// Otherwise it may not recognize browser input.
|
||||
func I18n(options ...Options) macaron.Handler {
|
||||
opt := prepareOptions(options)
|
||||
m := initLocales(opt)
|
||||
return func(ctx *macaron.Context) {
|
||||
isNeedRedir := false
|
||||
hasCookie := false
|
||||
|
||||
// 1. Check URL arguments.
|
||||
lang := ctx.Query(opt.Parameter)
|
||||
|
||||
// 2. Get language information from cookies.
|
||||
if len(lang) == 0 {
|
||||
lang = ctx.GetCookie("lang")
|
||||
hasCookie = true
|
||||
} else {
|
||||
isNeedRedir = true
|
||||
}
|
||||
|
||||
// Check again in case someone modify by purpose.
|
||||
if !i18n.IsExist(lang) {
|
||||
lang = ""
|
||||
isNeedRedir = false
|
||||
hasCookie = false
|
||||
}
|
||||
|
||||
// 3. Get language information from 'Accept-Language'.
|
||||
// The first element in the list is chosen to be the default language automatically.
|
||||
if len(lang) == 0 {
|
||||
tags, _, _ := language.ParseAcceptLanguage(ctx.Req.Header.Get("Accept-Language"))
|
||||
tag, _, _ := m.Match(tags...)
|
||||
lang = tag.String()
|
||||
isNeedRedir = false
|
||||
}
|
||||
|
||||
curLang := LangType{
|
||||
Lang: lang,
|
||||
}
|
||||
|
||||
// Save language information in cookies.
|
||||
if !hasCookie {
|
||||
ctx.SetCookie("lang", curLang.Lang, 1<<31-1, "/"+strings.TrimPrefix(opt.SubURL, "/"), opt.CookieDomain)
|
||||
}
|
||||
|
||||
restLangs := make([]LangType, 0, i18n.Count()-1)
|
||||
langs := i18n.ListLangs()
|
||||
names := i18n.ListLangDescs()
|
||||
for i, v := range langs {
|
||||
if lang != v {
|
||||
restLangs = append(restLangs, LangType{v, names[i]})
|
||||
} else {
|
||||
curLang.Name = names[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Set language properties.
|
||||
locale := Locale{i18n.Locale{lang}}
|
||||
ctx.Map(locale)
|
||||
ctx.Locale = locale
|
||||
ctx.Data[opt.TmplName] = locale
|
||||
ctx.Data["Tr"] = i18n.Tr
|
||||
ctx.Data["Lang"] = locale.Lang
|
||||
ctx.Data["LangName"] = curLang.Name
|
||||
ctx.Data["AllLangs"] = append([]LangType{curLang}, restLangs...)
|
||||
ctx.Data["RestLangs"] = restLangs
|
||||
|
||||
if opt.Redirect && isNeedRedir {
|
||||
ctx.Redirect(opt.SubURL + ctx.Req.RequestURI[:strings.Index(ctx.Req.RequestURI, "?")])
|
||||
}
|
||||
}
|
||||
}
|
20
vendor/gitea.com/macaron/inject/.drone.yml
generated
vendored
Normal file
20
vendor/gitea.com/macaron/inject/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
kind: pipeline
|
||||
name: go1-1-1
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: go1-1-2
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
191
vendor/gitea.com/macaron/inject/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/inject/LICENSE
generated
vendored
Normal 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
vendor/gitea.com/macaron/inject/README.md
generated
vendored
Normal file
11
vendor/gitea.com/macaron/inject/README.md
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# inject [](https://drone.gitea.com/macaron/inject) [](http://gocover.io/gitea.com/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.
|
5
vendor/gitea.com/macaron/inject/go.mod
generated
vendored
Normal file
5
vendor/gitea.com/macaron/inject/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitea.com/macaron/inject
|
||||
|
||||
go 1.11
|
||||
|
||||
require github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
13
vendor/gitea.com/macaron/inject/go.sum
generated
vendored
Normal file
13
vendor/gitea.com/macaron/inject/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
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 h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
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=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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=
|
262
vendor/gitea.com/macaron/inject/inject.go
generated
vendored
Normal file
262
vendor/gitea.com/macaron/inject/inject.go
generated
vendored
Normal 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
|
||||
}
|
10
vendor/gitea.com/macaron/macaron/.drone.yml
generated
vendored
Normal file
10
vendor/gitea.com/macaron/macaron/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
commands:
|
||||
- go get -u
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
3
vendor/gitea.com/macaron/macaron/.gitignore
generated
vendored
Normal file
3
vendor/gitea.com/macaron/macaron/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
macaron.sublime-project
|
||||
macaron.sublime-workspace
|
||||
.idea
|
191
vendor/gitea.com/macaron/macaron/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/macaron/LICENSE
generated
vendored
Normal 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.
|
93
vendor/gitea.com/macaron/macaron/README.md
generated
vendored
Normal file
93
vendor/gitea.com/macaron/macaron/README.md
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
Macaron [](https://travis-ci.org/go-macaron/macaron)
|
||||
=======================
|
||||
|
||||

|
||||
|
||||
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 gitea.com/macaron/macaron
|
||||
|
||||
The very basic usage of Macaron:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "gitea.com/macaron/macaron"
|
||||
|
||||
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
|
||||
- [Switch](https://gopm.io): Gopm registry
|
||||
- [Critical Stack Intel](https://intel.criticalstack.com/): A 100% free intel marketplace from Critical Stack, Inc.
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/gitea.com/macaron/macaron)
|
||||
- [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.
|
532
vendor/gitea.com/macaron/macaron/context.go
generated
vendored
Normal file
532
vendor/gitea.com/macaron/macaron/context.go
generated
vendored
Normal file
|
@ -0,0 +1,532 @@
|
|||
// 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"
|
||||
|
||||
"gitea.com/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]
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
11
vendor/gitea.com/macaron/macaron/go.mod
generated
vendored
Normal file
11
vendor/gitea.com/macaron/macaron/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
module gitea.com/macaron/macaron
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591
|
||||
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.44.0
|
||||
)
|
27
vendor/gitea.com/macaron/macaron/go.sum
generated
vendored
Normal file
27
vendor/gitea.com/macaron/macaron/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
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/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.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
73
vendor/gitea.com/macaron/macaron/logger.go
generated
vendored
Normal file
73
vendor/gitea.com/macaron/macaron/logger.go
generated
vendored
Normal 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
vendor/gitea.com/macaron/macaron/macaron.go
generated
vendored
Normal file
334
vendor/gitea.com/macaron/macaron/macaron.go
generated
vendored
Normal 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 (
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"gitea.com/macaron/inject"
|
||||
)
|
||||
|
||||
const _VERSION = "1.3.2.1216"
|
||||
|
||||
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/gitea.com/macaron/macaron/macaronlogo.png
generated
vendored
Normal file
BIN
vendor/gitea.com/macaron/macaron/macaronlogo.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
163
vendor/gitea.com/macaron/macaron/recovery.go
generated
vendored
Normal file
163
vendor/gitea.com/macaron/macaron/recovery.go
generated
vendored
Normal 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"
|
||||
|
||||
"gitea.com/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()
|
||||
}
|
||||
}
|
725
vendor/gitea.com/macaron/macaron/render.go
generated
vendored
Normal file
725
vendor/gitea.com/macaron/macaron/render.go
generated
vendored
Normal file
|
@ -0,0 +1,725 @@
|
|||
// 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_LENGTH = "Content-Length"
|
||||
_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, err 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
|
||||
}
|
114
vendor/gitea.com/macaron/macaron/response_writer.go
generated
vendored
Normal file
114
vendor/gitea.com/macaron/macaron/response_writer.go
generated
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
// 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"
|
||||
"fmt"
|
||||
"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
|
||||
// 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, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
|
||||
}
|
||||
return hijacker.Hijack()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
76
vendor/gitea.com/macaron/macaron/return_handler.go
generated
vendored
Normal file
76
vendor/gitea.com/macaron/macaron/return_handler.go
generated
vendored
Normal 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"
|
||||
|
||||
"gitea.com/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
vendor/gitea.com/macaron/macaron/router.go
generated
vendored
Normal file
380
vendor/gitea.com/macaron/macaron/router.go
generated
vendored
Normal 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)
|
||||
}
|
220
vendor/gitea.com/macaron/macaron/static.go
generated
vendored
Normal file
220
vendor/gitea.com/macaron/macaron/static.go
generated
vendored
Normal file
|
@ -0,0 +1,220 @@
|
|||
// 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() {
|
||||
// Redirect if missing trailing slash.
|
||||
if !strings.HasSuffix(ctx.Req.URL.Path, "/") {
|
||||
http.Redirect(ctx.Resp, ctx.Req.Request, ctx.Req.URL.Path+"/", 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)
|
||||
}
|
||||
|
||||
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
vendor/gitea.com/macaron/macaron/tree.go
generated
vendored
Normal file
390
vendor/gitea.com/macaron/macaron/tree.go
generated
vendored
Normal 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
vendor/gitea.com/macaron/macaron/util_go17.go
generated
vendored
Normal file
25
vendor/gitea.com/macaron/macaron/util_go17.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// +build !go1.8
|
||||
|
||||
// Copyright 2017 The Macaron Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package macaron
|
||||
|
||||
import "net/url"
|
||||
|
||||
// PathUnescape unescapes a path. Ideally, this function would use
|
||||
// url.PathUnescape(..), but the function was not introduced until go1.8.
|
||||
func PathUnescape(s string) (string, error) {
|
||||
return url.QueryUnescape(s)
|
||||
}
|
24
vendor/gitea.com/macaron/macaron/util_go18.go
generated
vendored
Normal file
24
vendor/gitea.com/macaron/macaron/util_go18.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
// +build go1.8
|
||||
|
||||
// Copyright 2017 The Macaron Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package macaron
|
||||
|
||||
import "net/url"
|
||||
|
||||
// PathUnescape unescapes a path.
|
||||
func PathUnescape(s string) (string, error) {
|
||||
return url.PathUnescape(s)
|
||||
}
|
11
vendor/gitea.com/macaron/session/.drone.yml
generated
vendored
Normal file
11
vendor/gitea.com/macaron/session/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.12
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
4
vendor/gitea.com/macaron/session/.gitignore
generated
vendored
Normal file
4
vendor/gitea.com/macaron/session/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
ledis/tmp.db
|
||||
nodb/tmp.db
|
||||
/vendor
|
||||
/.idea
|
191
vendor/gitea.com/macaron/session/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/session/LICENSE
generated
vendored
Normal 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.
|
22
vendor/gitea.com/macaron/session/README.md
generated
vendored
Normal file
22
vendor/gitea.com/macaron/session/README.md
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# session
|
||||
|
||||
Middleware session provides session management for [Macaron](https://gitea.com/macaron/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
|
||||
|
||||
### Installation
|
||||
|
||||
The minimum requirement of Go is 1.11 .
|
||||
|
||||
go get gitea.com/macaron/session
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/gitea.com/macaron/session)
|
||||
- [Documentation](https://go-macaron.com/docs/middlewares/session)
|
||||
|
||||
## Credits
|
||||
|
||||
This package is a modified version of [go-macaron/session](github.com/go-macaron/session).
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
227
vendor/gitea.com/macaron/session/couchbase/couchbase.go
generated
vendored
Normal file
227
vendor/gitea.com/macaron/session/couchbase/couchbase.go
generated
vendored
Normal file
|
@ -0,0 +1,227 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gitea.com/macaron/session"
|
||||
"github.com/couchbaselabs/go-couchbase"
|
||||
)
|
||||
|
||||
// CouchbaseSessionStore represents a couchbase session store implementation.
|
||||
type CouchbaseSessionStore struct {
|
||||
b *couchbase.Bucket
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
maxlifetime int64
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *CouchbaseSessionStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *CouchbaseSessionStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *CouchbaseSessionStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *CouchbaseSessionStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *CouchbaseSessionStore) Release() error {
|
||||
defer s.b.Close()
|
||||
|
||||
// Skip encoding if the data is empty
|
||||
if len(s.data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.b.Set(s.sid, int(s.maxlifetime), data)
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *CouchbaseSessionStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// CouchbaseProvider represents a couchbase session provider implementation.
|
||||
type CouchbaseProvider struct {
|
||||
maxlifetime int64
|
||||
connStr string
|
||||
pool string
|
||||
bucket string
|
||||
b *couchbase.Bucket
|
||||
}
|
||||
|
||||
func (cp *CouchbaseProvider) getBucket() *couchbase.Bucket {
|
||||
c, err := couchbase.Connect(cp.connStr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
pool, err := c.GetPool(cp.pool)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
bucket, err := pool.GetBucket(cp.bucket)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return bucket
|
||||
}
|
||||
|
||||
// Init initializes memory session provider.
|
||||
// connStr is couchbase server REST/JSON URL
|
||||
// e.g. http://host:port/, Pool, Bucket
|
||||
func (p *CouchbaseProvider) Init(maxlifetime int64, connStr string) error {
|
||||
p.maxlifetime = maxlifetime
|
||||
configs := strings.Split(connStr, ",")
|
||||
if len(configs) > 0 {
|
||||
p.connStr = configs[0]
|
||||
}
|
||||
if len(configs) > 1 {
|
||||
p.pool = configs[1]
|
||||
}
|
||||
if len(configs) > 2 {
|
||||
p.bucket = configs[2]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *CouchbaseProvider) Read(sid string) (session.RawStore, error) {
|
||||
p.b = p.getBucket()
|
||||
|
||||
var doc []byte
|
||||
|
||||
err := p.b.Get(sid, &doc)
|
||||
var kv map[interface{}]interface{}
|
||||
if doc == nil {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
cs := &CouchbaseSessionStore{b: p.b, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *CouchbaseProvider) Exist(sid string) bool {
|
||||
p.b = p.getBucket()
|
||||
defer p.b.Close()
|
||||
|
||||
var doc []byte
|
||||
|
||||
if err := p.b.Get(sid, &doc); err != nil || doc == nil {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *CouchbaseProvider) Destroy(sid string) error {
|
||||
p.b = p.getBucket()
|
||||
defer p.b.Close()
|
||||
|
||||
p.b.Delete(sid)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *CouchbaseProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
|
||||
p.b = p.getBucket()
|
||||
|
||||
var doc []byte
|
||||
if err := p.b.Get(oldsid, &doc); err != nil || doc == nil {
|
||||
p.b.Set(sid, int(p.maxlifetime), "")
|
||||
} else {
|
||||
err := p.b.Delete(oldsid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _ = p.b.Add(sid, int(p.maxlifetime), doc)
|
||||
}
|
||||
|
||||
err := p.b.Get(sid, &doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var kv map[interface{}]interface{}
|
||||
if doc == nil {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
cs := &CouchbaseSessionStore{b: p.b, sid: sid, data: kv, maxlifetime: p.maxlifetime}
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *CouchbaseProvider) Count() int {
|
||||
// FIXME
|
||||
return 0
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *CouchbaseProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("couchbase", &CouchbaseProvider{})
|
||||
}
|
266
vendor/gitea.com/macaron/session/file.go
generated
vendored
Normal file
266
vendor/gitea.com/macaron/session/file.go
generated
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
// FileStore represents a file session store implementation.
|
||||
type FileStore struct {
|
||||
p *FileProvider
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewFileStore creates and returns a file session store.
|
||||
func NewFileStore(p *FileProvider, sid string, kv map[interface{}]interface{}) *FileStore {
|
||||
return &FileStore{
|
||||
p: p,
|
||||
sid: sid,
|
||||
data: kv,
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *FileStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *FileStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *FileStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *FileStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *FileStore) Release() error {
|
||||
s.p.lock.Lock()
|
||||
defer s.p.lock.Unlock()
|
||||
|
||||
// Skip encoding if the data is empty
|
||||
if len(s.data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(s.p.filepath(s.sid), data, 0600)
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *FileStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// FileProvider represents a file session provider implementation.
|
||||
type FileProvider struct {
|
||||
lock sync.RWMutex
|
||||
maxlifetime int64
|
||||
rootPath string
|
||||
}
|
||||
|
||||
// Init initializes file session provider with given root path.
|
||||
func (p *FileProvider) Init(maxlifetime int64, rootPath string) error {
|
||||
p.lock.Lock()
|
||||
p.maxlifetime = maxlifetime
|
||||
p.rootPath = rootPath
|
||||
p.lock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *FileProvider) filepath(sid string) string {
|
||||
return path.Join(p.rootPath, string(sid[0]), string(sid[1]), sid)
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
|
||||
filename := p.filepath(sid)
|
||||
if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
var f *os.File
|
||||
if com.IsFile(filename) {
|
||||
f, err = os.OpenFile(filename, os.O_RDONLY, 0600)
|
||||
} else {
|
||||
f, err = os.Create(filename)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err = os.Chtimes(filename, time.Now(), time.Now()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(data) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = DecodeGob(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return NewFileStore(p, sid, kv), nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *FileProvider) Exist(sid string) bool {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
return com.IsFile(p.filepath(sid))
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *FileProvider) Destroy(sid string) error {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
return os.Remove(p.filepath(sid))
|
||||
}
|
||||
|
||||
func (p *FileProvider) regenerate(oldsid, sid string) (err error) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
filename := p.filepath(sid)
|
||||
if com.IsExist(filename) {
|
||||
return fmt.Errorf("new sid '%s' already exists", sid)
|
||||
}
|
||||
|
||||
oldname := p.filepath(oldsid)
|
||||
if !com.IsFile(oldname) {
|
||||
data, err := EncodeGob(make(map[interface{}]interface{}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.MkdirAll(path.Dir(oldname), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ioutil.WriteFile(oldname, data, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.Rename(oldname, filename); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *FileProvider) Regenerate(oldsid, sid string) (_ RawStore, err error) {
|
||||
if err := p.regenerate(oldsid, sid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.Read(sid)
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *FileProvider) Count() int {
|
||||
count := 0
|
||||
if err := filepath.Walk(p.rootPath, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !fi.IsDir() {
|
||||
count++
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Printf("error counting session files: %v", err)
|
||||
return 0
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *FileProvider) GC() {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
if !com.IsExist(p.rootPath) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := filepath.Walk(p.rootPath, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !fi.IsDir() &&
|
||||
(fi.ModTime().Unix()+p.maxlifetime) < time.Now().Unix() {
|
||||
return os.Remove(path)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Printf("error garbage collecting session files: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("file", &FileProvider{})
|
||||
}
|
61
vendor/gitea.com/macaron/session/flash.go
generated
vendored
Normal file
61
vendor/gitea.com/macaron/session/flash.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2018 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 session
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"gitea.com/macaron/macaron"
|
||||
)
|
||||
|
||||
type Flash struct {
|
||||
ctx *macaron.Context
|
||||
url.Values
|
||||
ErrorMsg, WarningMsg, InfoMsg, SuccessMsg string
|
||||
}
|
||||
|
||||
func (f *Flash) set(name, msg string, current ...bool) {
|
||||
isShow := false
|
||||
if (len(current) == 0 && macaron.FlashNow) ||
|
||||
(len(current) > 0 && current[0]) {
|
||||
isShow = true
|
||||
}
|
||||
|
||||
if isShow {
|
||||
f.ctx.Data["Flash"] = f
|
||||
} else {
|
||||
f.Set(name, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Flash) Error(msg string, current ...bool) {
|
||||
f.ErrorMsg = msg
|
||||
f.set("error", msg, current...)
|
||||
}
|
||||
|
||||
func (f *Flash) Warning(msg string, current ...bool) {
|
||||
f.WarningMsg = msg
|
||||
f.set("warning", msg, current...)
|
||||
}
|
||||
|
||||
func (f *Flash) Info(msg string, current ...bool) {
|
||||
f.InfoMsg = msg
|
||||
f.set("info", msg, current...)
|
||||
}
|
||||
|
||||
func (f *Flash) Success(msg string, current ...bool) {
|
||||
f.SuccessMsg = msg
|
||||
f.set("success", msg, current...)
|
||||
}
|
32
vendor/gitea.com/macaron/session/go.mod
generated
vendored
Normal file
32
vendor/gitea.com/macaron/session/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
module gitea.com/macaron/session
|
||||
|
||||
go 1.11
|
||||
|
||||
require (
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668
|
||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d // indirect
|
||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b // indirect
|
||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/go-redis/redis v6.15.2+incompatible
|
||||
github.com/go-sql-driver/mysql v1.4.1
|
||||
github.com/lib/pq v1.2.0
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de // indirect
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af
|
||||
github.com/mattn/go-sqlite3 v1.11.0 // indirect
|
||||
github.com/pelletier/go-toml v1.4.0 // indirect
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 // indirect
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d // indirect
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d // indirect
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect
|
||||
google.golang.org/appengine v1.6.1 // indirect
|
||||
gopkg.in/ini.v1 v1.44.0
|
||||
)
|
116
vendor/gitea.com/macaron/session/go.sum
generated
vendored
Normal file
116
vendor/gitea.com/macaron/session/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
|
||||
gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA=
|
||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d h1:XMf4E1U+b9E3ElF0mjvfXZdflBRZz4gLp16nQ/QSHQM=
|
||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b h1:bZ9rKU2/V8sY+NulSfxDOnXTWcs1rySqdF1sVepihvo=
|
||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7 h1:1XjEY/gnjQ+AfXef2U6dxCquhiRzkEpxZuWqs+QxTL8=
|
||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 h1:Lgdd/Qp96Qj8jqLpq2cI1I1X7BJnu06efS+XkhRoLUQ=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
|
||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
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/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk=
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ=
|
||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
|
||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
|
||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d h1:qQWKKOvHN7Q9c6GdmUteCef2F9ubxMpxY1IKwpIKz68=
|
||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY=
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92 h1:qvsJwGToa8rxb42cDRhkbKeX2H5N8BH+s2aUikGt8mI=
|
||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d h1:NVwnfyR3rENtlz62bcrkXME3INVUa4lcdGt+opvxExs=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
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/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
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-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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/sys v0.0.0-20190606165138-5da285871e9c h1:+EXw7AwNOKzPFXMZ1yNjO40aWCh3PIquJB2fYlv9wcs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0=
|
||||
gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
203
vendor/gitea.com/macaron/session/memcache/memcache.go
generated
vendored
Normal file
203
vendor/gitea.com/macaron/session/memcache/memcache.go
generated
vendored
Normal file
|
@ -0,0 +1,203 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gitea.com/macaron/session"
|
||||
"github.com/bradfitz/gomemcache/memcache"
|
||||
)
|
||||
|
||||
// MemcacheStore represents a memcache session store implementation.
|
||||
type MemcacheStore struct {
|
||||
c *memcache.Client
|
||||
sid string
|
||||
expire int32
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewMemcacheStore creates and returns a memcache session store.
|
||||
func NewMemcacheStore(c *memcache.Client, sid string, expire int32, kv map[interface{}]interface{}) *MemcacheStore {
|
||||
return &MemcacheStore{
|
||||
c: c,
|
||||
sid: sid,
|
||||
expire: expire,
|
||||
data: kv,
|
||||
}
|
||||
}
|
||||
|
||||
func NewItem(sid string, data []byte, expire int32) *memcache.Item {
|
||||
return &memcache.Item{
|
||||
Key: sid,
|
||||
Value: data,
|
||||
Expiration: expire,
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *MemcacheStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *MemcacheStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *MemcacheStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *MemcacheStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *MemcacheStore) Release() error {
|
||||
// Skip encoding if the data is empty
|
||||
if len(s.data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.c.Set(NewItem(s.sid, data, s.expire))
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *MemcacheStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// MemcacheProvider represents a memcache session provider implementation.
|
||||
type MemcacheProvider struct {
|
||||
c *memcache.Client
|
||||
expire int32
|
||||
}
|
||||
|
||||
// Init initializes memcache session provider.
|
||||
// connStrs: 127.0.0.1:9090;127.0.0.1:9091
|
||||
func (p *MemcacheProvider) Init(expire int64, connStrs string) error {
|
||||
p.expire = int32(expire)
|
||||
p.c = memcache.New(strings.Split(connStrs, ";")...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *MemcacheProvider) Read(sid string) (session.RawStore, error) {
|
||||
if !p.Exist(sid) {
|
||||
if err := p.c.Set(NewItem(sid, []byte(""), p.expire)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
item, err := p.c.Get(sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(item.Value) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob(item.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewMemcacheStore(p.c, sid, p.expire, kv), nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *MemcacheProvider) Exist(sid string) bool {
|
||||
_, err := p.c.Get(sid)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *MemcacheProvider) Destroy(sid string) error {
|
||||
return p.c.Delete(sid)
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *MemcacheProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||
if p.Exist(sid) {
|
||||
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||
}
|
||||
|
||||
item := NewItem(sid, []byte(""), p.expire)
|
||||
if p.Exist(oldsid) {
|
||||
item, err = p.c.Get(oldsid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if err = p.c.Delete(oldsid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.Key = sid
|
||||
}
|
||||
if err = p.c.Set(item); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
if len(item.Value) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob(item.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewMemcacheStore(p.c, sid, p.expire, kv), nil
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *MemcacheProvider) Count() int {
|
||||
// FIXME: how come this library does not have Stats method?
|
||||
return -1
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *MemcacheProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("memcache", &MemcacheProvider{})
|
||||
}
|
1
vendor/gitea.com/macaron/session/memcache/memcache.goconvey
generated
vendored
Normal file
1
vendor/gitea.com/macaron/session/memcache/memcache.goconvey
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ignore
|
217
vendor/gitea.com/macaron/session/memory.go
generated
vendored
Normal file
217
vendor/gitea.com/macaron/session/memory.go
generated
vendored
Normal file
|
@ -0,0 +1,217 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MemStore represents a in-memory session store implementation.
|
||||
type MemStore struct {
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
lastAccess time.Time
|
||||
}
|
||||
|
||||
// NewMemStore creates and returns a memory session store.
|
||||
func NewMemStore(sid string) *MemStore {
|
||||
return &MemStore{
|
||||
sid: sid,
|
||||
data: make(map[interface{}]interface{}),
|
||||
lastAccess: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *MemStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *MemStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete deletes a key from session.
|
||||
func (s *MemStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *MemStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (_ *MemStore) Release() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *MemStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// MemProvider represents a in-memory session provider implementation.
|
||||
type MemProvider struct {
|
||||
lock sync.RWMutex
|
||||
maxLifetime int64
|
||||
data map[string]*list.Element
|
||||
// A priority list whose lastAccess newer gets higer priority.
|
||||
list *list.List
|
||||
}
|
||||
|
||||
// Init initializes memory session provider.
|
||||
func (p *MemProvider) Init(maxLifetime int64, _ string) error {
|
||||
p.lock.Lock()
|
||||
p.maxLifetime = maxLifetime
|
||||
p.lock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// update expands time of session store by given ID.
|
||||
func (p *MemProvider) update(sid string) error {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
if e, ok := p.data[sid]; ok {
|
||||
e.Value.(*MemStore).lastAccess = time.Now()
|
||||
p.list.MoveToFront(e)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *MemProvider) Read(sid string) (_ RawStore, err error) {
|
||||
p.lock.RLock()
|
||||
e, ok := p.data[sid]
|
||||
p.lock.RUnlock()
|
||||
|
||||
if ok {
|
||||
if err = p.update(sid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e.Value.(*MemStore), nil
|
||||
}
|
||||
|
||||
// Create a new session.
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
s := NewMemStore(sid)
|
||||
p.data[sid] = p.list.PushBack(s)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *MemProvider) Exist(sid string) bool {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
_, ok := p.data[sid]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *MemProvider) Destroy(sid string) error {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
e, ok := p.data[sid]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
p.list.Remove(e)
|
||||
delete(p.data, sid)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *MemProvider) Regenerate(oldsid, sid string) (RawStore, error) {
|
||||
if p.Exist(sid) {
|
||||
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||
}
|
||||
|
||||
s, err := p.Read(oldsid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = p.Destroy(oldsid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.(*MemStore).sid = sid
|
||||
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
p.data[sid] = p.list.PushBack(s)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *MemProvider) Count() int {
|
||||
return p.list.Len()
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *MemProvider) GC() {
|
||||
p.lock.RLock()
|
||||
for {
|
||||
// No session in the list.
|
||||
e := p.list.Back()
|
||||
if e == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
|
||||
p.lock.RUnlock()
|
||||
p.lock.Lock()
|
||||
p.list.Remove(e)
|
||||
delete(p.data, e.Value.(*MemStore).sid)
|
||||
p.lock.Unlock()
|
||||
p.lock.RLock()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.lock.RUnlock()
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("memory", &MemProvider{list: list.New(), data: make(map[string]*list.Element)})
|
||||
}
|
199
vendor/gitea.com/macaron/session/mysql/mysql.go
generated
vendored
Normal file
199
vendor/gitea.com/macaron/session/mysql/mysql.go
generated
vendored
Normal file
|
@ -0,0 +1,199 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.com/macaron/session"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
// MysqlStore represents a mysql session store implementation.
|
||||
type MysqlStore struct {
|
||||
c *sql.DB
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewMysqlStore creates and returns a mysql session store.
|
||||
func NewMysqlStore(c *sql.DB, sid string, kv map[interface{}]interface{}) *MysqlStore {
|
||||
return &MysqlStore{
|
||||
c: c,
|
||||
sid: sid,
|
||||
data: kv,
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *MysqlStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *MysqlStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *MysqlStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *MysqlStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *MysqlStore) Release() error {
|
||||
// Skip encoding if the data is empty
|
||||
if len(s.data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = s.c.Exec("UPDATE session SET data=?, expiry=? WHERE `key`=?",
|
||||
data, time.Now().Unix(), s.sid)
|
||||
return err
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *MysqlStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// MysqlProvider represents a mysql session provider implementation.
|
||||
type MysqlProvider struct {
|
||||
c *sql.DB
|
||||
expire int64
|
||||
}
|
||||
|
||||
// Init initializes mysql session provider.
|
||||
// connStr: username:password@protocol(address)/dbname?param=value
|
||||
func (p *MysqlProvider) Init(expire int64, connStr string) (err error) {
|
||||
p.expire = expire
|
||||
|
||||
p.c, err = sql.Open("mysql", connStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.c.Ping()
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *MysqlProvider) Read(sid string) (session.RawStore, error) {
|
||||
var data []byte
|
||||
err := p.c.QueryRow("SELECT data FROM session WHERE `key`=?", sid).Scan(&data)
|
||||
if err == sql.ErrNoRows {
|
||||
_, err = p.c.Exec("INSERT INTO session(`key`,data,expiry) VALUES(?,?,?)",
|
||||
sid, "", time.Now().Unix())
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
if len(data) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewMysqlStore(p.c, sid, kv), nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *MysqlProvider) Exist(sid string) bool {
|
||||
var data []byte
|
||||
err := p.c.QueryRow("SELECT data FROM session WHERE `key`=?", sid).Scan(&data)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
panic("session/mysql: error checking existence: " + err.Error())
|
||||
}
|
||||
return err != sql.ErrNoRows
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *MysqlProvider) Destroy(sid string) error {
|
||||
_, err := p.c.Exec("DELETE FROM session WHERE `key`=?", sid)
|
||||
return err
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *MysqlProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||
if p.Exist(sid) {
|
||||
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||
}
|
||||
|
||||
if !p.Exist(oldsid) {
|
||||
if _, err = p.c.Exec("INSERT INTO session(`key`,data,expiry) VALUES(?,?,?)",
|
||||
oldsid, "", time.Now().Unix()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = p.c.Exec("UPDATE session SET `key`=? WHERE `key`=?", sid, oldsid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.Read(sid)
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *MysqlProvider) Count() (total int) {
|
||||
if err := p.c.QueryRow("SELECT COUNT(*) AS NUM FROM session").Scan(&total); err != nil {
|
||||
panic("session/mysql: error counting records: " + err.Error())
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *MysqlProvider) GC() {
|
||||
if _, err := p.c.Exec("DELETE FROM session WHERE expiry + ? <= UNIX_TIMESTAMP(NOW())", p.expire); err != nil {
|
||||
log.Printf("session/mysql: error garbage collecting: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
session.Register("mysql", &MysqlProvider{})
|
||||
}
|
1
vendor/gitea.com/macaron/session/mysql/mysql.goconvey
generated
vendored
Normal file
1
vendor/gitea.com/macaron/session/mysql/mysql.goconvey
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ignore
|
207
vendor/gitea.com/macaron/session/nodb/nodb.go
generated
vendored
Normal file
207
vendor/gitea.com/macaron/session/nodb/nodb.go
generated
vendored
Normal file
|
@ -0,0 +1,207 @@
|
|||
// 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 session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"gitea.com/macaron/session"
|
||||
"github.com/lunny/nodb"
|
||||
"github.com/lunny/nodb/config"
|
||||
)
|
||||
|
||||
// NodbStore represents a nodb session store implementation.
|
||||
type NodbStore struct {
|
||||
c *nodb.DB
|
||||
sid string
|
||||
expire int64
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewNodbStore creates and returns a ledis session store.
|
||||
func NewNodbStore(c *nodb.DB, sid string, expire int64, kv map[interface{}]interface{}) *NodbStore {
|
||||
return &NodbStore{
|
||||
c: c,
|
||||
expire: expire,
|
||||
sid: sid,
|
||||
data: kv,
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *NodbStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *NodbStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *NodbStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *NodbStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *NodbStore) Release() error {
|
||||
// Skip encoding if the data is empty
|
||||
if len(s.data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = s.c.Set([]byte(s.sid), data); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.c.Expire([]byte(s.sid), s.expire)
|
||||
return err
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *NodbStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// NodbProvider represents a ledis session provider implementation.
|
||||
type NodbProvider struct {
|
||||
c *nodb.DB
|
||||
expire int64
|
||||
}
|
||||
|
||||
// Init initializes nodb session provider.
|
||||
func (p *NodbProvider) Init(expire int64, configs string) error {
|
||||
p.expire = expire
|
||||
|
||||
cfg := new(config.Config)
|
||||
cfg.DataDir = configs
|
||||
dbs, err := nodb.Open(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("session/nodb: error opening db: %v", err)
|
||||
}
|
||||
|
||||
p.c, err = dbs.Select(0)
|
||||
return err
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *NodbProvider) Read(sid string) (session.RawStore, error) {
|
||||
if !p.Exist(sid) {
|
||||
if err := p.c.Set([]byte(sid), []byte("")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
kvs, err := p.c.Get([]byte(sid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(kvs) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob(kvs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewNodbStore(p.c, sid, p.expire, kv), nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *NodbProvider) Exist(sid string) bool {
|
||||
count, err := p.c.Exists([]byte(sid))
|
||||
return err == nil && count > 0
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *NodbProvider) Destroy(sid string) error {
|
||||
_, err := p.c.Del([]byte(sid))
|
||||
return err
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *NodbProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||
if p.Exist(sid) {
|
||||
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||
}
|
||||
|
||||
kvs := make([]byte, 0)
|
||||
if p.Exist(oldsid) {
|
||||
if kvs, err = p.c.Get([]byte(oldsid)); err != nil {
|
||||
return nil, err
|
||||
} else if _, err = p.c.Del([]byte(oldsid)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = p.c.Set([]byte(sid), kvs); err != nil {
|
||||
return nil, err
|
||||
} else if _, err = p.c.Expire([]byte(sid), p.expire); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
if len(kvs) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob([]byte(kvs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewNodbStore(p.c, sid, p.expire, kv), nil
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *NodbProvider) Count() int {
|
||||
// FIXME: how come this library does not have DbSize() method?
|
||||
return -1
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *NodbProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("nodb", &NodbProvider{})
|
||||
}
|
1
vendor/gitea.com/macaron/session/nodb/nodb.goconvey
generated
vendored
Normal file
1
vendor/gitea.com/macaron/session/nodb/nodb.goconvey
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ignore
|
200
vendor/gitea.com/macaron/session/postgres/postgres.go
generated
vendored
Normal file
200
vendor/gitea.com/macaron/session/postgres/postgres.go
generated
vendored
Normal file
|
@ -0,0 +1,200 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.com/macaron/session"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
// PostgresStore represents a postgres session store implementation.
|
||||
type PostgresStore struct {
|
||||
c *sql.DB
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewPostgresStore creates and returns a postgres session store.
|
||||
func NewPostgresStore(c *sql.DB, sid string, kv map[interface{}]interface{}) *PostgresStore {
|
||||
return &PostgresStore{
|
||||
c: c,
|
||||
sid: sid,
|
||||
data: kv,
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *PostgresStore) Set(key, value interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *PostgresStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *PostgresStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *PostgresStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// save postgres session values to database.
|
||||
// must call this method to save values to database.
|
||||
func (s *PostgresStore) Release() error {
|
||||
// Skip encoding if the data is empty
|
||||
if len(s.data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = s.c.Exec("UPDATE session SET data=$1, expiry=$2 WHERE key=$3",
|
||||
data, time.Now().Unix(), s.sid)
|
||||
return err
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *PostgresStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// PostgresProvider represents a postgres session provider implementation.
|
||||
type PostgresProvider struct {
|
||||
c *sql.DB
|
||||
maxlifetime int64
|
||||
}
|
||||
|
||||
// Init initializes postgres session provider.
|
||||
// connStr: user=a password=b host=localhost port=5432 dbname=c sslmode=disable
|
||||
func (p *PostgresProvider) Init(maxlifetime int64, connStr string) (err error) {
|
||||
p.maxlifetime = maxlifetime
|
||||
|
||||
p.c, err = sql.Open("postgres", connStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.c.Ping()
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *PostgresProvider) Read(sid string) (session.RawStore, error) {
|
||||
var data []byte
|
||||
err := p.c.QueryRow("SELECT data FROM session WHERE key=$1", sid).Scan(&data)
|
||||
if err == sql.ErrNoRows {
|
||||
_, err = p.c.Exec("INSERT INTO session(key,data,expiry) VALUES($1,$2,$3)",
|
||||
sid, "", time.Now().Unix())
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
if len(data) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewPostgresStore(p.c, sid, kv), nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *PostgresProvider) Exist(sid string) bool {
|
||||
var data []byte
|
||||
err := p.c.QueryRow("SELECT data FROM session WHERE key=$1", sid).Scan(&data)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
panic("session/postgres: error checking existence: " + err.Error())
|
||||
}
|
||||
return err != sql.ErrNoRows
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *PostgresProvider) Destroy(sid string) error {
|
||||
_, err := p.c.Exec("DELETE FROM session WHERE key=$1", sid)
|
||||
return err
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *PostgresProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||
if p.Exist(sid) {
|
||||
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||
}
|
||||
|
||||
if !p.Exist(oldsid) {
|
||||
if _, err = p.c.Exec("INSERT INTO session(key,data,expiry) VALUES($1,$2,$3)",
|
||||
oldsid, "", time.Now().Unix()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = p.c.Exec("UPDATE session SET key=$1 WHERE key=$2", sid, oldsid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.Read(sid)
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *PostgresProvider) Count() (total int) {
|
||||
if err := p.c.QueryRow("SELECT COUNT(*) AS NUM FROM session").Scan(&total); err != nil {
|
||||
panic("session/postgres: error counting records: " + err.Error())
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (p *PostgresProvider) GC() {
|
||||
if _, err := p.c.Exec("DELETE FROM session WHERE EXTRACT(EPOCH FROM NOW()) - expiry > $1", p.maxlifetime); err != nil {
|
||||
log.Printf("session/postgres: error garbage collecting: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
session.Register("postgres", &PostgresProvider{})
|
||||
}
|
1
vendor/gitea.com/macaron/session/postgres/postgres.goconvey
generated
vendored
Normal file
1
vendor/gitea.com/macaron/session/postgres/postgres.goconvey
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ignore
|
239
vendor/gitea.com/macaron/session/redis/redis.go
generated
vendored
Normal file
239
vendor/gitea.com/macaron/session/redis/redis.go
generated
vendored
Normal file
|
@ -0,0 +1,239 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.com/macaron/session"
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/unknwon/com"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// RedisStore represents a redis session store implementation.
|
||||
type RedisStore struct {
|
||||
c *redis.Client
|
||||
prefix, sid string
|
||||
duration time.Duration
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewRedisStore creates and returns a redis session store.
|
||||
func NewRedisStore(c *redis.Client, prefix, sid string, dur time.Duration, kv map[interface{}]interface{}) *RedisStore {
|
||||
return &RedisStore{
|
||||
c: c,
|
||||
prefix: prefix,
|
||||
sid: sid,
|
||||
duration: dur,
|
||||
data: kv,
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *RedisStore) Set(key, val interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *RedisStore) Get(key interface{}) interface{} {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *RedisStore) Delete(key interface{}) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
delete(s.data, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns current session ID.
|
||||
func (s *RedisStore) ID() string {
|
||||
return s.sid
|
||||
}
|
||||
|
||||
// Release releases resource and save data to provider.
|
||||
func (s *RedisStore) Release() error {
|
||||
// Skip encoding if the data is empty
|
||||
if len(s.data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := session.EncodeGob(s.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.c.Set(s.prefix+s.sid, string(data), s.duration).Err()
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
func (s *RedisStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
// RedisProvider represents a redis session provider implementation.
|
||||
type RedisProvider struct {
|
||||
c *redis.Client
|
||||
duration time.Duration
|
||||
prefix string
|
||||
}
|
||||
|
||||
// Init initializes redis session provider.
|
||||
// configs: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180,prefix=session;
|
||||
func (p *RedisProvider) Init(maxlifetime int64, configs string) (err error) {
|
||||
p.duration, err = time.ParseDuration(fmt.Sprintf("%ds", maxlifetime))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := ini.Load([]byte(strings.Replace(configs, ",", "\n", -1)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opt := &redis.Options{
|
||||
Network: "tcp",
|
||||
}
|
||||
for k, v := range cfg.Section("").KeysHash() {
|
||||
switch k {
|
||||
case "network":
|
||||
opt.Network = v
|
||||
case "addr":
|
||||
opt.Addr = v
|
||||
case "password":
|
||||
opt.Password = v
|
||||
case "db":
|
||||
opt.DB = com.StrTo(v).MustInt()
|
||||
case "pool_size":
|
||||
opt.PoolSize = com.StrTo(v).MustInt()
|
||||
case "idle_timeout":
|
||||
opt.IdleTimeout, err = time.ParseDuration(v + "s")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing idle timeout: %v", err)
|
||||
}
|
||||
case "prefix":
|
||||
p.prefix = v
|
||||
default:
|
||||
return fmt.Errorf("session/redis: unsupported option '%s'", k)
|
||||
}
|
||||
}
|
||||
|
||||
p.c = redis.NewClient(opt)
|
||||
return p.c.Ping().Err()
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *RedisProvider) Read(sid string) (session.RawStore, error) {
|
||||
psid := p.prefix + sid
|
||||
if !p.Exist(sid) {
|
||||
if err := p.c.Set(psid, "", p.duration).Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
kvs, err := p.c.Get(psid).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(kvs) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob([]byte(kvs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewRedisStore(p.c, p.prefix, sid, p.duration, kv), nil
|
||||
}
|
||||
|
||||
// Exist returns true if session with given ID exists.
|
||||
func (p *RedisProvider) Exist(sid string) bool {
|
||||
v, err := p.c.Exists(p.prefix + sid).Result()
|
||||
return err == nil && v == 1
|
||||
}
|
||||
|
||||
// Destroy deletes a session by session ID.
|
||||
func (p *RedisProvider) Destroy(sid string) error {
|
||||
return p.c.Del(p.prefix + sid).Err()
|
||||
}
|
||||
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
func (p *RedisProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
||||
poldsid := p.prefix + oldsid
|
||||
psid := p.prefix + sid
|
||||
|
||||
if p.Exist(sid) {
|
||||
return nil, fmt.Errorf("new sid '%s' already exists", sid)
|
||||
} else if !p.Exist(oldsid) {
|
||||
// Make a fake old session.
|
||||
if err = p.c.Set(poldsid, "", p.duration).Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = p.c.Rename(poldsid, psid).Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
kvs, err := p.c.Get(psid).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(kvs) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
} else {
|
||||
kv, err = session.DecodeGob([]byte(kvs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return NewRedisStore(p.c, p.prefix, sid, p.duration, kv), nil
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (p *RedisProvider) Count() int {
|
||||
return int(p.c.DbSize().Val())
|
||||
}
|
||||
|
||||
// GC calls GC to clean expired sessions.
|
||||
func (_ *RedisProvider) GC() {}
|
||||
|
||||
func init() {
|
||||
session.Register("redis", &RedisProvider{})
|
||||
}
|
1
vendor/gitea.com/macaron/session/redis/redis.goconvey
generated
vendored
Normal file
1
vendor/gitea.com/macaron/session/redis/redis.goconvey
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ignore
|
393
vendor/gitea.com/macaron/session/session.go
generated
vendored
Normal file
393
vendor/gitea.com/macaron/session/session.go
generated
vendored
Normal file
|
@ -0,0 +1,393 @@
|
|||
// Copyright 2013 Beego 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 session a middleware that provides the session management of Macaron.
|
||||
package session
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"gitea.com/macaron/macaron"
|
||||
)
|
||||
|
||||
const _VERSION = "0.6.0"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
}
|
||||
|
||||
// RawStore is the interface that operates the session data.
|
||||
type RawStore interface {
|
||||
// Set sets value to given key in session.
|
||||
Set(interface{}, interface{}) error
|
||||
// Get gets value by given key in session.
|
||||
Get(interface{}) interface{}
|
||||
// Delete deletes a key from session.
|
||||
Delete(interface{}) error
|
||||
// ID returns current session ID.
|
||||
ID() string
|
||||
// Release releases session resource and save data to provider.
|
||||
Release() error
|
||||
// Flush deletes all session data.
|
||||
Flush() error
|
||||
}
|
||||
|
||||
// Store is the interface that contains all data for one session process with specific ID.
|
||||
type Store interface {
|
||||
RawStore
|
||||
// Read returns raw session store by session ID.
|
||||
Read(string) (RawStore, error)
|
||||
// Destroy deletes a session.
|
||||
Destroy(*macaron.Context) error
|
||||
// RegenerateId regenerates a session store from old session ID to new one.
|
||||
RegenerateId(*macaron.Context) (RawStore, error)
|
||||
// Count counts and returns number of sessions.
|
||||
Count() int
|
||||
// GC calls GC to clean expired sessions.
|
||||
GC()
|
||||
}
|
||||
|
||||
type store struct {
|
||||
RawStore
|
||||
*Manager
|
||||
}
|
||||
|
||||
var _ Store = &store{}
|
||||
|
||||
// Options represents a struct for specifying configuration options for the session middleware.
|
||||
type Options struct {
|
||||
// Name of provider. Default is "memory".
|
||||
Provider string
|
||||
// Provider configuration, it's corresponding to provider.
|
||||
ProviderConfig string
|
||||
// Cookie name to save session ID. Default is "MacaronSession".
|
||||
CookieName string
|
||||
// Cookie path to store. Default is "/".
|
||||
CookiePath string
|
||||
// GC interval time in seconds. Default is 3600.
|
||||
Gclifetime int64
|
||||
// Max life time in seconds. Default is whatever GC interval time is.
|
||||
Maxlifetime int64
|
||||
// Use HTTPS only. Default is false.
|
||||
Secure bool
|
||||
// Cookie life time. Default is 0.
|
||||
CookieLifeTime int
|
||||
// Cookie domain name. Default is empty.
|
||||
Domain string
|
||||
// Session ID length. Default is 16.
|
||||
IDLength int
|
||||
// Configuration section name. Default is "session".
|
||||
Section string
|
||||
// Ignore release for websocket. Default is false.
|
||||
IgnoreReleaseForWebSocket bool
|
||||
}
|
||||
|
||||
func prepareOptions(options []Options) Options {
|
||||
var opt Options
|
||||
if len(options) > 0 {
|
||||
opt = options[0]
|
||||
}
|
||||
if len(opt.Section) == 0 {
|
||||
opt.Section = "session"
|
||||
}
|
||||
sec := macaron.Config().Section(opt.Section)
|
||||
|
||||
if len(opt.Provider) == 0 {
|
||||
opt.Provider = sec.Key("PROVIDER").MustString("memory")
|
||||
}
|
||||
if len(opt.ProviderConfig) == 0 {
|
||||
opt.ProviderConfig = sec.Key("PROVIDER_CONFIG").MustString("data/sessions")
|
||||
}
|
||||
if len(opt.CookieName) == 0 {
|
||||
opt.CookieName = sec.Key("COOKIE_NAME").MustString("MacaronSession")
|
||||
}
|
||||
if len(opt.CookiePath) == 0 {
|
||||
opt.CookiePath = sec.Key("COOKIE_PATH").MustString("/")
|
||||
}
|
||||
if opt.Gclifetime == 0 {
|
||||
opt.Gclifetime = sec.Key("GC_INTERVAL_TIME").MustInt64(3600)
|
||||
}
|
||||
if opt.Maxlifetime == 0 {
|
||||
opt.Maxlifetime = sec.Key("MAX_LIFE_TIME").MustInt64(opt.Gclifetime)
|
||||
}
|
||||
if !opt.Secure {
|
||||
opt.Secure = sec.Key("SECURE").MustBool()
|
||||
}
|
||||
if opt.CookieLifeTime == 0 {
|
||||
opt.CookieLifeTime = sec.Key("COOKIE_LIFE_TIME").MustInt()
|
||||
}
|
||||
if len(opt.Domain) == 0 {
|
||||
opt.Domain = sec.Key("DOMAIN").String()
|
||||
}
|
||||
if opt.IDLength == 0 {
|
||||
opt.IDLength = sec.Key("ID_LENGTH").MustInt(16)
|
||||
}
|
||||
if !opt.IgnoreReleaseForWebSocket {
|
||||
opt.IgnoreReleaseForWebSocket = sec.Key("IGNORE_RELEASE_FOR_WEBSOCKET").MustBool()
|
||||
}
|
||||
|
||||
return opt
|
||||
}
|
||||
|
||||
// Sessioner is a middleware that maps a session.SessionStore service into the Macaron handler chain.
|
||||
// An single variadic session.Options struct can be optionally provided to configure.
|
||||
func Sessioner(options ...Options) macaron.Handler {
|
||||
opt := prepareOptions(options)
|
||||
manager, err := NewManager(opt.Provider, opt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go manager.startGC()
|
||||
|
||||
return func(ctx *macaron.Context) {
|
||||
sess, err := manager.Start(ctx)
|
||||
if err != nil {
|
||||
panic("session(start): " + err.Error())
|
||||
}
|
||||
|
||||
// Get flash.
|
||||
vals, _ := url.ParseQuery(ctx.GetCookie("macaron_flash"))
|
||||
if len(vals) > 0 {
|
||||
f := &Flash{Values: vals}
|
||||
f.ErrorMsg = f.Get("error")
|
||||
f.SuccessMsg = f.Get("success")
|
||||
f.InfoMsg = f.Get("info")
|
||||
f.WarningMsg = f.Get("warning")
|
||||
ctx.Data["Flash"] = f
|
||||
ctx.SetCookie("macaron_flash", "", -1, opt.CookiePath)
|
||||
}
|
||||
|
||||
f := &Flash{ctx, url.Values{}, "", "", "", ""}
|
||||
ctx.Resp.Before(func(macaron.ResponseWriter) {
|
||||
if flash := f.Encode(); len(flash) > 0 {
|
||||
ctx.SetCookie("macaron_flash", flash, 0, opt.CookiePath)
|
||||
}
|
||||
})
|
||||
|
||||
ctx.Map(f)
|
||||
s := store{
|
||||
RawStore: sess,
|
||||
Manager: manager,
|
||||
}
|
||||
|
||||
ctx.MapTo(s, (*Store)(nil))
|
||||
|
||||
ctx.Next()
|
||||
|
||||
if manager.opt.IgnoreReleaseForWebSocket && ctx.Req.Header.Get("Upgrade") == "websocket" {
|
||||
return
|
||||
}
|
||||
|
||||
if err = sess.Release(); err != nil {
|
||||
panic("session(release): " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Provider is the interface that provides session manipulations.
|
||||
type Provider interface {
|
||||
// Init initializes session provider.
|
||||
Init(gclifetime int64, config string) error
|
||||
// Read returns raw session store by session ID.
|
||||
Read(sid string) (RawStore, error)
|
||||
// Exist returns true if session with given ID exists.
|
||||
Exist(sid string) bool
|
||||
// Destroy deletes a session by session ID.
|
||||
Destroy(sid string) error
|
||||
// Regenerate regenerates a session store from old session ID to new one.
|
||||
Regenerate(oldsid, sid string) (RawStore, error)
|
||||
// Count counts and returns number of sessions.
|
||||
Count() int
|
||||
// GC calls GC to clean expired sessions.
|
||||
GC()
|
||||
}
|
||||
|
||||
var providers = make(map[string]Provider)
|
||||
|
||||
// Register registers a provider.
|
||||
func Register(name string, provider Provider) {
|
||||
if provider == nil {
|
||||
panic("session: cannot register provider with nil value")
|
||||
}
|
||||
if _, dup := providers[name]; dup {
|
||||
panic(fmt.Errorf("session: cannot register provider '%s' twice", name))
|
||||
}
|
||||
providers[name] = provider
|
||||
}
|
||||
|
||||
// _____
|
||||
// / \ _____ ____ _____ ____ ___________
|
||||
// / \ / \\__ \ / \\__ \ / ___\_/ __ \_ __ \
|
||||
// / Y \/ __ \| | \/ __ \_/ /_/ > ___/| | \/
|
||||
// \____|__ (____ /___| (____ /\___ / \___ >__|
|
||||
// \/ \/ \/ \//_____/ \/
|
||||
|
||||
// Manager represents a struct that contains session provider and its configuration.
|
||||
type Manager struct {
|
||||
provider Provider
|
||||
opt Options
|
||||
}
|
||||
|
||||
// NewManager creates and returns a new session manager by given provider name and configuration.
|
||||
// It panics when given provider isn't registered.
|
||||
func NewManager(name string, opt Options) (*Manager, error) {
|
||||
p, ok := providers[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("session: unknown provider '%s'(forgotten import?)", name)
|
||||
}
|
||||
return &Manager{p, opt}, p.Init(opt.Maxlifetime, opt.ProviderConfig)
|
||||
}
|
||||
|
||||
// sessionID generates a new session ID with rand string, unix nano time, remote addr by hash function.
|
||||
func (m *Manager) sessionID() string {
|
||||
return hex.EncodeToString(generateRandomKey(m.opt.IDLength / 2))
|
||||
}
|
||||
|
||||
// validSessionID tests whether a provided session ID is a valid session ID.
|
||||
func (m *Manager) validSessionID(sid string) (bool, error) {
|
||||
if len(sid) != m.opt.IDLength {
|
||||
return false, errors.New("invalid 'sid': " + sid)
|
||||
}
|
||||
|
||||
for i := range sid {
|
||||
switch {
|
||||
case '0' <= sid[i] && sid[i] <= '9':
|
||||
case 'a' <= sid[i] && sid[i] <= 'f':
|
||||
default:
|
||||
return false, errors.New("invalid 'sid': " + sid)
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Start starts a session by generating new one
|
||||
// or retrieve existence one by reading session ID from HTTP request if it's valid.
|
||||
func (m *Manager) Start(ctx *macaron.Context) (RawStore, error) {
|
||||
sid := ctx.GetCookie(m.opt.CookieName)
|
||||
valid, _ := m.validSessionID(sid)
|
||||
if len(sid) > 0 && valid && m.provider.Exist(sid) {
|
||||
return m.provider.Read(sid)
|
||||
}
|
||||
|
||||
sid = m.sessionID()
|
||||
sess, err := m.provider.Read(sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cookie := &http.Cookie{
|
||||
Name: m.opt.CookieName,
|
||||
Value: sid,
|
||||
Path: m.opt.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: m.opt.Secure,
|
||||
Domain: m.opt.Domain,
|
||||
}
|
||||
if m.opt.CookieLifeTime >= 0 {
|
||||
cookie.MaxAge = m.opt.CookieLifeTime
|
||||
}
|
||||
http.SetCookie(ctx.Resp, cookie)
|
||||
ctx.Req.AddCookie(cookie)
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// Read returns raw session store by session ID.
|
||||
func (m *Manager) Read(sid string) (RawStore, error) {
|
||||
// Ensure we're trying to read a valid session ID
|
||||
if _, err := m.validSessionID(sid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m.provider.Read(sid)
|
||||
}
|
||||
|
||||
// Destroy deletes a session by given ID.
|
||||
func (m *Manager) Destroy(ctx *macaron.Context) error {
|
||||
sid := ctx.GetCookie(m.opt.CookieName)
|
||||
if len(sid) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := m.validSessionID(sid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.provider.Destroy(sid); err != nil {
|
||||
return err
|
||||
}
|
||||
cookie := &http.Cookie{
|
||||
Name: m.opt.CookieName,
|
||||
Path: m.opt.CookiePath,
|
||||
HttpOnly: true,
|
||||
Expires: time.Now(),
|
||||
MaxAge: -1,
|
||||
}
|
||||
http.SetCookie(ctx.Resp, cookie)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegenerateId regenerates a session store from old session ID to new one.
|
||||
func (m *Manager) RegenerateId(ctx *macaron.Context) (sess RawStore, err error) {
|
||||
sid := m.sessionID()
|
||||
oldsid := ctx.GetCookie(m.opt.CookieName)
|
||||
_, err = m.validSessionID(oldsid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sess, err = m.provider.Regenerate(oldsid, sid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cookie := &http.Cookie{
|
||||
Name: m.opt.CookieName,
|
||||
Value: sid,
|
||||
Path: m.opt.CookiePath,
|
||||
HttpOnly: true,
|
||||
Secure: m.opt.Secure,
|
||||
Domain: m.opt.Domain,
|
||||
}
|
||||
if m.opt.CookieLifeTime >= 0 {
|
||||
cookie.MaxAge = m.opt.CookieLifeTime
|
||||
}
|
||||
http.SetCookie(ctx.Resp, cookie)
|
||||
ctx.Req.AddCookie(cookie)
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// Count counts and returns number of sessions.
|
||||
func (m *Manager) Count() int {
|
||||
return m.provider.Count()
|
||||
}
|
||||
|
||||
// GC starts GC job in a certain period.
|
||||
func (m *Manager) GC() {
|
||||
m.provider.GC()
|
||||
}
|
||||
|
||||
// startGC starts GC job in a certain period.
|
||||
func (m *Manager) startGC() {
|
||||
m.GC()
|
||||
time.AfterFunc(time.Duration(m.opt.Gclifetime)*time.Second, func() { m.startGC() })
|
||||
}
|
||||
|
||||
// SetSecure indicates whether to set cookie with HTTPS or not.
|
||||
func (m *Manager) SetSecure(secure bool) {
|
||||
m.opt.Secure = secure
|
||||
}
|
63
vendor/gitea.com/macaron/session/utils.go
generated
vendored
Normal file
63
vendor/gitea.com/macaron/session/utils.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2013 Beego 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 session
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/gob"
|
||||
"io"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register([]interface{}{})
|
||||
gob.Register(map[int]interface{}{})
|
||||
gob.Register(map[string]interface{}{})
|
||||
gob.Register(map[interface{}]interface{}{})
|
||||
gob.Register(map[string]string{})
|
||||
gob.Register(map[int]string{})
|
||||
gob.Register(map[int]int{})
|
||||
gob.Register(map[int]int64{})
|
||||
}
|
||||
|
||||
func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) {
|
||||
for _, v := range obj {
|
||||
gob.Register(v)
|
||||
}
|
||||
buf := bytes.NewBuffer(nil)
|
||||
err := gob.NewEncoder(buf).Encode(obj)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func DecodeGob(encoded []byte) (out map[interface{}]interface{}, err error) {
|
||||
buf := bytes.NewBuffer(encoded)
|
||||
err = gob.NewDecoder(buf).Decode(&out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// NOTE: A local copy in case of underlying package change
|
||||
var alphanum = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
|
||||
|
||||
// generateRandomKey creates a random key with the given strength.
|
||||
func generateRandomKey(strength int) []byte {
|
||||
k := make([]byte, strength)
|
||||
if n, err := io.ReadFull(rand.Reader, k); n != strength || err != nil {
|
||||
return com.RandomCreateBytes(strength, alphanum...)
|
||||
}
|
||||
return k
|
||||
}
|
9
vendor/gitea.com/macaron/toolbox/.drone.yml
generated
vendored
Normal file
9
vendor/gitea.com/macaron/toolbox/.drone.yml
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.11
|
||||
commands:
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
2
vendor/gitea.com/macaron/toolbox/.gitignore
generated
vendored
Normal file
2
vendor/gitea.com/macaron/toolbox/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
profile/
|
||||
/.idea
|
191
vendor/gitea.com/macaron/toolbox/LICENSE
generated
vendored
Normal file
191
vendor/gitea.com/macaron/toolbox/LICENSE
generated
vendored
Normal 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.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue